* [PATCH 0/8] mac80211 sta info and related changes
@ 2008-02-22 11:16 Johannes Berg
2008-02-22 11:16 ` [PATCH 1/8] mac80211: clarify use of TX status/RX callbacks Johannes Berg
` (8 more replies)
0 siblings, 9 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
This patch series contains a few loosely related changes in mac80211
I did over the past few days:
* clarify use of TX status/RX callbacks
as per my previous mail, the irqsafe/non-irq-safe stuff
* safely free beacon in ieee80211_if_reinit
This is necessary for reentrancy reasons with ieee80211_beacon_get()
* split ieee80211_key_alloc
Preparation for RCU-ifying STA info, split key allocation into
allocation and insertion
* RCU-ify STA info structure access
Remove STA refcount and instead protect them by RCU
* split ieee80211_txrx_data
Mostly unrelated, split up txrx_data and flags into one struct for TX
and one for RX
* split sta_info_add
Split sta_info_add into _alloc and _link to resolve a few races and
allow GFP_KERNEL allocations in many cases (which was removed by the
RCU-ification patch)
* remove STA info's last_ack stuff
Remove some unused stats members
* clean up sta_info and document locking
Document and clean up the definition of struct sta_info and document
the locking (deficiencies)
I'd like to have somebody else look over these but I'm confident that the
changes do not, at least, introduce regressions.
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/8] mac80211: clarify use of TX status/RX callbacks
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 2/8] mac80211: safely free beacon in ieee80211_if_reinit Johannes Berg
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
This patch clarifies the use of the irqsafe vs. non-irq-safe
functions and their respective locking requirements.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/net/mac80211.h | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
--- everything.orig/include/net/mac80211.h 2008-02-22 11:45:11.000000000 +0100
+++ everything/include/net/mac80211.h 2008-02-22 11:49:23.000000000 +0100
@@ -38,7 +38,11 @@
* called in hardware interrupt context. The low-level driver must not call any
* other functions in hardware interrupt context. If there is a need for such
* call, the low-level driver should first ACK the interrupt and perform the
- * IEEE 802.11 code call after this, e.g. from a scheduled workqueue function.
+ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
+ * tasklet function.
+ *
+ * NOTE: If the driver opts to use the _irqsafe() functions, it may not also
+ * use the non-irqsafe functions!
*/
/**
@@ -1204,7 +1208,10 @@ void __ieee80211_rx(struct ieee80211_hw
* buffer in @skb must start with an IEEE 802.11 header or a radiotap
* header if %RX_FLAG_RADIOTAP is set in the @status flags.
*
- * This function may not be called in IRQ context.
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function and ieee80211_rx_irqsafe() may not be mixed for a
+ * single hardware.
*
* @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call
@@ -1221,7 +1228,10 @@ static inline void ieee80211_rx(struct i
* ieee80211_rx_irqsafe - receive frame
*
* Like ieee80211_rx() but can be called in IRQ context
- * (internally defers to a workqueue.)
+ * (internally defers to a tasklet.)
+ *
+ * Calls to this function and ieee80211_rx() may not be mixed for a
+ * single hardware.
*
* @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call
@@ -1240,6 +1250,11 @@ void ieee80211_rx_irqsafe(struct ieee802
* transmitted. It is permissible to not call this function for
* multicast frames but this can affect statistics.
*
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function and ieee80211_tx_status_irqsafe() may not be mixed
+ * for a single hardware.
+ *
* @hw: the hardware the frame was transmitted by
* @skb: the frame that was transmitted, owned by mac80211 after this call
* @status: status information for this frame; the status pointer need not
@@ -1249,6 +1264,22 @@ void ieee80211_rx_irqsafe(struct ieee802
void ieee80211_tx_status(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct ieee80211_tx_status *status);
+
+/**
+ * ieee80211_tx_status_irqsafe - irq-safe transmit status callback
+ *
+ * Like ieee80211_tx_status() but can be called in IRQ context
+ * (internally defers to a tasklet.)
+ *
+ * Calls to this function and ieee80211_tx_status() may not be mixed for a
+ * single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ * @status: status information for this frame; the status pointer need not
+ * be valid after this function returns and is not freed by mac80211,
+ * it is recommended that it points to a stack area
+ */
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct ieee80211_tx_status *status);
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/8] mac80211: safely free beacon in ieee80211_if_reinit
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
2008-02-22 11:16 ` [PATCH 1/8] mac80211: clarify use of TX status/RX callbacks Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 3/8] mac80211: split ieee80211_key_alloc Johannes Berg
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
If ieee80211_if_reinit() is called from ieee80211_unregister_hw()
then it is possible that the driver will still request a beacon
(it is allowed to until ieee80211_unregister_hw() has returned.)
This means we need to use an RCU-protected write to the beacon
information even in this function.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/ieee80211_iface.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- everything.orig/net/mac80211/ieee80211_iface.c 2008-02-21 14:35:24.000000000 +0100
+++ everything/net/mac80211/ieee80211_iface.c 2008-02-21 15:13:17.000000000 +0100
@@ -193,6 +193,7 @@ void ieee80211_if_reinit(struct net_devi
/* Remove all virtual interfaces that use this BSS
* as their sdata->bss */
struct ieee80211_sub_if_data *tsdata, *n;
+ struct beacon_data *beacon;
list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
@@ -210,7 +211,10 @@ void ieee80211_if_reinit(struct net_devi
}
}
- kfree(sdata->u.ap.beacon);
+ beacon = sdata->u.ap.beacon;
+ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+ synchronize_rcu();
+ kfree(beacon);
while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
local->total_ps_buffered--;
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/8] mac80211: split ieee80211_key_alloc
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
2008-02-22 11:16 ` [PATCH 1/8] mac80211: clarify use of TX status/RX callbacks Johannes Berg
2008-02-22 11:16 ` [PATCH 2/8] mac80211: safely free beacon in ieee80211_if_reinit Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 4/8] mac80211: RCU-ify STA info structure access Johannes Berg
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
In order to RCU-ify sta_info, we need to be able to allocate
a key without linking it to an sdata/sta structure (because
allocation cannot be done in an rcu critical section). This
patch splits up ieee80211_key_alloc() and updates all users
appropriately.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 13 ++++-
net/mac80211/ieee80211_ioctl.c | 91 ++++++++++++++++++++++-------------------
net/mac80211/ieee80211_key.h | 11 +++-
net/mac80211/key.c | 32 +++++++++-----
4 files changed, 87 insertions(+), 60 deletions(-)
--- everything.orig/net/mac80211/ieee80211_ioctl.c 2008-02-21 16:02:41.000000000 +0100
+++ everything/net/mac80211/ieee80211_ioctl.c 2008-02-21 16:12:55.000000000 +0100
@@ -33,8 +33,8 @@ static int ieee80211_set_encryption(stru
size_t key_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- int ret = 0;
- struct sta_info *sta;
+ int ret;
+ struct sta_info *sta = NULL;
struct ieee80211_key *key;
struct ieee80211_sub_if_data *sdata;
@@ -46,58 +46,65 @@ static int ieee80211_set_encryption(stru
return -EINVAL;
}
- if (is_broadcast_ether_addr(sta_addr)) {
- sta = NULL;
- key = sdata->keys[idx];
- } else {
- set_tx_key = 0;
- /*
- * According to the standard, the key index of a pairwise
- * key must be zero. However, some AP are broken when it
- * comes to WEP key indices, so we work around this.
- */
- if (idx != 0 && alg != ALG_WEP) {
- printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
- "individual key\n", dev->name);
- return -EINVAL;
+ if (remove) {
+ if (is_broadcast_ether_addr(sta_addr)) {
+ key = sdata->keys[idx];
+ } else {
+ sta = sta_info_get(local, sta_addr);
+ if (!sta) {
+ ret = -ENOENT;
+ key = NULL;
+ goto err_out;
+ }
+
+ key = sta->key;
}
- sta = sta_info_get(local, sta_addr);
- if (!sta) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- DECLARE_MAC_BUF(mac);
- printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
- "%s\n",
- dev->name, print_mac(mac, sta_addr));
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ if (!key)
+ ret = -ENOENT;
+ else
+ ret = 0;
+ } else {
+ key = ieee80211_key_alloc(alg, idx, key_len, _key);
+ if (!key)
+ return -ENOMEM;
+
+ if (!is_broadcast_ether_addr(sta_addr)) {
+ set_tx_key = 0;
+ /*
+ * According to the standard, the key index of a
+ * pairwise key must be zero. However, some AP are
+ * broken when it comes to WEP key indices, so we
+ * work around this.
+ */
+ if (idx != 0 && alg != ALG_WEP) {
+ ret = -EINVAL;
+ goto err_out;
+ }
- return -ENOENT;
+ sta = sta_info_get(local, sta_addr);
+ if (!sta) {
+ ret = -ENOENT;
+ goto err_out;
+ }
}
- key = sta->key;
- }
+ /* Automatically frees any old key if present. */
+ ieee80211_key_link(key, sdata, sta);
- if (remove) {
- ieee80211_key_free(key);
+ if (set_tx_key || (!sta && !sdata->default_key && key))
+ ieee80211_set_default_key(sdata, idx);
+
+ /* don't free key later */
key = NULL;
- } else {
- /*
- * Automatically frees any old key if present.
- */
- key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
- if (!key) {
- ret = -ENOMEM;
- goto err_out;
- }
- }
- if (set_tx_key || (!sta && !sdata->default_key && key))
- ieee80211_set_default_key(sdata, idx);
+ ret = 0;
+ }
- ret = 0;
err_out:
if (sta)
sta_info_put(sta);
+ ieee80211_key_free(key);
return ret;
}
--- everything.orig/net/mac80211/ieee80211_key.h 2008-02-21 16:02:40.000000000 +0100
+++ everything/net/mac80211/ieee80211_key.h 2008-02-21 16:02:46.000000000 +0100
@@ -112,12 +112,17 @@ struct ieee80211_key {
struct ieee80211_key_conf conf;
};
-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta,
- enum ieee80211_key_alg alg,
+struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
const u8 *key_data);
+/*
+ * Insert a key into data structures (sdata, sta if necessary)
+ * to make it used.
+ */
+void ieee80211_key_link(struct ieee80211_key *key,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta);
void ieee80211_key_free(struct ieee80211_key *key);
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
--- everything.orig/net/mac80211/key.c 2008-02-21 16:02:41.000000000 +0100
+++ everything/net/mac80211/key.c 2008-02-21 16:18:13.000000000 +0100
@@ -111,9 +111,7 @@ static void ieee80211_key_disable_hw_acc
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
}
-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta,
- enum ieee80211_key_alg alg,
+struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
const u8 *key_data)
@@ -138,10 +136,6 @@ struct ieee80211_key *ieee80211_key_allo
key->conf.keylen = key_len;
memcpy(key->conf.key, key_data, key_len);
- key->local = sdata->local;
- key->sdata = sdata;
- key->sta = sta;
-
if (alg == ALG_CCMP) {
/*
* Initialize AES key state here as an optimization so that
@@ -154,6 +148,23 @@ struct ieee80211_key *ieee80211_key_allo
}
}
+ return key;
+}
+
+void ieee80211_key_link(struct ieee80211_key *key,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta)
+{
+ int idx;
+
+ BUG_ON(!sdata);
+ BUG_ON(!key);
+
+ idx = key->conf.keyidx;
+ key->local = sdata->local;
+ key->sdata = sdata;
+ key->sta = sta;
+
ieee80211_debugfs_key_add(key->local, key);
/* remove key first */
@@ -196,8 +207,6 @@ struct ieee80211_key *ieee80211_key_allo
rcu_assign_pointer(sdata->keys[idx], key);
list_add(&key->list, &sdata->key_list);
-
- return key;
}
void ieee80211_key_free(struct ieee80211_key *key)
@@ -207,7 +216,7 @@ void ieee80211_key_free(struct ieee80211
if (key->sta) {
rcu_assign_pointer(key->sta->key, NULL);
- } else {
+ } else if (key->sdata) {
if (key->sdata->default_key == key)
ieee80211_set_default_key(key->sdata, -1);
if (key->conf.keyidx >= 0 &&
@@ -228,7 +237,8 @@ void ieee80211_key_free(struct ieee80211
ieee80211_aes_key_free(key->u.ccmp.tfm);
ieee80211_debugfs_key_remove(key);
- list_del(&key->list);
+ if (key->sdata)
+ list_del(&key->list);
kfree(key);
}
--- everything.orig/net/mac80211/cfg.c 2008-02-21 16:13:31.000000000 +0100
+++ everything/net/mac80211/cfg.c 2008-02-21 16:15:07.000000000 +0100
@@ -129,6 +129,7 @@ static int ieee80211_add_key(struct wiph
struct sta_info *sta = NULL;
enum ieee80211_key_alg alg;
int ret;
+ struct ieee80211_key *key;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -147,16 +148,20 @@ static int ieee80211_add_key(struct wiph
return -EINVAL;
}
+ key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
+ if (!key)
+ return -ENOMEM;
+
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
- if (!sta)
+ if (!sta) {
+ ieee80211_key_free(key);
return -ENOENT;
+ }
}
+ ieee80211_key_link(key, sdata, sta);
ret = 0;
- if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
- params->key_len, params->key))
- ret = -ENOMEM;
if (sta)
sta_info_put(sta);
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/8] mac80211: RCU-ify STA info structure access
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (2 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 3/8] mac80211: split ieee80211_key_alloc Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-03-05 1:57 ` Chatre, Reinette
2008-02-22 11:16 ` [PATCH 5/8] mac80211: split ieee80211_txrx_data Johannes Berg
` (4 subsequent siblings)
8 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
This makes access to the STA hash table/list use RCU to protect
against freeing of items. However, it's not a true RCU, the
copy step is missing: whenever somebody changes a STA item it
is simply updated. That will be addressed by a later change.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 31 +-
drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 27 +-
net/mac80211/cfg.c | 82 ++++--
net/mac80211/debugfs_sta.c | 4
net/mac80211/debugfs_sta.h | 2
net/mac80211/ieee80211.c | 76 ++++--
net/mac80211/ieee80211_i.h | 13 -
net/mac80211/ieee80211_iface.c | 11
net/mac80211/ieee80211_ioctl.c | 60 +++-
net/mac80211/ieee80211_rate.c | 8
net/mac80211/ieee80211_rate.h | 1
net/mac80211/ieee80211_sta.c | 126 ++++++----
net/mac80211/key.c | 5
net/mac80211/rc80211_pid_algo.c | 23 +
net/mac80211/rc80211_simple.c | 18 -
net/mac80211/rx.c | 24 -
net/mac80211/sta_info.c | 350 +++++++++++++++++------------
net/mac80211/sta_info.h | 58 +++-
net/mac80211/tx.c | 48 ++-
net/mac80211/wme.c | 8
20 files changed, 612 insertions(+), 363 deletions(-)
--- everything.orig/net/mac80211/ieee80211_i.h 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211_i.h 2008-02-22 00:48:34.000000000 +0100
@@ -426,6 +426,7 @@ struct ieee80211_local {
unsigned int filter_flags; /* FIF_* */
struct iw_statistics wstats;
u8 wstats_flags;
+ bool tim_in_locked_section; /* see ieee80211_beacon_get() */
int tx_headroom; /* required headroom for hardware/radiotap */
enum {
@@ -443,9 +444,15 @@ struct ieee80211_local {
struct sk_buff_head skb_queue;
struct sk_buff_head skb_queue_unreliable;
- /* Station data structures */
- rwlock_t sta_lock; /* protects STA data structures */
- int num_sta; /* number of stations in sta_list */
+ /* Station data */
+ /*
+ * The lock only protects the list, hash, timer and counter
+ * against manipulation, reads are done in RCU. Additionally,
+ * the lock protects each BSS's TIM bitmap and a few items
+ * in a STA info structure.
+ */
+ spinlock_t sta_lock;
+ unsigned long num_sta;
struct list_head sta_list;
struct sta_info *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
--- everything.orig/net/mac80211/ieee80211_sta.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211_sta.c 2008-02-22 00:48:31.000000000 +0100
@@ -856,6 +856,8 @@ static void ieee80211_associated(struct
ifsta->state = IEEE80211_ASSOCIATED;
+ rcu_read_lock();
+
sta = sta_info_get(local, ifsta->bssid);
if (!sta) {
printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
@@ -871,7 +873,7 @@ static void ieee80211_associated(struct
"range\n",
dev->name, print_mac(mac, ifsta->bssid));
disassoc = 1;
- sta_info_free(sta);
+ sta_info_unlink(&sta);
} else
ieee80211_send_probe_req(dev, ifsta->bssid,
local->scan_ssid,
@@ -887,8 +889,15 @@ static void ieee80211_associated(struct
ifsta->ssid_len);
}
}
- sta_info_put(sta);
}
+
+ rcu_read_unlock();
+
+ if (disassoc && sta) {
+ synchronize_rcu();
+ sta_info_destroy(sta);
+ }
+
if (disassoc) {
ifsta->state = IEEE80211_DISABLED;
ieee80211_set_associated(dev, ifsta, 0);
@@ -1114,9 +1123,13 @@ static void ieee80211_sta_process_addba_
int ret = -EOPNOTSUPP;
DECLARE_MAC_BUF(mac);
+ rcu_read_lock();
+
sta = sta_info_get(local, mgmt->sa);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
+ }
/* extract session parameters from addba request frame */
dialog_token = mgmt->u.action.u.addba_req.dialog_token;
@@ -1207,9 +1220,9 @@ end:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
end_no_lock:
- ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token,
- status, 1, buf_size, timeout);
- sta_info_put(sta);
+ ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
+ dialog_token, status, 1, buf_size, timeout);
+ rcu_read_unlock();
}
static void ieee80211_sta_process_addba_resp(struct net_device *dev,
@@ -1223,9 +1236,13 @@ static void ieee80211_sta_process_addba_
u16 tid;
u8 *state;
+ rcu_read_lock();
+
sta = sta_info_get(local, mgmt->sa);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
+ }
capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
@@ -1240,7 +1257,7 @@ static void ieee80211_sta_process_addba_
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -1254,7 +1271,7 @@ static void ieee80211_sta_process_addba_
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
"%d\n", *state);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -1281,7 +1298,7 @@ static void ieee80211_sta_process_addba_
ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
WLAN_BACK_INITIATOR);
}
- sta_info_put(sta);
+ rcu_read_unlock();
}
void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
@@ -1336,16 +1353,20 @@ void ieee80211_sta_stop_rx_ba_session(st
struct sta_info *sta;
int ret, i;
+ rcu_read_lock();
+
sta = sta_info_get(local, ra);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
+ }
/* check if TID is in operational state */
spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
if (sta->ampdu_mlme.tid_rx[tid].state
!= HT_AGG_STATE_OPERATIONAL) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
sta->ampdu_mlme.tid_rx[tid].state =
@@ -1384,7 +1405,7 @@ void ieee80211_sta_stop_rx_ba_session(st
kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf);
sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE;
- sta_info_put(sta);
+ rcu_read_unlock();
}
@@ -1397,9 +1418,13 @@ static void ieee80211_sta_process_delba(
u16 initiator;
DECLARE_MAC_BUF(mac);
+ rcu_read_lock();
+
sta = sta_info_get(local, mgmt->sa);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
+ }
params = le16_to_cpu(mgmt->u.action.u.delba.params);
tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
@@ -1424,7 +1449,7 @@ static void ieee80211_sta_process_delba(
ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
WLAN_BACK_RECIPIENT);
}
- sta_info_put(sta);
+ rcu_read_unlock();
}
/*
@@ -1447,9 +1472,13 @@ void sta_addba_resp_timer_expired(unsign
struct sta_info *sta;
u8 *state;
+ rcu_read_lock();
+
sta = sta_info_get(local, temp_sta->addr);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return;
+ }
state = &sta->ampdu_mlme.tid_tx[tid].state;
/* check if the TID waits for addBA response */
@@ -1471,7 +1500,7 @@ void sta_addba_resp_timer_expired(unsign
WLAN_BACK_INITIATOR);
timer_expired_exit:
- sta_info_put(sta);
+ rcu_read_unlock();
}
/*
@@ -1491,8 +1520,8 @@ void sta_rx_agg_session_timer_expired(un
timer_to_tid[0]);
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, (u16)*ptid,
- WLAN_BACK_TIMER,
+ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
+ (u16)*ptid, WLAN_BACK_TIMER,
WLAN_REASON_QSTA_TIMEOUT);
}
@@ -1801,14 +1830,18 @@ static void ieee80211_rx_mgmt_assoc_resp
if (ifsta->assocresp_ies)
memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
+ rcu_read_lock();
+
/* Add STA entry for the AP */
sta = sta_info_get(local, ifsta->bssid);
if (!sta) {
struct ieee80211_sta_bss *bss;
- sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
+
+ sta = sta_info_add(sdata, ifsta->bssid);
if (IS_ERR(sta)) {
printk(KERN_DEBUG "%s: failed to add STA entry for the"
" AP (error %ld)\n", dev->name, PTR_ERR(sta));
+ rcu_read_unlock();
return;
}
bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
@@ -1822,7 +1855,6 @@ static void ieee80211_rx_mgmt_assoc_resp
}
}
- sta->dev = dev;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
WLAN_STA_AUTHORIZED;
@@ -1893,7 +1925,7 @@ static void ieee80211_rx_mgmt_assoc_resp
bss_conf->aid = aid;
ieee80211_set_associated(dev, ifsta, 1);
- sta_info_put(sta);
+ rcu_read_unlock();
ieee80211_associated(dev, ifsta);
}
@@ -2218,6 +2250,8 @@ static void ieee80211_rx_bss_info(struct
beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+ rcu_read_lock();
+
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
(sta = sta_info_get(local, mgmt->sa))) {
@@ -2272,9 +2306,10 @@ static void ieee80211_rx_bss_info(struct
(unsigned long long) supp_rates,
(unsigned long long) sta->supp_rates[rx_status->band]);
}
- sta_info_put(sta);
}
+ rcu_read_unlock();
+
if (!elems.ssid)
return;
@@ -2459,8 +2494,10 @@ static void ieee80211_rx_bss_info(struct
"local TSF - IBSS merge with BSSID %s\n",
dev->name, print_mac(mac, mgmt->bssid));
ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
+ rcu_read_lock();
ieee80211_ibss_add_sta(dev, NULL,
mgmt->bssid, mgmt->sa);
+ rcu_read_unlock();
}
}
@@ -2788,45 +2825,49 @@ static int ieee80211_sta_active_ibss(str
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int active = 0;
struct sta_info *sta;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ rcu_read_lock();
- read_lock_bh(&local->sta_lock);
- list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->dev == dev &&
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ if (sta->sdata == sdata &&
time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
jiffies)) {
active++;
break;
}
}
- read_unlock_bh(&local->sta_lock);
+
+ rcu_read_unlock();
return active;
}
-static void ieee80211_sta_expire(struct net_device *dev)
+static void ieee80211_sta_expire_ibss(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta, *tmp;
LIST_HEAD(tmp_list);
DECLARE_MAC_BUF(mac);
+ unsigned long flags;
- write_lock_bh(&local->sta_lock);
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx +
IEEE80211_IBSS_INACTIVITY_LIMIT)) {
printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
dev->name, print_mac(mac, sta->addr));
- __sta_info_get(sta);
- sta_info_remove(sta);
- list_add(&sta->list, &tmp_list);
- }
- write_unlock_bh(&local->sta_lock);
-
- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
- sta_info_free(sta);
- sta_info_put(sta);
- }
+ sta_info_unlink(&sta);
+ if (sta)
+ list_add(&sta->list, &tmp_list);
+ }
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+ synchronize_rcu();
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
+ sta_info_destroy(sta);
}
@@ -2835,7 +2876,7 @@ static void ieee80211_sta_merge_ibss(str
{
mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
- ieee80211_sta_expire(dev);
+ ieee80211_sta_expire_ibss(dev);
if (ieee80211_sta_active_ibss(dev))
return;
@@ -3796,6 +3837,7 @@ int ieee80211_sta_set_extra_ie(struct ne
}
+/* must be called under RCU read lock */
struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
struct sk_buff *skb, u8 *bssid,
u8 *addr)
@@ -3818,7 +3860,7 @@ struct sta_info * ieee80211_ibss_add_sta
printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
- sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+ sta = sta_info_add(sdata, addr);
if (IS_ERR(sta))
return NULL;
@@ -3829,7 +3871,7 @@ struct sta_info * ieee80211_ibss_add_sta
rate_control_rate_init(sta, local);
- return sta; /* caller will call sta_info_put() */
+ return sta;
}
--- everything.orig/net/mac80211/sta_info.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/sta_info.c 2008-02-22 00:50:38.000000000 +0100
@@ -22,14 +22,43 @@
#include "sta_info.h"
#include "debugfs_sta.h"
-/* Caller must hold local->sta_lock */
-static void sta_info_hash_add(struct ieee80211_local *local,
- struct sta_info *sta)
-{
- sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
- local->sta_hash[STA_HASH(sta->addr)] = sta;
-}
-
+/**
+ * DOC: STA information lifetime rules
+ *
+ * STA info structures (&struct sta_info) are managed in a hash table
+ * for faster lookup and a list for iteration. They are managed using
+ * RCU, i.e. access to the list and hash table is protected by RCU.
+ *
+ * STA info structures are always "alive" when they are added with
+ * @sta_info_add() [this may be changed in the future to allow allocating
+ * outside of a critical section!], they are then added to the hash
+ * table and list. Therefore, @sta_info_add() must also be RCU protected,
+ * also, the caller of @sta_info_add() cannot assume that it owns the
+ * structure.
+ *
+ * Because there are debugfs entries for each station, and adding those
+ * must be able to sleep, it is also possible to "pin" a station entry,
+ * that means it can be removed from the hash table but not be freed.
+ * See the comment in @__sta_info_unlink() for more information.
+ *
+ * In order to remove a STA info structure, the caller needs to first
+ * unlink it (@sta_info_unlink()) from the list and hash tables and
+ * then wait for an RCU synchronisation before it can be freed. Due to
+ * the pinning and the possibility of multiple callers trying to remove
+ * the same STA info at the same time, @sta_info_unlink() can clear the
+ * STA info pointer it is passed to indicate that the STA info is owned
+ * by somebody else now.
+ *
+ * If @sta_info_unlink() did not clear the pointer then the caller owns
+ * the STA info structure now and is responsible of destroying it with
+ * a call to @sta_info_destroy(), not before RCU synchronisation, of
+ * course.
+ *
+ * In all other cases, there is no concept of ownership on a STA entry,
+ * each structure is owned by the global hash table/list until it is
+ * removed. All users of the structure need to be RCU protected so that
+ * the structure won't be freed before they are done using it.
+ */
/* Caller must hold local->sta_lock */
static int sta_info_hash_del(struct ieee80211_local *local,
@@ -41,109 +70,108 @@ static int sta_info_hash_del(struct ieee
if (!s)
return -ENOENT;
if (s == sta) {
- local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)],
+ s->hnext);
return 0;
}
while (s->hnext && s->hnext != sta)
s = s->hnext;
if (s->hnext) {
- s->hnext = sta->hnext;
+ rcu_assign_pointer(s->hnext, sta->hnext);
return 0;
}
return -ENOENT;
}
-/* must hold local->sta_lock */
+/* protected by RCU */
static struct sta_info *__sta_info_find(struct ieee80211_local *local,
u8 *addr)
{
struct sta_info *sta;
- sta = local->sta_hash[STA_HASH(addr)];
+ sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
while (sta) {
if (compare_ether_addr(sta->addr, addr) == 0)
break;
- sta = sta->hnext;
+ sta = rcu_dereference(sta->hnext);
}
return sta;
}
struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
{
- struct sta_info *sta;
-
- read_lock_bh(&local->sta_lock);
- sta = __sta_info_find(local, addr);
- if (sta)
- __sta_info_get(sta);
- read_unlock_bh(&local->sta_lock);
-
- return sta;
+ return __sta_info_find(local, addr);
}
EXPORT_SYMBOL(sta_info_get);
-static void sta_info_release(struct kref *kref)
+void sta_info_destroy(struct sta_info *sta)
{
- struct sta_info *sta = container_of(kref, struct sta_info, kref);
struct ieee80211_local *local = sta->local;
struct sk_buff *skb;
int i;
- /* free sta structure; it has already been removed from
- * hash table etc. external structures. Make sure that all
- * buffered frames are release (one might have been added
- * after sta_info_free() was called). */
+ ieee80211_key_free(sta->key);
+ sta->key = NULL;
+
+ rate_control_remove_sta_debugfs(sta);
+ ieee80211_sta_debugfs_remove(sta);
+
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
local->total_ps_buffered--;
dev_kfree_skb_any(skb);
}
- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+
+ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
dev_kfree_skb_any(skb);
- }
+
for (i = 0; i < STA_TID_NUM; i++) {
del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer);
del_timer_sync(&sta->ampdu_mlme.tid_tx[i].addba_resp_timer);
}
rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
rate_control_put(sta->rate_ctrl);
+
kfree(sta);
}
-void sta_info_put(struct sta_info *sta)
+/* Caller must hold local->sta_lock */
+static void sta_info_hash_add(struct ieee80211_local *local,
+ struct sta_info *sta)
{
- kref_put(&sta->kref, sta_info_release);
+ sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
}
-EXPORT_SYMBOL(sta_info_put);
-
-struct sta_info *sta_info_add(struct ieee80211_local *local,
- struct net_device *dev, u8 *addr, gfp_t gfp)
+struct sta_info *sta_info_add(struct ieee80211_sub_if_data *sdata,
+ u8 *addr)
{
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int i;
DECLARE_MAC_BUF(mac);
+ unsigned long flags;
- sta = kzalloc(sizeof(*sta), gfp);
+ sta = kzalloc(sizeof(*sta), GFP_ATOMIC);
if (!sta)
return ERR_PTR(-ENOMEM);
- kref_init(&sta->kref);
+ memcpy(sta->addr, addr, ETH_ALEN);
+ sta->local = local;
+ sta->sdata = sdata;
sta->rate_ctrl = rate_control_get(local->rate_ctrl);
- sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
+ sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
+ GFP_ATOMIC);
if (!sta->rate_ctrl_priv) {
rate_control_put(sta->rate_ctrl);
kfree(sta);
return ERR_PTR(-ENOMEM);
}
- memcpy(sta->addr, addr, ETH_ALEN);
- sta->local = local;
- sta->dev = dev;
spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
spin_lock_init(&sta->ampdu_mlme.ampdu_tx);
for (i = 0; i < STA_TID_NUM; i++) {
@@ -168,29 +196,26 @@ struct sta_info *sta_info_add(struct iee
}
skb_queue_head_init(&sta->ps_tx_buf);
skb_queue_head_init(&sta->tx_filtered);
- write_lock_bh(&local->sta_lock);
- /* mark sta as used (by caller) */
- __sta_info_get(sta);
+ spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
if (__sta_info_find(local, addr)) {
- write_unlock_bh(&local->sta_lock);
- sta_info_put(sta);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
return ERR_PTR(-EEXIST);
}
list_add(&sta->list, &local->sta_list);
local->num_sta++;
sta_info_hash_add(local, sta);
- if (local->ops->sta_notify) {
- struct ieee80211_sub_if_data *sdata;
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ /* notify driver */
+ if (local->ops->sta_notify) {
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
sdata = sdata->u.vlan.ap;
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_ADD, addr);
}
- write_unlock_bh(&local->sta_lock);
+
+ spin_unlock_irqrestore(&local->sta_lock, flags);
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Added STA %s\n",
@@ -230,19 +255,20 @@ static void __sta_info_set_tim_bit(struc
{
if (bss)
__bss_tim_set(bss, sta->aid);
- if (sta->local->ops->set_tim)
+ if (sta->local->ops->set_tim) {
+ sta->local->tim_in_locked_section = true;
sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
+ sta->local->tim_in_locked_section = false;
+ }
}
void sta_info_set_tim_bit(struct sta_info *sta)
{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ unsigned long flags;
- read_lock_bh(&sta->local->sta_lock);
- __sta_info_set_tim_bit(sdata->bss, sta);
- read_unlock_bh(&sta->local->sta_lock);
+ spin_lock_irqsave(&sta->local->sta_lock, flags);
+ __sta_info_set_tim_bit(sta->sdata->bss, sta);
+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
}
static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
@@ -250,88 +276,128 @@ static void __sta_info_clear_tim_bit(str
{
if (bss)
__bss_tim_clear(bss, sta->aid);
- if (sta->local->ops->set_tim)
+ if (sta->local->ops->set_tim) {
+ sta->local->tim_in_locked_section = true;
sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
+ sta->local->tim_in_locked_section = false;
+ }
}
void sta_info_clear_tim_bit(struct sta_info *sta)
{
- struct ieee80211_sub_if_data *sdata;
+ unsigned long flags;
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ spin_lock_irqsave(&sta->local->sta_lock, flags);
+ __sta_info_clear_tim_bit(sta->sdata->bss, sta);
+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
+}
- read_lock_bh(&sta->local->sta_lock);
- __sta_info_clear_tim_bit(sdata->bss, sta);
- read_unlock_bh(&sta->local->sta_lock);
+/*
+ * See comment in __sta_info_unlink,
+ * caller must hold local->sta_lock.
+ */
+static void __sta_info_pin(struct sta_info *sta)
+{
+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL);
+ sta->pin_status = STA_INFO_PIN_STAT_PINNED;
}
-/* Caller must hold local->sta_lock */
-void sta_info_remove(struct sta_info *sta)
+/*
+ * See comment in __sta_info_unlink, returns sta if it
+ * needs to be destroyed.
+ */
+static struct sta_info *__sta_info_unpin(struct sta_info *sta)
{
- struct ieee80211_local *local = sta->local;
- struct ieee80211_sub_if_data *sdata;
+ struct sta_info *ret = NULL;
+ unsigned long flags;
- /* don't do anything if we've been removed already */
- if (sta_info_hash_del(local, sta))
- return;
+ spin_lock_irqsave(&sta->local->sta_lock, flags);
+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY &&
+ sta->pin_status != STA_INFO_PIN_STAT_PINNED);
+ if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY)
+ ret = sta;
+ sta->pin_status = STA_INFO_PIN_STAT_NORMAL;
+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
- list_del(&sta->list);
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
- if (sta->flags & WLAN_STA_PS) {
- sta->flags &= ~WLAN_STA_PS;
- if (sdata->bss)
- atomic_dec(&sdata->bss->num_sta_ps);
- __sta_info_clear_tim_bit(sdata->bss, sta);
- }
- local->num_sta--;
+ return ret;
}
-void sta_info_free(struct sta_info *sta)
+static void __sta_info_unlink(struct sta_info **sta)
{
- struct sk_buff *skb;
- struct ieee80211_local *local = sta->local;
- DECLARE_MAC_BUF(mac);
+ struct ieee80211_local *local = (*sta)->local;
+ struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ DECLARE_MAC_BUF(mbuf);
+#endif
+ /*
+ * pull caller's reference if we're already gone.
+ */
+ if (sta_info_hash_del(local, *sta)) {
+ *sta = NULL;
+ return;
+ }
- might_sleep();
+ /*
+ * Also pull caller's reference if the STA is pinned by the
+ * task that is adding the debugfs entries. In that case, we
+ * leave the STA "to be freed".
+ *
+ * The rules are not trivial, but not too complex either:
+ * (1) pin_status is only modified under the sta_lock
+ * (2) sta_info_debugfs_add_work() will set the status
+ * to PINNED when it found an item that needs a new
+ * debugfs directory created. In that case, that item
+ * must not be freed although all *RCU* users are done
+ * with it. Hence, we tell the caller of _unlink()
+ * that the item is already gone (as can happen when
+ * two tasks try to unlink/destroy at the same time)
+ * (3) We set the pin_status to DESTROY here when we
+ * find such an item.
+ * (4) sta_info_debugfs_add_work() will reset the pin_status
+ * from PINNED to NORMAL when it is done with the item,
+ * but will check for DESTROY before resetting it in
+ * which case it will free the item.
+ */
+ if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) {
+ (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY;
+ *sta = NULL;
+ return;
+ }
- write_lock_bh(&local->sta_lock);
- sta_info_remove(sta);
- write_unlock_bh(&local->sta_lock);
+ list_del(&(*sta)->list);
- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
- local->total_ps_buffered--;
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
- dev_kfree_skb(skb);
+ if ((*sta)->flags & WLAN_STA_PS) {
+ (*sta)->flags &= ~WLAN_STA_PS;
+ if (sdata->bss)
+ atomic_dec(&sdata->bss->num_sta_ps);
+ __sta_info_clear_tim_bit(sdata->bss, *sta);
}
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Removed STA %s\n",
- wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
- ieee80211_key_free(sta->key);
- sta->key = NULL;
+ local->num_sta--;
if (local->ops->sta_notify) {
- struct ieee80211_sub_if_data *sdata;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
sdata = sdata->u.vlan.ap;
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
- STA_NOTIFY_REMOVE, sta->addr);
+ STA_NOTIFY_REMOVE, (*sta)->addr);
}
- rate_control_remove_sta_debugfs(sta);
- ieee80211_sta_debugfs_remove(sta);
-
- sta_info_put(sta);
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Removed STA %s\n",
+ wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
}
+void sta_info_unlink(struct sta_info **sta)
+{
+ struct ieee80211_local *local = (*sta)->local;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->sta_lock, flags);
+ __sta_info_unlink(sta);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+}
static inline int sta_info_buffer_expired(struct ieee80211_local *local,
struct sta_info *sta,
@@ -377,7 +443,7 @@ static void sta_info_cleanup_expire_buff
if (!skb)
break;
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
local->total_ps_buffered--;
printk(KERN_DEBUG "Buffered frame expired (STA "
"%s)\n", print_mac(mac, sta->addr));
@@ -394,13 +460,10 @@ static void sta_info_cleanup(unsigned lo
struct ieee80211_local *local = (struct ieee80211_local *) data;
struct sta_info *sta;
- read_lock_bh(&local->sta_lock);
- list_for_each_entry(sta, &local->sta_list, list) {
- __sta_info_get(sta);
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list)
sta_info_cleanup_expire_buffered(local, sta);
- sta_info_put(sta);
- }
- read_unlock_bh(&local->sta_lock);
+ rcu_read_unlock();
local->sta_cleanup.expires =
round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
@@ -408,37 +471,45 @@ static void sta_info_cleanup(unsigned lo
}
#ifdef CONFIG_MAC80211_DEBUGFS
-static void sta_info_debugfs_add_task(struct work_struct *work)
+static void sta_info_debugfs_add_work(struct work_struct *work)
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, sta_debugfs_add);
struct sta_info *sta, *tmp;
+ unsigned long flags;
while (1) {
sta = NULL;
- read_lock_bh(&local->sta_lock);
+
+ spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry(tmp, &local->sta_list, list) {
if (!tmp->debugfs.dir) {
sta = tmp;
- __sta_info_get(sta);
+ __sta_info_pin(sta);
break;
}
}
- read_unlock_bh(&local->sta_lock);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
if (!sta)
break;
ieee80211_sta_debugfs_add(sta);
rate_control_add_sta_debugfs(sta);
- sta_info_put(sta);
+
+ sta = __sta_info_unpin(sta);
+
+ if (sta) {
+ synchronize_rcu();
+ sta_info_destroy(sta);
+ }
}
}
#endif
void sta_info_init(struct ieee80211_local *local)
{
- rwlock_init(&local->sta_lock);
+ spin_lock_init(&local->sta_lock);
INIT_LIST_HEAD(&local->sta_list);
setup_timer(&local->sta_cleanup, sta_info_cleanup,
@@ -447,7 +518,7 @@ void sta_info_init(struct ieee80211_loca
round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
#ifdef CONFIG_MAC80211_DEBUGFS
- INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
+ INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work);
#endif
}
@@ -466,24 +537,29 @@ void sta_info_stop(struct ieee80211_loca
/**
* sta_info_flush - flush matching STA entries from the STA table
* @local: local interface data
- * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
+ * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
*/
-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
+void sta_info_flush(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
{
struct sta_info *sta, *tmp;
LIST_HEAD(tmp_list);
+ unsigned long flags;
- write_lock_bh(&local->sta_lock);
- list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
- if (!dev || dev == sta->dev) {
- __sta_info_get(sta);
- sta_info_remove(sta);
- list_add_tail(&sta->list, &tmp_list);
- }
- write_unlock_bh(&local->sta_lock);
+ might_sleep();
- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
- sta_info_free(sta);
- sta_info_put(sta);
+ spin_lock_irqsave(&local->sta_lock, flags);
+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
+ if (!sdata || sdata == sta->sdata) {
+ __sta_info_unlink(&sta);
+ if (sta)
+ list_add_tail(&sta->list, &tmp_list);
+ }
}
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+ synchronize_rcu();
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
+ sta_info_destroy(sta);
}
--- everything.orig/net/mac80211/sta_info.h 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/sta_info.h 2008-02-22 00:48:31.000000000 +0100
@@ -12,7 +12,6 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/if_ether.h>
-#include <linux/kref.h>
#include "ieee80211_key.h"
/**
@@ -124,8 +123,14 @@ struct sta_ampdu_mlme {
u8 dialog_token_allocator;
};
+
+/* see __sta_info_unlink */
+#define STA_INFO_PIN_STAT_NORMAL 0
+#define STA_INFO_PIN_STAT_PINNED 1
+#define STA_INFO_PIN_STAT_DESTROY 2
+
+
struct sta_info {
- struct kref kref;
struct list_head list;
struct sta_info *hnext; /* next entry in hash table list */
@@ -154,8 +159,8 @@ struct sta_info {
/* last rates used to send a frame to this STA */
int last_txrate_idx, last_nonerp_txrate_idx;
- struct net_device *dev; /* which net device is this station associated
- * to */
+ /* sub_if_data this sta belongs to */
+ struct ieee80211_sub_if_data *sdata;
struct ieee80211_key *key;
@@ -189,6 +194,12 @@ struct sta_info {
u16 listen_interval;
+ /*
+ * for use by the internal lifetime management,
+ * see __sta_info_unlink
+ */
+ u8 pin_status;
+
struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
of this STA */
struct sta_ampdu_mlme ampdu_mlme;
@@ -232,23 +243,32 @@ struct sta_info {
*/
#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
-static inline void __sta_info_get(struct sta_info *sta)
-{
- kref_get(&sta->kref);
-}
-
-struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
-void sta_info_put(struct sta_info *sta);
-struct sta_info *sta_info_add(struct ieee80211_local *local,
- struct net_device *dev, u8 *addr, gfp_t gfp);
-void sta_info_remove(struct sta_info *sta);
-void sta_info_free(struct sta_info *sta);
-void sta_info_init(struct ieee80211_local *local);
-int sta_info_start(struct ieee80211_local *local);
-void sta_info_stop(struct ieee80211_local *local);
-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
+/*
+ * Get a STA info, must have be under RCU read lock.
+ */
+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
+/*
+ * Add a new STA info, must be under RCU read lock
+ * because otherwise the returned reference isn't
+ * necessarily valid long enough.
+ */
+struct sta_info *sta_info_add(struct ieee80211_sub_if_data *sdata,
+ u8 *addr);
+/*
+ * Unlink a STA info from the hash table/list.
+ * This can NULL the STA pointer if somebody else
+ * has already unlinked it.
+ */
+void sta_info_unlink(struct sta_info **sta);
+void sta_info_destroy(struct sta_info *sta);
void sta_info_set_tim_bit(struct sta_info *sta);
void sta_info_clear_tim_bit(struct sta_info *sta);
+void sta_info_init(struct ieee80211_local *local);
+int sta_info_start(struct ieee80211_local *local);
+void sta_info_stop(struct ieee80211_local *local);
+void sta_info_flush(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata);
+
#endif /* STA_INFO_H */
--- everything.orig/net/mac80211/tx.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/tx.c 2008-02-22 00:48:34.000000000 +0100
@@ -323,10 +323,8 @@ static void purge_old_ps_buffers(struct
}
total += skb_queue_len(&ap->ps_bc_buf);
}
- rcu_read_unlock();
- read_lock_bh(&local->sta_lock);
- list_for_each_entry(sta, &local->sta_list, list) {
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
skb = skb_dequeue(&sta->ps_tx_buf);
if (skb) {
purged++;
@@ -334,7 +332,8 @@ static void purge_old_ps_buffers(struct
}
total += skb_queue_len(&sta->ps_tx_buf);
}
- read_unlock_bh(&local->sta_lock);
+
+ rcu_read_unlock();
local->total_ps_buffered = total;
printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
@@ -1137,20 +1136,17 @@ static int ieee80211_tx(struct net_devic
return 0;
}
+ rcu_read_lock();
+
/* initialises tx */
res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
if (res_prepare == TX_DROP) {
dev_kfree_skb(skb);
+ rcu_read_unlock();
return 0;
}
- /*
- * key references are protected using RCU and this requires that
- * we are in a read-site RCU section during receive processing
- */
- rcu_read_lock();
-
sta = tx.sta;
tx.u.tx.channel = local->hw.conf.channel;
@@ -1163,9 +1159,6 @@ static int ieee80211_tx(struct net_devic
skb = tx.skb; /* handlers are allowed to change skb */
- if (sta)
- sta_info_put(sta);
-
if (unlikely(res == TX_DROP)) {
I802_DEBUG_INC(local->tx_handlers_drop);
goto drop;
@@ -1453,11 +1446,11 @@ int ieee80211_subif_start_xmit(struct sk
* in AP mode)
*/
if (!is_multicast_ether_addr(hdr.addr1)) {
+ rcu_read_lock();
sta = sta_info_get(local, hdr.addr1);
- if (sta) {
+ if (sta)
sta_flags = sta->flags;
- sta_info_put(sta);
- }
+ rcu_read_unlock();
}
/* receiver is QoS enabled, use a QoS type frame */
@@ -1680,7 +1673,6 @@ static void ieee80211_beacon_add_tim(str
/* Generate bitmap for TIM only if there are any STAs in power save
* mode. */
- read_lock_bh(&local->sta_lock);
if (atomic_read(&bss->num_sta_ps) > 0)
/* in the hope that this is faster than
* checking byte-for-byte */
@@ -1731,7 +1723,6 @@ static void ieee80211_beacon_add_tim(str
*pos++ = aid0; /* Bitmap control */
*pos++ = 0; /* Part Virt Bitmap */
}
- read_unlock_bh(&local->sta_lock);
}
struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
@@ -1779,7 +1770,22 @@ struct sk_buff *ieee80211_beacon_get(str
ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
- ieee80211_beacon_add_tim(local, ap, skb, beacon);
+ /*
+ * Not very nice, but we want to allow the driver to call
+ * ieee80211_beacon_get() as a response to the set_tim()
+ * callback. That, however, is already invoked under the
+ * sta_lock to guarantee consistent and race-free update
+ * of the tim bitmap in mac80211 and the driver.
+ */
+ if (local->tim_in_locked_section) {
+ ieee80211_beacon_add_tim(local, ap, skb, beacon);
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&local->sta_lock, flags);
+ ieee80211_beacon_add_tim(local, ap, skb, beacon);
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+ }
if (beacon->tail)
memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
@@ -1881,7 +1887,6 @@ ieee80211_get_buffered_bc(struct ieee802
rcu_read_unlock();
return NULL;
}
- rcu_read_unlock();
if (bss->dtim_count != 0)
return NULL; /* send buffered bc/mc only after DTIM beacon */
@@ -1926,8 +1931,7 @@ ieee80211_get_buffered_bc(struct ieee802
skb = NULL;
}
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return skb;
}
--- everything.orig/net/mac80211/cfg.c 2008-02-21 22:09:29.000000000 +0100
+++ everything/net/mac80211/cfg.c 2008-02-22 00:48:31.000000000 +0100
@@ -128,7 +128,6 @@ static int ieee80211_add_key(struct wiph
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta = NULL;
enum ieee80211_key_alg alg;
- int ret;
struct ieee80211_key *key;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -152,21 +151,22 @@ static int ieee80211_add_key(struct wiph
if (!key)
return -ENOMEM;
+ rcu_read_lock();
+
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta) {
ieee80211_key_free(key);
+ rcu_read_unlock();
return -ENOENT;
}
}
ieee80211_key_link(key, sdata, sta);
- ret = 0;
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
- return ret;
+ return 0;
}
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
@@ -179,9 +179,13 @@ static int ieee80211_del_key(struct wiph
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (mac_addr) {
+ rcu_read_lock();
+
sta = sta_info_get(sdata->local, mac_addr);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
ret = 0;
if (sta->key)
@@ -189,7 +193,7 @@ static int ieee80211_del_key(struct wiph
else
ret = -ENOENT;
- sta_info_put(sta);
+ rcu_read_unlock();
return ret;
}
@@ -215,6 +219,8 @@ static int ieee80211_get_key(struct wiph
u16 iv16;
int err = -ENOENT;
+ rcu_read_lock();
+
if (mac_addr) {
sta = sta_info_get(sdata->local, mac_addr);
if (!sta)
@@ -278,8 +284,7 @@ static int ieee80211_get_key(struct wiph
err = 0;
out:
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return err;
}
@@ -301,9 +306,13 @@ static int ieee80211_get_station(struct
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
+ rcu_read_lock();
+
sta = sta_info_get(local, mac);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
/* XXX: verify sta->dev == dev */
@@ -315,7 +324,7 @@ static int ieee80211_get_station(struct
stats->rx_bytes = sta->rx_bytes;
stats->tx_bytes = sta->tx_bytes;
- sta_info_put(sta);
+ rcu_read_unlock();
return 0;
}
@@ -510,8 +519,8 @@ static void ieee80211_send_layer2_update
msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
- skb->dev = sta->dev;
- skb->protocol = eth_type_trans(skb, sta->dev);
+ skb->dev = sta->sdata->dev;
+ skb->protocol = eth_type_trans(skb, sta->sdata->dev);
memset(skb->cb, 0, sizeof(skb->cb));
netif_rx(skb);
}
@@ -582,11 +591,14 @@ static int ieee80211_add_station(struct
} else
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sta = sta_info_add(local, dev, mac, GFP_KERNEL);
- if (IS_ERR(sta))
+ rcu_read_lock();
+
+ sta = sta_info_add(sdata, mac);
+ if (IS_ERR(sta)) {
+ rcu_read_unlock();
return PTR_ERR(sta);
+ }
- sta->dev = sdata->dev;
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
sdata->vif.type == IEEE80211_IF_TYPE_AP)
ieee80211_send_layer2_update(sta);
@@ -597,7 +609,7 @@ static int ieee80211_add_station(struct
rate_control_rate_init(sta, local);
- sta_info_put(sta);
+ rcu_read_unlock();
return 0;
}
@@ -605,19 +617,29 @@ static int ieee80211_add_station(struct
static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
if (mac) {
/* XXX: get sta belonging to dev */
+ rcu_read_lock();
sta = sta_info_get(local, mac);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
+
+ sta_info_unlink(&sta);
- sta_info_free(sta);
- sta_info_put(sta);
+ rcu_read_unlock();
+
+ if (sta) {
+ synchronize_rcu();
+ sta_info_destroy(sta);
+ }
} else
- sta_info_flush(local, dev);
+ sta_info_flush(local, sdata);
return 0;
}
@@ -631,25 +653,31 @@ static int ieee80211_change_station(stru
struct sta_info *sta;
struct ieee80211_sub_if_data *vlansdata;
+ rcu_read_lock();
+
/* XXX: get sta belonging to dev */
sta = sta_info_get(local, mac);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
- if (params->vlan && params->vlan != sta->dev) {
+ if (params->vlan && params->vlan != sta->sdata->dev) {
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
- vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
+ vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
+ rcu_read_unlock();
return -EINVAL;
+ }
- sta->dev = params->vlan;
+ sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
ieee80211_send_layer2_update(sta);
}
sta_apply_parameters(local, sta, params);
- sta_info_put(sta);
+ rcu_read_unlock();
return 0;
}
--- everything.orig/net/mac80211/ieee80211.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211.c 2008-02-22 00:48:31.000000000 +0100
@@ -367,15 +367,19 @@ static int ieee80211_stop(struct net_dev
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->dev == dev)
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ if (sta->sdata == sdata)
for (i = 0; i < STA_TID_NUM; i++)
- ieee80211_sta_stop_rx_ba_session(sta->dev,
+ ieee80211_sta_stop_rx_ba_session(sdata->dev,
sta->addr, i,
WLAN_BACK_RECIPIENT,
WLAN_REASON_QSTA_LEAVE_QBSS);
}
+ rcu_read_unlock();
+
netif_stop_queue(dev);
/*
@@ -511,9 +515,12 @@ int ieee80211_start_tx_ba_session(struct
print_mac(mac, ra), tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
+ rcu_read_lock();
+
sta = sta_info_get(local, ra);
if (!sta) {
printk(KERN_DEBUG "Could not find the station\n");
+ rcu_read_unlock();
return -ENOENT;
}
@@ -553,7 +560,7 @@ int ieee80211_start_tx_ba_session(struct
spin_unlock_bh(&local->mdev->queue_lock);
goto start_ba_exit;
}
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
/* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
* call back right away, it must see that the flow has begun */
@@ -590,7 +597,7 @@ int ieee80211_start_tx_ba_session(struct
sta->ampdu_mlme.dialog_token_allocator;
sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num;
- ieee80211_send_addba_request(sta->dev, ra, tid,
+ ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
sta->ampdu_mlme.tid_tx[tid].dialog_token,
sta->ampdu_mlme.tid_tx[tid].ssn,
0x40, 5000);
@@ -603,7 +610,7 @@ int ieee80211_start_tx_ba_session(struct
start_ba_exit:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta_info_put(sta);
+ rcu_read_unlock();
return ret;
}
EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
@@ -626,9 +633,12 @@ int ieee80211_stop_tx_ba_session(struct
print_mac(mac, ra), tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
+ rcu_read_lock();
sta = sta_info_get(local, ra);
- if (!sta)
+ if (!sta) {
+ rcu_read_unlock();
return -ENOENT;
+ }
/* check if the TID is in aggregation */
state = &sta->ampdu_mlme.tid_tx[tid].state;
@@ -662,7 +672,7 @@ int ieee80211_stop_tx_ba_session(struct
stop_BA_exit:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta_info_put(sta);
+ rcu_read_unlock();
return ret;
}
EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
@@ -680,8 +690,10 @@ void ieee80211_start_tx_ba_cb(struct iee
return;
}
+ rcu_read_lock();
sta = sta_info_get(local, ra);
if (!sta) {
+ rcu_read_unlock();
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
return;
@@ -694,7 +706,7 @@ void ieee80211_start_tx_ba_cb(struct iee
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -707,7 +719,7 @@ void ieee80211_start_tx_ba_cb(struct iee
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta_info_put(sta);
+ rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
@@ -728,10 +740,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee
printk(KERN_DEBUG "Stop a BA session requested on DA %s tid %d\n",
print_mac(mac, ra), tid);
+ rcu_read_lock();
sta = sta_info_get(local, ra);
if (!sta) {
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
+ rcu_read_unlock();
return;
}
state = &sta->ampdu_mlme.tid_tx[tid].state;
@@ -739,13 +753,13 @@ void ieee80211_stop_tx_ba_cb(struct ieee
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
- sta_info_put(sta);
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ rcu_read_unlock();
return;
}
if (*state & HT_AGG_STATE_INITIATOR_MSK)
- ieee80211_send_delba(sta->dev, ra, tid,
+ ieee80211_send_delba(sta->sdata->dev, ra, tid,
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
agg_queue = sta->tid_to_tx_q[tid];
@@ -766,7 +780,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee
sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta_info_put(sta);
+ rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
@@ -876,32 +890,41 @@ int ieee80211_if_update_wds(struct net_d
struct sta_info *sta;
DECLARE_MAC_BUF(mac);
+ might_sleep();
+
if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
return 0;
+ rcu_read_lock();
+
/* Create STA entry for the new peer */
- sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
- if (IS_ERR(sta))
+ sta = sta_info_add(sdata, remote_addr);
+ if (IS_ERR(sta)) {
+ rcu_read_unlock();
return PTR_ERR(sta);
+ }
sta->flags |= WLAN_STA_AUTHORIZED;
- sta_info_put(sta);
-
/* Remove STA entry for the old peer */
sta = sta_info_get(local, sdata->u.wds.remote_addr);
- if (sta) {
- sta_info_free(sta);
- sta_info_put(sta);
- } else {
+ if (sta)
+ sta_info_unlink(&sta);
+ else
printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
"peer %s\n",
dev->name, print_mac(mac, sdata->u.wds.remote_addr));
- }
/* Update WDS link data */
memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
+ rcu_read_unlock();
+
+ if (sta) {
+ synchronize_rcu();
+ sta_info_destroy(sta);
+ }
+
return 0;
}
@@ -1311,6 +1334,8 @@ void ieee80211_tx_status(struct ieee8021
return;
}
+ rcu_read_lock();
+
if (status->excessive_retries) {
struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
@@ -1324,10 +1349,9 @@ void ieee80211_tx_status(struct ieee8021
status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
ieee80211_handle_filtered_frame(local, sta,
skb, status);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
- sta_info_put(sta);
}
}
@@ -1337,12 +1361,14 @@ void ieee80211_tx_status(struct ieee8021
if (sta) {
ieee80211_handle_filtered_frame(local, sta, skb,
status);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
} else
rate_control_tx_status(local->mdev, skb, status);
+ rcu_read_unlock();
+
ieee80211_led_tx(local, 0);
/* SNMP counters
--- everything.orig/net/mac80211/rc80211_pid_algo.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/rc80211_pid_algo.c 2008-02-21 22:09:30.000000000 +0100
@@ -77,7 +77,7 @@ static void rate_control_pid_adjust_rate
int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
int cur = sta->txrate_idx;
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
band = sband->band;
n_bitrates = sband->n_bitrates;
@@ -239,23 +239,25 @@ static void rate_control_pid_tx_status(v
unsigned long period;
struct ieee80211_supported_band *sband;
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
if (!sta)
- return;
+ goto unlock;
/* Don't update the state if we're not controlling the rate. */
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
- return;
+ goto unlock;
}
/* Ignore all frames that were sent with a different rate than the rate
* we currently advise mac80211 to use. */
if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
- goto ignore;
+ goto unlock;
spinfo = sta->rate_ctrl_priv;
spinfo->tx_num_xmit++;
@@ -296,8 +298,8 @@ static void rate_control_pid_tx_status(v
if (time_after(jiffies, spinfo->last_sample + period))
rate_control_pid_sample(pinfo, local, sta);
-ignore:
- sta_info_put(sta);
+ unlock:
+ rcu_read_unlock();
}
static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
@@ -312,6 +314,8 @@ static void rate_control_pid_get_rate(vo
int rateidx;
u16 fc;
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
@@ -320,8 +324,7 @@ static void rate_control_pid_get_rate(vo
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) || !sta) {
sel->rate = rate_lowest(local, sband, sta);
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -337,7 +340,7 @@ static void rate_control_pid_get_rate(vo
sta->last_txrate_idx = rateidx;
- sta_info_put(sta);
+ rcu_read_unlock();
sel->rate = &sband->bitrates[rateidx];
--- everything.orig/net/mac80211/rc80211_simple.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/rc80211_simple.c 2008-02-21 22:09:30.000000000 +0100
@@ -40,7 +40,7 @@ static void rate_control_rate_inc(struct
int i = sta->txrate_idx;
int maxrate;
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
/* forced unicast rate - do not change STA rate */
return;
@@ -70,7 +70,7 @@ static void rate_control_rate_dec(struct
struct ieee80211_supported_band *sband;
int i = sta->txrate_idx;
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
/* forced unicast rate - do not change STA rate */
return;
@@ -118,10 +118,12 @@ static void rate_control_simple_tx_statu
struct sta_info *sta;
struct sta_rate_control *srctrl;
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
if (!sta)
- return;
+ goto unlock;
srctrl = sta->rate_ctrl_priv;
srctrl->tx_num_xmit++;
@@ -194,7 +196,8 @@ static void rate_control_simple_tx_statu
}
}
- sta_info_put(sta);
+ unlock:
+ rcu_read_unlock();
}
@@ -211,6 +214,8 @@ rate_control_simple_get_rate(void *priv,
int rateidx;
u16 fc;
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
@@ -219,8 +224,7 @@ rate_control_simple_get_rate(void *priv,
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) || !sta) {
sel->rate = rate_lowest(local, sband, sta);
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -236,7 +240,7 @@ rate_control_simple_get_rate(void *priv,
sta->last_txrate_idx = rateidx;
- sta_info_put(sta);
+ rcu_read_unlock();
sel->rate = &sband->bitrates[rateidx];
}
--- everything.orig/net/mac80211/rx.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/rx.c 2008-02-22 00:48:34.000000000 +0100
@@ -574,7 +574,7 @@ static void ap_sta_ps_start(struct net_d
struct ieee80211_sub_if_data *sdata;
DECLARE_MAC_BUF(mac);
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
if (sdata->bss)
atomic_inc(&sdata->bss->num_sta_ps);
@@ -595,7 +595,7 @@ static int ap_sta_ps_end(struct net_devi
struct ieee80211_tx_packet_data *pkt_data;
DECLARE_MAC_BUF(mac);
- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+ sdata = sta->sdata;
if (sdata->bss)
atomic_dec(&sdata->bss->num_sta_ps);
@@ -1212,7 +1212,7 @@ ieee80211_deliver_skb(struct ieee80211_t
"multicast frame\n", dev->name);
} else {
dsta = sta_info_get(local, skb->data);
- if (dsta && dsta->dev == dev) {
+ if (dsta && dsta->sdata->dev == dev) {
/*
* The destination station is associated to
* this AP (in this VLAN), so send the frame
@@ -1222,8 +1222,6 @@ ieee80211_deliver_skb(struct ieee80211_t
xmit_skb = skb;
skb = NULL;
}
- if (dsta)
- sta_info_put(dsta);
}
}
@@ -1786,13 +1784,13 @@ static void __ieee80211_rx_handle_packet
rx.sta = sta_info_get(local, hdr->addr2);
if (rx.sta) {
- rx.dev = rx.sta->dev;
- rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+ rx.sdata = rx.sta->sdata;
+ rx.dev = rx.sta->sdata->dev;
}
if ((status->flag & RX_FLAG_MMIC_ERROR)) {
ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
- goto end;
+ return;
}
if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
@@ -1851,10 +1849,6 @@ static void __ieee80211_rx_handle_packet
ieee80211_invoke_rx_handlers(prev, &rx, skb);
} else
dev_kfree_skb(skb);
-
- end:
- if (rx.sta)
- sta_info_put(rx.sta);
}
#define SEQ_MODULO 0x1000
@@ -2031,7 +2025,7 @@ static u8 ieee80211_rx_reorder_ampdu(str
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr,
+ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
ret = 1;
goto end_reorder;
@@ -2041,9 +2035,7 @@ static u8 ieee80211_rx_reorder_ampdu(str
mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
mpdu_seq_num, 0);
-end_reorder:
- if (sta)
- sta_info_put(sta);
+ end_reorder:
return ret;
}
--- everything.orig/net/mac80211/ieee80211_ioctl.c 2008-02-21 22:09:29.000000000 +0100
+++ everything/net/mac80211/ieee80211_ioctl.c 2008-02-21 22:09:30.000000000 +0100
@@ -47,14 +47,15 @@ static int ieee80211_set_encryption(stru
}
if (remove) {
+ rcu_read_lock();
+
if (is_broadcast_ether_addr(sta_addr)) {
key = sdata->keys[idx];
} else {
sta = sta_info_get(local, sta_addr);
if (!sta) {
ret = -ENOENT;
- key = NULL;
- goto err_out;
+ goto out_rcu_unlock;
}
key = sta->key;
@@ -64,11 +65,18 @@ static int ieee80211_set_encryption(stru
ret = -ENOENT;
else
ret = 0;
+
+ ieee80211_key_free(key);
+ out_rcu_unlock:
+ rcu_read_unlock();
+
+ return ret;
} else {
key = ieee80211_key_alloc(alg, idx, key_len, _key);
if (!key)
return -ENOMEM;
+ rcu_read_lock();
if (!is_broadcast_ether_addr(sta_addr)) {
set_tx_key = 0;
/*
@@ -79,13 +87,13 @@ static int ieee80211_set_encryption(stru
*/
if (idx != 0 && alg != ALG_WEP) {
ret = -EINVAL;
- goto err_out;
+ goto out_free_unlock;
}
sta = sta_info_get(local, sta_addr);
if (!sta) {
ret = -ENOENT;
- goto err_out;
+ goto out_free_unlock;
}
}
@@ -95,17 +103,17 @@ static int ieee80211_set_encryption(stru
if (set_tx_key || (!sta && !sdata->default_key && key))
ieee80211_set_default_key(sdata, idx);
+ ret = 0;
+
/* don't free key later */
key = NULL;
- ret = 0;
- }
+ out_free_unlock:
+ ieee80211_key_free(key);
+ rcu_read_unlock();
- err_out:
- if (sta)
- sta_info_put(sta);
- ieee80211_key_free(key);
- return ret;
+ return ret;
+ }
}
static int ieee80211_ioctl_siwgenie(struct net_device *dev,
@@ -611,15 +619,22 @@ static int ieee80211_ioctl_giwrate(struc
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_supported_band *sband;
+ int ret = 0;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+ rcu_read_lock();
+
+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
sta = sta_info_get(local, sdata->u.sta.bssid);
- else
- return -EOPNOTSUPP;
- if (!sta)
- return -ENODEV;
+ } else {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ if (!sta) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
@@ -628,8 +643,11 @@ static int ieee80211_ioctl_giwrate(struc
else
rate->value = 0;
rate->value *= 100000;
- sta_info_put(sta);
- return 0;
+
+ out_unlock:
+ rcu_read_unlock();
+
+ return ret;
}
static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
@@ -988,6 +1006,8 @@ static struct iw_statistics *ieee80211_g
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta = NULL;
+ rcu_read_lock();
+
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
sta = sta_info_get(local, sdata->u.sta.bssid);
@@ -1003,8 +1023,10 @@ static struct iw_statistics *ieee80211_g
wstats->qual.qual = sta->last_signal;
wstats->qual.noise = sta->last_noise;
wstats->qual.updated = local->wstats_flags;
- sta_info_put(sta);
}
+
+ rcu_read_unlock();
+
return wstats;
}
--- everything.orig/net/mac80211/ieee80211_iface.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211_iface.c 2008-02-21 22:09:30.000000000 +0100
@@ -224,16 +224,21 @@ void ieee80211_if_reinit(struct net_devi
break;
}
case IEEE80211_IF_TYPE_WDS:
+ rcu_read_lock();
sta = sta_info_get(local, sdata->u.wds.remote_addr);
if (sta) {
- sta_info_free(sta);
- sta_info_put(sta);
+ sta_info_unlink(&sta);
} else {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Someone had deleted my STA "
"entry for the WDS link\n", dev->name);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
}
+ rcu_read_unlock();
+ if (sta) {
+ synchronize_rcu();
+ sta_info_destroy(sta);
+ }
break;
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
@@ -258,7 +263,7 @@ void ieee80211_if_reinit(struct net_devi
}
/* remove all STAs that are bound to this virtual interface */
- sta_info_flush(local, dev);
+ sta_info_flush(local, sdata);
memset(&sdata->u, 0, sizeof(sdata->u));
ieee80211_if_sdata_init(sdata);
--- everything.orig/net/mac80211/ieee80211_rate.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211_rate.c 2008-02-21 22:09:30.000000000 +0100
@@ -170,9 +170,12 @@ void rate_control_get_rate(struct net_de
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct sta_info *sta = sta_info_get(local, hdr->addr1);
+ struct sta_info *sta;
int i;
+ rcu_read_lock();
+ sta = sta_info_get(local, hdr->addr1);
+
memset(sel, 0, sizeof(struct rate_selection));
ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
@@ -190,8 +193,7 @@ void rate_control_get_rate(struct net_de
}
}
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
}
struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
--- everything.orig/net/mac80211/ieee80211_rate.h 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/ieee80211_rate.h 2008-02-21 22:09:30.000000000 +0100
@@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/types.h>
+#include <linux/kref.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "sta_info.h"
--- everything.orig/net/mac80211/key.c 2008-02-21 22:09:29.000000000 +0100
+++ everything/net/mac80211/key.c 2008-02-21 22:09:30.000000000 +0100
@@ -186,14 +186,17 @@ void ieee80211_key_link(struct ieee80211
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
struct sta_info *ap;
+ rcu_read_lock();
+
/* same here, the AP could be using QoS */
ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
if (ap) {
if (ap->flags & WLAN_STA_WME)
key->conf.flags |=
IEEE80211_KEY_FLAG_WMM_STA;
- sta_info_put(ap);
}
+
+ rcu_read_unlock();
}
}
--- everything.orig/net/mac80211/debugfs_sta.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/debugfs_sta.c 2008-02-21 22:09:30.000000000 +0100
@@ -51,7 +51,7 @@ static const struct file_operations sta_
STA_OPS(name)
STA_FILE(aid, aid, D);
-STA_FILE(dev, dev->name, S);
+STA_FILE(dev, sdata->dev->name, S);
STA_FILE(rx_packets, rx_packets, LU);
STA_FILE(tx_packets, tx_packets, LU);
STA_FILE(rx_bytes, rx_bytes, LU);
@@ -225,7 +225,7 @@ static ssize_t sta_agg_status_write(stru
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct sta_info *sta = file->private_data;
- struct net_device *dev = sta->dev;
+ struct net_device *dev = sta->sdata->dev;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hw *hw = &local->hw;
u8 *da = sta->addr;
--- everything.orig/net/mac80211/wme.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/wme.c 2008-02-21 22:09:30.000000000 +0100
@@ -153,6 +153,7 @@ static int wme_qdiscop_enqueue(struct sk
if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
queue = pkt_data->queue;
+ rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
if (sta) {
@@ -164,8 +165,8 @@ static int wme_qdiscop_enqueue(struct sk
} else {
pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
}
- sta_info_put(sta);
}
+ rcu_read_unlock();
skb_queue_tail(&q->requeued[queue], skb);
qd->q.qlen++;
return 0;
@@ -187,6 +188,8 @@ static int wme_qdiscop_enqueue(struct sk
p++;
*p = 0;
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
if (sta) {
int ampdu_queue = sta->tid_to_tx_q[tid];
@@ -197,8 +200,9 @@ static int wme_qdiscop_enqueue(struct sk
} else {
pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
}
- sta_info_put(sta);
}
+
+ rcu_read_unlock();
}
if (unlikely(queue >= local->hw.queues)) {
--- everything.orig/net/mac80211/debugfs_sta.h 2008-02-21 22:09:14.000000000 +0100
+++ everything/net/mac80211/debugfs_sta.h 2008-02-21 22:09:30.000000000 +0100
@@ -1,6 +1,8 @@
#ifndef __MAC80211_DEBUGFS_STA_H
#define __MAC80211_DEBUGFS_STA_H
+#include "sta_info.h"
+
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_sta_debugfs_add(struct sta_info *sta);
void ieee80211_sta_debugfs_remove(struct sta_info *sta);
--- everything.orig/drivers/net/wireless/iwlwifi/iwl-3945-rs.c 2008-02-21 22:09:15.000000000 +0100
+++ everything/drivers/net/wireless/iwlwifi/iwl-3945-rs.c 2008-02-21 22:09:30.000000000 +0100
@@ -471,10 +471,11 @@ static void rs_tx_status(void *priv_rate
return;
}
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
if (!sta || !sta->rate_ctrl_priv) {
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
return;
}
@@ -547,7 +548,7 @@ static void rs_tx_status(void *priv_rate
spin_unlock_irqrestore(&rs_sta->lock, flags);
- sta_info_put(sta);
+ rcu_read_unlock();
IWL_DEBUG_RATE("leave\n");
@@ -658,6 +659,8 @@ static void rs_get_rate(void *priv_rate,
IWL_DEBUG_RATE("enter\n");
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
@@ -668,8 +671,7 @@ static void rs_get_rate(void *priv_rate,
!sta || !sta->rate_ctrl_priv) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
sel->rate = rate_lowest(local, band, sta);
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -811,7 +813,7 @@ static void rs_get_rate(void *priv_rate,
else
sta->txrate_idx = sta->last_txrate_idx;
- sta_info_put(sta);
+ rcu_read_unlock();
IWL_DEBUG_RATE("leave: %d\n", index);
@@ -843,13 +845,15 @@ int iwl3945_fill_rs_info(struct ieee8021
unsigned long now = jiffies;
u32 max_time = 0;
+ rcu_read_lock();
+
sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
if (!sta || !sta->rate_ctrl_priv) {
- if (sta) {
- sta_info_put(sta);
+ if (sta)
IWL_DEBUG_RATE("leave - no private rate data!\n");
- } else
+ else
IWL_DEBUG_RATE("leave - no station!\n");
+ rcu_read_unlock();
return sprintf(buf, "station %d not found\n", sta_id);
}
@@ -890,7 +894,7 @@ int iwl3945_fill_rs_info(struct ieee8021
i = j;
}
spin_unlock_irqrestore(&rs_sta->lock, flags);
- sta_info_put(sta);
+ rcu_read_unlock();
/* Display the average rate of all samples taken.
*
@@ -927,11 +931,12 @@ void iwl3945_rate_scale_init(struct ieee
return;
}
+ rcu_read_lock();
+
sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
if (!sta || !sta->rate_ctrl_priv) {
- if (sta)
- sta_info_put(sta);
IWL_DEBUG_RATE("leave - no private rate data!\n");
+ rcu_read_unlock();
return;
}
@@ -958,7 +963,7 @@ void iwl3945_rate_scale_init(struct ieee
break;
}
- sta_info_put(sta);
+ rcu_read_unlock();
spin_unlock_irqrestore(&rs_sta->lock, flags);
rssi = priv->last_rx_rssi;
--- everything.orig/drivers/net/wireless/iwlwifi/iwl-4965-rs.c 2008-02-21 22:09:14.000000000 +0100
+++ everything/drivers/net/wireless/iwlwifi/iwl-4965-rs.c 2008-02-21 22:09:30.000000000 +0100
@@ -847,12 +847,12 @@ static void rs_tx_status(void *priv_rate
if (retries > 15)
retries = 15;
+ rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
if (!sta || !sta->rate_ctrl_priv) {
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -891,7 +891,7 @@ static void rs_tx_status(void *priv_rate
if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
rs_index, tx_mcs.rate_n_flags);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -909,7 +909,7 @@ static void rs_tx_status(void *priv_rate
IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n",
tx_mcs.rate_n_flags,
le32_to_cpu(table->rs_table[0].rate_n_flags));
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -1025,7 +1025,7 @@ static void rs_tx_status(void *priv_rate
/* See if there's a better rate or modulation mode to try. */
rs_rate_scale_perform(priv, dev, hdr, sta);
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -2219,6 +2219,8 @@ static void rs_get_rate(void *priv_rate,
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
+ rcu_read_lock();
+
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
@@ -2227,8 +2229,7 @@ static void rs_get_rate(void *priv_rate,
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
sel->rate = rate_lowest(local, sband, sta);
- if (sta)
- sta_info_put(sta);
+ rcu_read_unlock();
return;
}
@@ -2261,7 +2262,7 @@ static void rs_get_rate(void *priv_rate,
sel->rate = rate_lowest(local, sband, sta);
return;
}
- sta_info_put(sta);
+ rcu_read_unlock();
sel->rate = &priv->ieee_rates[i];
}
@@ -2735,13 +2736,15 @@ int iwl4965_fill_rs_info(struct ieee8021
u32 max_time = 0;
u8 lq_type, antenna;
+ rcu_read_lock();
+
sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
if (!sta || !sta->rate_ctrl_priv) {
- if (sta) {
- sta_info_put(sta);
+ if (sta)
IWL_DEBUG_RATE("leave - no private rate data!\n");
- } else
+ else
IWL_DEBUG_RATE("leave - no station!\n");
+ rcu_read_unlock();
return sprintf(buf, "station %d not found\n", sta_id);
}
@@ -2808,7 +2811,7 @@ int iwl4965_fill_rs_info(struct ieee8021
"active_search %d rate index %d\n", lq_type, antenna,
lq_sta->search_better_tbl, sta->last_txrate_idx);
- sta_info_put(sta);
+ rcu_read_unlock();
return cnt;
}
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/8] mac80211: split ieee80211_txrx_data
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (3 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 4/8] mac80211: RCU-ify STA info structure access Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 6/8] mac80211: split sta_info_add Johannes Berg
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
Split it into ieee80211_tx_data and ieee80211_rx_data to clarify
usage/flag usage and remove the stupid union thing.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/ieee80211_i.h | 86 ++++++++-------
net/mac80211/rx.c | 159 ++++++++++++++---------------
net/mac80211/tx.c | 244 ++++++++++++++++++++++-----------------------
net/mac80211/util.c | 8 -
net/mac80211/wep.c | 24 ++--
net/mac80211/wep.h | 4
net/mac80211/wpa.c | 80 +++++++-------
net/mac80211/wpa.h | 12 +-
8 files changed, 313 insertions(+), 304 deletions(-)
--- everything.orig/net/mac80211/ieee80211_i.h 2008-02-21 22:09:30.000000000 +0100
+++ everything/net/mac80211/ieee80211_i.h 2008-02-21 22:09:32.000000000 +0100
@@ -113,26 +113,51 @@ typedef unsigned __bitwise__ ieee80211_t
#define TX_DROP ((__force ieee80211_tx_result) 1u)
#define TX_QUEUED ((__force ieee80211_tx_result) 2u)
+#define IEEE80211_TX_FRAGMENTED BIT(0)
+#define IEEE80211_TX_UNICAST BIT(1)
+#define IEEE80211_TX_PS_BUFFERED BIT(2)
+#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3)
+#define IEEE80211_TX_INJECTED BIT(4)
+
+struct ieee80211_tx_data {
+ struct sk_buff *skb;
+ struct net_device *dev;
+ struct ieee80211_local *local;
+ struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta;
+ u16 fc, ethertype;
+ struct ieee80211_key *key;
+ unsigned int flags;
+
+ struct ieee80211_tx_control *control;
+ struct ieee80211_channel *channel;
+ struct ieee80211_rate *rate;
+ /* use this rate (if set) for last fragment; rate can
+ * be set to lower rate for the first fragments, e.g.,
+ * when using CTS protection with IEEE 802.11g. */
+ struct ieee80211_rate *last_frag_rate;
+
+ /* Extra fragments (in addition to the first fragment
+ * in skb) */
+ int num_extra_frag;
+ struct sk_buff **extra_frag;
+};
+
+
typedef unsigned __bitwise__ ieee80211_rx_result;
#define RX_CONTINUE ((__force ieee80211_rx_result) 0u)
#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
-
-/* flags used in struct ieee80211_txrx_data.flags */
-/* whether the MSDU was fragmented */
-#define IEEE80211_TXRXD_FRAGMENTED BIT(0)
-#define IEEE80211_TXRXD_TXUNICAST BIT(1)
-#define IEEE80211_TXRXD_TXPS_BUFFERED BIT(2)
-#define IEEE80211_TXRXD_TXPROBE_LAST_FRAG BIT(3)
-#define IEEE80211_TXRXD_RXIN_SCAN BIT(4)
+#define IEEE80211_RX_IN_SCAN BIT(0)
/* frame is destined to interface currently processed (incl. multicast frames) */
-#define IEEE80211_TXRXD_RXRA_MATCH BIT(5)
-#define IEEE80211_TXRXD_TX_INJECTED BIT(6)
-#define IEEE80211_TXRXD_RX_AMSDU BIT(7)
-#define IEEE80211_TXRXD_RX_CMNTR_REPORTED BIT(8)
-struct ieee80211_txrx_data {
+#define IEEE80211_RX_RA_MATCH BIT(1)
+#define IEEE80211_RX_AMSDU BIT(2)
+#define IEEE80211_RX_CMNTR_REPORTED BIT(3)
+#define IEEE80211_RX_FRAGMENTED BIT(4)
+
+struct ieee80211_rx_data {
struct sk_buff *skb;
struct net_device *dev;
struct ieee80211_local *local;
@@ -141,31 +166,14 @@ struct ieee80211_txrx_data {
u16 fc, ethertype;
struct ieee80211_key *key;
unsigned int flags;
- union {
- struct {
- struct ieee80211_tx_control *control;
- struct ieee80211_channel *channel;
- struct ieee80211_rate *rate;
- /* use this rate (if set) for last fragment; rate can
- * be set to lower rate for the first fragments, e.g.,
- * when using CTS protection with IEEE 802.11g. */
- struct ieee80211_rate *last_frag_rate;
-
- /* Extra fragments (in addition to the first fragment
- * in skb) */
- int num_extra_frag;
- struct sk_buff **extra_frag;
- } tx;
- struct {
- struct ieee80211_rx_status *status;
- struct ieee80211_rate *rate;
- int sent_ps_buffered;
- int queue;
- int load;
- u32 tkip_iv32;
- u16 tkip_iv16;
- } rx;
- } u;
+
+ struct ieee80211_rx_status *status;
+ struct ieee80211_rate *rate;
+ int sent_ps_buffered;
+ int queue;
+ int load;
+ u32 tkip_iv32;
+ u16 tkip_iv16;
};
/* flags used in struct ieee80211_tx_packet_data.flags */
@@ -658,7 +666,7 @@ static inline int ieee80211_bssid_match(
int ieee80211_hw_config(struct ieee80211_local *local);
int ieee80211_if_config(struct net_device *dev);
int ieee80211_if_config_beacon(struct net_device *dev);
-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
+void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
void ieee80211_if_setup(struct net_device *dev);
int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
--- everything.orig/net/mac80211/rx.c 2008-02-21 22:09:30.000000000 +0100
+++ everything/net/mac80211/rx.c 2008-02-21 22:09:32.000000000 +0100
@@ -250,7 +250,7 @@ ieee80211_rx_monitor(struct ieee80211_lo
}
-static void ieee80211_parse_qos(struct ieee80211_txrx_data *rx)
+static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
{
u8 *data = rx->skb->data;
int tid;
@@ -261,9 +261,9 @@ static void ieee80211_parse_qos(struct i
/* frame has qos control */
tid = qc[0] & QOS_CONTROL_TID_MASK;
if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
- rx->flags |= IEEE80211_TXRXD_RX_AMSDU;
+ rx->flags |= IEEE80211_RX_AMSDU;
else
- rx->flags &= ~IEEE80211_TXRXD_RX_AMSDU;
+ rx->flags &= ~IEEE80211_RX_AMSDU;
} else {
if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
/* Separate TID for management frames */
@@ -279,13 +279,13 @@ static void ieee80211_parse_qos(struct i
if (rx->sta)
I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
- rx->u.rx.queue = tid;
+ rx->queue = tid;
/* Set skb->priority to 1d tag if highest order bit of TID is not set.
* For now, set skb->priority to 0 for other cases. */
rx->skb->priority = (tid > 7) ? 0 : tid;
}
-static void ieee80211_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
{
#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
int hdrlen;
@@ -313,7 +313,7 @@ static void ieee80211_verify_ip_alignmen
* to move the 802.11 header further back in that case.
*/
hdrlen = ieee80211_get_hdrlen(rx->fc);
- if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
+ if (rx->flags & IEEE80211_RX_AMSDU)
hdrlen += ETH_HLEN;
WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
#endif
@@ -356,32 +356,32 @@ static u32 ieee80211_rx_load_stats(struc
/* rx handlers */
static ieee80211_rx_result
-ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_if_stats(struct ieee80211_rx_data *rx)
{
if (rx->sta)
- rx->sta->channel_use_raw += rx->u.rx.load;
- rx->sdata->channel_use_raw += rx->u.rx.load;
+ rx->sta->channel_use_raw += rx->load;
+ rx->sdata->channel_use_raw += rx->load;
return RX_CONTINUE;
}
static ieee80211_rx_result
-ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
struct sk_buff *skb = rx->skb;
if (unlikely(local->sta_hw_scanning))
- return ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
+ return ieee80211_sta_rx_scan(rx->dev, skb, rx->status);
if (unlikely(local->sta_sw_scanning)) {
/* drop all the other packets during a software scan anyway */
- if (ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status)
+ if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status)
!= RX_QUEUED)
dev_kfree_skb(skb);
return RX_QUEUED;
}
- if (unlikely(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) {
+ if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
/* scanning finished during invoking of handlers */
I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
return RX_DROP_UNUSABLE;
@@ -391,7 +391,7 @@ ieee80211_rx_h_passive_scan(struct ieee8
}
static ieee80211_rx_result
-ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *) rx->skb->data;
@@ -399,15 +399,15 @@ ieee80211_rx_h_check(struct ieee80211_tx
/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
- rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
+ rx->sta->last_seq_ctrl[rx->queue] ==
hdr->seq_ctrl)) {
- if (rx->flags & IEEE80211_TXRXD_RXRA_MATCH) {
+ if (rx->flags & IEEE80211_RX_RA_MATCH) {
rx->local->dot11FrameDuplicateCount++;
rx->sta->num_duplicates++;
}
return RX_DROP_MONITOR;
} else
- rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
+ rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
}
if (unlikely(rx->skb->len < 16)) {
@@ -431,7 +431,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
!(rx->fc & IEEE80211_FCTL_TODS) &&
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
- || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
+ || !(rx->flags & IEEE80211_RX_RA_MATCH)) {
/* Drop IBSS frames and frames for other hosts
* silently. */
return RX_DROP_MONITOR;
@@ -445,7 +445,7 @@ ieee80211_rx_h_check(struct ieee80211_tx
static ieee80211_rx_result
-ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
int keyidx;
@@ -486,7 +486,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_
* No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
*/
- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_CONTINUE;
if (rx->sta)
@@ -504,8 +504,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_
* we somehow allow the driver to tell us which key
* the hardware used if this flag is set?
*/
- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
+ (rx->status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
hdrlen = ieee80211_get_hdrlen(rx->fc);
@@ -546,8 +546,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_
/* Check for weak IVs if possible */
if (rx->sta && rx->key->conf.alg == ALG_WEP &&
((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
- (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
- !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) &&
+ (!(rx->status->flag & RX_FLAG_IV_STRIPPED) ||
+ !(rx->status->flag & RX_FLAG_DECRYPTED)) &&
ieee80211_wep_is_weak_iv(rx->skb, rx->key))
rx->sta->wep_weak_iv_count++;
@@ -564,7 +564,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_
}
/* either the frame has been decrypted or will be dropped */
- rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;
+ rx->status->flag |= RX_FLAG_DECRYPTED;
return result;
}
@@ -634,7 +634,7 @@ static int ap_sta_ps_end(struct net_devi
}
static ieee80211_rx_result
-ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
struct sta_info *sta = rx->sta;
struct net_device *dev = rx->dev;
@@ -661,20 +661,20 @@ ieee80211_rx_h_sta_process(struct ieee80
sta->last_rx = jiffies;
}
- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_CONTINUE;
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
- sta->last_rssi = rx->u.rx.status->ssi;
- sta->last_signal = rx->u.rx.status->signal;
- sta->last_noise = rx->u.rx.status->noise;
+ sta->last_rssi = rx->status->ssi;
+ sta->last_signal = rx->status->signal;
+ sta->last_noise = rx->status->noise;
if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
/* Change STA power saving mode only in the end of a frame
* exchange sequence */
if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
- rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
+ rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
else if (!(sta->flags & WLAN_STA_PS) &&
(rx->fc & IEEE80211_FCTL_PM))
ap_sta_ps_start(dev, sta);
@@ -779,7 +779,7 @@ ieee80211_reassemble_find(struct ieee802
}
static ieee80211_rx_result
-ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr;
u16 sc;
@@ -805,14 +805,14 @@ ieee80211_rx_h_defragment(struct ieee802
if (frag == 0) {
/* This is the first fragment of a new frame. */
entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
- rx->u.rx.queue, &(rx->skb));
+ rx->queue, &(rx->skb));
if (rx->key && rx->key->conf.alg == ALG_CCMP &&
(rx->fc & IEEE80211_FCTL_PROTECTED)) {
/* Store CCMP PN so that we can verify that the next
* fragment has a sequential PN value. */
entry->ccmp = 1;
memcpy(entry->last_pn,
- rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
+ rx->key->u.ccmp.rx_pn[rx->queue],
CCMP_PN_LEN);
}
return RX_QUEUED;
@@ -822,7 +822,7 @@ ieee80211_rx_h_defragment(struct ieee802
* fragment cache. Add this fragment to the end of the pending entry.
*/
entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
- rx->u.rx.queue, hdr);
+ rx->queue, hdr);
if (!entry) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
return RX_DROP_MONITOR;
@@ -841,7 +841,7 @@ ieee80211_rx_h_defragment(struct ieee802
if (pn[i])
break;
}
- rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
+ rpn = rx->key->u.ccmp.rx_pn[rx->queue];
if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
if (net_ratelimit())
printk(KERN_DEBUG "%s: defrag: CCMP PN not "
@@ -882,7 +882,7 @@ ieee80211_rx_h_defragment(struct ieee802
}
/* Complete frame has been reassembled - process it now */
- rx->flags |= IEEE80211_TXRXD_FRAGMENTED;
+ rx->flags |= IEEE80211_RX_FRAGMENTED;
out:
if (rx->sta)
@@ -895,7 +895,7 @@ ieee80211_rx_h_defragment(struct ieee802
}
static ieee80211_rx_result
-ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
struct sk_buff *skb;
@@ -905,7 +905,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_
if (likely(!rx->sta ||
(rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
- !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))
+ !(rx->flags & IEEE80211_RX_RA_MATCH)))
return RX_CONTINUE;
if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
@@ -949,7 +949,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_
if (no_pending_pkts)
sta_info_clear_tim_bit(rx->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- } else if (!rx->u.rx.sent_ps_buffered) {
+ } else if (!rx->sent_ps_buffered) {
/*
* FIXME: This can be the result of a race condition between
* us expiring a frame and the station polling for it.
@@ -970,7 +970,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_
}
static ieee80211_rx_result
-ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
{
u16 fc = rx->fc;
u8 *data = rx->skb->data;
@@ -990,7 +990,7 @@ ieee80211_rx_h_remove_qos_control(struct
}
static int
-ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
+ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{
if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
#ifdef CONFIG_MAC80211_DEBUG
@@ -1005,13 +1005,13 @@ ieee80211_802_1x_port_control(struct iee
}
static int
-ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
+ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
{
/*
* Pass through unencrypted frames if the hardware has
* decrypted them already.
*/
- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
+ if (rx->status->flag & RX_FLAG_DECRYPTED)
return 0;
/* Drop unencrypted frames if key is set. */
@@ -1028,7 +1028,7 @@ ieee80211_drop_unencrypted(struct ieee80
}
static int
-ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
@@ -1160,7 +1160,7 @@ ieee80211_data_to_8023(struct ieee80211_
/*
* requires that rx->skb is a frame with ethernet header
*/
-static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
+static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
{
static const u8 pae_group_addr[ETH_ALEN]
= { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
@@ -1186,7 +1186,7 @@ static bool ieee80211_frame_allowed(stru
* requires that rx->skb is a frame with ethernet header
*/
static void
-ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
struct ieee80211_local *local = rx->local;
@@ -1200,7 +1200,7 @@ ieee80211_deliver_skb(struct ieee80211_t
if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
- (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
+ (rx->flags & IEEE80211_RX_RA_MATCH)) {
if (is_multicast_ether_addr(ehdr->h_dest)) {
/*
* send multicast frames both to higher layers in
@@ -1242,7 +1242,7 @@ ieee80211_deliver_skb(struct ieee80211_t
}
static ieee80211_rx_result
-ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
struct ieee80211_local *local = rx->local;
@@ -1262,7 +1262,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_tx
if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
return RX_DROP_MONITOR;
- if (!(rx->flags & IEEE80211_TXRXD_RX_AMSDU))
+ if (!(rx->flags & IEEE80211_RX_AMSDU))
return RX_CONTINUE;
err = ieee80211_data_to_8023(rx);
@@ -1359,7 +1359,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_tx
}
static ieee80211_rx_result
-ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
struct net_device *dev = rx->dev;
u16 fc;
@@ -1390,7 +1390,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
}
static ieee80211_rx_result
-ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
{
struct ieee80211_local *local = rx->local;
struct ieee80211_hw *hw = &local->hw;
@@ -1433,18 +1433,18 @@ ieee80211_rx_h_ctrl(struct ieee80211_txr
}
static ieee80211_rx_result
-ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata;
- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_MONITOR;
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
!(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
- ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
+ ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status);
else
return RX_DROP_MONITOR;
@@ -1453,7 +1453,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_txr
static void ieee80211_rx_michael_mic_report(struct net_device *dev,
struct ieee80211_hdr *hdr,
- struct ieee80211_txrx_data *rx)
+ struct ieee80211_rx_data *rx)
{
int keyidx, hdrlen;
DECLARE_MAC_BUF(mac);
@@ -1523,7 +1523,8 @@ static void ieee80211_rx_michael_mic_rep
rx->skb = NULL;
}
-static void ieee80211_rx_cooked_monitor(struct ieee80211_txrx_data *rx)
+/* TODO: use IEEE80211_RX_FRAGMENTED */
+static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local = rx->local;
@@ -1536,9 +1537,9 @@ static void ieee80211_rx_cooked_monitor(
} __attribute__ ((packed)) *rthdr;
struct sk_buff *skb = rx->skb, *skb2;
struct net_device *prev_dev = NULL;
- struct ieee80211_rx_status *status = rx->u.rx.status;
+ struct ieee80211_rx_status *status = rx->status;
- if (rx->flags & IEEE80211_TXRXD_RX_CMNTR_REPORTED)
+ if (rx->flags & IEEE80211_RX_CMNTR_REPORTED)
goto out_free_skb;
if (skb_headroom(skb) < sizeof(*rthdr) &&
@@ -1553,7 +1554,7 @@ static void ieee80211_rx_cooked_monitor(
(1 << IEEE80211_RADIOTAP_RATE) |
(1 << IEEE80211_RADIOTAP_CHANNEL));
- rthdr->rate = rx->u.rx.rate->bitrate / 5;
+ rthdr->rate = rx->rate->bitrate / 5;
rthdr->chan_freq = cpu_to_le16(status->freq);
if (status->band == IEEE80211_BAND_5GHZ)
@@ -1596,14 +1597,14 @@ static void ieee80211_rx_cooked_monitor(
} else
goto out_free_skb;
- rx->flags |= IEEE80211_TXRXD_RX_CMNTR_REPORTED;
+ rx->flags |= IEEE80211_RX_CMNTR_REPORTED;
return;
out_free_skb:
dev_kfree_skb(skb);
}
-typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_txrx_data *);
+typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
static ieee80211_rx_handler ieee80211_rx_handlers[] =
{
ieee80211_rx_h_if_stats,
@@ -1627,7 +1628,7 @@ static ieee80211_rx_handler ieee80211_rx
};
static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_txrx_data *rx,
+ struct ieee80211_rx_data *rx,
struct sk_buff *skb)
{
ieee80211_rx_handler *handler;
@@ -1670,7 +1671,7 @@ static void ieee80211_invoke_rx_handlers
/* main receive path */
static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
- u8 *bssid, struct ieee80211_txrx_data *rx,
+ u8 *bssid, struct ieee80211_rx_data *rx,
struct ieee80211_hdr *hdr)
{
int multicast = is_multicast_ether_addr(hdr->addr1);
@@ -1680,15 +1681,15 @@ static int prepare_for_handlers(struct i
if (!bssid)
return 0;
if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
return 0;
- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!multicast &&
compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
break;
case IEEE80211_IF_TYPE_IBSS:
@@ -1698,15 +1699,15 @@ static int prepare_for_handlers(struct i
(rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
return 1;
else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
return 0;
- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!multicast &&
compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1) != 0) {
if (!(sdata->dev->flags & IFF_PROMISC))
return 0;
- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta)
rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
bssid, hdr->addr2);
@@ -1719,12 +1720,12 @@ static int prepare_for_handlers(struct i
return 0;
} else if (!ieee80211_bssid_match(bssid,
sdata->dev->dev_addr)) {
- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
return 0;
- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
if (sdata->dev == sdata->local->mdev &&
- !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
+ !(rx->flags & IEEE80211_RX_IN_SCAN))
/* do not receive anything via
* master device when not scanning */
return 0;
@@ -1761,7 +1762,7 @@ static void __ieee80211_rx_handle_packet
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr;
- struct ieee80211_txrx_data rx;
+ struct ieee80211_rx_data rx;
u16 type;
int prepares;
struct ieee80211_sub_if_data *prev = NULL;
@@ -1773,9 +1774,9 @@ static void __ieee80211_rx_handle_packet
rx.skb = skb;
rx.local = local;
- rx.u.rx.status = status;
- rx.u.rx.load = load;
- rx.u.rx.rate = rate;
+ rx.status = status;
+ rx.load = load;
+ rx.rate = rate;
rx.fc = le16_to_cpu(hdr->frame_control);
type = rx.fc & IEEE80211_FCTL_FTYPE;
@@ -1794,7 +1795,7 @@ static void __ieee80211_rx_handle_packet
}
if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
- rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
+ rx.flags |= IEEE80211_RX_IN_SCAN;
ieee80211_parse_qos(&rx);
ieee80211_verify_ip_alignment(&rx);
@@ -1809,7 +1810,7 @@ static void __ieee80211_rx_handle_packet
continue;
bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
- rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
+ rx.flags |= IEEE80211_RX_RA_MATCH;
prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
if (!prepares)
--- everything.orig/net/mac80211/tx.c 2008-02-21 22:09:30.000000000 +0100
+++ everything/net/mac80211/tx.c 2008-02-21 22:09:32.000000000 +0100
@@ -86,11 +86,11 @@ static inline void ieee80211_dump_frame(
}
#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
-static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
int next_frag_len)
{
int rate, mrate, erp, dur, i;
- struct ieee80211_rate *txrate = tx->u.tx.rate;
+ struct ieee80211_rate *txrate = tx->rate;
struct ieee80211_local *local = tx->local;
struct ieee80211_supported_band *sband;
@@ -233,7 +233,7 @@ static int inline is_ieee80211_device(st
/* tx handlers */
static ieee80211_tx_result
-ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
{
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
struct sk_buff *skb = tx->skb;
@@ -241,7 +241,7 @@ ieee80211_tx_h_check_assoc(struct ieee80
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
u32 sta_flags;
- if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
+ if (unlikely(tx->flags & IEEE80211_TX_INJECTED))
return TX_CONTINUE;
if (unlikely(tx->local->sta_sw_scanning) &&
@@ -249,12 +249,12 @@ ieee80211_tx_h_check_assoc(struct ieee80
(tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
return TX_DROP;
- if (tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED)
+ if (tx->flags & IEEE80211_TX_PS_BUFFERED)
return TX_CONTINUE;
sta_flags = tx->sta ? tx->sta->flags : 0;
- if (likely(tx->flags & IEEE80211_TXRXD_TXUNICAST)) {
+ if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
(tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
@@ -284,7 +284,7 @@ ieee80211_tx_h_check_assoc(struct ieee80
}
static ieee80211_tx_result
-ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
@@ -341,7 +341,7 @@ static void purge_old_ps_buffers(struct
}
static ieee80211_tx_result
-ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
{
/*
* broadcast/multicast frame
@@ -378,13 +378,13 @@ ieee80211_tx_h_multicast_ps_buf(struct i
}
/* buffered in hardware */
- tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
+ tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
return TX_CONTINUE;
}
static ieee80211_tx_result
-ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
{
struct sta_info *sta = tx->sta;
DECLARE_MAC_BUF(mac);
@@ -438,32 +438,32 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
}
static ieee80211_tx_result
-ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
{
- if (unlikely(tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED))
+ if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
return TX_CONTINUE;
- if (tx->flags & IEEE80211_TXRXD_TXUNICAST)
+ if (tx->flags & IEEE80211_TX_UNICAST)
return ieee80211_tx_h_unicast_ps_buf(tx);
else
return ieee80211_tx_h_multicast_ps_buf(tx);
}
static ieee80211_tx_result
-ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{
struct ieee80211_key *key;
u16 fc = tx->fc;
- if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+ if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
tx->key = NULL;
else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
tx->key = key;
else if ((key = rcu_dereference(tx->sdata->default_key)))
tx->key = key;
else if (tx->sdata->drop_unencrypted &&
- !(tx->u.tx.control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
- !(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) {
+ !(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
+ !(tx->flags & IEEE80211_TX_INJECTED)) {
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
return TX_DROP;
} else
@@ -492,13 +492,13 @@ ieee80211_tx_h_select_key(struct ieee802
}
if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
- tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
return TX_CONTINUE;
}
static ieee80211_tx_result
-ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
@@ -508,7 +508,7 @@ ieee80211_tx_h_fragment(struct ieee80211
u8 *pos;
int frag_threshold = tx->local->fragmentation_threshold;
- if (!(tx->flags & IEEE80211_TXRXD_FRAGMENTED))
+ if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
return TX_CONTINUE;
first = tx->skb;
@@ -560,8 +560,8 @@ ieee80211_tx_h_fragment(struct ieee80211
}
skb_trim(first, hdrlen + per_fragm);
- tx->u.tx.num_extra_frag = num_fragm - 1;
- tx->u.tx.extra_frag = frags;
+ tx->num_extra_frag = num_fragm - 1;
+ tx->extra_frag = frags;
return TX_CONTINUE;
@@ -578,7 +578,7 @@ ieee80211_tx_h_fragment(struct ieee80211
}
static ieee80211_tx_result
-ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
return TX_CONTINUE;
@@ -598,56 +598,56 @@ ieee80211_tx_h_encrypt(struct ieee80211_
}
static ieee80211_tx_result
-ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{
struct rate_selection rsel;
struct ieee80211_supported_band *sband;
sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
- if (likely(!tx->u.tx.rate)) {
+ if (likely(!tx->rate)) {
rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
- tx->u.tx.rate = rsel.rate;
+ tx->rate = rsel.rate;
if (unlikely(rsel.probe)) {
- tx->u.tx.control->flags |=
+ tx->control->flags |=
IEEE80211_TXCTL_RATE_CTRL_PROBE;
- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
- tx->u.tx.control->alt_retry_rate = tx->u.tx.rate;
- tx->u.tx.rate = rsel.probe;
+ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
+ tx->control->alt_retry_rate = tx->rate;
+ tx->rate = rsel.probe;
} else
- tx->u.tx.control->alt_retry_rate = NULL;
+ tx->control->alt_retry_rate = NULL;
- if (!tx->u.tx.rate)
+ if (!tx->rate)
return TX_DROP;
} else
- tx->u.tx.control->alt_retry_rate = NULL;
+ tx->control->alt_retry_rate = NULL;
if (tx->sdata->bss_conf.use_cts_prot &&
- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) {
- tx->u.tx.last_frag_rate = tx->u.tx.rate;
+ (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) {
+ tx->last_frag_rate = tx->rate;
if (rsel.probe)
- tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+ tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
else
- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
- tx->u.tx.rate = rsel.nonerp;
- tx->u.tx.control->tx_rate = rsel.nonerp;
- tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
+ tx->rate = rsel.nonerp;
+ tx->control->tx_rate = rsel.nonerp;
+ tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
} else {
- tx->u.tx.last_frag_rate = tx->u.tx.rate;
- tx->u.tx.control->tx_rate = tx->u.tx.rate;
+ tx->last_frag_rate = tx->rate;
+ tx->control->tx_rate = tx->rate;
}
- tx->u.tx.control->tx_rate = tx->u.tx.rate;
+ tx->control->tx_rate = tx->rate;
return TX_CONTINUE;
}
static ieee80211_tx_result
-ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
u16 fc = le16_to_cpu(hdr->frame_control);
u16 dur;
- struct ieee80211_tx_control *control = tx->u.tx.control;
+ struct ieee80211_tx_control *control = tx->control;
if (!control->retry_limit) {
if (!is_multicast_ether_addr(hdr->addr1)) {
@@ -669,7 +669,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
}
}
- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
+ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
/* Do not use multiple retry rates when sending fragmented
* frames.
* TODO: The last fragment could still use multiple retry
@@ -681,8 +681,8 @@ ieee80211_tx_h_misc(struct ieee80211_txr
* there are associated non-ERP stations and RTS/CTS is not configured
* for the frame. */
if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
- (tx->u.tx.rate->flags & IEEE80211_RATE_ERP_G) &&
- (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
+ (tx->rate->flags & IEEE80211_RATE_ERP_G) &&
+ (tx->flags & IEEE80211_TX_UNICAST) &&
tx->sdata->bss_conf.use_cts_prot &&
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
@@ -691,18 +691,18 @@ ieee80211_tx_h_misc(struct ieee80211_txr
* short preambles at the selected rate and short preambles are
* available on the network at the current point in time. */
if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
- (tx->u.tx.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
+ (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
tx->sdata->bss_conf.use_short_preamble &&
(!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
- tx->u.tx.control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
}
/* Setup duration field for the first fragment of the frame. Duration
* for remaining fragments will be updated when they are being sent
* to low-level driver in ieee80211_tx(). */
dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) ?
- tx->u.tx.extra_frag[0]->len : 0);
+ (tx->flags & IEEE80211_TX_FRAGMENTED) ?
+ tx->extra_frag[0]->len : 0);
hdr->duration_id = cpu_to_le16(dur);
if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
@@ -718,7 +718,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
control->alt_retry_rate = NULL;
/* Use min(data rate, max base rate) as CTS/RTS rate */
- rate = tx->u.tx.rate;
+ rate = tx->rate;
baserate = NULL;
for (idx = 0; idx < sband->n_bitrates; idx++) {
@@ -740,12 +740,12 @@ ieee80211_tx_h_misc(struct ieee80211_txr
tx->sta->tx_packets++;
tx->sta->tx_fragments++;
tx->sta->tx_bytes += tx->skb->len;
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
int i;
- tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+ tx->sta->tx_fragments += tx->num_extra_frag;
+ for (i = 0; i < tx->num_extra_frag; i++) {
tx->sta->tx_bytes +=
- tx->u.tx.extra_frag[i]->len;
+ tx->extra_frag[i]->len;
}
}
}
@@ -754,13 +754,13 @@ ieee80211_tx_h_misc(struct ieee80211_txr
}
static ieee80211_tx_result
-ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
{
struct ieee80211_local *local = tx->local;
struct sk_buff *skb = tx->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u32 load = 0, hdrtime;
- struct ieee80211_rate *rate = tx->u.tx.rate;
+ struct ieee80211_rate *rate = tx->rate;
/* TODO: this could be part of tx_status handling, so that the number
* of retries would be known; TX rate should in that case be stored
@@ -771,8 +771,8 @@ ieee80211_tx_h_load_stats(struct ieee802
/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
* 1 usec = 1/8 * (1080 / 10) = 13.5 */
- if (tx->u.tx.channel->band == IEEE80211_BAND_5GHZ ||
- (tx->u.tx.channel->band == IEEE80211_BAND_2GHZ &&
+ if (tx->channel->band == IEEE80211_BAND_5GHZ ||
+ (tx->channel->band == IEEE80211_BAND_2GHZ &&
rate->flags & IEEE80211_RATE_ERP_G))
hdrtime = CHAN_UTIL_HDR_SHORT;
else
@@ -782,20 +782,20 @@ ieee80211_tx_h_load_stats(struct ieee802
if (!is_multicast_ether_addr(hdr->addr1))
load += hdrtime;
- if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
load += 2 * hdrtime;
- else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
load += hdrtime;
/* TODO: optimise again */
load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
int i;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+ for (i = 0; i < tx->num_extra_frag; i++) {
load += 2 * hdrtime;
- load += tx->u.tx.extra_frag[i]->len *
- tx->u.tx.rate->bitrate;
+ load += tx->extra_frag[i]->len *
+ tx->rate->bitrate;
}
}
@@ -810,7 +810,7 @@ ieee80211_tx_h_load_stats(struct ieee802
}
-typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_txrx_data *);
+typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
static ieee80211_tx_handler ieee80211_tx_handlers[] =
{
ieee80211_tx_h_check_assoc,
@@ -833,7 +833,7 @@ static ieee80211_tx_handler ieee80211_tx
* with Radiotap Header -- only called for monitor mode interface
*/
static ieee80211_tx_result
-__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
struct sk_buff *skb)
{
/*
@@ -849,13 +849,13 @@ __ieee80211_parse_tx_radiotap(struct iee
(struct ieee80211_radiotap_header *) skb->data;
struct ieee80211_supported_band *sband;
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
- struct ieee80211_tx_control *control = tx->u.tx.control;
+ struct ieee80211_tx_control *control = tx->control;
sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
- tx->flags |= IEEE80211_TXRXD_TX_INJECTED;
- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
+ tx->flags |= IEEE80211_TX_INJECTED;
+ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
/*
* for every radiotap entry that is present
@@ -891,7 +891,7 @@ __ieee80211_parse_tx_radiotap(struct iee
r = &sband->bitrates[i];
if (r->bitrate == target_rate) {
- tx->u.tx.rate = r;
+ tx->rate = r;
break;
}
}
@@ -929,7 +929,7 @@ __ieee80211_parse_tx_radiotap(struct iee
control->flags &=
~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
+ tx->flags |= IEEE80211_TX_FRAGMENTED;
break;
/*
@@ -960,7 +960,7 @@ __ieee80211_parse_tx_radiotap(struct iee
* initialises @tx
*/
static ieee80211_tx_result
-__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
struct sk_buff *skb,
struct net_device *dev,
struct ieee80211_tx_control *control)
@@ -976,12 +976,12 @@ __ieee80211_tx_prepare(struct ieee80211_
tx->dev = dev; /* use original interface */
tx->local = local;
tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- tx->u.tx.control = control;
+ tx->control = control;
/*
* Set this flag (used below to indicate "automatic fragmentation"),
* it will be cleared/left by radiotap as desired.
*/
- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
+ tx->flags |= IEEE80211_TX_FRAGMENTED;
/* process and remove the injection radiotap header */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1002,20 +1002,20 @@ __ieee80211_tx_prepare(struct ieee80211_
tx->fc = le16_to_cpu(hdr->frame_control);
if (is_multicast_ether_addr(hdr->addr1)) {
- tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;
+ tx->flags &= ~IEEE80211_TX_UNICAST;
control->flags |= IEEE80211_TXCTL_NO_ACK;
} else {
- tx->flags |= IEEE80211_TXRXD_TXUNICAST;
+ tx->flags |= IEEE80211_TX_UNICAST;
control->flags &= ~IEEE80211_TXCTL_NO_ACK;
}
- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
- if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
+ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
+ if ((tx->flags & IEEE80211_TX_UNICAST) &&
skb->len + FCS_LEN > local->fragmentation_threshold &&
!local->ops->set_frag_threshold)
- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
+ tx->flags |= IEEE80211_TX_FRAGMENTED;
else
- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
+ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
}
if (!tx->sta)
@@ -1038,7 +1038,7 @@ __ieee80211_tx_prepare(struct ieee80211_
/*
* NB: @tx is uninitialised when passed in here
*/
-static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
struct sk_buff *skb,
struct net_device *mdev,
struct ieee80211_tx_control *control)
@@ -1061,9 +1061,9 @@ static int ieee80211_tx_prepare(struct i
}
static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
- struct ieee80211_txrx_data *tx)
+ struct ieee80211_tx_data *tx)
{
- struct ieee80211_tx_control *control = tx->u.tx.control;
+ struct ieee80211_tx_control *control = tx->control;
int ret, i;
if (!ieee80211_qdisc_installed(local->mdev) &&
@@ -1080,20 +1080,20 @@ static int __ieee80211_tx(struct ieee802
local->mdev->trans_start = jiffies;
ieee80211_led_tx(local, 1);
}
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
IEEE80211_TXCTL_USE_CTS_PROTECT |
IEEE80211_TXCTL_CLEAR_PS_FILT |
IEEE80211_TXCTL_FIRST_FRAGMENT);
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
- if (!tx->u.tx.extra_frag[i])
+ for (i = 0; i < tx->num_extra_frag; i++) {
+ if (!tx->extra_frag[i])
continue;
if (__ieee80211_queue_stopped(local, control->queue))
return IEEE80211_TX_FRAG_AGAIN;
- if (i == tx->u.tx.num_extra_frag) {
- control->tx_rate = tx->u.tx.last_frag_rate;
+ if (i == tx->num_extra_frag) {
+ control->tx_rate = tx->last_frag_rate;
- if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG)
+ if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
control->flags |=
IEEE80211_TXCTL_RATE_CTRL_PROBE;
else
@@ -1103,18 +1103,18 @@ static int __ieee80211_tx(struct ieee802
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
"TX to low-level driver",
- tx->u.tx.extra_frag[i]);
+ tx->extra_frag[i]);
ret = local->ops->tx(local_to_hw(local),
- tx->u.tx.extra_frag[i],
+ tx->extra_frag[i],
control);
if (ret)
return IEEE80211_TX_FRAG_AGAIN;
local->mdev->trans_start = jiffies;
ieee80211_led_tx(local, 1);
- tx->u.tx.extra_frag[i] = NULL;
+ tx->extra_frag[i] = NULL;
}
- kfree(tx->u.tx.extra_frag);
- tx->u.tx.extra_frag = NULL;
+ kfree(tx->extra_frag);
+ tx->extra_frag = NULL;
}
return IEEE80211_TX_OK;
}
@@ -1125,7 +1125,7 @@ static int ieee80211_tx(struct net_devic
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
ieee80211_tx_handler *handler;
- struct ieee80211_txrx_data tx;
+ struct ieee80211_tx_data tx;
ieee80211_tx_result res = TX_DROP, res_prepare;
int ret, i;
@@ -1148,7 +1148,7 @@ static int ieee80211_tx(struct net_devic
}
sta = tx.sta;
- tx.u.tx.channel = local->hw.conf.channel;
+ tx.channel = local->hw.conf.channel;
for (handler = ieee80211_tx_handlers; *handler != NULL;
handler++) {
@@ -1170,18 +1170,18 @@ static int ieee80211_tx(struct net_devic
return 0;
}
- if (tx.u.tx.extra_frag) {
- for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
+ if (tx.extra_frag) {
+ for (i = 0; i < tx.num_extra_frag; i++) {
int next_len, dur;
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *)
- tx.u.tx.extra_frag[i]->data;
+ tx.extra_frag[i]->data;
- if (i + 1 < tx.u.tx.num_extra_frag) {
- next_len = tx.u.tx.extra_frag[i + 1]->len;
+ if (i + 1 < tx.num_extra_frag) {
+ next_len = tx.extra_frag[i + 1]->len;
} else {
next_len = 0;
- tx.u.tx.rate = tx.u.tx.last_frag_rate;
+ tx.rate = tx.last_frag_rate;
}
dur = ieee80211_duration(&tx, 0, next_len);
hdr->duration_id = cpu_to_le16(dur);
@@ -1216,11 +1216,11 @@ retry:
memcpy(&store->control, control,
sizeof(struct ieee80211_tx_control));
store->skb = skb;
- store->extra_frag = tx.u.tx.extra_frag;
- store->num_extra_frag = tx.u.tx.num_extra_frag;
- store->last_frag_rate = tx.u.tx.last_frag_rate;
+ store->extra_frag = tx.extra_frag;
+ store->num_extra_frag = tx.num_extra_frag;
+ store->last_frag_rate = tx.last_frag_rate;
store->last_frag_rate_ctrl_probe =
- !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
+ !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
}
rcu_read_unlock();
return 0;
@@ -1228,10 +1228,10 @@ retry:
drop:
if (skb)
dev_kfree_skb(skb);
- for (i = 0; i < tx.u.tx.num_extra_frag; i++)
- if (tx.u.tx.extra_frag[i])
- dev_kfree_skb(tx.u.tx.extra_frag[i]);
- kfree(tx.u.tx.extra_frag);
+ for (i = 0; i < tx.num_extra_frag; i++)
+ if (tx.extra_frag[i])
+ dev_kfree_skb(tx.extra_frag[i]);
+ kfree(tx.extra_frag);
rcu_read_unlock();
return 0;
}
@@ -1621,7 +1621,7 @@ void ieee80211_tx_pending(unsigned long
struct ieee80211_local *local = (struct ieee80211_local *)data;
struct net_device *dev = local->mdev;
struct ieee80211_tx_stored_packet *store;
- struct ieee80211_txrx_data tx;
+ struct ieee80211_tx_data tx;
int i, ret, reschedule = 0;
netif_tx_lock_bh(dev);
@@ -1633,13 +1633,13 @@ void ieee80211_tx_pending(unsigned long
continue;
}
store = &local->pending_packet[i];
- tx.u.tx.control = &store->control;
- tx.u.tx.extra_frag = store->extra_frag;
- tx.u.tx.num_extra_frag = store->num_extra_frag;
- tx.u.tx.last_frag_rate = store->last_frag_rate;
+ tx.control = &store->control;
+ tx.extra_frag = store->extra_frag;
+ tx.num_extra_frag = store->num_extra_frag;
+ tx.last_frag_rate = store->last_frag_rate;
tx.flags = 0;
if (store->last_frag_rate_ctrl_probe)
- tx.flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+ tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
ret = __ieee80211_tx(local, store->skb, &tx);
if (ret) {
if (ret == IEEE80211_TX_FRAG_AGAIN)
@@ -1865,7 +1865,7 @@ ieee80211_get_buffered_bc(struct ieee802
struct sk_buff *skb;
struct sta_info *sta;
ieee80211_tx_handler *handler;
- struct ieee80211_txrx_data tx;
+ struct ieee80211_tx_data tx;
ieee80211_tx_result res = TX_DROP;
struct net_device *bdev;
struct ieee80211_sub_if_data *sdata;
@@ -1912,8 +1912,8 @@ ieee80211_get_buffered_bc(struct ieee802
dev_kfree_skb_any(skb);
}
sta = tx.sta;
- tx.flags |= IEEE80211_TXRXD_TXPS_BUFFERED;
- tx.u.tx.channel = local->hw.conf.channel;
+ tx.flags |= IEEE80211_TX_PS_BUFFERED;
+ tx.channel = local->hw.conf.channel;
for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
res = (*handler)(&tx);
--- everything.orig/net/mac80211/wep.c 2008-02-21 22:09:12.000000000 +0100
+++ everything/net/mac80211/wep.c 2008-02-21 22:09:32.000000000 +0100
@@ -306,14 +306,14 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_
}
ieee80211_rx_result
-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx)
+ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
{
if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
(rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
return RX_CONTINUE;
- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
+ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
@@ -322,7 +322,7 @@ ieee80211_crypto_wep_decrypt(struct ieee
#endif /* CONFIG_MAC80211_DEBUG */
return RX_DROP_UNUSABLE;
}
- } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
+ } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) {
ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
/* remove ICV */
skb_trim(rx->skb, rx->skb->len - 4);
@@ -331,13 +331,13 @@ ieee80211_crypto_wep_decrypt(struct ieee
return RX_CONTINUE;
}
-static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
+static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
return -1;
} else {
- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->key_idx = tx->key->conf.hw_key_idx;
if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
return -1;
@@ -347,21 +347,21 @@ static int wep_encrypt_skb(struct ieee80
}
ieee80211_tx_result
-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx)
+ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
{
- tx->u.tx.control->iv_len = WEP_IV_LEN;
- tx->u.tx.control->icv_len = WEP_ICV_LEN;
- ieee80211_tx_set_iswep(tx);
+ tx->control->iv_len = WEP_IV_LEN;
+ tx->control->icv_len = WEP_ICV_LEN;
+ ieee80211_tx_set_protected(tx);
if (wep_encrypt_skb(tx, tx->skb) < 0) {
I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
return TX_DROP;
}
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
int i;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
- if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
+ for (i = 0; i < tx->num_extra_frag; i++) {
+ if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) {
I802_DEBUG_INC(tx->local->
tx_handlers_drop_wep);
return TX_DROP;
--- everything.orig/net/mac80211/wep.h 2008-02-21 22:09:12.000000000 +0100
+++ everything/net/mac80211/wep.h 2008-02-21 22:09:32.000000000 +0100
@@ -29,8 +29,8 @@ int ieee80211_wep_decrypt(struct ieee802
u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
ieee80211_rx_result
-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx);
+ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
ieee80211_tx_result
-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx);
#endif /* WEP_H */
--- everything.orig/net/mac80211/wpa.c 2008-02-21 22:09:12.000000000 +0100
+++ everything/net/mac80211/wpa.c 2008-02-21 22:09:32.000000000 +0100
@@ -71,7 +71,7 @@ static int ieee80211_get_hdr_info(const
ieee80211_tx_result
-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
u8 *data, *sa, *da, *key, *mic, qos_tid;
size_t data_len;
@@ -90,7 +90,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
return TX_DROP;
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
- !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
+ !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
!wpa_test) {
/* hwaccel - with no need for preallocated room for Michael MIC
@@ -124,7 +124,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
ieee80211_rx_result
-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
{
u8 *data, *sa, *da, *key = NULL, qos_tid;
size_t data_len;
@@ -139,7 +139,7 @@ ieee80211_rx_h_michael_mic_verify(struct
/*
* No way to verify the MIC if the hardware stripped it
*/
- if (rx->u.rx.status->flag & RX_FLAG_MMIC_STRIPPED)
+ if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
return RX_CONTINUE;
if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
@@ -161,7 +161,7 @@ ieee80211_rx_h_michael_mic_verify(struct
ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_UNUSABLE;
printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
@@ -176,14 +176,14 @@ ieee80211_rx_h_michael_mic_verify(struct
skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
/* update IV in key information to be able to detect replays */
- rx->key->u.tkip.iv32_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv32;
- rx->key->u.tkip.iv16_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv16;
+ rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32;
+ rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16;
return RX_CONTINUE;
}
-static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
struct sk_buff *skb, int test)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -228,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee8
0x7f),
(u8) key->u.tkip.iv16);
- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->key_idx = tx->key->conf.hw_key_idx;
return 0;
}
@@ -243,30 +243,30 @@ static int tkip_encrypt_skb(struct ieee8
ieee80211_tx_result
-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx)
+ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
int wpa_test = 0, test = 0;
- tx->u.tx.control->icv_len = TKIP_ICV_LEN;
- tx->u.tx.control->iv_len = TKIP_IV_LEN;
- ieee80211_tx_set_iswep(tx);
+ tx->control->icv_len = TKIP_ICV_LEN;
+ tx->control->iv_len = TKIP_IV_LEN;
+ ieee80211_tx_set_protected(tx);
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
!wpa_test) {
/* hwaccel - with no need for preallocated room for IV/ICV */
- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->key_idx = tx->key->conf.hw_key_idx;
return TX_CONTINUE;
}
if (tkip_encrypt_skb(tx, skb, test) < 0)
return TX_DROP;
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
int i;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
- if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+ for (i = 0; i < tx->num_extra_frag; i++) {
+ if (tkip_encrypt_skb(tx, tx->extra_frag[i], test)
< 0)
return TX_DROP;
}
@@ -277,7 +277,7 @@ ieee80211_crypto_tkip_encrypt(struct iee
ieee80211_rx_result
-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
u16 fc;
@@ -295,8 +295,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
if (!rx->sta || skb->len - hdrlen < 12)
return RX_DROP_UNUSABLE;
- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) {
- if (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) {
+ if (rx->status->flag & RX_FLAG_DECRYPTED) {
+ if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
/*
* Hardware took care of all processing, including
* replay protection, and stripped the ICV/IV so
@@ -312,9 +312,9 @@ ieee80211_crypto_tkip_decrypt(struct iee
res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
key, skb->data + hdrlen,
skb->len - hdrlen, rx->sta->addr,
- hwaccel, rx->u.rx.queue,
- &rx->u.rx.tkip_iv32,
- &rx->u.rx.tkip_iv16);
+ hwaccel, rx->queue,
+ &rx->tkip_iv32,
+ &rx->tkip_iv16);
if (res != TKIP_DECRYPT_OK || wpa_test) {
#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
@@ -429,7 +429,7 @@ static inline int ccmp_hdr2pn(u8 *pn, u8
}
-static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
struct sk_buff *skb, int test)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -478,7 +478,7 @@ static int ccmp_encrypt_skb(struct ieee8
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
/* hwaccel - with preallocated room for CCMP header */
- tx->u.tx.control->key_idx = key->conf.hw_key_idx;
+ tx->control->key_idx = key->conf.hw_key_idx;
return 0;
}
@@ -492,30 +492,30 @@ static int ccmp_encrypt_skb(struct ieee8
ieee80211_tx_result
-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx)
+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
int test = 0;
- tx->u.tx.control->icv_len = CCMP_MIC_LEN;
- tx->u.tx.control->iv_len = CCMP_HDR_LEN;
- ieee80211_tx_set_iswep(tx);
+ tx->control->icv_len = CCMP_MIC_LEN;
+ tx->control->iv_len = CCMP_HDR_LEN;
+ ieee80211_tx_set_protected(tx);
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
/* hwaccel - with no need for preallocated room for CCMP "
* header or MIC fields */
- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+ tx->control->key_idx = tx->key->conf.hw_key_idx;
return TX_CONTINUE;
}
if (ccmp_encrypt_skb(tx, skb, test) < 0)
return TX_DROP;
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
int i;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
- if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+ for (i = 0; i < tx->num_extra_frag; i++) {
+ if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test)
< 0)
return TX_DROP;
}
@@ -526,7 +526,7 @@ ieee80211_crypto_ccmp_encrypt(struct iee
ieee80211_rx_result
-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
u16 fc;
@@ -547,15 +547,15 @@ ieee80211_crypto_ccmp_decrypt(struct iee
if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE;
- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
+ (rx->status->flag & RX_FLAG_IV_STRIPPED))
return RX_CONTINUE;
(void) ccmp_hdr2pn(pn, skb->data + hdrlen);
- if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
+ if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
#ifdef CONFIG_MAC80211_DEBUG
- u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
+ u8 *ppn = key->u.ccmp.rx_pn[rx->queue];
printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
"%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
@@ -568,7 +568,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
return RX_DROP_UNUSABLE;
}
- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
+ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
/* hardware didn't decrypt/verify MIC */
u8 *scratch, *b_0, *aad;
@@ -593,7 +593,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
}
}
- memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
+ memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
/* Remove CCMP header and MIC */
skb_trim(skb, skb->len - CCMP_MIC_LEN);
--- everything.orig/net/mac80211/wpa.h 2008-02-21 22:09:12.000000000 +0100
+++ everything/net/mac80211/wpa.h 2008-02-21 22:09:32.000000000 +0100
@@ -14,18 +14,18 @@
#include "ieee80211_i.h"
ieee80211_tx_result
-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
+ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx);
ieee80211_rx_result
-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx);
ieee80211_tx_result
-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx);
ieee80211_rx_result
-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx);
+ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
ieee80211_tx_result
-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
ieee80211_rx_result
-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx);
+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
#endif /* WPA_H */
--- everything.orig/net/mac80211/util.c 2008-02-21 22:09:27.000000000 +0100
+++ everything/net/mac80211/util.c 2008-02-21 22:09:41.000000000 +0100
@@ -146,17 +146,17 @@ int ieee80211_get_hdrlen_from_skb(const
}
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
+void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- if (tx->u.tx.extra_frag) {
+ if (tx->extra_frag) {
struct ieee80211_hdr *fhdr;
int i;
- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+ for (i = 0; i < tx->num_extra_frag; i++) {
fhdr = (struct ieee80211_hdr *)
- tx->u.tx.extra_frag[i]->data;
+ tx->extra_frag[i]->data;
fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
}
}
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 6/8] mac80211: split sta_info_add
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (4 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 5/8] mac80211: split ieee80211_txrx_data Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 7/8] mac80211: remove STA infos last_ack stuff Johannes Berg
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
sta_info_add() has two functions: allocating a station info
structure and inserting it into the hash table/list. Splitting
these two functions allows allocating with GFP_KERNEL in many
places instead of GFP_ATOMIC which is now required by the RCU
protection. Additionally, in many places RCU protection is now
no longer needed at all because between sta_info_alloc() and
sta_info_insert() the caller owns the structure.
This fixes a few race conditions with setting initial flags
and similar, but not all (see comments in ieee80211_sta.c and
cfg.c).
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 38 ++++++++++++++++-------
net/mac80211/ieee80211.c | 18 ++++++-----
net/mac80211/ieee80211_sta.c | 44 ++++++++++++++++++++-------
net/mac80211/sta_info.c | 69 +++++++++++++++++++++++++++++--------------
net/mac80211/sta_info.h | 17 +++++++---
5 files changed, 129 insertions(+), 57 deletions(-)
--- everything.orig/net/mac80211/sta_info.c 2008-02-22 11:53:23.000000000 +0100
+++ everything/net/mac80211/sta_info.c 2008-02-22 11:54:34.000000000 +0100
@@ -29,12 +29,13 @@
* for faster lookup and a list for iteration. They are managed using
* RCU, i.e. access to the list and hash table is protected by RCU.
*
- * STA info structures are always "alive" when they are added with
- * @sta_info_add() [this may be changed in the future to allow allocating
- * outside of a critical section!], they are then added to the hash
- * table and list. Therefore, @sta_info_add() must also be RCU protected,
- * also, the caller of @sta_info_add() cannot assume that it owns the
- * structure.
+ * Upon allocating a STA info structure with @sta_info_alloc(), the
+ * caller owns that structure. It must then either destroy it using
+ * @sta_info_destroy() (which is pretty useless) or insert it into
+ * the hash table using @sta_info_insert() which demotes the reference
+ * from ownership to a regular RCU-protected reference, if the function
+ * is called without protection by an RCU critical section the reference
+ * is instantly invalidated.
*
* Because there are debugfs entries for each station, and adding those
* must be able to sleep, it is also possible to "pin" a station entry,
@@ -112,6 +113,10 @@ void sta_info_destroy(struct sta_info *s
struct ieee80211_local *local = sta->local;
struct sk_buff *skb;
int i;
+ DECLARE_MAC_BUF(mbuf);
+
+ if (!sta)
+ return;
ieee80211_key_free(sta->key);
sta->key = NULL;
@@ -134,6 +139,11 @@ void sta_info_destroy(struct sta_info *s
rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
rate_control_put(sta->rate_ctrl);
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Destroyed STA %s\n",
+ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
kfree(sta);
}
@@ -146,18 +156,17 @@ static void sta_info_hash_add(struct iee
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
}
-struct sta_info *sta_info_add(struct ieee80211_sub_if_data *sdata,
- u8 *addr)
+struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
+ u8 *addr, gfp_t gfp)
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int i;
- DECLARE_MAC_BUF(mac);
- unsigned long flags;
+ DECLARE_MAC_BUF(mbuf);
- sta = kzalloc(sizeof(*sta), GFP_ATOMIC);
+ sta = kzalloc(sizeof(*sta), gfp);
if (!sta)
- return ERR_PTR(-ENOMEM);
+ return NULL;
memcpy(sta->addr, addr, ETH_ALEN);
sta->local = local;
@@ -165,11 +174,11 @@ struct sta_info *sta_info_add(struct iee
sta->rate_ctrl = rate_control_get(local->rate_ctrl);
sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
- GFP_ATOMIC);
+ gfp);
if (!sta->rate_ctrl_priv) {
rate_control_put(sta->rate_ctrl);
kfree(sta);
- return ERR_PTR(-ENOMEM);
+ return NULL;
}
spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
@@ -196,11 +205,27 @@ struct sta_info *sta_info_add(struct iee
}
skb_queue_head_init(&sta->ps_tx_buf);
skb_queue_head_init(&sta->tx_filtered);
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ printk(KERN_DEBUG "%s: Allocated STA %s\n",
+ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+ return sta;
+}
+
+int sta_info_insert(struct sta_info *sta)
+{
+ struct ieee80211_local *local = sta->local;
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
- if (__sta_info_find(local, addr)) {
+ if (__sta_info_find(local, sta->addr)) {
spin_unlock_irqrestore(&local->sta_lock, flags);
- return ERR_PTR(-EEXIST);
+ return -EEXIST;
}
list_add(&sta->list, &local->sta_list);
local->num_sta++;
@@ -212,16 +237,16 @@ struct sta_info *sta_info_add(struct iee
sdata = sdata->u.vlan.ap;
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
- STA_NOTIFY_ADD, addr);
+ STA_NOTIFY_ADD, sta->addr);
}
- spin_unlock_irqrestore(&local->sta_lock, flags);
-
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- printk(KERN_DEBUG "%s: Added STA %s\n",
- wiphy_name(local->hw.wiphy), print_mac(mac, addr));
+ printk(KERN_DEBUG "%s: Inserted STA %s\n",
+ wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ spin_unlock_irqrestore(&local->sta_lock, flags);
+
#ifdef CONFIG_MAC80211_DEBUGFS
/* debugfs entry adding might sleep, so schedule process
* context task for adding entry for STAs that do not yet
@@ -229,7 +254,7 @@ struct sta_info *sta_info_add(struct iee
queue_work(local->hw.workqueue, &local->sta_debugfs_add);
#endif
- return sta;
+ return 0;
}
static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
--- everything.orig/net/mac80211/sta_info.h 2008-02-22 11:53:23.000000000 +0100
+++ everything/net/mac80211/sta_info.h 2008-02-22 11:54:34.000000000 +0100
@@ -248,12 +248,19 @@ struct sta_info {
*/
struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
/*
- * Add a new STA info, must be under RCU read lock
- * because otherwise the returned reference isn't
- * necessarily valid long enough.
+ * Create a new STA info, caller owns returned structure
+ * until sta_info_insert().
*/
-struct sta_info *sta_info_add(struct ieee80211_sub_if_data *sdata,
- u8 *addr);
+struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
+ u8 *addr, gfp_t gfp);
+/*
+ * Insert STA info into hash table/list, returns zero or a
+ * -EEXIST if (if the same MAC address is already present).
+ *
+ * Calling this without RCU protection makes the caller
+ * relinquish its reference to @sta.
+ */
+int sta_info_insert(struct sta_info *sta);
/*
* Unlink a STA info from the hash table/list.
* This can NULL the STA pointer if somebody else
--- everything.orig/net/mac80211/cfg.c 2008-02-22 11:53:23.000000000 +0100
+++ everything/net/mac80211/cfg.c 2008-02-22 12:03:23.000000000 +0100
@@ -533,6 +533,12 @@ static void sta_apply_parameters(struct
int i, j;
struct ieee80211_supported_band *sband;
+ /*
+ * FIXME: updating the flags is racy when this function is
+ * called from ieee80211_change_station(), this will
+ * be resolved in a future patch.
+ */
+
if (params->station_flags & STATION_FLAG_CHANGED) {
sta->flags &= ~WLAN_STA_AUTHORIZED;
if (params->station_flags & STATION_FLAG_AUTHORIZED)
@@ -547,6 +553,13 @@ static void sta_apply_parameters(struct
sta->flags |= WLAN_STA_WME;
}
+ /*
+ * FIXME: updating the following information is racy when this
+ * function is called from ieee80211_change_station().
+ * However, all this information should be static so
+ * maybe we should just reject attemps to change it.
+ */
+
if (params->aid) {
sta->aid = params->aid;
if (sta->aid > IEEE80211_MAX_AID)
@@ -577,6 +590,7 @@ static int ieee80211_add_station(struct
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
+ int err;
/* Prevent a race with changing the rate control algorithm */
if (!netif_running(dev))
@@ -591,17 +605,9 @@ static int ieee80211_add_station(struct
} else
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- rcu_read_lock();
-
- sta = sta_info_add(sdata, mac);
- if (IS_ERR(sta)) {
- rcu_read_unlock();
- return PTR_ERR(sta);
- }
-
- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
- sdata->vif.type == IEEE80211_IF_TYPE_AP)
- ieee80211_send_layer2_update(sta);
+ sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
+ if (!sta)
+ return -ENOMEM;
sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
@@ -609,7 +615,15 @@ static int ieee80211_add_station(struct
rate_control_rate_init(sta, local);
- rcu_read_unlock();
+ err = sta_info_insert(sta);
+ if (err) {
+ sta_info_destroy(sta);
+ return err;
+ }
+
+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
+ sdata->vif.type == IEEE80211_IF_TYPE_AP)
+ ieee80211_send_layer2_update(sta);
return 0;
}
--- everything.orig/net/mac80211/ieee80211.c 2008-02-22 11:53:23.000000000 +0100
+++ everything/net/mac80211/ieee80211.c 2008-02-22 11:54:34.000000000 +0100
@@ -888,6 +888,7 @@ int ieee80211_if_update_wds(struct net_d
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
+ int err;
DECLARE_MAC_BUF(mac);
might_sleep();
@@ -895,16 +896,19 @@ int ieee80211_if_update_wds(struct net_d
if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
return 0;
- rcu_read_lock();
-
/* Create STA entry for the new peer */
- sta = sta_info_add(sdata, remote_addr);
- if (IS_ERR(sta)) {
- rcu_read_unlock();
- return PTR_ERR(sta);
- }
+ sta = sta_info_alloc(sdata, remote_addr, GFP_KERNEL);
+ if (!sta)
+ return -ENOMEM;
sta->flags |= WLAN_STA_AUTHORIZED;
+ err = sta_info_insert(sta);
+ if (err) {
+ sta_info_destroy(sta);
+ return err;
+ }
+
+ rcu_read_lock();
/* Remove STA entry for the old peer */
sta = sta_info_get(local, sdata->u.wds.remote_addr);
--- everything.orig/net/mac80211/ieee80211_sta.c 2008-02-22 11:53:23.000000000 +0100
+++ everything/net/mac80211/ieee80211_sta.c 2008-02-22 11:56:41.000000000 +0100
@@ -1461,7 +1461,7 @@ void sta_addba_resp_timer_expired(unsign
{
/* not an elegant detour, but there is no choice as the timer passes
* only one argument, and both sta_info and TID are needed, so init
- * flow in sta_info_add gives the TID as data, while the timer_to_id
+ * flow in sta_info_create gives the TID as data, while the timer_to_id
* array gives the sta through container_of */
u16 tid = *(int *)data;
struct sta_info *temp_sta = container_of((void *)data,
@@ -1512,7 +1512,7 @@ void sta_rx_agg_session_timer_expired(un
{
/* not an elegant detour, but there is no choice as the timer passes
* only one argument, and verious sta_info are needed here, so init
- * flow in sta_info_add gives the TID as data, while the timer_to_id
+ * flow in sta_info_create gives the TID as data, while the timer_to_id
* array gives the sta through container_of */
u8 *ptid = (u8 *)data;
u8 *timer_to_id = ptid - *ptid;
@@ -1836,11 +1836,12 @@ static void ieee80211_rx_mgmt_assoc_resp
sta = sta_info_get(local, ifsta->bssid);
if (!sta) {
struct ieee80211_sta_bss *bss;
+ int err;
- sta = sta_info_add(sdata, ifsta->bssid);
- if (IS_ERR(sta)) {
- printk(KERN_DEBUG "%s: failed to add STA entry for the"
- " AP (error %ld)\n", dev->name, PTR_ERR(sta));
+ sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
+ if (!sta) {
+ printk(KERN_DEBUG "%s: failed to alloc STA entry for"
+ " the AP\n", dev->name);
rcu_read_unlock();
return;
}
@@ -1853,8 +1854,27 @@ static void ieee80211_rx_mgmt_assoc_resp
sta->last_noise = bss->noise;
ieee80211_rx_bss_put(dev, bss);
}
+
+ err = sta_info_insert(sta);
+ if (err) {
+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
+ " the AP (error %d)\n", dev->name, err);
+ sta_info_destroy(sta);
+ rcu_read_unlock();
+ return;
+ }
}
+ /*
+ * FIXME: Do we really need to update the sta_info's information here?
+ * We already know about the AP (we found it in our list) so it
+ * should already be filled with the right info, no?
+ * As is stands, all this is racy because typically we assume
+ * the information that is filled in here (except flags) doesn't
+ * change while a STA structure is alive. As such, it should move
+ * to between the sta_info_alloc() and sta_info_insert() above.
+ */
+
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
WLAN_STA_AUTHORIZED;
@@ -2494,10 +2514,8 @@ static void ieee80211_rx_bss_info(struct
"local TSF - IBSS merge with BSSID %s\n",
dev->name, print_mac(mac, mgmt->bssid));
ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
- rcu_read_lock();
ieee80211_ibss_add_sta(dev, NULL,
mgmt->bssid, mgmt->sa);
- rcu_read_unlock();
}
}
@@ -3837,7 +3855,6 @@ int ieee80211_sta_set_extra_ie(struct ne
}
-/* must be called under RCU read lock */
struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
struct sk_buff *skb, u8 *bssid,
u8 *addr)
@@ -3860,8 +3877,8 @@ struct sta_info * ieee80211_ibss_add_sta
printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
- sta = sta_info_add(sdata, addr);
- if (IS_ERR(sta))
+ sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
+ if (!sta)
return NULL;
sta->flags |= WLAN_STA_AUTHORIZED;
@@ -3871,6 +3888,11 @@ struct sta_info * ieee80211_ibss_add_sta
rate_control_rate_init(sta, local);
+ if (sta_info_insert(sta)) {
+ sta_info_destroy(sta);
+ return NULL;
+ }
+
return sta;
}
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 7/8] mac80211: remove STA infos last_ack stuff
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (5 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 6/8] mac80211: split sta_info_add Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 11:16 ` [PATCH 8/8] mac80211: clean up sta_info and document locking Johannes Berg
2008-02-22 21:41 ` [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
These things aren't used and the only possible use is within
rate control algorithms, however those can, if they need it,
keep track of it in their private data. last_ack_ms isn't
even updated so completely useless.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/debugfs_sta.c | 29 -----------------------------
net/mac80211/rc80211_pid_algo.c | 3 ---
net/mac80211/rc80211_simple.c | 3 ---
net/mac80211/sta_info.h | 4 ----
4 files changed, 39 deletions(-)
--- everything.orig/net/mac80211/sta_info.h 2008-02-22 09:56:08.000000000 +0100
+++ everything/net/mac80211/sta_info.h 2008-02-22 09:57:17.000000000 +0100
@@ -182,8 +182,6 @@ struct sta_info {
int last_rssi; /* RSSI of last received frame from this STA */
int last_signal; /* signal of last received frame from this STA */
int last_noise; /* noise of last received frame from this STA */
- int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
- unsigned long last_ack;
int channel_use;
int channel_use_raw;
@@ -211,8 +209,6 @@ struct sta_info {
struct dentry *dir;
struct dentry *flags;
struct dentry *num_ps_buf_frames;
- struct dentry *last_ack_rssi;
- struct dentry *last_ack_ms;
struct dentry *inactive_ms;
struct dentry *last_seq_ctrl;
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
--- everything.orig/net/mac80211/debugfs_sta.c 2008-02-22 09:58:02.000000000 +0100
+++ everything/net/mac80211/debugfs_sta.c 2008-02-22 09:58:12.000000000 +0100
@@ -98,31 +98,6 @@ static ssize_t sta_num_ps_buf_frames_rea
}
STA_OPS(num_ps_buf_frames);
-static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- char buf[100];
- struct sta_info *sta = file->private_data;
- int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
- sta->last_ack_rssi[0],
- sta->last_ack_rssi[1],
- sta->last_ack_rssi[2]);
- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
-}
-STA_OPS(last_ack_rssi);
-
-static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- char buf[20];
- struct sta_info *sta = file->private_data;
- int res = scnprintf(buf, sizeof(buf), "%d\n",
- sta->last_ack ?
- jiffies_to_msecs(jiffies - sta->last_ack) : -1);
- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
-}
-STA_OPS(last_ack_ms);
-
static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -311,8 +286,6 @@ void ieee80211_sta_debugfs_add(struct st
DEBUGFS_ADD(flags);
DEBUGFS_ADD(num_ps_buf_frames);
- DEBUGFS_ADD(last_ack_rssi);
- DEBUGFS_ADD(last_ack_ms);
DEBUGFS_ADD(inactive_ms);
DEBUGFS_ADD(last_seq_ctrl);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
@@ -326,8 +299,6 @@ void ieee80211_sta_debugfs_remove(struct
{
DEBUGFS_DEL(flags);
DEBUGFS_DEL(num_ps_buf_frames);
- DEBUGFS_DEL(last_ack_rssi);
- DEBUGFS_DEL(last_ack_ms);
DEBUGFS_DEL(inactive_ms);
DEBUGFS_DEL(last_seq_ctrl);
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
--- everything.orig/net/mac80211/rc80211_pid_algo.c 2008-02-22 09:56:46.000000000 +0100
+++ everything/net/mac80211/rc80211_pid_algo.c 2008-02-22 09:56:52.000000000 +0100
@@ -282,9 +282,6 @@ static void rate_control_pid_tx_status(v
sta->tx_num_consecutive_failures++;
sta->tx_num_mpdu_fail++;
} else {
- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
- sta->last_ack_rssi[2] = status->ack_signal;
sta->tx_num_consecutive_failures = 0;
sta->tx_num_mpdu_ok++;
}
--- everything.orig/net/mac80211/rc80211_simple.c 2008-02-22 09:58:29.000000000 +0100
+++ everything/net/mac80211/rc80211_simple.c 2008-02-22 09:59:32.000000000 +0100
@@ -133,9 +133,6 @@ static void rate_control_simple_tx_statu
sta->tx_num_consecutive_failures++;
sta->tx_num_mpdu_fail++;
} else {
- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
- sta->last_ack_rssi[2] = status->ack_signal;
sta->tx_num_consecutive_failures = 0;
sta->tx_num_mpdu_ok++;
}
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 8/8] mac80211: clean up sta_info and document locking
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (6 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 7/8] mac80211: remove STA infos last_ack stuff Johannes Berg
@ 2008-02-22 11:16 ` Johannes Berg
2008-02-22 21:41 ` [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 11:16 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
This patch cleans up the sta_info struct and documents how
each set of variables is locked. Notably, flags locking is
completely missing. It also adds kernel-doc for some (but
not all yet) members of the struct.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/debugfs_sta.c | 2
net/mac80211/sta_info.h | 125 +++++++++++++++++++++++++++------------------
2 files changed, 76 insertions(+), 51 deletions(-)
--- everything.orig/net/mac80211/sta_info.h 2008-02-22 12:03:55.000000000 +0100
+++ everything/net/mac80211/sta_info.h 2008-02-22 12:04:11.000000000 +0100
@@ -129,79 +129,104 @@ struct sta_ampdu_mlme {
#define STA_INFO_PIN_STAT_PINNED 1
#define STA_INFO_PIN_STAT_DESTROY 2
-
+/**
+ * struct sta_info - STA information
+ *
+ * This structure collects information about a station that
+ * mac80211 is communicating with.
+ *
+ * @list: global linked list entry
+ * @hnext: hash table linked list pointer
+ * @local: pointer to the global information
+ * @addr: MAC address of this STA
+ * @aid: STA's unique AID (1..2007, 0 = not assigned yet),
+ * only used in AP (and IBSS?) mode
+ * @flags: STA flags, see &enum ieee80211_sta_info_flags
+ * @ps_tx_buf: buffer of frames to transmit to this station
+ * when it leaves power saving state
+ * @tx_filtered: buffer of frames we already tried to transmit
+ * but were filtered by hardware due to STA having entered
+ * power saving state
+ * @rx_packets: Number of MSDUs received from this STA
+ * @rx_bytes: Number of bytes received from this STA
+ * @supp_rates: Bitmap of supported rates (per band)
+ * @ht_info: HT capabilities of this STA
+ */
struct sta_info {
+ /* General information, mostly static */
struct list_head list;
- struct sta_info *hnext; /* next entry in hash table list */
-
+ struct sta_info *hnext;
struct ieee80211_local *local;
-
- u8 addr[ETH_ALEN];
- u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
- u32 flags; /* WLAN_STA_ */
-
- struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
- * power saving state */
- struct sk_buff_head tx_filtered; /* buffer of TX frames that were
- * already given to low-level driver,
- * but were filtered */
- unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
- unsigned long rx_bytes, tx_bytes;
- unsigned long tx_retry_failed, tx_retry_count;
- unsigned long tx_filtered_count;
-
- unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
-
- unsigned long last_rx;
- /* bitmap of supported rates per band */
- u64 supp_rates[IEEE80211_NUM_BANDS];
- int txrate_idx;
- /* last rates used to send a frame to this STA */
- int last_txrate_idx, last_nonerp_txrate_idx;
-
- /* sub_if_data this sta belongs to */
struct ieee80211_sub_if_data *sdata;
-
struct ieee80211_key *key;
-
- u32 tx_num_consecutive_failures;
- u32 tx_num_mpdu_ok;
- u32 tx_num_mpdu_fail;
-
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
+ struct ieee80211_ht_info ht_info;
+ u64 supp_rates[IEEE80211_NUM_BANDS];
+ u8 addr[ETH_ALEN];
+ u16 aid;
+ u16 listen_interval;
- /* last received seq/frag number from this STA (per RX queue) */
- __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+ /*
+ * for use by the internal lifetime management,
+ * see __sta_info_unlink
+ */
+ u8 pin_status;
+
+ /* frequently updated information, needs locking? */
+ u32 flags;
+
+ /*
+ * STA powersave frame queues, no more than the internal
+ * locking required.
+ */
+ struct sk_buff_head ps_tx_buf;
+ struct sk_buff_head tx_filtered;
+
+ /* Updated from RX path only, no locking requirements */
+ unsigned long rx_packets, rx_bytes;
+ unsigned long wep_weak_iv_count;
+ unsigned long last_rx;
unsigned long num_duplicates; /* number of duplicate frames received
* from this STA */
- unsigned long tx_fragments; /* number of transmitted MPDUs */
unsigned long rx_fragments; /* number of received MPDUs */
unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
-
int last_rssi; /* RSSI of last received frame from this STA */
int last_signal; /* signal of last received frame from this STA */
int last_noise; /* noise of last received frame from this STA */
- int channel_use;
- int channel_use_raw;
-
+ /* last received seq/frag number from this STA (per RX queue) */
+ __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
+#endif
+
+ /* Updated from TX status path only, no locking requirements */
+ unsigned long tx_filtered_count;
+ unsigned long tx_retry_failed, tx_retry_count;
+ /* TODO: update in generic code not rate control */
+ u32 tx_num_consecutive_failures;
+ u32 tx_num_mpdu_ok;
+ u32 tx_num_mpdu_fail;
+
+ /* Updated from TX path only, no locking requirements */
+ unsigned long tx_packets; /* number of RX/TX MSDUs */
+ unsigned long tx_bytes;
+ unsigned long tx_fragments; /* number of transmitted MPDUs */
+ int txrate_idx;
+ int last_txrate_idx;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
-#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+#endif
- u16 listen_interval;
+ /* Debug counters, no locking doesn't matter */
+ int channel_use;
+ int channel_use_raw;
/*
- * for use by the internal lifetime management,
- * see __sta_info_unlink
+ * Aggregation information, comes with own locking.
*/
- u8 pin_status;
-
- struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
- of this STA */
struct sta_ampdu_mlme ampdu_mlme;
- u8 timer_to_tid[STA_TID_NUM]; /* convert timer id to tid */
+ u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */
#ifdef CONFIG_MAC80211_DEBUGFS
--- everything.orig/net/mac80211/debugfs_sta.c 2008-02-22 12:03:55.000000000 +0100
+++ everything/net/mac80211/debugfs_sta.c 2008-02-22 12:04:11.000000000 +0100
@@ -67,7 +67,7 @@ STA_FILE(last_rssi, last_rssi, D);
STA_FILE(last_signal, last_signal, D);
STA_FILE(last_noise, last_noise, D);
STA_FILE(channel_use, channel_use, D);
-STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
+STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
--
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/8] mac80211 sta info and related changes
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
` (7 preceding siblings ...)
2008-02-22 11:16 ` [PATCH 8/8] mac80211: clean up sta_info and document locking Johannes Berg
@ 2008-02-22 21:41 ` Johannes Berg
8 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2008-02-22 21:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Ron Rindjunsky
[-- Attachment #1: Type: text/plain, Size: 358 bytes --]
> * split ieee80211_key_alloc
> Preparation for RCU-ifying STA info, split key allocation into
> allocation and insertion
>
> * RCU-ify STA info structure access
> Remove STA refcount and instead protect them by RCU
This made key.c spew warnings, sorry, I'm fixing it now. I'll also
rebase this on top of the 11s patches.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 4/8] mac80211: RCU-ify STA info structure access
2008-02-22 11:16 ` [PATCH 4/8] mac80211: RCU-ify STA info structure access Johannes Berg
@ 2008-03-05 1:57 ` Chatre, Reinette
2008-03-05 9:23 ` Johannes Berg
0 siblings, 1 reply; 13+ messages in thread
From: Chatre, Reinette @ 2008-03-05 1:57 UTC (permalink / raw)
To: Johannes Berg, John Linville, Winkler, Tomas
Cc: linux-wireless, Rindjunsky, Ron
On , Johannes Berg wrote:
> This makes access to the STA hash table/list use RCU to protect
> against freeing of items. However, it's not a true RCU, the
> copy step is missing: whenever somebody changes a STA item it
> is simply updated. That will be addressed by a later change.
>
This patch is causing some problems in the iwlwifi driver. Often when
one of these RCU locks are held the driver tries to send a command to
the device and waits for the response, or it does some other activity
requiring sleeping. This causes numerous BUG messages as seen below:
BUG: sleeping function called from invalid context at
/home/rchatre/wifi/repos.git/iwlwifi-2.6/kernel/mutex.c:209
in_atomic():1, irqs_disabled():0
3 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c0118a4d>] __might_sleep+0xc2/0xc9
[<c02ab3f3>] mutex_lock_nested+0x1d/0x231
[<c01300d8>] ? sys_timer_settime+0x2a/0x225
[<c02acae9>] ? _spin_unlock_irqrestore+0x38/0x58
[<dca8e637>] iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
BUG: scheduling while atomic: iwl3945/3831/0x00000002
4 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
#3: (&priv->mutex){--..}, at: [<dca8e637>]
iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c011af81>] __schedule_bug+0x59/0x60
[<c02aa617>] schedule+0x91/0x5f7
[<c013b2dc>] ? mark_held_locks+0x4e/0x66
[<c02ab50b>] ? mutex_lock_nested+0x135/0x231
[<c02ab520>] mutex_lock_nested+0x14a/0x231
[<dca8e637>] ? iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
[<dca8e637>] iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
BUG: scheduling while atomic: iwl3945/3831/0x00000002
4 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
#3: (&priv->mutex){--..}, at: [<dca8e637>]
iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c011af81>] __schedule_bug+0x59/0x60
[<c02aa617>] schedule+0x91/0x5f7
[<c02acaf3>] ? _spin_unlock_irqrestore+0x42/0x58
[<c0127b22>] ? __mod_timer+0xa5/0xb0
[<c02aad57>] schedule_timeout+0x6d/0x8b
[<c0127703>] ? process_timeout+0x0/0xa
[<c02aad52>] ? schedule_timeout+0x68/0x8b
[<dca86643>] iwl3945_send_cmd_sync+0x5e9/0x1180 [iwl3945]
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<dca87302>] iwl3945_send_cmd_pdu+0x2f/0x37 [iwl3945]
[<dca875c7>] iwl3945_activate_qos+0xce/0xd7 [iwl3945]
[<dca8e661>] iwl3945_mac_conf_tx+0x1da/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
BUG: scheduling while atomic: iwl3945/3831/0x00000002
4 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
#3: (&priv->mutex){--..}, at: [<dca8e637>]
iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c011af81>] __schedule_bug+0x59/0x60
[<c02aa617>] schedule+0x91/0x5f7
[<c02acaf3>] ? _spin_unlock_irqrestore+0x42/0x58
[<c0127b22>] ? __mod_timer+0xa5/0xb0
[<c02aad57>] schedule_timeout+0x6d/0x8b
[<c0127703>] ? process_timeout+0x0/0xa
[<c02aad52>] ? schedule_timeout+0x68/0x8b
[<dca86643>] iwl3945_send_cmd_sync+0x5e9/0x1180 [iwl3945]
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<dca87302>] iwl3945_send_cmd_pdu+0x2f/0x37 [iwl3945]
[<dca875c7>] iwl3945_activate_qos+0xce/0xd7 [iwl3945]
[<dca8e661>] iwl3945_mac_conf_tx+0x1da/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
BUG: scheduling while atomic: iwl3945/3831/0x00000002
4 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
#3: (&priv->mutex){--..}, at: [<dca8e637>]
iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c011af81>] __schedule_bug+0x59/0x60
[<c02aa617>] schedule+0x91/0x5f7
[<c02acaf3>] ? _spin_unlock_irqrestore+0x42/0x58
[<c0127b22>] ? __mod_timer+0xa5/0xb0
[<c02aad57>] schedule_timeout+0x6d/0x8b
[<c0127703>] ? process_timeout+0x0/0xa
[<c02aad52>] ? schedule_timeout+0x68/0x8b
[<dca86643>] iwl3945_send_cmd_sync+0x5e9/0x1180 [iwl3945]
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<dca87302>] iwl3945_send_cmd_pdu+0x2f/0x37 [iwl3945]
[<dca875c7>] iwl3945_activate_qos+0xce/0xd7 [iwl3945]
[<dca8e661>] iwl3945_mac_conf_tx+0x1da/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
BUG: scheduling while atomic: iwl3945/3831/0x00000002
4 locks held by iwl3945/3831:
#0: ((name)){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#1: (&ifsta->work){--..}, at: [<c012d841>] run_workqueue+0x80/0x18b
#2: (rcu_read_lock){..--}, at: [<dc9d558d>]
ieee80211_rx_mgmt_assoc_resp+0x273/0x773 [mac80211]
#3: (&priv->mutex){--..}, at: [<dca8e637>]
iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
Pid: 3831, comm: iwl3945 Not tainted 2.6.25-rc3-wl #7
[<c011af81>] __schedule_bug+0x59/0x60
[<c02aa617>] schedule+0x91/0x5f7
[<c02acaf3>] ? _spin_unlock_irqrestore+0x42/0x58
[<c0127b22>] ? __mod_timer+0xa5/0xb0
[<c02aad57>] schedule_timeout+0x6d/0x8b
[<c0127703>] ? process_timeout+0x0/0xa
[<c02aad52>] ? schedule_timeout+0x68/0x8b
[<dca86643>] iwl3945_send_cmd_sync+0x5e9/0x1180 [iwl3945]
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<dca87302>] iwl3945_send_cmd_pdu+0x2f/0x37 [iwl3945]
[<dca875c7>] iwl3945_activate_qos+0xce/0xd7 [iwl3945]
[<dca8e661>] iwl3945_mac_conf_tx+0x1da/0x234 [iwl3945]
[<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
[<dc9d5a19>] ieee80211_rx_mgmt_assoc_resp+0x6ff/0x773 [mac80211]
[<c01662b7>] ? cache_flusharray+0xdf/0xf2
[<c013c360>] ? __lock_acquire+0xb0c/0xb39
[<dc9d70ab>] ieee80211_sta_work+0x726/0xfde [mac80211]
[<c013c371>] ? __lock_acquire+0xb1d/0xb39
[<c012d841>] ? run_workqueue+0x80/0x18b
[<c012d87c>] run_workqueue+0xbb/0x18b
[<c012d841>] ? run_workqueue+0x80/0x18b
[<dc9d6985>] ? ieee80211_sta_work+0x0/0xfde [mac80211]
[<c012e21f>] worker_thread+0xb6/0xc2
[<c013076e>] ? autoremove_wake_function+0x0/0x30
[<c012e169>] ? worker_thread+0x0/0xc2
[<c01306b0>] kthread+0x3b/0x63
[<c0130675>] ? kthread+0x0/0x63
[<c01057af>] kernel_thread_helper+0x7/0x10
=======================
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 4/8] mac80211: RCU-ify STA info structure access
2008-03-05 1:57 ` Chatre, Reinette
@ 2008-03-05 9:23 ` Johannes Berg
2008-03-05 19:25 ` Chatre, Reinette
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2008-03-05 9:23 UTC (permalink / raw)
To: Chatre, Reinette
Cc: John Linville, Winkler, Tomas, linux-wireless, Rindjunsky, Ron
> This patch is causing some problems in the iwlwifi driver. Often when
> one of these RCU locks are held the driver tries to send a command to
> the device and waits for the response, or it does some other activity
> requiring sleeping. This causes numerous BUG messages as seen below:
>
> BUG: sleeping function called from invalid context at
> /home/rchatre/wifi/repos.git/iwlwifi-2.6/kernel/mutex.c:209
> [<dca8e637>] iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
> [<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
Ouch, sorry. Try this patch please.
johannes
---
net/mac80211/ieee80211_sta.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- everything.orig/net/mac80211/ieee80211_sta.c 2008-03-05 10:17:37.000000000 +0100
+++ everything/net/mac80211/ieee80211_sta.c 2008-03-05 10:18:12.000000000 +0100
@@ -1930,16 +1930,16 @@ static void ieee80211_rx_mgmt_assoc_resp
if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
sta->flags |= WLAN_STA_WME;
+ rcu_read_unlock();
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
- }
+ } else
+ rcu_read_unlock();
/* set AID, ieee80211_set_associated() will tell the driver */
bss_conf->aid = aid;
ieee80211_set_associated(dev, ifsta, 1);
- rcu_read_unlock();
-
ieee80211_associated(dev, ifsta);
}
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 4/8] mac80211: RCU-ify STA info structure access
2008-03-05 9:23 ` Johannes Berg
@ 2008-03-05 19:25 ` Chatre, Reinette
0 siblings, 0 replies; 13+ messages in thread
From: Chatre, Reinette @ 2008-03-05 19:25 UTC (permalink / raw)
To: Johannes Berg
Cc: John Linville, Winkler, Tomas, linux-wireless, Rindjunsky, Ron
On Wednesday, March 05, 2008 1:23 AM, Johannes Berg wrote:
>> This patch is causing some problems in the iwlwifi driver. Often when
>> one of these RCU locks are held the driver tries to send a command to
>> the device and waits for the response, or it does some other activity
>> requiring sleeping. This causes numerous BUG messages as seen below:
>>
>> BUG: sleeping function called from invalid context at
>> /home/rchatre/wifi/repos.git/iwlwifi-2.6/kernel/mutex.c:209
>
>
>> [<dca8e637>] iwl3945_mac_conf_tx+0x1b0/0x234 [iwl3945]
>> [<dc9d186a>] ieee80211_sta_wmm_params+0x165/0x195 [mac80211]
>
> Ouch, sorry. Try this patch please.
This patch made those BUG messages disappear. Thank you very much.
Tested-by: Reinette Chatre <reinette.chatre@intel.com>
Reinette
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-03-05 19:35 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-22 11:16 [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
2008-02-22 11:16 ` [PATCH 1/8] mac80211: clarify use of TX status/RX callbacks Johannes Berg
2008-02-22 11:16 ` [PATCH 2/8] mac80211: safely free beacon in ieee80211_if_reinit Johannes Berg
2008-02-22 11:16 ` [PATCH 3/8] mac80211: split ieee80211_key_alloc Johannes Berg
2008-02-22 11:16 ` [PATCH 4/8] mac80211: RCU-ify STA info structure access Johannes Berg
2008-03-05 1:57 ` Chatre, Reinette
2008-03-05 9:23 ` Johannes Berg
2008-03-05 19:25 ` Chatre, Reinette
2008-02-22 11:16 ` [PATCH 5/8] mac80211: split ieee80211_txrx_data Johannes Berg
2008-02-22 11:16 ` [PATCH 6/8] mac80211: split sta_info_add Johannes Berg
2008-02-22 11:16 ` [PATCH 7/8] mac80211: remove STA infos last_ack stuff Johannes Berg
2008-02-22 11:16 ` [PATCH 8/8] mac80211: clean up sta_info and document locking Johannes Berg
2008-02-22 21:41 ` [PATCH 0/8] mac80211 sta info and related changes Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).