aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-05-13 08:15:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-16 14:10:41 -0400
commit40b275b69ee660274b77fb612b0db31fd282fc3f (patch)
tree29a4f82a44a12edcf9db5de6a3c6df9615a5799e /net
parentec034b208dc8aa5dc73ec46c3f27e34c5efbf113 (diff)
mac80211: sparse RCU annotations
This adds sparse RCU annotations to most of mac80211, only the mesh code remains to be done. Due the the previous patches, the annotations are pretty simple. The only thing that this actually changes is removing the RCU usage of key->sta in debugfs since this pointer isn't actually an RCU-managed pointer (it only has a single assignment done before the key even goes live). As that is otherwise harmless, I decided to make it part of this patch. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-rx.c3
-rw-r--r--net/mac80211/agg-tx.c36
-rw-r--r--net/mac80211/cfg.c17
-rw-r--r--net/mac80211/debugfs_key.c21
-rw-r--r--net/mac80211/ht.c2
-rw-r--r--net/mac80211/ibss.c11
-rw-r--r--net/mac80211/ieee80211_i.h16
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/key.c22
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/mesh.h2
-rw-r--r--net/mac80211/mesh_hwmp.c20
-rw-r--r--net/mac80211/sta_info.c15
-rw-r--r--net/mac80211/sta_info.h17
-rw-r--r--net/mac80211/tx.c2
16 files changed, 118 insertions, 74 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 0c9d0c07eae6..9c0d76cdca92 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -63,7 +63,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
63 63
64 lockdep_assert_held(&sta->ampdu_mlme.mtx); 64 lockdep_assert_held(&sta->ampdu_mlme.mtx);
65 65
66 tid_rx = sta->ampdu_mlme.tid_rx[tid]; 66 tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
67 lockdep_is_held(&sta->ampdu_mlme.mtx));
67 68
68 if (!tid_rx) 69 if (!tid_rx)
69 return; 70 return;
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index f614ee602089..cd5125f77cc5 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -157,16 +157,19 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
157 bool tx) 157 bool tx)
158{ 158{
159 struct ieee80211_local *local = sta->local; 159 struct ieee80211_local *local = sta->local;
160 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 160 struct tid_ampdu_tx *tid_tx;
161 int ret; 161 int ret;
162 162
163 lockdep_assert_held(&sta->ampdu_mlme.mtx); 163 lockdep_assert_held(&sta->ampdu_mlme.mtx);
164 164
165 if (!tid_tx)
166 return -ENOENT;
167
168 spin_lock_bh(&sta->lock); 165 spin_lock_bh(&sta->lock);
169 166
167 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
168 if (!tid_tx) {
169 spin_unlock_bh(&sta->lock);
170 return -ENOENT;
171 }
172
170 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { 173 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
171 /* not even started yet! */ 174 /* not even started yet! */
172 ieee80211_assign_tid_tx(sta, tid, NULL); 175 ieee80211_assign_tid_tx(sta, tid, NULL);
@@ -291,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
291 294
292void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) 295void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
293{ 296{
294 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 297 struct tid_ampdu_tx *tid_tx;
295 struct ieee80211_local *local = sta->local; 298 struct ieee80211_local *local = sta->local;
296 struct ieee80211_sub_if_data *sdata = sta->sdata; 299 struct ieee80211_sub_if_data *sdata = sta->sdata;
297 u16 start_seq_num; 300 u16 start_seq_num;
298 int ret; 301 int ret;
299 302
300 lockdep_assert_held(&sta->ampdu_mlme.mtx); 303 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
301 304
302 /* 305 /*
303 * While we're asking the driver about the aggregation, 306 * While we're asking the driver about the aggregation,
@@ -404,7 +407,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
404 goto err_unlock_sta; 407 goto err_unlock_sta;
405 } 408 }
406 409
407 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 410 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
408 /* check if the TID is not in aggregation flow already */ 411 /* check if the TID is not in aggregation flow already */
409 if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { 412 if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
410#ifdef CONFIG_MAC80211_HT_DEBUG 413#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -491,16 +494,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
491static void ieee80211_agg_tx_operational(struct ieee80211_local *local, 494static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
492 struct sta_info *sta, u16 tid) 495 struct sta_info *sta, u16 tid)
493{ 496{
497 struct tid_ampdu_tx *tid_tx;
498
494 lockdep_assert_held(&sta->ampdu_mlme.mtx); 499 lockdep_assert_held(&sta->ampdu_mlme.mtx);
495 500
501 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
502
496#ifdef CONFIG_MAC80211_HT_DEBUG 503#ifdef CONFIG_MAC80211_HT_DEBUG
497 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); 504 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
498#endif 505#endif
499 506
500 drv_ampdu_action(local, sta->sdata, 507 drv_ampdu_action(local, sta->sdata,
501 IEEE80211_AMPDU_TX_OPERATIONAL, 508 IEEE80211_AMPDU_TX_OPERATIONAL,
502 &sta->sta, tid, NULL, 509 &sta->sta, tid, NULL, tid_tx->buf_size);
503 sta->ampdu_mlme.tid_tx[tid]->buf_size);
504 510
505 /* 511 /*
506 * synchronize with TX path, while splicing the TX path 512 * synchronize with TX path, while splicing the TX path
@@ -508,13 +514,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
508 */ 514 */
509 spin_lock_bh(&sta->lock); 515 spin_lock_bh(&sta->lock);
510 516
511 ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); 517 ieee80211_agg_splice_packets(local, tid_tx, tid);
512 /* 518 /*
513 * Now mark as operational. This will be visible 519 * Now mark as operational. This will be visible
514 * in the TX path, and lets it go lock-free in 520 * in the TX path, and lets it go lock-free in
515 * the common case. 521 * the common case.
516 */ 522 */
517 set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); 523 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
518 ieee80211_agg_splice_finish(local, tid); 524 ieee80211_agg_splice_finish(local, tid);
519 525
520 spin_unlock_bh(&sta->lock); 526 spin_unlock_bh(&sta->lock);
@@ -548,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
548 } 554 }
549 555
550 mutex_lock(&sta->ampdu_mlme.mtx); 556 mutex_lock(&sta->ampdu_mlme.mtx);
551 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 557 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
552 558
553 if (WARN_ON(!tid_tx)) { 559 if (WARN_ON(!tid_tx)) {
554#ifdef CONFIG_MAC80211_HT_DEBUG 560#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -626,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
626 return -EINVAL; 632 return -EINVAL;
627 633
628 spin_lock_bh(&sta->lock); 634 spin_lock_bh(&sta->lock);
629 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 635 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
630 636
631 if (!tid_tx) { 637 if (!tid_tx) {
632 ret = -ENOENT; 638 ret = -ENOENT;
@@ -682,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
682 688
683 mutex_lock(&sta->ampdu_mlme.mtx); 689 mutex_lock(&sta->ampdu_mlme.mtx);
684 spin_lock_bh(&sta->lock); 690 spin_lock_bh(&sta->lock);
685 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 691 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
686 692
687 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { 693 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
688#ifdef CONFIG_MAC80211_HT_DEBUG 694#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -763,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
763 769
764 mutex_lock(&sta->ampdu_mlme.mtx); 770 mutex_lock(&sta->ampdu_mlme.mtx);
765 771
766 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 772 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
767 if (!tid_tx) 773 if (!tid_tx)
768 goto out; 774 goto out;
769 775
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 2d1c1a5f3c51..6ecd5862735d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -177,11 +177,11 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
177 goto out_unlock; 177 goto out_unlock;
178 178
179 if (pairwise) 179 if (pairwise)
180 key = sta->ptk; 180 key = key_mtx_dereference(local, sta->ptk);
181 else 181 else
182 key = sta->gtk[key_idx]; 182 key = key_mtx_dereference(local, sta->gtk[key_idx]);
183 } else 183 } else
184 key = sdata->keys[key_idx]; 184 key = key_mtx_dereference(local, sdata->keys[key_idx]);
185 185
186 if (!key) { 186 if (!key) {
187 ret = -ENOENT; 187 ret = -ENOENT;
@@ -463,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
463 int size; 463 int size;
464 int err = -EINVAL; 464 int err = -EINVAL;
465 465
466 old = sdata->u.ap.beacon; 466 old = rtnl_dereference(sdata->u.ap.beacon);
467 467
468 /* head must not be zero-length */ 468 /* head must not be zero-length */
469 if (params->head && !params->head_len) 469 if (params->head && !params->head_len)
@@ -558,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
558 558
559 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 559 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
560 560
561 old = sdata->u.ap.beacon; 561 old = rtnl_dereference(sdata->u.ap.beacon);
562
563 if (old) 562 if (old)
564 return -EALREADY; 563 return -EALREADY;
565 564
@@ -574,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
574 573
575 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 574 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
576 575
577 old = sdata->u.ap.beacon; 576 old = rtnl_dereference(sdata->u.ap.beacon);
578
579 if (!old) 577 if (!old)
580 return -ENOENT; 578 return -ENOENT;
581 579
@@ -589,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
589 587
590 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 588 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
591 589
592 old = sdata->u.ap.beacon; 590 old = rtnl_dereference(sdata->u.ap.beacon);
593
594 if (!old) 591 if (!old)
595 return -ENOENT; 592 return -ENOENT;
596 593
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index f7ef3477c24a..33c58b85c911 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -241,16 +241,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
241 if (!key->debugfs.dir) 241 if (!key->debugfs.dir)
242 return; 242 return;
243 243
244 rcu_read_lock(); 244 sta = key->sta;
245 sta = rcu_dereference(key->sta); 245 if (sta) {
246 if (sta)
247 sprintf(buf, "../../stations/%pM", sta->sta.addr); 246 sprintf(buf, "../../stations/%pM", sta->sta.addr);
248 rcu_read_unlock();
249
250 /* using sta as a boolean is fine outside RCU lock */
251 if (sta)
252 key->debugfs.stalink = 247 key->debugfs.stalink =
253 debugfs_create_symlink("station", key->debugfs.dir, buf); 248 debugfs_create_symlink("station", key->debugfs.dir, buf);
249 }
254 250
255 DEBUGFS_ADD(keylen); 251 DEBUGFS_ADD(keylen);
256 DEBUGFS_ADD(flags); 252 DEBUGFS_ADD(flags);
@@ -286,7 +282,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
286 lockdep_assert_held(&sdata->local->key_mtx); 282 lockdep_assert_held(&sdata->local->key_mtx);
287 283
288 if (sdata->default_unicast_key) { 284 if (sdata->default_unicast_key) {
289 key = sdata->default_unicast_key; 285 key = key_mtx_dereference(sdata->local,
286 sdata->default_unicast_key);
290 sprintf(buf, "../keys/%d", key->debugfs.cnt); 287 sprintf(buf, "../keys/%d", key->debugfs.cnt);
291 sdata->debugfs.default_unicast_key = 288 sdata->debugfs.default_unicast_key =
292 debugfs_create_symlink("default_unicast_key", 289 debugfs_create_symlink("default_unicast_key",
@@ -297,7 +294,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
297 } 294 }
298 295
299 if (sdata->default_multicast_key) { 296 if (sdata->default_multicast_key) {
300 key = sdata->default_multicast_key; 297 key = key_mtx_dereference(sdata->local,
298 sdata->default_multicast_key);
301 sprintf(buf, "../keys/%d", key->debugfs.cnt); 299 sprintf(buf, "../keys/%d", key->debugfs.cnt);
302 sdata->debugfs.default_multicast_key = 300 sdata->debugfs.default_multicast_key =
303 debugfs_create_symlink("default_multicast_key", 301 debugfs_create_symlink("default_multicast_key",
@@ -316,9 +314,8 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
316 if (!sdata->debugfs.dir) 314 if (!sdata->debugfs.dir)
317 return; 315 return;
318 316
319 /* this is running under the key lock */ 317 key = key_mtx_dereference(sdata->local,
320 318 sdata->default_mgmt_key);
321 key = sdata->default_mgmt_key;
322 if (key) { 319 if (key) {
323 sprintf(buf, "../keys/%d", key->debugfs.cnt); 320 sprintf(buf, "../keys/%d", key->debugfs.cnt);
324 sdata->debugfs.default_mgmt_key = 321 sdata->debugfs.default_mgmt_key =
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 9f5842a43111..591add22bcc0 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -160,7 +160,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
160 continue; 160 continue;
161 } 161 }
162 162
163 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 163 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
164 if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, 164 if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
165 &tid_tx->state)) 165 &tid_tx->state))
166 ___ieee80211_stop_tx_ba_session(sta, tid, 166 ___ieee80211_stop_tx_ba_session(sta, tid,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index b81860c94698..421eaa6b0c2b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -662,12 +662,16 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
662 int tx_last_beacon, len = req->len; 662 int tx_last_beacon, len = req->len;
663 struct sk_buff *skb; 663 struct sk_buff *skb;
664 struct ieee80211_mgmt *resp; 664 struct ieee80211_mgmt *resp;
665 struct sk_buff *presp;
665 u8 *pos, *end; 666 u8 *pos, *end;
666 667
667 lockdep_assert_held(&ifibss->mtx); 668 lockdep_assert_held(&ifibss->mtx);
668 669
670 presp = rcu_dereference_protected(ifibss->presp,
671 lockdep_is_held(&ifibss->mtx));
672
669 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || 673 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
670 len < 24 + 2 || !ifibss->presp) 674 len < 24 + 2 || !presp)
671 return; 675 return;
672 676
673 tx_last_beacon = drv_tx_last_beacon(local); 677 tx_last_beacon = drv_tx_last_beacon(local);
@@ -705,7 +709,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
705 } 709 }
706 710
707 /* Reply with ProbeResp */ 711 /* Reply with ProbeResp */
708 skb = skb_copy(ifibss->presp, GFP_KERNEL); 712 skb = skb_copy(presp, GFP_KERNEL);
709 if (!skb) 713 if (!skb)
710 return; 714 return;
711 715
@@ -985,7 +989,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
985 989
986 /* remove beacon */ 990 /* remove beacon */
987 kfree(sdata->u.ibss.ie); 991 kfree(sdata->u.ibss.ie);
988 skb = sdata->u.ibss.presp; 992 skb = rcu_dereference_protected(sdata->u.ibss.presp,
993 lockdep_is_held(&sdata->u.ibss.mtx));
989 rcu_assign_pointer(sdata->u.ibss.presp, NULL); 994 rcu_assign_pointer(sdata->u.ibss.presp, NULL);
990 sdata->vif.bss_conf.ibss_joined = false; 995 sdata->vif.bss_conf.ibss_joined = false;
991 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 996 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 82f90ff8bb18..ed755889645d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -214,7 +214,7 @@ struct beacon_data {
214}; 214};
215 215
216struct ieee80211_if_ap { 216struct ieee80211_if_ap {
217 struct beacon_data *beacon; 217 struct beacon_data __rcu *beacon;
218 218
219 struct list_head vlans; 219 struct list_head vlans;
220 220
@@ -237,7 +237,7 @@ struct ieee80211_if_vlan {
237 struct list_head list; 237 struct list_head list;
238 238
239 /* used for all tx if the VLAN is configured to 4-addr mode */ 239 /* used for all tx if the VLAN is configured to 4-addr mode */
240 struct sta_info *sta; 240 struct sta_info __rcu *sta;
241}; 241};
242 242
243struct mesh_stats { 243struct mesh_stats {
@@ -442,7 +442,8 @@ struct ieee80211_if_ibss {
442 442
443 unsigned long ibss_join_req; 443 unsigned long ibss_join_req;
444 /* probe response/beacon for IBSS */ 444 /* probe response/beacon for IBSS */
445 struct sk_buff *presp, *skb; 445 struct sk_buff __rcu *presp;
446 struct sk_buff *skb;
446 447
447 enum { 448 enum {
448 IEEE80211_IBSS_MLME_SEARCH, 449 IEEE80211_IBSS_MLME_SEARCH,
@@ -567,9 +568,10 @@ struct ieee80211_sub_if_data {
567 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; 568 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
568 unsigned int fragment_next; 569 unsigned int fragment_next;
569 570
570 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 571 struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
571 struct ieee80211_key *default_unicast_key, *default_multicast_key; 572 struct ieee80211_key __rcu *default_unicast_key;
572 struct ieee80211_key *default_mgmt_key; 573 struct ieee80211_key __rcu *default_multicast_key;
574 struct ieee80211_key __rcu *default_mgmt_key;
573 575
574 u16 sequence_number; 576 u16 sequence_number;
575 __be16 control_port_protocol; 577 __be16 control_port_protocol;
@@ -805,7 +807,7 @@ struct ieee80211_local {
805 spinlock_t sta_lock; 807 spinlock_t sta_lock;
806 unsigned long num_sta; 808 unsigned long num_sta;
807 struct list_head sta_list, sta_pending_list; 809 struct list_head sta_list, sta_pending_list;
808 struct sta_info *sta_hash[STA_HASH_SIZE]; 810 struct sta_info __rcu *sta_hash[STA_HASH_SIZE];
809 struct timer_list sta_cleanup; 811 struct timer_list sta_cleanup;
810 struct work_struct sta_finish_work; 812 struct work_struct sta_finish_work;
811 int sta_generation; 813 int sta_generation;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4054399be907..0d00ac93d958 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -449,7 +449,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
449 /* APs need special treatment */ 449 /* APs need special treatment */
450 if (sdata->vif.type == NL80211_IFTYPE_AP) { 450 if (sdata->vif.type == NL80211_IFTYPE_AP) {
451 struct ieee80211_sub_if_data *vlan, *tmpsdata; 451 struct ieee80211_sub_if_data *vlan, *tmpsdata;
452 struct beacon_data *old_beacon = sdata->u.ap.beacon; 452 struct beacon_data *old_beacon =
453 rtnl_dereference(sdata->u.ap.beacon);
453 454
454 /* sdata_running will return false, so this will disable */ 455 /* sdata_running will return false, so this will disable */
455 ieee80211_bss_info_change_notify(sdata, 456 ieee80211_bss_info_change_notify(sdata,
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 958832dd4f0a..31afd712930d 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -195,7 +195,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
195 assert_key_lock(sdata->local); 195 assert_key_lock(sdata->local);
196 196
197 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 197 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
198 key = sdata->keys[idx]; 198 key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
199 199
200 if (uni) 200 if (uni)
201 rcu_assign_pointer(sdata->default_unicast_key, key); 201 rcu_assign_pointer(sdata->default_unicast_key, key);
@@ -222,7 +222,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
222 222
223 if (idx >= NUM_DEFAULT_KEYS && 223 if (idx >= NUM_DEFAULT_KEYS &&
224 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 224 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
225 key = sdata->keys[idx]; 225 key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
226 226
227 rcu_assign_pointer(sdata->default_mgmt_key, key); 227 rcu_assign_pointer(sdata->default_mgmt_key, key);
228 228
@@ -266,9 +266,15 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
266 else 266 else
267 idx = new->conf.keyidx; 267 idx = new->conf.keyidx;
268 268
269 defunikey = old && sdata->default_unicast_key == old; 269 defunikey = old &&
270 defmultikey = old && sdata->default_multicast_key == old; 270 old == key_mtx_dereference(sdata->local,
271 defmgmtkey = old && sdata->default_mgmt_key == old; 271 sdata->default_unicast_key);
272 defmultikey = old &&
273 old == key_mtx_dereference(sdata->local,
274 sdata->default_multicast_key);
275 defmgmtkey = old &&
276 old == key_mtx_dereference(sdata->local,
277 sdata->default_mgmt_key);
272 278
273 if (defunikey && !new) 279 if (defunikey && !new)
274 __ieee80211_set_default_key(sdata, -1, true, false); 280 __ieee80211_set_default_key(sdata, -1, true, false);
@@ -451,11 +457,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
451 mutex_lock(&sdata->local->key_mtx); 457 mutex_lock(&sdata->local->key_mtx);
452 458
453 if (sta && pairwise) 459 if (sta && pairwise)
454 old_key = sta->ptk; 460 old_key = key_mtx_dereference(sdata->local, sta->ptk);
455 else if (sta) 461 else if (sta)
456 old_key = sta->gtk[idx]; 462 old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
457 else 463 else
458 old_key = sdata->keys[idx]; 464 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
459 465
460 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); 466 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
461 __ieee80211_key_destroy(old_key); 467 __ieee80211_key_destroy(old_key);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index e5432ef8b203..d801d5351336 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -146,4 +146,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
146void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); 146void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
147void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); 147void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
148 148
149#define key_mtx_dereference(local, ref) \
150 rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
151
149#endif /* IEEE80211_KEY_H */ 152#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 79a2281678bf..0d7b08db8e56 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
871 * and we need some headroom for passing the frame to monitor 871 * and we need some headroom for passing the frame to monitor
872 * interfaces, but never both at the same time. 872 * interfaces, but never both at the same time.
873 */ 873 */
874#ifndef __CHECKER__
874 BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != 875 BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
875 sizeof(struct ieee80211_tx_status_rtap_hdr)); 876 sizeof(struct ieee80211_tx_status_rtap_hdr));
877#endif
876 local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, 878 local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
877 sizeof(struct ieee80211_tx_status_rtap_hdr)); 879 sizeof(struct ieee80211_tx_status_rtap_hdr));
878 880
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 5c0c20389a1a..e7c5fddb4804 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -92,7 +92,7 @@ struct mesh_path {
92 u8 dst[ETH_ALEN]; 92 u8 dst[ETH_ALEN];
93 u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ 93 u8 mpp[ETH_ALEN]; /* used for MPP or MAP */
94 struct ieee80211_sub_if_data *sdata; 94 struct ieee80211_sub_if_data *sdata;
95 struct sta_info *next_hop; 95 struct sta_info __rcu *next_hop;
96 struct timer_list timer; 96 struct timer_list timer;
97 struct sk_buff_head frame_queue; 97 struct sk_buff_head frame_queue;
98 struct rcu_head rcu; 98 struct rcu_head rcu;
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 2aec7c4f357b..2b18053070c1 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -560,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
560} 560}
561 561
562 562
563static inline struct sta_info *
564next_hop_deref_protected(struct mesh_path *mpath)
565{
566 return rcu_dereference_protected(mpath->next_hop,
567 lockdep_is_held(&mpath->state_lock));
568}
569
570
563static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, 571static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
564 struct ieee80211_mgmt *mgmt, 572 struct ieee80211_mgmt *mgmt,
565 u8 *prep_elem, u32 metric) 573 u8 *prep_elem, u32 metric)
@@ -599,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
599 spin_unlock_bh(&mpath->state_lock); 607 spin_unlock_bh(&mpath->state_lock);
600 goto fail; 608 goto fail;
601 } 609 }
602 memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); 610 memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);
603 spin_unlock_bh(&mpath->state_lock); 611 spin_unlock_bh(&mpath->state_lock);
604 --ttl; 612 --ttl;
605 flags = PREP_IE_FLAGS(prep_elem); 613 flags = PREP_IE_FLAGS(prep_elem);
@@ -651,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
651 if (mpath) { 659 if (mpath) {
652 spin_lock_bh(&mpath->state_lock); 660 spin_lock_bh(&mpath->state_lock);
653 if (mpath->flags & MESH_PATH_ACTIVE && 661 if (mpath->flags & MESH_PATH_ACTIVE &&
654 memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && 662 memcmp(ta, next_hop_deref_protected(mpath)->sta.addr,
663 ETH_ALEN) == 0 &&
655 (!(mpath->flags & MESH_PATH_SN_VALID) || 664 (!(mpath->flags & MESH_PATH_SN_VALID) ||
656 SN_GT(target_sn, mpath->sn))) { 665 SN_GT(target_sn, mpath->sn))) {
657 mpath->flags &= ~MESH_PATH_ACTIVE; 666 mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -913,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
913{ 922{
914 struct sk_buff *skb_to_free = NULL; 923 struct sk_buff *skb_to_free = NULL;
915 struct mesh_path *mpath; 924 struct mesh_path *mpath;
925 struct sta_info *next_hop;
916 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 926 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
917 u8 *target_addr = hdr->addr3; 927 u8 *target_addr = hdr->addr3;
918 int err = 0; 928 int err = 0;
@@ -940,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
940 mesh_queue_preq(mpath, 950 mesh_queue_preq(mpath,
941 PREQ_Q_F_START | PREQ_Q_F_REFRESH); 951 PREQ_Q_F_START | PREQ_Q_F_REFRESH);
942 } 952 }
943 memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); 953 next_hop = rcu_dereference(mpath->next_hop);
954 if (next_hop)
955 memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
956 else
957 err = -ENOENT;
944 } else { 958 } else {
945 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 959 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
946 if (!(mpath->flags & MESH_PATH_RESOLVING)) { 960 if (!(mpath->flags & MESH_PATH_RESOLVING)) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cba8309e9ace..82ab6b4643fc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -67,7 +67,8 @@ static int sta_info_hash_del(struct ieee80211_local *local,
67{ 67{
68 struct sta_info *s; 68 struct sta_info *s;
69 69
70 s = local->sta_hash[STA_HASH(sta->sta.addr)]; 70 s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)],
71 lockdep_is_held(&local->sta_lock));
71 if (!s) 72 if (!s)
72 return -ENOENT; 73 return -ENOENT;
73 if (s == sta) { 74 if (s == sta) {
@@ -76,9 +77,11 @@ static int sta_info_hash_del(struct ieee80211_local *local,
76 return 0; 77 return 0;
77 } 78 }
78 79
79 while (s->hnext && s->hnext != sta) 80 while (rcu_access_pointer(s->hnext) &&
80 s = s->hnext; 81 rcu_access_pointer(s->hnext) != sta)
81 if (s->hnext) { 82 s = rcu_dereference_protected(s->hnext,
83 lockdep_is_held(&local->sta_lock));
84 if (rcu_access_pointer(s->hnext)) {
82 rcu_assign_pointer(s->hnext, sta->hnext); 85 rcu_assign_pointer(s->hnext, sta->hnext);
83 return 0; 86 return 0;
84 } 87 }
@@ -654,9 +657,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
654 657
655 mutex_lock(&local->key_mtx); 658 mutex_lock(&local->key_mtx);
656 for (i = 0; i < NUM_DEFAULT_KEYS; i++) 659 for (i = 0; i < NUM_DEFAULT_KEYS; i++)
657 __ieee80211_key_free(sta->gtk[i]); 660 __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
658 if (sta->ptk) 661 if (sta->ptk)
659 __ieee80211_key_free(sta->ptk); 662 __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
660 mutex_unlock(&local->key_mtx); 663 mutex_unlock(&local->key_mtx);
661 664
662 sta->dead = true; 665 sta->dead = true;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 55c51855ceb7..d6b566076f05 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -164,11 +164,11 @@ struct tid_ampdu_rx {
164struct sta_ampdu_mlme { 164struct sta_ampdu_mlme {
165 struct mutex mtx; 165 struct mutex mtx;
166 /* rx */ 166 /* rx */
167 struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; 167 struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM];
168 unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; 168 unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
169 /* tx */ 169 /* tx */
170 struct work_struct work; 170 struct work_struct work;
171 struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; 171 struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM];
172 struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; 172 struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM];
173 u8 addba_req_num[STA_TID_NUM]; 173 u8 addba_req_num[STA_TID_NUM];
174 u8 dialog_token_allocator; 174 u8 dialog_token_allocator;
@@ -243,11 +243,11 @@ struct sta_ampdu_mlme {
243struct sta_info { 243struct sta_info {
244 /* General information, mostly static */ 244 /* General information, mostly static */
245 struct list_head list; 245 struct list_head list;
246 struct sta_info *hnext; 246 struct sta_info __rcu *hnext;
247 struct ieee80211_local *local; 247 struct ieee80211_local *local;
248 struct ieee80211_sub_if_data *sdata; 248 struct ieee80211_sub_if_data *sdata;
249 struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 249 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
250 struct ieee80211_key *ptk; 250 struct ieee80211_key __rcu *ptk;
251 struct rate_control_ref *rate_ctrl; 251 struct rate_control_ref *rate_ctrl;
252 void *rate_ctrl_priv; 252 void *rate_ctrl_priv;
253 spinlock_t lock; 253 spinlock_t lock;
@@ -403,6 +403,13 @@ static inline u32 get_sta_flags(struct sta_info *sta)
403void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, 403void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
404 struct tid_ampdu_tx *tid_tx); 404 struct tid_ampdu_tx *tid_tx);
405 405
406static inline struct tid_ampdu_tx *
407rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
408{
409 return rcu_dereference_protected(sta->ampdu_mlme.tid_tx[tid],
410 lockdep_is_held(&sta->lock) ||
411 lockdep_is_held(&sta->ampdu_mlme.mtx));
412}
406 413
407#define STA_HASH_SIZE 256 414#define STA_HASH_SIZE 256
408#define STA_HASH(sta) (sta[5]) 415#define STA_HASH(sta) (sta[5])
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c9f12113ca6a..6eeaaa2bbafe 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1147,7 +1147,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
1147 * packet pass through because splicing the frames 1147 * packet pass through because splicing the frames
1148 * back is already done. 1148 * back is already done.
1149 */ 1149 */
1150 tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; 1150 tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid);
1151 1151
1152 if (!tid_tx) { 1152 if (!tid_tx) {
1153 /* do nothing, let packet pass through */ 1153 /* do nothing, let packet pass through */