aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-25 10:27:46 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:46 -0500
commitd0709a65181beb787ef3f58cfe45536a2bb254c8 (patch)
tree29e5f36583b0e0a3f11b291347e57672eab41dad /net/mac80211/tx.c
parent5cf121c3cdb955583bf0c5d28c992b7968a4aa1a (diff)
mac80211: RCU-ify STA info structure access
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. This is an existing race condition that is now somewhat understandable. This patch also fixes the race key freeing vs. STA destruction by making sure that sta_info_destroy() is always called under RTNL and frees the key. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c48
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
1779struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, 1770struct 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}