aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-05-02 19:02:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-14 16:29:34 -0400
commit07346f81e87d6e4cca7ae9adfa711d0c61c87b56 (patch)
tree237450c49843e0e19afc79356240a891da64d9fa /net/mac80211/tx.c
parent3434fbd39862d471c92b66c28cd449deea8e9f90 (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/tx.c')
-rw-r--r--net/mac80211/tx.c21
1 files changed, 11 insertions, 10 deletions
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
391ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) 391ieee80211_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