aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.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/rx.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/rx.c')
-rw-r--r--net/mac80211/rx.c24
1 files changed, 8 insertions, 16 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2e65ca1cd1aa..8e1e2859bfd5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -631,7 +631,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
631 struct ieee80211_sub_if_data *sdata; 631 struct ieee80211_sub_if_data *sdata;
632 DECLARE_MAC_BUF(mac); 632 DECLARE_MAC_BUF(mac);
633 633
634 sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 634 sdata = sta->sdata;
635 635
636 if (sdata->bss) 636 if (sdata->bss)
637 atomic_inc(&sdata->bss->num_sta_ps); 637 atomic_inc(&sdata->bss->num_sta_ps);
@@ -652,7 +652,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
652 struct ieee80211_tx_packet_data *pkt_data; 652 struct ieee80211_tx_packet_data *pkt_data;
653 DECLARE_MAC_BUF(mac); 653 DECLARE_MAC_BUF(mac);
654 654
655 sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 655 sdata = sta->sdata;
656 656
657 if (sdata->bss) 657 if (sdata->bss)
658 atomic_dec(&sdata->bss->num_sta_ps); 658 atomic_dec(&sdata->bss->num_sta_ps);
@@ -1287,7 +1287,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1287 "multicast frame\n", dev->name); 1287 "multicast frame\n", dev->name);
1288 } else { 1288 } else {
1289 dsta = sta_info_get(local, skb->data); 1289 dsta = sta_info_get(local, skb->data);
1290 if (dsta && dsta->dev == dev) { 1290 if (dsta && dsta->sdata->dev == dev) {
1291 /* 1291 /*
1292 * The destination station is associated to 1292 * The destination station is associated to
1293 * this AP (in this VLAN), so send the frame 1293 * this AP (in this VLAN), so send the frame
@@ -1297,8 +1297,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1297 xmit_skb = skb; 1297 xmit_skb = skb;
1298 skb = NULL; 1298 skb = NULL;
1299 } 1299 }
1300 if (dsta)
1301 sta_info_put(dsta);
1302 } 1300 }
1303 } 1301 }
1304 1302
@@ -1905,13 +1903,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
1905 1903
1906 rx.sta = sta_info_get(local, hdr->addr2); 1904 rx.sta = sta_info_get(local, hdr->addr2);
1907 if (rx.sta) { 1905 if (rx.sta) {
1908 rx.dev = rx.sta->dev; 1906 rx.sdata = rx.sta->sdata;
1909 rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); 1907 rx.dev = rx.sta->sdata->dev;
1910 } 1908 }
1911 1909
1912 if ((status->flag & RX_FLAG_MMIC_ERROR)) { 1910 if ((status->flag & RX_FLAG_MMIC_ERROR)) {
1913 ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx); 1911 ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
1914 goto end; 1912 return;
1915 } 1913 }
1916 1914
1917 if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning)) 1915 if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
@@ -1970,10 +1968,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
1970 ieee80211_invoke_rx_handlers(prev, &rx, skb); 1968 ieee80211_invoke_rx_handlers(prev, &rx, skb);
1971 } else 1969 } else
1972 dev_kfree_skb(skb); 1970 dev_kfree_skb(skb);
1973
1974 end:
1975 if (rx.sta)
1976 sta_info_put(rx.sta);
1977} 1971}
1978 1972
1979#define SEQ_MODULO 0x1000 1973#define SEQ_MODULO 0x1000
@@ -2150,7 +2144,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2150 /* if this mpdu is fragmented - terminate rx aggregation session */ 2144 /* if this mpdu is fragmented - terminate rx aggregation session */
2151 sc = le16_to_cpu(hdr->seq_ctrl); 2145 sc = le16_to_cpu(hdr->seq_ctrl);
2152 if (sc & IEEE80211_SCTL_FRAG) { 2146 if (sc & IEEE80211_SCTL_FRAG) {
2153 ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, 2147 ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
2154 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); 2148 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
2155 ret = 1; 2149 ret = 1;
2156 goto end_reorder; 2150 goto end_reorder;
@@ -2160,9 +2154,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2160 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; 2154 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2161 ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, 2155 ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
2162 mpdu_seq_num, 0); 2156 mpdu_seq_num, 0);
2163end_reorder: 2157 end_reorder:
2164 if (sta)
2165 sta_info_put(sta);
2166 return ret; 2158 return ret;
2167} 2159}
2168 2160