diff options
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 33e314f3aab7..80f4343a3007 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -327,10 +327,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
327 | } | 327 | } |
328 | total += skb_queue_len(&ap->ps_bc_buf); | 328 | total += skb_queue_len(&ap->ps_bc_buf); |
329 | } | 329 | } |
330 | rcu_read_unlock(); | ||
331 | 330 | ||
332 | read_lock_bh(&local->sta_lock); | 331 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
333 | list_for_each_entry(sta, &local->sta_list, list) { | ||
334 | skb = skb_dequeue(&sta->ps_tx_buf); | 332 | skb = skb_dequeue(&sta->ps_tx_buf); |
335 | if (skb) { | 333 | if (skb) { |
336 | purged++; | 334 | purged++; |
@@ -338,7 +336,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
338 | } | 336 | } |
339 | total += skb_queue_len(&sta->ps_tx_buf); | 337 | total += skb_queue_len(&sta->ps_tx_buf); |
340 | } | 338 | } |
341 | read_unlock_bh(&local->sta_lock); | 339 | |
340 | rcu_read_unlock(); | ||
342 | 341 | ||
343 | local->total_ps_buffered = total; | 342 | local->total_ps_buffered = total; |
344 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", | 343 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", |
@@ -1141,20 +1140,17 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1141 | return 0; | 1140 | return 0; |
1142 | } | 1141 | } |
1143 | 1142 | ||
1143 | rcu_read_lock(); | ||
1144 | |||
1144 | /* initialises tx */ | 1145 | /* initialises tx */ |
1145 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); | 1146 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); |
1146 | 1147 | ||
1147 | if (res_prepare == TX_DROP) { | 1148 | if (res_prepare == TX_DROP) { |
1148 | dev_kfree_skb(skb); | 1149 | dev_kfree_skb(skb); |
1150 | rcu_read_unlock(); | ||
1149 | return 0; | 1151 | return 0; |
1150 | } | 1152 | } |
1151 | 1153 | ||
1152 | /* | ||
1153 | * key references are protected using RCU and this requires that | ||
1154 | * we are in a read-site RCU section during receive processing | ||
1155 | */ | ||
1156 | rcu_read_lock(); | ||
1157 | |||
1158 | sta = tx.sta; | 1154 | sta = tx.sta; |
1159 | tx.channel = local->hw.conf.channel; | 1155 | tx.channel = local->hw.conf.channel; |
1160 | 1156 | ||
@@ -1167,9 +1163,6 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1167 | 1163 | ||
1168 | skb = tx.skb; /* handlers are allowed to change skb */ | 1164 | skb = tx.skb; /* handlers are allowed to change skb */ |
1169 | 1165 | ||
1170 | if (sta) | ||
1171 | sta_info_put(sta); | ||
1172 | |||
1173 | if (unlikely(res == TX_DROP)) { | 1166 | if (unlikely(res == TX_DROP)) { |
1174 | I802_DEBUG_INC(local->tx_handlers_drop); | 1167 | I802_DEBUG_INC(local->tx_handlers_drop); |
1175 | goto drop; | 1168 | goto drop; |
@@ -1489,11 +1482,11 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1489 | * in AP mode) | 1482 | * in AP mode) |
1490 | */ | 1483 | */ |
1491 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1484 | if (!is_multicast_ether_addr(hdr.addr1)) { |
1485 | rcu_read_lock(); | ||
1492 | sta = sta_info_get(local, hdr.addr1); | 1486 | sta = sta_info_get(local, hdr.addr1); |
1493 | if (sta) { | 1487 | if (sta) |
1494 | sta_flags = sta->flags; | 1488 | sta_flags = sta->flags; |
1495 | sta_info_put(sta); | 1489 | rcu_read_unlock(); |
1496 | } | ||
1497 | } | 1490 | } |
1498 | 1491 | ||
1499 | /* receiver is QoS enabled, use a QoS type frame */ | 1492 | /* receiver is QoS enabled, use a QoS type frame */ |
@@ -1722,7 +1715,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local, | |||
1722 | 1715 | ||
1723 | /* Generate bitmap for TIM only if there are any STAs in power save | 1716 | /* Generate bitmap for TIM only if there are any STAs in power save |
1724 | * mode. */ | 1717 | * mode. */ |
1725 | read_lock_bh(&local->sta_lock); | ||
1726 | if (atomic_read(&bss->num_sta_ps) > 0) | 1718 | if (atomic_read(&bss->num_sta_ps) > 0) |
1727 | /* in the hope that this is faster than | 1719 | /* in the hope that this is faster than |
1728 | * checking byte-for-byte */ | 1720 | * checking byte-for-byte */ |
@@ -1773,7 +1765,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local, | |||
1773 | *pos++ = aid0; /* Bitmap control */ | 1765 | *pos++ = aid0; /* Bitmap control */ |
1774 | *pos++ = 0; /* Part Virt Bitmap */ | 1766 | *pos++ = 0; /* Part Virt Bitmap */ |
1775 | } | 1767 | } |
1776 | read_unlock_bh(&local->sta_lock); | ||
1777 | } | 1768 | } |
1778 | 1769 | ||
1779 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 1770 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
@@ -1821,7 +1812,22 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1821 | ieee80211_include_sequence(sdata, | 1812 | ieee80211_include_sequence(sdata, |
1822 | (struct ieee80211_hdr *)skb->data); | 1813 | (struct ieee80211_hdr *)skb->data); |
1823 | 1814 | ||
1824 | ieee80211_beacon_add_tim(local, ap, skb, beacon); | 1815 | /* |
1816 | * Not very nice, but we want to allow the driver to call | ||
1817 | * ieee80211_beacon_get() as a response to the set_tim() | ||
1818 | * callback. That, however, is already invoked under the | ||
1819 | * sta_lock to guarantee consistent and race-free update | ||
1820 | * of the tim bitmap in mac80211 and the driver. | ||
1821 | */ | ||
1822 | if (local->tim_in_locked_section) { | ||
1823 | ieee80211_beacon_add_tim(local, ap, skb, beacon); | ||
1824 | } else { | ||
1825 | unsigned long flags; | ||
1826 | |||
1827 | spin_lock_irqsave(&local->sta_lock, flags); | ||
1828 | ieee80211_beacon_add_tim(local, ap, skb, beacon); | ||
1829 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1830 | } | ||
1825 | 1831 | ||
1826 | if (beacon->tail) | 1832 | if (beacon->tail) |
1827 | memcpy(skb_put(skb, beacon->tail_len), | 1833 | memcpy(skb_put(skb, beacon->tail_len), |
@@ -1965,7 +1971,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1965 | rcu_read_unlock(); | 1971 | rcu_read_unlock(); |
1966 | return NULL; | 1972 | return NULL; |
1967 | } | 1973 | } |
1968 | rcu_read_unlock(); | ||
1969 | 1974 | ||
1970 | if (bss->dtim_count != 0) | 1975 | if (bss->dtim_count != 0) |
1971 | return NULL; /* send buffered bc/mc only after DTIM beacon */ | 1976 | return NULL; /* send buffered bc/mc only after DTIM beacon */ |
@@ -2010,8 +2015,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2010 | skb = NULL; | 2015 | skb = NULL; |
2011 | } | 2016 | } |
2012 | 2017 | ||
2013 | if (sta) | 2018 | rcu_read_unlock(); |
2014 | sta_info_put(sta); | ||
2015 | 2019 | ||
2016 | return skb; | 2020 | return skb; |
2017 | } | 2021 | } |