aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */