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>
This commit is contained in:
committed by
John W. Linville
parent
3434fbd398
commit
07346f81e8
@ -479,7 +479,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
||||
((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
|
||||
(rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
|
||||
rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
|
||||
(!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
|
||||
(!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
|
||||
if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
|
||||
!(rx->fc & IEEE80211_FCTL_TODS) &&
|
||||
(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)
|
||||
|
||||
if (sdata->bss)
|
||||
atomic_inc(&sdata->bss->num_sta_ps);
|
||||
sta->flags |= WLAN_STA_PS;
|
||||
sta->flags &= ~WLAN_STA_PSPOLL;
|
||||
set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
|
||||
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)
|
||||
if (sdata->bss)
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
|
||||
sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL);
|
||||
clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
|
||||
|
||||
if (!skb_queue_empty(&sta->ps_tx_buf))
|
||||
sta_info_clear_tim_bit(sta);
|
||||
@ -727,9 +726,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
||||
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))
|
||||
if (test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
!(rx->fc & IEEE80211_FCTL_PM))
|
||||
rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
|
||||
else if (!(sta->flags & WLAN_STA_PS) &&
|
||||
else if (!test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
(rx->fc & IEEE80211_FCTL_PM))
|
||||
ap_sta_ps_start(dev, sta);
|
||||
}
|
||||
@ -983,7 +983,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
|
||||
* Tell TX path to send one frame even though the STA may
|
||||
* still remain is PS mode after this frame exchange.
|
||||
*/
|
||||
rx->sta->flags |= WLAN_STA_PSPOLL;
|
||||
set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
|
||||
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
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)
|
||||
static int
|
||||
ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
|
||||
if (unlikely(!rx->sta ||
|
||||
!test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) {
|
||||
#ifdef CONFIG_MAC80211_DEBUG
|
||||
if (net_ratelimit())
|
||||
printk(KERN_DEBUG "%s: dropped frame "
|
||||
|
Reference in New Issue
Block a user