aboutsummaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
Diffstat (limited to 'driver')
-rw-r--r--driver/modules/hostap_ap.c70
-rw-r--r--driver/modules/hostap_ap.h4
-rw-r--r--driver/modules/hostap_wlan.h3
3 files changed, 43 insertions, 34 deletions
diff --git a/driver/modules/hostap_ap.c b/driver/modules/hostap_ap.c
index f561a9f..44054d6 100644
--- a/driver/modules/hostap_ap.c
+++ b/driver/modules/hostap_ap.c
@@ -277,9 +277,9 @@ static void ap_handle_timer(unsigned long data)
/* station activity detected; reset timeout state */
sta->timeout_next = STA_NULLFUNC;
next_time = sta->last_rx + ap->max_inactivity;
- } else if (sta->timeout_next == STA_DISASSOC && sta->txexc == 0) {
- /* data nullfunc frame poll did not produce TX errors; assume
- * station ACKed it */
+ } else if (sta->timeout_next == STA_DISASSOC &&
+ !(sta->flags & WLAN_STA_PENDING_POLL)) {
+ /* STA ACKed data nullfunc frame poll */
sta->timeout_next = STA_NULLFUNC;
next_time = jiffies + ap->max_inactivity;
}
@@ -321,13 +321,13 @@ static void ap_handle_timer(unsigned long data)
} else if (sta->timeout_next == STA_NULLFUNC) {
/* send data frame to poll STA and check whether this frame
* is ACKed */
- sta->txexc = 0;
/* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but
* it is apparently not retried so TX Exc events are not
* received for it */
+ sta->flags |= WLAN_STA_PENDING_POLL;
prism2_send_mgmt(local->dev, WLAN_FC_TYPE_DATA,
WLAN_FC_STYPE_DATA, NULL, 0, 1,
- sta->addr, 0);
+ sta->addr, ap->tx_callback_poll);
} else {
int deauth = sta->timeout_next == STA_DEAUTH;
u16 resp;
@@ -832,6 +832,33 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
}
dev_kfree_skb(skb);
}
+
+/* Called only as a tasklet (software IRQ); TX callback for poll frames used
+ * in verifying whether the STA is still present. */
+static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
+{
+ struct ap_data *ap = data;
+ struct net_device *dev = ap->local->dev;
+ struct hostap_ieee80211_hdr *hdr;
+ struct sta_info *sta;
+
+ if (skb->len < 24)
+ goto fail;
+ hdr = (struct hostap_ieee80211_hdr *) skb->data;
+ if (ok) {
+ spin_lock(&ap->sta_table_lock);
+ sta = ap_get_sta(ap, hdr->addr1);
+ if (sta)
+ sta->flags &= ~WLAN_STA_PENDING_POLL;
+ spin_unlock(&ap->sta_table_lock);
+ } else {
+ PDEBUG(DEBUG_AP, "%s: STA " MACSTR " did not ACK activity "
+ "poll frame\n", dev->name, MAC2STR(hdr->addr1));
+ }
+
+ fail:
+ dev_kfree_skb(skb);
+}
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
@@ -886,7 +913,10 @@ void hostap_init_data(local_info_t *local)
hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap);
ap->tx_callback_assoc =
hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap);
- if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0)
+ ap->tx_callback_poll =
+ hostap_tx_callback_register(local, hostap_ap_tx_cb_poll, ap);
+ if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0 ||
+ ap->tx_callback_poll == 0)
printk(KERN_WARNING "%s: failed to register TX callback for "
"AP\n", local->dev->name);
@@ -1056,7 +1086,7 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
}
p += sprintf(p, "%s=" MACSTR "\nusers=%d\naid=%d\n"
- "flags=0x%04x%s%s%s%s%s%s\n"
+ "flags=0x%04x%s%s%s%s%s%s%s\n"
"capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
sta->ap ? "AP" : "STA",
MAC2STR(sta->addr), atomic_read(&sta->users), sta->aid,
@@ -1067,6 +1097,7 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
sta->flags & WLAN_STA_TIM ? " TIM" : "",
sta->flags & WLAN_STA_PERM ? " PERM" : "",
sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",
+ sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",
sta->capability, sta->listen_interval);
/* supported_rates: 500 kbit/s units with msb ignored */
for (i = 0; i < sizeof(sta->supported_rates); i++)
@@ -1081,8 +1112,7 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
"last_rx: silence=%d signal=%d rate=%d\n"
"tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"
"tx[11M]=%d\n"
- "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n"
- "txexc=%d\n",
+ "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",
jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,
sta->last_tx,
sta->rx_packets, sta->tx_packets, sta->rx_bytes,
@@ -1091,8 +1121,7 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
sta->last_rx_signal, sta->last_rx_rate,
sta->tx_rate, sta->tx_count[0], sta->tx_count[1],
sta->tx_count[2], sta->tx_count[3], sta->rx_count[0],
- sta->rx_count[1], sta->rx_count[2], sta->rx_count[3],
- sta->txexc);
+ sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);
if (sta->crypt && sta->crypt->ops)
p += sprintf(p, "crypt=%s\n", sta->crypt->ops->name);
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
@@ -2653,7 +2682,6 @@ static int prism2_hostapd_get_info_sta(struct ap_data *ap,
return -ENOENT;
param->u.get_info_sta.inactive_sec = (jiffies - sta->last_rx) / HZ;
- param->u.get_info_sta.txexc = sta->txexc;
atomic_dec(&sta->users);
@@ -2661,21 +2689,6 @@ static int prism2_hostapd_get_info_sta(struct ap_data *ap,
}
-static int prism2_hostapd_reset_txexc_sta(struct ap_data *ap,
- struct prism2_hostapd_param *param)
-{
- struct sta_info *sta;
-
- spin_lock_bh(&ap->sta_table_lock);
- sta = ap_get_sta(ap, param->sta_addr);
- if (sta)
- sta->txexc = 0;
- spin_unlock_bh(&ap->sta_table_lock);
-
- return sta ? 0 : -ENOENT;
-}
-
-
static int prism2_hostapd_set_flags_sta(struct ap_data *ap,
struct prism2_hostapd_param *param)
{
@@ -2709,8 +2722,6 @@ static int prism2_hostapd(struct ap_data *ap,
return prism2_hostapd_remove_sta(ap, param);
case PRISM2_HOSTAPD_GET_INFO_STA:
return prism2_hostapd_get_info_sta(ap, param);
- case PRISM2_HOSTAPD_RESET_TXEXC_STA:
- return prism2_hostapd_reset_txexc_sta(ap, param);
case PRISM2_HOSTAPD_SET_FLAGS_STA:
return prism2_hostapd_set_flags_sta(ap, param);
default:
@@ -2903,7 +2914,6 @@ void hostap_handle_sta_tx_exc(local_info_t *local,
return;
}
- sta->txexc++;
sta->tx_since_last_failure = 0;
sta->tx_consecutive_exc++;
diff --git a/driver/modules/hostap_ap.h b/driver/modules/hostap_ap.h
index 7ac6955..afbfce9 100644
--- a/driver/modules/hostap_ap.h
+++ b/driver/modules/hostap_ap.h
@@ -25,6 +25,7 @@
* controlling whether STA is authorized to
* send and receive non-IEEE 802.1X frames
*/
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
#define WLAN_RATE_1M BIT(0)
#define WLAN_RATE_2M BIT(1)
@@ -78,7 +79,6 @@ struct sta_info {
u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate)
*/
u32 tx_since_last_failure;
- u32 txexc;
u32 tx_consecutive_exc;
struct prism2_crypt_data *crypt;
@@ -212,7 +212,7 @@ struct ap_data {
*/
struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
- u16 tx_callback_auth, tx_callback_assoc;
+ u16 tx_callback_auth, tx_callback_assoc, tx_callback_poll;
/* WEP operations for generating challenges to be used with shared key
* authentication */
diff --git a/driver/modules/hostap_wlan.h b/driver/modules/hostap_wlan.h
index 438fdd6..f7dbe93 100644
--- a/driver/modules/hostap_wlan.h
+++ b/driver/modules/hostap_wlan.h
@@ -922,7 +922,7 @@ enum {
PRISM2_HOSTAPD_ADD_STA = 2,
PRISM2_HOSTAPD_REMOVE_STA = 3,
PRISM2_HOSTAPD_GET_INFO_STA = 4,
- PRISM2_HOSTAPD_RESET_TXEXC_STA = 5,
+ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
PRISM2_SET_ENCRYPTION = 6,
PRISM2_GET_ENCRYPTION = 7,
PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
@@ -946,7 +946,6 @@ struct prism2_hostapd_param {
} add_sta;
struct {
u32 inactive_sec;
- u32 txexc;
} get_info_sta;
struct {
u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];