diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-05-02 19:02:02 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-14 16:29:34 -0400 |
commit | 07346f81e87d6e4cca7ae9adfa711d0c61c87b56 (patch) | |
tree | 237450c49843e0e19afc79356240a891da64d9fa /net/mac80211 | |
parent | 3434fbd39862d471c92b66c28cd449deea8e9f90 (diff) |
mac80211: proper STA info locking
As discussed earlier, we can unify locking in struct sta_info
and use just a single spinlock protecting all members of the
structure that need protection. Many don't, but one of the
especially bad ones is the 'flags' member that can currently
be clobbered when RX and TX is being processed on different
CPUs at the same time.
Because having four spinlocks for different, mostly exclusive
parts of a single structure is overkill, this patch also kills
the ampdu and mesh plink spinlocks and uses just a single one
for everything. Because none of the spinlocks are nested, this
is safe.
It remains to be seen whether or not we should make the sta
flags use atomic bit operations instead, for now though this
is a safe thing and using atomic operations instead will be
very simple using the new static inline functions this patch
introduces for accessing sta->flags.
Since spin_lock_bh() is used with this lock, there shouldn't
be any contention even if aggregation is enabled at around the
same time as both requires frame transmission/reception which
is in a bh context.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Tomas Winkler <tomasw@gmail.com>
Cc: Ron Rindjunsky <ron.rindjunsky@intel.com>
Cc: Luis Carlos Cobo <luisca@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 15 | ||||
-rw-r--r-- | net/mac80211/key.c | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 31 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 88 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 38 | ||||
-rw-r--r-- | net/mac80211/rx.c | 17 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 14 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 72 | ||||
-rw-r--r-- | net/mac80211/tx.c | 21 |
10 files changed, 179 insertions, 123 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 699d97b8de5e..3cef80dcd0e5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -602,6 +602,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
602 | */ | 602 | */ |
603 | 603 | ||
604 | if (params->station_flags & STATION_FLAG_CHANGED) { | 604 | if (params->station_flags & STATION_FLAG_CHANGED) { |
605 | spin_lock_bh(&sta->lock); | ||
605 | sta->flags &= ~WLAN_STA_AUTHORIZED; | 606 | sta->flags &= ~WLAN_STA_AUTHORIZED; |
606 | if (params->station_flags & STATION_FLAG_AUTHORIZED) | 607 | if (params->station_flags & STATION_FLAG_AUTHORIZED) |
607 | sta->flags |= WLAN_STA_AUTHORIZED; | 608 | sta->flags |= WLAN_STA_AUTHORIZED; |
@@ -613,6 +614,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
613 | sta->flags &= ~WLAN_STA_WME; | 614 | sta->flags &= ~WLAN_STA_WME; |
614 | if (params->station_flags & STATION_FLAG_WME) | 615 | if (params->station_flags & STATION_FLAG_WME) |
615 | sta->flags |= WLAN_STA_WME; | 616 | sta->flags |= WLAN_STA_WME; |
617 | spin_unlock_bh(&sta->lock); | ||
616 | } | 618 | } |
617 | 619 | ||
618 | /* | 620 | /* |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 676a93202ff9..1f00273d99c2 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -74,14 +74,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
74 | { | 74 | { |
75 | char buf[100]; | 75 | char buf[100]; |
76 | struct sta_info *sta = file->private_data; | 76 | struct sta_info *sta = file->private_data; |
77 | u32 staflags = get_sta_flags(sta); | ||
77 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", | 78 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s", |
78 | sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "", | 79 | staflags & WLAN_STA_AUTH ? "AUTH\n" : "", |
79 | sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "", | 80 | staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", |
80 | sta->flags & WLAN_STA_PS ? "PS\n" : "", | 81 | staflags & WLAN_STA_PS ? "PS\n" : "", |
81 | sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", | 82 | staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", |
82 | sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", | 83 | staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", |
83 | sta->flags & WLAN_STA_WME ? "WME\n" : "", | 84 | staflags & WLAN_STA_WME ? "WME\n" : "", |
84 | sta->flags & WLAN_STA_WDS ? "WDS\n" : ""); | 85 | staflags & WLAN_STA_WDS ? "WDS\n" : ""); |
85 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 86 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
86 | } | 87 | } |
87 | STA_OPS(flags); | 88 | STA_OPS(flags); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 88b211af7c1f..d4893bd17754 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -321,7 +321,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
321 | * some hardware cannot handle TKIP with QoS, so | 321 | * some hardware cannot handle TKIP with QoS, so |
322 | * we indicate whether QoS could be in use. | 322 | * we indicate whether QoS could be in use. |
323 | */ | 323 | */ |
324 | if (sta->flags & WLAN_STA_WME) | 324 | if (test_sta_flags(sta, WLAN_STA_WME)) |
325 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 325 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
326 | 326 | ||
327 | /* | 327 | /* |
@@ -342,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
342 | /* same here, the AP could be using QoS */ | 342 | /* same here, the AP could be using QoS */ |
343 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); | 343 | ap = sta_info_get(key->local, key->sdata->u.sta.bssid); |
344 | if (ap) { | 344 | if (ap) { |
345 | if (ap->flags & WLAN_STA_WME) | 345 | if (test_sta_flags(ap, WLAN_STA_WME)) |
346 | key->conf.flags |= | 346 | key->conf.flags |= |
347 | IEEE80211_KEY_FLAG_WMM_STA; | 347 | IEEE80211_KEY_FLAG_WMM_STA; |
348 | } | 348 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 55e76117da9e..f277407f0f5a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -346,6 +346,7 @@ static int ieee80211_open(struct net_device *dev) | |||
346 | goto err_del_interface; | 346 | goto err_del_interface; |
347 | } | 347 | } |
348 | 348 | ||
349 | /* no locking required since STA is not live yet */ | ||
349 | sta->flags |= WLAN_STA_AUTHORIZED; | 350 | sta->flags |= WLAN_STA_AUTHORIZED; |
350 | 351 | ||
351 | res = sta_info_insert(sta); | 352 | res = sta_info_insert(sta); |
@@ -588,7 +589,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
588 | return -ENOENT; | 589 | return -ENOENT; |
589 | } | 590 | } |
590 | 591 | ||
591 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 592 | spin_lock_bh(&sta->lock); |
592 | 593 | ||
593 | /* we have tried too many times, receiver does not want A-MPDU */ | 594 | /* we have tried too many times, receiver does not want A-MPDU */ |
594 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | 595 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
@@ -691,7 +692,7 @@ start_ba_err: | |||
691 | spin_unlock_bh(&local->mdev->queue_lock); | 692 | spin_unlock_bh(&local->mdev->queue_lock); |
692 | ret = -EBUSY; | 693 | ret = -EBUSY; |
693 | start_ba_exit: | 694 | start_ba_exit: |
694 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 695 | spin_unlock_bh(&sta->lock); |
695 | rcu_read_unlock(); | 696 | rcu_read_unlock(); |
696 | return ret; | 697 | return ret; |
697 | } | 698 | } |
@@ -719,7 +720,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
719 | 720 | ||
720 | /* check if the TID is in aggregation */ | 721 | /* check if the TID is in aggregation */ |
721 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 722 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
722 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 723 | spin_lock_bh(&sta->lock); |
723 | 724 | ||
724 | if (*state != HT_AGG_STATE_OPERATIONAL) { | 725 | if (*state != HT_AGG_STATE_OPERATIONAL) { |
725 | ret = -ENOENT; | 726 | ret = -ENOENT; |
@@ -749,7 +750,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
749 | } | 750 | } |
750 | 751 | ||
751 | stop_BA_exit: | 752 | stop_BA_exit: |
752 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 753 | spin_unlock_bh(&sta->lock); |
753 | rcu_read_unlock(); | 754 | rcu_read_unlock(); |
754 | return ret; | 755 | return ret; |
755 | } | 756 | } |
@@ -778,12 +779,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
778 | } | 779 | } |
779 | 780 | ||
780 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 781 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
781 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 782 | spin_lock_bh(&sta->lock); |
782 | 783 | ||
783 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 784 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
784 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | 785 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", |
785 | *state); | 786 | *state); |
786 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 787 | spin_unlock_bh(&sta->lock); |
787 | rcu_read_unlock(); | 788 | rcu_read_unlock(); |
788 | return; | 789 | return; |
789 | } | 790 | } |
@@ -796,7 +797,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
796 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 797 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); |
797 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 798 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
798 | } | 799 | } |
799 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 800 | spin_unlock_bh(&sta->lock); |
800 | rcu_read_unlock(); | 801 | rcu_read_unlock(); |
801 | } | 802 | } |
802 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | 803 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); |
@@ -830,10 +831,10 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
830 | } | 831 | } |
831 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 832 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
832 | 833 | ||
833 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 834 | spin_lock_bh(&sta->lock); |
834 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 835 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { |
835 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | 836 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); |
836 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 837 | spin_unlock_bh(&sta->lock); |
837 | rcu_read_unlock(); | 838 | rcu_read_unlock(); |
838 | return; | 839 | return; |
839 | } | 840 | } |
@@ -860,7 +861,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
860 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 861 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
861 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 862 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
862 | sta->ampdu_mlme.tid_tx[tid] = NULL; | 863 | sta->ampdu_mlme.tid_tx[tid] = NULL; |
863 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 864 | spin_unlock_bh(&sta->lock); |
864 | 865 | ||
865 | rcu_read_unlock(); | 866 | rcu_read_unlock(); |
866 | } | 867 | } |
@@ -1315,7 +1316,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1315 | * packet. If the STA went to power save mode, this will happen | 1316 | * packet. If the STA went to power save mode, this will happen |
1316 | * happen when it wakes up for the next time. | 1317 | * happen when it wakes up for the next time. |
1317 | */ | 1318 | */ |
1318 | sta->flags |= WLAN_STA_CLEAR_PS_FILT; | 1319 | set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); |
1319 | 1320 | ||
1320 | /* | 1321 | /* |
1321 | * This code races in the following way: | 1322 | * This code races in the following way: |
@@ -1347,7 +1348,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1347 | * can be unknown, for example with different interrupt status | 1348 | * can be unknown, for example with different interrupt status |
1348 | * bits. | 1349 | * bits. |
1349 | */ | 1350 | */ |
1350 | if (sta->flags & WLAN_STA_PS && | 1351 | if (test_sta_flags(sta, WLAN_STA_PS) && |
1351 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 1352 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
1352 | ieee80211_remove_tx_extra(local, sta->key, skb, | 1353 | ieee80211_remove_tx_extra(local, sta->key, skb, |
1353 | &status->control); | 1354 | &status->control); |
@@ -1355,7 +1356,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1355 | return; | 1356 | return; |
1356 | } | 1357 | } |
1357 | 1358 | ||
1358 | if (!(sta->flags & WLAN_STA_PS) && | 1359 | if (!test_sta_flags(sta, WLAN_STA_PS) && |
1359 | !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) { | 1360 | !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) { |
1360 | /* Software retry the packet once */ | 1361 | /* Software retry the packet once */ |
1361 | status->control.flags |= IEEE80211_TXCTL_REQUEUE; | 1362 | status->control.flags |= IEEE80211_TXCTL_REQUEUE; |
@@ -1370,7 +1371,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
1370 | "queue_len=%d PS=%d @%lu\n", | 1371 | "queue_len=%d PS=%d @%lu\n", |
1371 | wiphy_name(local->hw.wiphy), | 1372 | wiphy_name(local->hw.wiphy), |
1372 | skb_queue_len(&sta->tx_filtered), | 1373 | skb_queue_len(&sta->tx_filtered), |
1373 | !!(sta->flags & WLAN_STA_PS), jiffies); | 1374 | !!test_sta_flags(sta, WLAN_STA_PS), jiffies); |
1374 | dev_kfree_skb(skb); | 1375 | dev_kfree_skb(skb); |
1375 | } | 1376 | } |
1376 | 1377 | ||
@@ -1399,7 +1400,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1399 | struct sta_info *sta; | 1400 | struct sta_info *sta; |
1400 | sta = sta_info_get(local, hdr->addr1); | 1401 | sta = sta_info_get(local, hdr->addr1); |
1401 | if (sta) { | 1402 | if (sta) { |
1402 | if (sta->flags & WLAN_STA_PS) { | 1403 | if (test_sta_flags(sta, WLAN_STA_PS)) { |
1403 | /* | 1404 | /* |
1404 | * The STA is in power save mode, so assume | 1405 | * The STA is in power save mode, so assume |
1405 | * that this TX packet failed because of that. | 1406 | * that this TX packet failed because of that. |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 37f0c2b94ae7..9efeb1f07025 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -79,7 +79,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | |||
79 | * | 79 | * |
80 | * @sta: mes peer link to restart | 80 | * @sta: mes peer link to restart |
81 | * | 81 | * |
82 | * Locking: this function must be called holding sta->plink_lock | 82 | * Locking: this function must be called holding sta->lock |
83 | */ | 83 | */ |
84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) | 84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) |
85 | { | 85 | { |
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
105 | if (!sta) | 105 | if (!sta) |
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | sta->flags |= WLAN_STA_AUTHORIZED; | 108 | sta->flags = WLAN_STA_AUTHORIZED; |
109 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 109 | sta->supp_rates[local->hw.conf.channel->band] = rates; |
110 | 110 | ||
111 | return sta; | 111 | return sta; |
@@ -118,7 +118,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
118 | * | 118 | * |
119 | * All mesh paths with this peer as next hop will be flushed | 119 | * All mesh paths with this peer as next hop will be flushed |
120 | * | 120 | * |
121 | * Locking: the caller must hold sta->plink_lock | 121 | * Locking: the caller must hold sta->lock |
122 | */ | 122 | */ |
123 | static void __mesh_plink_deactivate(struct sta_info *sta) | 123 | static void __mesh_plink_deactivate(struct sta_info *sta) |
124 | { | 124 | { |
@@ -139,9 +139,9 @@ static void __mesh_plink_deactivate(struct sta_info *sta) | |||
139 | */ | 139 | */ |
140 | void mesh_plink_deactivate(struct sta_info *sta) | 140 | void mesh_plink_deactivate(struct sta_info *sta) |
141 | { | 141 | { |
142 | spin_lock_bh(&sta->plink_lock); | 142 | spin_lock_bh(&sta->lock); |
143 | __mesh_plink_deactivate(sta); | 143 | __mesh_plink_deactivate(sta); |
144 | spin_unlock_bh(&sta->plink_lock); | 144 | spin_unlock_bh(&sta->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int mesh_plink_frame_tx(struct net_device *dev, | 147 | static int mesh_plink_frame_tx(struct net_device *dev, |
@@ -270,10 +270,10 @@ static void mesh_plink_timer(unsigned long data) | |||
270 | */ | 270 | */ |
271 | sta = (struct sta_info *) data; | 271 | sta = (struct sta_info *) data; |
272 | 272 | ||
273 | spin_lock_bh(&sta->plink_lock); | 273 | spin_lock_bh(&sta->lock); |
274 | if (sta->ignore_plink_timer) { | 274 | if (sta->ignore_plink_timer) { |
275 | sta->ignore_plink_timer = false; | 275 | sta->ignore_plink_timer = false; |
276 | spin_unlock_bh(&sta->plink_lock); | 276 | spin_unlock_bh(&sta->lock); |
277 | return; | 277 | return; |
278 | } | 278 | } |
279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", | 279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", |
@@ -298,7 +298,7 @@ static void mesh_plink_timer(unsigned long data) | |||
298 | rand % sta->plink_timeout; | 298 | rand % sta->plink_timeout; |
299 | ++sta->plink_retries; | 299 | ++sta->plink_retries; |
300 | mod_plink_timer(sta, sta->plink_timeout); | 300 | mod_plink_timer(sta, sta->plink_timeout); |
301 | spin_unlock_bh(&sta->plink_lock); | 301 | spin_unlock_bh(&sta->lock); |
302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, |
303 | 0, 0); | 303 | 0, 0); |
304 | break; | 304 | break; |
@@ -311,7 +311,7 @@ static void mesh_plink_timer(unsigned long data) | |||
311 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); | 311 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); |
312 | sta->plink_state = PLINK_HOLDING; | 312 | sta->plink_state = PLINK_HOLDING; |
313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
314 | spin_unlock_bh(&sta->plink_lock); | 314 | spin_unlock_bh(&sta->lock); |
315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, | 315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, |
316 | reason); | 316 | reason); |
317 | break; | 317 | break; |
@@ -319,10 +319,10 @@ static void mesh_plink_timer(unsigned long data) | |||
319 | /* holding timer */ | 319 | /* holding timer */ |
320 | del_timer(&sta->plink_timer); | 320 | del_timer(&sta->plink_timer); |
321 | mesh_plink_fsm_restart(sta); | 321 | mesh_plink_fsm_restart(sta); |
322 | spin_unlock_bh(&sta->plink_lock); | 322 | spin_unlock_bh(&sta->lock); |
323 | break; | 323 | break; |
324 | default: | 324 | default: |
325 | spin_unlock_bh(&sta->plink_lock); | 325 | spin_unlock_bh(&sta->lock); |
326 | break; | 326 | break; |
327 | } | 327 | } |
328 | } | 328 | } |
@@ -344,16 +344,16 @@ int mesh_plink_open(struct sta_info *sta) | |||
344 | DECLARE_MAC_BUF(mac); | 344 | DECLARE_MAC_BUF(mac); |
345 | #endif | 345 | #endif |
346 | 346 | ||
347 | spin_lock_bh(&sta->plink_lock); | 347 | spin_lock_bh(&sta->lock); |
348 | get_random_bytes(&llid, 2); | 348 | get_random_bytes(&llid, 2); |
349 | sta->llid = llid; | 349 | sta->llid = llid; |
350 | if (sta->plink_state != PLINK_LISTEN) { | 350 | if (sta->plink_state != PLINK_LISTEN) { |
351 | spin_unlock_bh(&sta->plink_lock); | 351 | spin_unlock_bh(&sta->lock); |
352 | return -EBUSY; | 352 | return -EBUSY; |
353 | } | 353 | } |
354 | sta->plink_state = PLINK_OPN_SNT; | 354 | sta->plink_state = PLINK_OPN_SNT; |
355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
356 | spin_unlock_bh(&sta->plink_lock); | 356 | spin_unlock_bh(&sta->lock); |
357 | mpl_dbg("Mesh plink: starting establishment with %s\n", | 357 | mpl_dbg("Mesh plink: starting establishment with %s\n", |
358 | print_mac(mac, sta->addr)); | 358 | print_mac(mac, sta->addr)); |
359 | 359 | ||
@@ -367,10 +367,10 @@ void mesh_plink_block(struct sta_info *sta) | |||
367 | DECLARE_MAC_BUF(mac); | 367 | DECLARE_MAC_BUF(mac); |
368 | #endif | 368 | #endif |
369 | 369 | ||
370 | spin_lock_bh(&sta->plink_lock); | 370 | spin_lock_bh(&sta->lock); |
371 | __mesh_plink_deactivate(sta); | 371 | __mesh_plink_deactivate(sta); |
372 | sta->plink_state = PLINK_BLOCKED; | 372 | sta->plink_state = PLINK_BLOCKED; |
373 | spin_unlock_bh(&sta->plink_lock); | 373 | spin_unlock_bh(&sta->lock); |
374 | } | 374 | } |
375 | 375 | ||
376 | int mesh_plink_close(struct sta_info *sta) | 376 | int mesh_plink_close(struct sta_info *sta) |
@@ -383,14 +383,14 @@ int mesh_plink_close(struct sta_info *sta) | |||
383 | 383 | ||
384 | mpl_dbg("Mesh plink: closing link with %s\n", | 384 | mpl_dbg("Mesh plink: closing link with %s\n", |
385 | print_mac(mac, sta->addr)); | 385 | print_mac(mac, sta->addr)); |
386 | spin_lock_bh(&sta->plink_lock); | 386 | spin_lock_bh(&sta->lock); |
387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); | 387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); |
388 | reason = sta->reason; | 388 | reason = sta->reason; |
389 | 389 | ||
390 | if (sta->plink_state == PLINK_LISTEN || | 390 | if (sta->plink_state == PLINK_LISTEN || |
391 | sta->plink_state == PLINK_BLOCKED) { | 391 | sta->plink_state == PLINK_BLOCKED) { |
392 | mesh_plink_fsm_restart(sta); | 392 | mesh_plink_fsm_restart(sta); |
393 | spin_unlock_bh(&sta->plink_lock); | 393 | spin_unlock_bh(&sta->lock); |
394 | return 0; | 394 | return 0; |
395 | } else if (sta->plink_state == PLINK_ESTAB) { | 395 | } else if (sta->plink_state == PLINK_ESTAB) { |
396 | __mesh_plink_deactivate(sta); | 396 | __mesh_plink_deactivate(sta); |
@@ -402,7 +402,7 @@ int mesh_plink_close(struct sta_info *sta) | |||
402 | sta->plink_state = PLINK_HOLDING; | 402 | sta->plink_state = PLINK_HOLDING; |
403 | llid = sta->llid; | 403 | llid = sta->llid; |
404 | plid = sta->plid; | 404 | plid = sta->plid; |
405 | spin_unlock_bh(&sta->plink_lock); | 405 | spin_unlock_bh(&sta->lock); |
406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, | 406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, |
407 | plid, reason); | 407 | plid, reason); |
408 | return 0; | 408 | return 0; |
@@ -490,7 +490,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
490 | /* avoid warning */ | 490 | /* avoid warning */ |
491 | break; | 491 | break; |
492 | } | 492 | } |
493 | spin_lock_bh(&sta->plink_lock); | 493 | spin_lock_bh(&sta->lock); |
494 | } else if (!sta) { | 494 | } else if (!sta) { |
495 | /* ftype == PLINK_OPEN */ | 495 | /* ftype == PLINK_OPEN */ |
496 | u64 rates; | 496 | u64 rates; |
@@ -512,9 +512,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
512 | return; | 512 | return; |
513 | } | 513 | } |
514 | event = OPN_ACPT; | 514 | event = OPN_ACPT; |
515 | spin_lock_bh(&sta->plink_lock); | 515 | spin_lock_bh(&sta->lock); |
516 | } else { | 516 | } else { |
517 | spin_lock_bh(&sta->plink_lock); | 517 | spin_lock_bh(&sta->lock); |
518 | switch (ftype) { | 518 | switch (ftype) { |
519 | case PLINK_OPEN: | 519 | case PLINK_OPEN: |
520 | if (!mesh_plink_free_count(sdata) || | 520 | if (!mesh_plink_free_count(sdata) || |
@@ -551,7 +551,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
551 | break; | 551 | break; |
552 | default: | 552 | default: |
553 | mpl_dbg("Mesh plink: unknown frame subtype\n"); | 553 | mpl_dbg("Mesh plink: unknown frame subtype\n"); |
554 | spin_unlock_bh(&sta->plink_lock); | 554 | spin_unlock_bh(&sta->lock); |
555 | rcu_read_unlock(); | 555 | rcu_read_unlock(); |
556 | return; | 556 | return; |
557 | } | 557 | } |
@@ -568,7 +568,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
568 | switch (event) { | 568 | switch (event) { |
569 | case CLS_ACPT: | 569 | case CLS_ACPT: |
570 | mesh_plink_fsm_restart(sta); | 570 | mesh_plink_fsm_restart(sta); |
571 | spin_unlock_bh(&sta->plink_lock); | 571 | spin_unlock_bh(&sta->lock); |
572 | break; | 572 | break; |
573 | case OPN_ACPT: | 573 | case OPN_ACPT: |
574 | sta->plink_state = PLINK_OPN_RCVD; | 574 | sta->plink_state = PLINK_OPN_RCVD; |
@@ -576,14 +576,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
576 | get_random_bytes(&llid, 2); | 576 | get_random_bytes(&llid, 2); |
577 | sta->llid = llid; | 577 | sta->llid = llid; |
578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
579 | spin_unlock_bh(&sta->plink_lock); | 579 | spin_unlock_bh(&sta->lock); |
580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, |
581 | 0, 0); | 581 | 0, 0); |
582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, | 582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, |
583 | llid, plid, 0); | 583 | llid, plid, 0); |
584 | break; | 584 | break; |
585 | default: | 585 | default: |
586 | spin_unlock_bh(&sta->plink_lock); | 586 | spin_unlock_bh(&sta->lock); |
587 | break; | 587 | break; |
588 | } | 588 | } |
589 | break; | 589 | break; |
@@ -603,7 +603,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
603 | sta->ignore_plink_timer = true; | 603 | sta->ignore_plink_timer = true; |
604 | 604 | ||
605 | llid = sta->llid; | 605 | llid = sta->llid; |
606 | spin_unlock_bh(&sta->plink_lock); | 606 | spin_unlock_bh(&sta->lock); |
607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
608 | plid, reason); | 608 | plid, reason); |
609 | break; | 609 | break; |
@@ -612,7 +612,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
612 | sta->plink_state = PLINK_OPN_RCVD; | 612 | sta->plink_state = PLINK_OPN_RCVD; |
613 | sta->plid = plid; | 613 | sta->plid = plid; |
614 | llid = sta->llid; | 614 | llid = sta->llid; |
615 | spin_unlock_bh(&sta->plink_lock); | 615 | spin_unlock_bh(&sta->lock); |
616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
617 | plid, 0); | 617 | plid, 0); |
618 | break; | 618 | break; |
@@ -622,10 +622,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
622 | dot11MeshConfirmTimeout(sdata))) | 622 | dot11MeshConfirmTimeout(sdata))) |
623 | sta->ignore_plink_timer = true; | 623 | sta->ignore_plink_timer = true; |
624 | 624 | ||
625 | spin_unlock_bh(&sta->plink_lock); | 625 | spin_unlock_bh(&sta->lock); |
626 | break; | 626 | break; |
627 | default: | 627 | default: |
628 | spin_unlock_bh(&sta->plink_lock); | 628 | spin_unlock_bh(&sta->lock); |
629 | break; | 629 | break; |
630 | } | 630 | } |
631 | break; | 631 | break; |
@@ -645,13 +645,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
645 | sta->ignore_plink_timer = true; | 645 | sta->ignore_plink_timer = true; |
646 | 646 | ||
647 | llid = sta->llid; | 647 | llid = sta->llid; |
648 | spin_unlock_bh(&sta->plink_lock); | 648 | spin_unlock_bh(&sta->lock); |
649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
650 | plid, reason); | 650 | plid, reason); |
651 | break; | 651 | break; |
652 | case OPN_ACPT: | 652 | case OPN_ACPT: |
653 | llid = sta->llid; | 653 | llid = sta->llid; |
654 | spin_unlock_bh(&sta->plink_lock); | 654 | spin_unlock_bh(&sta->lock); |
655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
656 | plid, 0); | 656 | plid, 0); |
657 | break; | 657 | break; |
@@ -659,12 +659,12 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
659 | del_timer(&sta->plink_timer); | 659 | del_timer(&sta->plink_timer); |
660 | sta->plink_state = PLINK_ESTAB; | 660 | sta->plink_state = PLINK_ESTAB; |
661 | mesh_plink_inc_estab_count(sdata); | 661 | mesh_plink_inc_estab_count(sdata); |
662 | spin_unlock_bh(&sta->plink_lock); | 662 | spin_unlock_bh(&sta->lock); |
663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
664 | print_mac(mac, sta->addr)); | 664 | print_mac(mac, sta->addr)); |
665 | break; | 665 | break; |
666 | default: | 666 | default: |
667 | spin_unlock_bh(&sta->plink_lock); | 667 | spin_unlock_bh(&sta->lock); |
668 | break; | 668 | break; |
669 | } | 669 | } |
670 | break; | 670 | break; |
@@ -684,7 +684,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
684 | sta->ignore_plink_timer = true; | 684 | sta->ignore_plink_timer = true; |
685 | 685 | ||
686 | llid = sta->llid; | 686 | llid = sta->llid; |
687 | spin_unlock_bh(&sta->plink_lock); | 687 | spin_unlock_bh(&sta->lock); |
688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
689 | plid, reason); | 689 | plid, reason); |
690 | break; | 690 | break; |
@@ -692,14 +692,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
692 | del_timer(&sta->plink_timer); | 692 | del_timer(&sta->plink_timer); |
693 | sta->plink_state = PLINK_ESTAB; | 693 | sta->plink_state = PLINK_ESTAB; |
694 | mesh_plink_inc_estab_count(sdata); | 694 | mesh_plink_inc_estab_count(sdata); |
695 | spin_unlock_bh(&sta->plink_lock); | 695 | spin_unlock_bh(&sta->lock); |
696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
697 | print_mac(mac, sta->addr)); | 697 | print_mac(mac, sta->addr)); |
698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
699 | plid, 0); | 699 | plid, 0); |
700 | break; | 700 | break; |
701 | default: | 701 | default: |
702 | spin_unlock_bh(&sta->plink_lock); | 702 | spin_unlock_bh(&sta->lock); |
703 | break; | 703 | break; |
704 | } | 704 | } |
705 | break; | 705 | break; |
@@ -713,18 +713,18 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
713 | sta->plink_state = PLINK_HOLDING; | 713 | sta->plink_state = PLINK_HOLDING; |
714 | llid = sta->llid; | 714 | llid = sta->llid; |
715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
716 | spin_unlock_bh(&sta->plink_lock); | 716 | spin_unlock_bh(&sta->lock); |
717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
718 | plid, reason); | 718 | plid, reason); |
719 | break; | 719 | break; |
720 | case OPN_ACPT: | 720 | case OPN_ACPT: |
721 | llid = sta->llid; | 721 | llid = sta->llid; |
722 | spin_unlock_bh(&sta->plink_lock); | 722 | spin_unlock_bh(&sta->lock); |
723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, |
724 | plid, 0); | 724 | plid, 0); |
725 | break; | 725 | break; |
726 | default: | 726 | default: |
727 | spin_unlock_bh(&sta->plink_lock); | 727 | spin_unlock_bh(&sta->lock); |
728 | break; | 728 | break; |
729 | } | 729 | } |
730 | break; | 730 | break; |
@@ -734,7 +734,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
734 | if (del_timer(&sta->plink_timer)) | 734 | if (del_timer(&sta->plink_timer)) |
735 | sta->ignore_plink_timer = 1; | 735 | sta->ignore_plink_timer = 1; |
736 | mesh_plink_fsm_restart(sta); | 736 | mesh_plink_fsm_restart(sta); |
737 | spin_unlock_bh(&sta->plink_lock); | 737 | spin_unlock_bh(&sta->lock); |
738 | break; | 738 | break; |
739 | case OPN_ACPT: | 739 | case OPN_ACPT: |
740 | case CNF_ACPT: | 740 | case CNF_ACPT: |
@@ -742,19 +742,19 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
742 | case CNF_RJCT: | 742 | case CNF_RJCT: |
743 | llid = sta->llid; | 743 | llid = sta->llid; |
744 | reason = sta->reason; | 744 | reason = sta->reason; |
745 | spin_unlock_bh(&sta->plink_lock); | 745 | spin_unlock_bh(&sta->lock); |
746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
747 | plid, reason); | 747 | plid, reason); |
748 | break; | 748 | break; |
749 | default: | 749 | default: |
750 | spin_unlock_bh(&sta->plink_lock); | 750 | spin_unlock_bh(&sta->lock); |
751 | } | 751 | } |
752 | break; | 752 | break; |
753 | default: | 753 | default: |
754 | /* should not get here, PLINK_BLOCKED is dealt with at the | 754 | /* should not get here, PLINK_BLOCKED is dealt with at the |
755 | * beggining of the function | 755 | * beggining of the function |
756 | */ | 756 | */ |
757 | spin_unlock_bh(&sta->plink_lock); | 757 | spin_unlock_bh(&sta->lock); |
758 | break; | 758 | break; |
759 | } | 759 | } |
760 | 760 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 108c6fc42fe2..6c4b27be35da 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1241,7 +1241,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1241 | 1241 | ||
1242 | 1242 | ||
1243 | /* examine state machine */ | 1243 | /* examine state machine */ |
1244 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1244 | spin_lock_bh(&sta->lock); |
1245 | 1245 | ||
1246 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 1246 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { |
1247 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1247 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -1308,7 +1308,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1308 | tid_agg_rx->stored_mpdu_num = 0; | 1308 | tid_agg_rx->stored_mpdu_num = 0; |
1309 | status = WLAN_STATUS_SUCCESS; | 1309 | status = WLAN_STATUS_SUCCESS; |
1310 | end: | 1310 | end: |
1311 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1311 | spin_unlock_bh(&sta->lock); |
1312 | 1312 | ||
1313 | end_no_lock: | 1313 | end_no_lock: |
1314 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, | 1314 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, |
@@ -1340,10 +1340,10 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1340 | 1340 | ||
1341 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 1341 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1342 | 1342 | ||
1343 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1343 | spin_lock_bh(&sta->lock); |
1344 | 1344 | ||
1345 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1345 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
1346 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1346 | spin_unlock_bh(&sta->lock); |
1347 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | 1347 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" |
1348 | "%d\n", *state); | 1348 | "%d\n", *state); |
1349 | goto addba_resp_exit; | 1349 | goto addba_resp_exit; |
@@ -1351,7 +1351,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1351 | 1351 | ||
1352 | if (mgmt->u.action.u.addba_resp.dialog_token != | 1352 | if (mgmt->u.action.u.addba_resp.dialog_token != |
1353 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | 1353 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { |
1354 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1354 | spin_unlock_bh(&sta->lock); |
1355 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1355 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1356 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 1356 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
1357 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1357 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
@@ -1375,7 +1375,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1375 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 1375 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
1376 | } | 1376 | } |
1377 | 1377 | ||
1378 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1378 | spin_unlock_bh(&sta->lock); |
1379 | printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid); | 1379 | printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid); |
1380 | } else { | 1380 | } else { |
1381 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); | 1381 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); |
@@ -1383,7 +1383,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1383 | sta->ampdu_mlme.addba_req_num[tid]++; | 1383 | sta->ampdu_mlme.addba_req_num[tid]++; |
1384 | /* this will allow the state check in stop_BA_session */ | 1384 | /* this will allow the state check in stop_BA_session */ |
1385 | *state = HT_AGG_STATE_OPERATIONAL; | 1385 | *state = HT_AGG_STATE_OPERATIONAL; |
1386 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1386 | spin_unlock_bh(&sta->lock); |
1387 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 1387 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, |
1388 | WLAN_BACK_INITIATOR); | 1388 | WLAN_BACK_INITIATOR); |
1389 | } | 1389 | } |
@@ -1453,17 +1453,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | /* check if TID is in operational state */ | 1455 | /* check if TID is in operational state */ |
1456 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1456 | spin_lock_bh(&sta->lock); |
1457 | if (sta->ampdu_mlme.tid_state_rx[tid] | 1457 | if (sta->ampdu_mlme.tid_state_rx[tid] |
1458 | != HT_AGG_STATE_OPERATIONAL) { | 1458 | != HT_AGG_STATE_OPERATIONAL) { |
1459 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1459 | spin_unlock_bh(&sta->lock); |
1460 | rcu_read_unlock(); | 1460 | rcu_read_unlock(); |
1461 | return; | 1461 | return; |
1462 | } | 1462 | } |
1463 | sta->ampdu_mlme.tid_state_rx[tid] = | 1463 | sta->ampdu_mlme.tid_state_rx[tid] = |
1464 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 1464 | HT_AGG_STATE_REQ_STOP_BA_MSK | |
1465 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 1465 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
1466 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1466 | spin_unlock_bh(&sta->lock); |
1467 | 1467 | ||
1468 | /* stop HW Rx aggregation. ampdu_action existence | 1468 | /* stop HW Rx aggregation. ampdu_action existence |
1469 | * already verified in session init so we add the BUG_ON */ | 1469 | * already verified in session init so we add the BUG_ON */ |
@@ -1540,10 +1540,10 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1540 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, | 1540 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, |
1541 | WLAN_BACK_INITIATOR, 0); | 1541 | WLAN_BACK_INITIATOR, 0); |
1542 | else { /* WLAN_BACK_RECIPIENT */ | 1542 | else { /* WLAN_BACK_RECIPIENT */ |
1543 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1543 | spin_lock_bh(&sta->lock); |
1544 | sta->ampdu_mlme.tid_state_tx[tid] = | 1544 | sta->ampdu_mlme.tid_state_tx[tid] = |
1545 | HT_AGG_STATE_OPERATIONAL; | 1545 | HT_AGG_STATE_OPERATIONAL; |
1546 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1546 | spin_unlock_bh(&sta->lock); |
1547 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | 1547 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, |
1548 | WLAN_BACK_RECIPIENT); | 1548 | WLAN_BACK_RECIPIENT); |
1549 | } | 1549 | } |
@@ -1580,9 +1580,9 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1580 | 1580 | ||
1581 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 1581 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1582 | /* check if the TID waits for addBA response */ | 1582 | /* check if the TID waits for addBA response */ |
1583 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1583 | spin_lock_bh(&sta->lock); |
1584 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1584 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
1585 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1585 | spin_unlock_bh(&sta->lock); |
1586 | *state = HT_AGG_STATE_IDLE; | 1586 | *state = HT_AGG_STATE_IDLE; |
1587 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 1587 | printk(KERN_DEBUG "timer expired on tid %d but we are not " |
1588 | "expecting addBA response there", tid); | 1588 | "expecting addBA response there", tid); |
@@ -1593,7 +1593,7 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1593 | 1593 | ||
1594 | /* go through the state check in stop_BA_session */ | 1594 | /* go through the state check in stop_BA_session */ |
1595 | *state = HT_AGG_STATE_OPERATIONAL; | 1595 | *state = HT_AGG_STATE_OPERATIONAL; |
1596 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1596 | spin_unlock_bh(&sta->lock); |
1597 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, | 1597 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, |
1598 | WLAN_BACK_INITIATOR); | 1598 | WLAN_BACK_INITIATOR); |
1599 | 1599 | ||
@@ -1984,8 +1984,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1984 | * to between the sta_info_alloc() and sta_info_insert() above. | 1984 | * to between the sta_info_alloc() and sta_info_insert() above. |
1985 | */ | 1985 | */ |
1986 | 1986 | ||
1987 | sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | | 1987 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | |
1988 | WLAN_STA_AUTHORIZED; | 1988 | WLAN_STA_AUTHORIZED); |
1989 | 1989 | ||
1990 | rates = 0; | 1990 | rates = 0; |
1991 | basic_rates = 0; | 1991 | basic_rates = 0; |
@@ -2044,7 +2044,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2044 | rate_control_rate_init(sta, local); | 2044 | rate_control_rate_init(sta, local); |
2045 | 2045 | ||
2046 | if (elems.wmm_param) { | 2046 | if (elems.wmm_param) { |
2047 | sta->flags |= WLAN_STA_WME; | 2047 | set_sta_flags(sta, WLAN_STA_WME); |
2048 | rcu_read_unlock(); | 2048 | rcu_read_unlock(); |
2049 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 2049 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, |
2050 | elems.wmm_param_len); | 2050 | elems.wmm_param_len); |
@@ -4237,7 +4237,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | |||
4237 | if (!sta) | 4237 | if (!sta) |
4238 | return NULL; | 4238 | return NULL; |
4239 | 4239 | ||
4240 | sta->flags |= WLAN_STA_AUTHORIZED; | 4240 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
4241 | 4241 | ||
4242 | sta->supp_rates[local->hw.conf.channel->band] = | 4242 | sta->supp_rates[local->hw.conf.channel->band] = |
4243 | sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; | 4243 | sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e8b89c89e875..b399e09ec7aa 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -479,7 +479,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
479 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && | 479 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && |
480 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && | 480 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && |
481 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 481 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
482 | (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) { | 482 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
483 | if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && | 483 | if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && |
484 | !(rx->fc & IEEE80211_FCTL_TODS) && | 484 | !(rx->fc & IEEE80211_FCTL_TODS) && |
485 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) | 485 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) |
@@ -630,8 +630,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | |||
630 | 630 | ||
631 | if (sdata->bss) | 631 | if (sdata->bss) |
632 | atomic_inc(&sdata->bss->num_sta_ps); | 632 | atomic_inc(&sdata->bss->num_sta_ps); |
633 | sta->flags |= WLAN_STA_PS; | 633 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
634 | sta->flags &= ~WLAN_STA_PSPOLL; | ||
635 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 634 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
636 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 635 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
637 | dev->name, print_mac(mac, sta->addr), sta->aid); | 636 | dev->name, print_mac(mac, sta->addr), sta->aid); |
@@ -652,7 +651,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
652 | if (sdata->bss) | 651 | if (sdata->bss) |
653 | atomic_dec(&sdata->bss->num_sta_ps); | 652 | atomic_dec(&sdata->bss->num_sta_ps); |
654 | 653 | ||
655 | sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL); | 654 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
656 | 655 | ||
657 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 656 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
658 | sta_info_clear_tim_bit(sta); | 657 | sta_info_clear_tim_bit(sta); |
@@ -727,9 +726,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
727 | if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { | 726 | if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { |
728 | /* Change STA power saving mode only in the end of a frame | 727 | /* Change STA power saving mode only in the end of a frame |
729 | * exchange sequence */ | 728 | * exchange sequence */ |
730 | if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM)) | 729 | if (test_sta_flags(sta, WLAN_STA_PS) && |
730 | !(rx->fc & IEEE80211_FCTL_PM)) | ||
731 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 731 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); |
732 | else if (!(sta->flags & WLAN_STA_PS) && | 732 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
733 | (rx->fc & IEEE80211_FCTL_PM)) | 733 | (rx->fc & IEEE80211_FCTL_PM)) |
734 | ap_sta_ps_start(dev, sta); | 734 | ap_sta_ps_start(dev, sta); |
735 | } | 735 | } |
@@ -983,7 +983,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
983 | * Tell TX path to send one frame even though the STA may | 983 | * Tell TX path to send one frame even though the STA may |
984 | * still remain is PS mode after this frame exchange. | 984 | * still remain is PS mode after this frame exchange. |
985 | */ | 985 | */ |
986 | rx->sta->flags |= WLAN_STA_PSPOLL; | 986 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); |
987 | 987 | ||
988 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 988 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
989 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", | 989 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", |
@@ -1046,7 +1046,8 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | |||
1046 | static int | 1046 | static int |
1047 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1047 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1048 | { | 1048 | { |
1049 | if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) { | 1049 | if (unlikely(!rx->sta || |
1050 | !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) { | ||
1050 | #ifdef CONFIG_MAC80211_DEBUG | 1051 | #ifdef CONFIG_MAC80211_DEBUG |
1051 | if (net_ratelimit()) | 1052 | if (net_ratelimit()) |
1052 | printk(KERN_DEBUG "%s: dropped frame " | 1053 | printk(KERN_DEBUG "%s: dropped frame " |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 631943e8af8b..baf5e4746884 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -202,14 +202,12 @@ void sta_info_destroy(struct sta_info *sta) | |||
202 | dev_kfree_skb_any(skb); | 202 | dev_kfree_skb_any(skb); |
203 | 203 | ||
204 | for (i = 0; i < STA_TID_NUM; i++) { | 204 | for (i = 0; i < STA_TID_NUM; i++) { |
205 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 205 | spin_lock_bh(&sta->lock); |
206 | if (sta->ampdu_mlme.tid_rx[i]) | 206 | if (sta->ampdu_mlme.tid_rx[i]) |
207 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); | 207 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); |
208 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | ||
209 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
210 | if (sta->ampdu_mlme.tid_tx[i]) | 208 | if (sta->ampdu_mlme.tid_tx[i]) |
211 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); | 209 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); |
212 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 210 | spin_unlock_bh(&sta->lock); |
213 | } | 211 | } |
214 | 212 | ||
215 | __sta_info_free(local, sta); | 213 | __sta_info_free(local, sta); |
@@ -236,6 +234,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
236 | if (!sta) | 234 | if (!sta) |
237 | return NULL; | 235 | return NULL; |
238 | 236 | ||
237 | spin_lock_init(&sta->lock); | ||
238 | |||
239 | memcpy(sta->addr, addr, ETH_ALEN); | 239 | memcpy(sta->addr, addr, ETH_ALEN); |
240 | sta->local = local; | 240 | sta->local = local; |
241 | sta->sdata = sdata; | 241 | sta->sdata = sdata; |
@@ -249,8 +249,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
249 | return NULL; | 249 | return NULL; |
250 | } | 250 | } |
251 | 251 | ||
252 | spin_lock_init(&sta->ampdu_mlme.ampdu_rx); | ||
253 | spin_lock_init(&sta->ampdu_mlme.ampdu_tx); | ||
254 | for (i = 0; i < STA_TID_NUM; i++) { | 252 | for (i = 0; i < STA_TID_NUM; i++) { |
255 | /* timer_to_tid must be initialized with identity mapping to | 253 | /* timer_to_tid must be initialized with identity mapping to |
256 | * enable session_timer's data differentiation. refer to | 254 | * enable session_timer's data differentiation. refer to |
@@ -276,7 +274,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
276 | 274 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 275 | #ifdef CONFIG_MAC80211_MESH |
278 | sta->plink_state = PLINK_LISTEN; | 276 | sta->plink_state = PLINK_LISTEN; |
279 | spin_lock_init(&sta->plink_lock); | ||
280 | init_timer(&sta->plink_timer); | 277 | init_timer(&sta->plink_timer); |
281 | #endif | 278 | #endif |
282 | 279 | ||
@@ -437,8 +434,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
437 | 434 | ||
438 | list_del(&(*sta)->list); | 435 | list_del(&(*sta)->list); |
439 | 436 | ||
440 | if ((*sta)->flags & WLAN_STA_PS) { | 437 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { |
441 | (*sta)->flags &= ~WLAN_STA_PS; | ||
442 | if (sdata->bss) | 438 | if (sdata->bss) |
443 | atomic_dec(&sdata->bss->num_sta_ps); | 439 | atomic_dec(&sdata->bss->num_sta_ps); |
444 | __sta_info_clear_tim_bit(sdata->bss, *sta); | 440 | __sta_info_clear_tim_bit(sdata->bss, *sta); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index f8c95bc9659c..97a61c39ad90 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -129,23 +129,19 @@ enum plink_state { | |||
129 | * | 129 | * |
130 | * @tid_state_rx: TID's state in Rx session state machine. | 130 | * @tid_state_rx: TID's state in Rx session state machine. |
131 | * @tid_rx: aggregation info for Rx per TID | 131 | * @tid_rx: aggregation info for Rx per TID |
132 | * @ampdu_rx: for locking sections in aggregation Rx flow | ||
133 | * @tid_state_tx: TID's state in Tx session state machine. | 132 | * @tid_state_tx: TID's state in Tx session state machine. |
134 | * @tid_tx: aggregation info for Tx per TID | 133 | * @tid_tx: aggregation info for Tx per TID |
135 | * @addba_req_num: number of times addBA request has been sent. | 134 | * @addba_req_num: number of times addBA request has been sent. |
136 | * @ampdu_tx: for locking sectionsi in aggregation Tx flow | ||
137 | * @dialog_token_allocator: dialog token enumerator for each new session; | 135 | * @dialog_token_allocator: dialog token enumerator for each new session; |
138 | */ | 136 | */ |
139 | struct sta_ampdu_mlme { | 137 | struct sta_ampdu_mlme { |
140 | /* rx */ | 138 | /* rx */ |
141 | u8 tid_state_rx[STA_TID_NUM]; | 139 | u8 tid_state_rx[STA_TID_NUM]; |
142 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 140 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
143 | spinlock_t ampdu_rx; | ||
144 | /* tx */ | 141 | /* tx */ |
145 | u8 tid_state_tx[STA_TID_NUM]; | 142 | u8 tid_state_tx[STA_TID_NUM]; |
146 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; | 143 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; |
147 | u8 addba_req_num[STA_TID_NUM]; | 144 | u8 addba_req_num[STA_TID_NUM]; |
148 | spinlock_t ampdu_tx; | ||
149 | u8 dialog_token_allocator; | 145 | u8 dialog_token_allocator; |
150 | }; | 146 | }; |
151 | 147 | ||
@@ -177,6 +173,8 @@ struct sta_ampdu_mlme { | |||
177 | * @rx_bytes: Number of bytes received from this STA | 173 | * @rx_bytes: Number of bytes received from this STA |
178 | * @supp_rates: Bitmap of supported rates (per band) | 174 | * @supp_rates: Bitmap of supported rates (per band) |
179 | * @ht_info: HT capabilities of this STA | 175 | * @ht_info: HT capabilities of this STA |
176 | * @lock: used for locking all fields that require locking, see comments | ||
177 | * in the header file. | ||
180 | */ | 178 | */ |
181 | struct sta_info { | 179 | struct sta_info { |
182 | /* General information, mostly static */ | 180 | /* General information, mostly static */ |
@@ -187,6 +185,7 @@ struct sta_info { | |||
187 | struct ieee80211_key *key; | 185 | struct ieee80211_key *key; |
188 | struct rate_control_ref *rate_ctrl; | 186 | struct rate_control_ref *rate_ctrl; |
189 | void *rate_ctrl_priv; | 187 | void *rate_ctrl_priv; |
188 | spinlock_t lock; | ||
190 | struct ieee80211_ht_info ht_info; | 189 | struct ieee80211_ht_info ht_info; |
191 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 190 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
192 | u8 addr[ETH_ALEN]; | 191 | u8 addr[ETH_ALEN]; |
@@ -199,7 +198,7 @@ struct sta_info { | |||
199 | */ | 198 | */ |
200 | u8 pin_status; | 199 | u8 pin_status; |
201 | 200 | ||
202 | /* frequently updated information, needs locking? */ | 201 | /* frequently updated information, locked with lock spinlock */ |
203 | u32 flags; | 202 | u32 flags; |
204 | 203 | ||
205 | /* | 204 | /* |
@@ -251,7 +250,7 @@ struct sta_info { | |||
251 | int channel_use_raw; | 250 | int channel_use_raw; |
252 | 251 | ||
253 | /* | 252 | /* |
254 | * Aggregation information, comes with own locking. | 253 | * Aggregation information, locked with lock. |
255 | */ | 254 | */ |
256 | struct sta_ampdu_mlme ampdu_mlme; | 255 | struct sta_ampdu_mlme ampdu_mlme; |
257 | u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ | 256 | u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ |
@@ -270,9 +269,6 @@ struct sta_info { | |||
270 | enum plink_state plink_state; | 269 | enum plink_state plink_state; |
271 | u32 plink_timeout; | 270 | u32 plink_timeout; |
272 | struct timer_list plink_timer; | 271 | struct timer_list plink_timer; |
273 | spinlock_t plink_lock; /* For peer_state reads / updates and other | ||
274 | updates in the structure. Ensures robust | ||
275 | transitions for the peerlink FSM */ | ||
276 | #endif | 272 | #endif |
277 | 273 | ||
278 | #ifdef CONFIG_MAC80211_DEBUGFS | 274 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -299,6 +295,64 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta) | |||
299 | return PLINK_LISTEN; | 295 | return PLINK_LISTEN; |
300 | } | 296 | } |
301 | 297 | ||
298 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | ||
299 | { | ||
300 | spin_lock_bh(&sta->lock); | ||
301 | sta->flags |= flags; | ||
302 | spin_unlock_bh(&sta->lock); | ||
303 | } | ||
304 | |||
305 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | ||
306 | { | ||
307 | spin_lock_bh(&sta->lock); | ||
308 | sta->flags &= ~flags; | ||
309 | spin_unlock_bh(&sta->lock); | ||
310 | } | ||
311 | |||
312 | static inline void set_and_clear_sta_flags(struct sta_info *sta, | ||
313 | const u32 set, const u32 clear) | ||
314 | { | ||
315 | spin_lock_bh(&sta->lock); | ||
316 | sta->flags |= set; | ||
317 | sta->flags &= ~clear; | ||
318 | spin_unlock_bh(&sta->lock); | ||
319 | } | ||
320 | |||
321 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | ||
322 | { | ||
323 | u32 ret; | ||
324 | |||
325 | spin_lock_bh(&sta->lock); | ||
326 | ret = sta->flags & flags; | ||
327 | spin_unlock_bh(&sta->lock); | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | ||
333 | const u32 flags) | ||
334 | { | ||
335 | u32 ret; | ||
336 | |||
337 | spin_lock_bh(&sta->lock); | ||
338 | ret = sta->flags & flags; | ||
339 | sta->flags &= ~flags; | ||
340 | spin_unlock_bh(&sta->lock); | ||
341 | |||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | static inline u32 get_sta_flags(struct sta_info *sta) | ||
346 | { | ||
347 | u32 ret; | ||
348 | |||
349 | spin_lock_bh(&sta->lock); | ||
350 | ret = sta->flags; | ||
351 | spin_unlock_bh(&sta->lock); | ||
352 | |||
353 | return ret; | ||
354 | } | ||
355 | |||
302 | 356 | ||
303 | /* Maximum number of concurrently registered stations */ | 357 | /* Maximum number of concurrently registered stations */ |
304 | #define MAX_STA_COUNT 2007 | 358 | #define MAX_STA_COUNT 2007 |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3a03d7807c39..5f31a6233e13 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -256,7 +256,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
256 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 256 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
257 | return TX_CONTINUE; | 257 | return TX_CONTINUE; |
258 | 258 | ||
259 | sta_flags = tx->sta ? tx->sta->flags : 0; | 259 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; |
260 | 260 | ||
261 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 261 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
262 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 262 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && |
@@ -391,6 +391,7 @@ static ieee80211_tx_result | |||
391 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | 391 | ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) |
392 | { | 392 | { |
393 | struct sta_info *sta = tx->sta; | 393 | struct sta_info *sta = tx->sta; |
394 | u32 staflags; | ||
394 | DECLARE_MAC_BUF(mac); | 395 | DECLARE_MAC_BUF(mac); |
395 | 396 | ||
396 | if (unlikely(!sta || | 397 | if (unlikely(!sta || |
@@ -398,8 +399,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
398 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) | 399 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) |
399 | return TX_CONTINUE; | 400 | return TX_CONTINUE; |
400 | 401 | ||
401 | if (unlikely((sta->flags & WLAN_STA_PS) && | 402 | staflags = get_sta_flags(sta); |
402 | !(sta->flags & WLAN_STA_PSPOLL))) { | 403 | |
404 | if (unlikely((staflags & WLAN_STA_PS) && | ||
405 | !(staflags & WLAN_STA_PSPOLL))) { | ||
403 | struct ieee80211_tx_packet_data *pkt_data; | 406 | struct ieee80211_tx_packet_data *pkt_data; |
404 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 407 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
405 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " | 408 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " |
@@ -430,13 +433,13 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
430 | return TX_QUEUED; | 433 | return TX_QUEUED; |
431 | } | 434 | } |
432 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 435 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
433 | else if (unlikely(sta->flags & WLAN_STA_PS)) { | 436 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { |
434 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " | 437 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " |
435 | "set -> send frame\n", tx->dev->name, | 438 | "set -> send frame\n", tx->dev->name, |
436 | print_mac(mac, sta->addr)); | 439 | print_mac(mac, sta->addr)); |
437 | } | 440 | } |
438 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 441 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
439 | sta->flags &= ~WLAN_STA_PSPOLL; | 442 | clear_sta_flags(sta, WLAN_STA_PSPOLL); |
440 | 443 | ||
441 | return TX_CONTINUE; | 444 | return TX_CONTINUE; |
442 | } | 445 | } |
@@ -697,7 +700,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
697 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | 700 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && |
698 | (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | 701 | (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && |
699 | tx->sdata->bss_conf.use_short_preamble && | 702 | tx->sdata->bss_conf.use_short_preamble && |
700 | (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) { | 703 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { |
701 | tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; | 704 | tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; |
702 | } | 705 | } |
703 | 706 | ||
@@ -1025,10 +1028,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1025 | 1028 | ||
1026 | if (!tx->sta) | 1029 | if (!tx->sta) |
1027 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; | 1030 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; |
1028 | else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) { | 1031 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1029 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; | 1032 | control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; |
1030 | tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT; | ||
1031 | } | ||
1032 | 1033 | ||
1033 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 1034 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
1034 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 1035 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
@@ -1486,7 +1487,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1486 | rcu_read_lock(); | 1487 | rcu_read_lock(); |
1487 | sta = sta_info_get(local, hdr.addr1); | 1488 | sta = sta_info_get(local, hdr.addr1); |
1488 | if (sta) | 1489 | if (sta) |
1489 | sta_flags = sta->flags; | 1490 | sta_flags = get_sta_flags(sta); |
1490 | rcu_read_unlock(); | 1491 | rcu_read_unlock(); |
1491 | } | 1492 | } |
1492 | 1493 | ||