aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-07-06 15:39:28 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-07-12 06:10:43 -0400
commite2fd5dbc1c7031be5b5de043bcc0a18c7a59a68a (patch)
treef9febb7e331ff24efec9289e2a13be9e146f9cd5 /net/mac80211
parentd811b3d5566f1441b321a1219c260124b209e0bd (diff)
mac80211: make scan_sdata pointer usable with RCU
Making the scan_sdata pointer usable with RCU makes it possible to dereference it in the RX path to see if a received frame actually matches the interface that is scanning. This is just preparations, making the pointer __rcu. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c9
-rw-r--r--net/mac80211/scan.c33
3 files changed, 30 insertions, 14 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c3241c3ec6d1..9f2534a41243 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -972,7 +972,7 @@ struct ieee80211_local {
972 unsigned long leave_oper_channel_time; 972 unsigned long leave_oper_channel_time;
973 enum mac80211_scan_state next_scan_state; 973 enum mac80211_scan_state next_scan_state;
974 struct delayed_work scan_work; 974 struct delayed_work scan_work;
975 struct ieee80211_sub_if_data *scan_sdata; 975 struct ieee80211_sub_if_data __rcu *scan_sdata;
976 enum nl80211_channel_type _oper_channel_type; 976 enum nl80211_channel_type _oper_channel_type;
977 struct ieee80211_channel *oper_channel, *csa_channel; 977 struct ieee80211_channel *oper_channel, *csa_channel;
978 978
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b1edf60fbba7..e3c49748ce8f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -112,10 +112,11 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
112 } 112 }
113 } 113 }
114 114
115 if (local->scan_sdata && 115 sdata = rcu_dereference_protected(local->scan_sdata,
116 !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { 116 lockdep_is_held(&local->mtx));
117 if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
117 scanning = true; 118 scanning = true;
118 local->scan_sdata->vif.bss_conf.idle = false; 119 sdata->vif.bss_conf.idle = false;
119 } 120 }
120 121
121 list_for_each_entry(sdata, &local->interfaces, list) { 122 list_for_each_entry(sdata, &local->interfaces, list) {
@@ -628,7 +629,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
628 629
629 clear_bit(SDATA_STATE_RUNNING, &sdata->state); 630 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
630 631
631 if (local->scan_sdata == sdata) 632 if (rcu_access_pointer(local->scan_sdata) == sdata)
632 ieee80211_scan_cancel(local); 633 ieee80211_scan_cancel(local);
633 634
634 /* 635 /*
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 1ff04f689d1f..704dcf847761 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -293,7 +293,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
293 return; 293 return;
294 294
295 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { 295 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
296 int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); 296 int rc;
297
298 rc = drv_hw_scan(local,
299 rcu_dereference_protected(local->scan_sdata,
300 lockdep_is_held(&local->mtx)),
301 local->hw_scan_req);
302
297 if (rc == 0) 303 if (rc == 0)
298 return; 304 return;
299 } 305 }
@@ -394,7 +400,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local)
394 if (!local->scan_req || local->scanning) 400 if (!local->scan_req || local->scanning)
395 return; 401 return;
396 402
397 if (!ieee80211_can_scan(local, local->scan_sdata)) 403 if (!ieee80211_can_scan(local,
404 rcu_dereference_protected(
405 local->scan_sdata,
406 lockdep_is_held(&local->mtx))))
398 return; 407 return;
399 408
400 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 409 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
@@ -405,9 +414,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
405 unsigned long *next_delay) 414 unsigned long *next_delay)
406{ 415{
407 int i; 416 int i;
408 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 417 struct ieee80211_sub_if_data *sdata;
409 enum ieee80211_band band = local->hw.conf.channel->band; 418 enum ieee80211_band band = local->hw.conf.channel->band;
410 419
420 sdata = rcu_dereference_protected(local->scan_sdata,
421 lockdep_is_held(&local->mtx));;
422
411 for (i = 0; i < local->scan_req->n_ssids; i++) 423 for (i = 0; i < local->scan_req->n_ssids; i++)
412 ieee80211_send_probe_req( 424 ieee80211_send_probe_req(
413 sdata, NULL, 425 sdata, NULL,
@@ -439,7 +451,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
439 if (!ieee80211_can_scan(local, sdata)) { 451 if (!ieee80211_can_scan(local, sdata)) {
440 /* wait for the work to finish/time out */ 452 /* wait for the work to finish/time out */
441 local->scan_req = req; 453 local->scan_req = req;
442 local->scan_sdata = sdata; 454 rcu_assign_pointer(local->scan_sdata, sdata);
443 return 0; 455 return 0;
444 } 456 }
445 457
@@ -473,7 +485,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
473 } 485 }
474 486
475 local->scan_req = req; 487 local->scan_req = req;
476 local->scan_sdata = sdata; 488 rcu_assign_pointer(local->scan_sdata, sdata);
477 489
478 if (local->ops->hw_scan) { 490 if (local->ops->hw_scan) {
479 __set_bit(SCAN_HW_SCANNING, &local->scanning); 491 __set_bit(SCAN_HW_SCANNING, &local->scanning);
@@ -533,7 +545,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
533 ieee80211_recalc_idle(local); 545 ieee80211_recalc_idle(local);
534 546
535 local->scan_req = NULL; 547 local->scan_req = NULL;
536 local->scan_sdata = NULL; 548 rcu_assign_pointer(local->scan_sdata, NULL);
537 } 549 }
538 550
539 return rc; 551 return rc;
@@ -720,7 +732,8 @@ void ieee80211_scan_work(struct work_struct *work)
720 732
721 mutex_lock(&local->mtx); 733 mutex_lock(&local->mtx);
722 734
723 sdata = local->scan_sdata; 735 sdata = rcu_dereference_protected(local->scan_sdata,
736 lockdep_is_held(&local->mtx));
724 737
725 /* When scanning on-channel, the first-callback means completed. */ 738 /* When scanning on-channel, the first-callback means completed. */
726 if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { 739 if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
@@ -741,7 +754,7 @@ void ieee80211_scan_work(struct work_struct *work)
741 int rc; 754 int rc;
742 755
743 local->scan_req = NULL; 756 local->scan_req = NULL;
744 local->scan_sdata = NULL; 757 rcu_assign_pointer(local->scan_sdata, NULL);
745 758
746 rc = __ieee80211_start_scan(sdata, req); 759 rc = __ieee80211_start_scan(sdata, req);
747 if (rc) { 760 if (rc) {
@@ -893,7 +906,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
893 906
894 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { 907 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
895 if (local->ops->cancel_hw_scan) 908 if (local->ops->cancel_hw_scan)
896 drv_cancel_hw_scan(local, local->scan_sdata); 909 drv_cancel_hw_scan(local,
910 rcu_dereference_protected(local->scan_sdata,
911 lockdep_is_held(&local->mtx)));
897 goto out; 912 goto out;
898 } 913 }
899 914