diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-11-19 05:55:49 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-11-19 12:45:58 -0500 |
commit | 6ea0a69ca21bbddab5b3979c2190013b0263e749 (patch) | |
tree | 27fe05578c960fa946d68ce8db3dfead88b47b49 /net/mac80211 | |
parent | ad2b26abc157460ca6fac1a53a2bfeade283adfa (diff) |
mac80211: rcu-ify scan and scheduled scan request pointers
In order to use the scan and scheduled scan request pointers during
RX to check for randomisation, make them accessible using RCU.
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/scan.c | 79 | ||||
-rw-r--r-- | net/mac80211/util.c | 7 |
3 files changed, 56 insertions, 34 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 34168c21bf06..dd27180060b9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1238,7 +1238,7 @@ struct ieee80211_local { | |||
1238 | unsigned long scanning; | 1238 | unsigned long scanning; |
1239 | struct cfg80211_ssid scan_ssid; | 1239 | struct cfg80211_ssid scan_ssid; |
1240 | struct cfg80211_scan_request *int_scan_req; | 1240 | struct cfg80211_scan_request *int_scan_req; |
1241 | struct cfg80211_scan_request *scan_req; | 1241 | struct cfg80211_scan_request __rcu *scan_req; |
1242 | struct ieee80211_scan_request *hw_scan_req; | 1242 | struct ieee80211_scan_request *hw_scan_req; |
1243 | struct cfg80211_chan_def scan_chandef; | 1243 | struct cfg80211_chan_def scan_chandef; |
1244 | enum ieee80211_band hw_scan_band; | 1244 | enum ieee80211_band hw_scan_band; |
@@ -1248,7 +1248,7 @@ struct ieee80211_local { | |||
1248 | 1248 | ||
1249 | struct work_struct sched_scan_stopped_work; | 1249 | struct work_struct sched_scan_stopped_work; |
1250 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | 1250 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; |
1251 | struct cfg80211_sched_scan_request *sched_scan_req; | 1251 | struct cfg80211_sched_scan_request __rcu *sched_scan_req; |
1252 | 1252 | ||
1253 | unsigned long leave_oper_channel_time; | 1253 | unsigned long leave_oper_channel_time; |
1254 | enum mac80211_scan_state next_scan_state; | 1254 | enum mac80211_scan_state next_scan_state; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index d23c8d90c3b4..e75e64b8042c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -234,11 +234,14 @@ ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef, | |||
234 | /* return false if no more work */ | 234 | /* return false if no more work */ |
235 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | 235 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) |
236 | { | 236 | { |
237 | struct cfg80211_scan_request *req = local->scan_req; | 237 | struct cfg80211_scan_request *req; |
238 | struct cfg80211_chan_def chandef; | 238 | struct cfg80211_chan_def chandef; |
239 | u8 bands_used = 0; | 239 | u8 bands_used = 0; |
240 | int i, ielen, n_chans; | 240 | int i, ielen, n_chans; |
241 | 241 | ||
242 | req = rcu_dereference_protected(local->scan_req, | ||
243 | lockdep_is_held(&local->mtx)); | ||
244 | |||
242 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) | 245 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) |
243 | return false; | 246 | return false; |
244 | 247 | ||
@@ -290,6 +293,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
290 | struct ieee80211_local *local = hw_to_local(hw); | 293 | struct ieee80211_local *local = hw_to_local(hw); |
291 | bool hw_scan = local->ops->hw_scan; | 294 | bool hw_scan = local->ops->hw_scan; |
292 | bool was_scanning = local->scanning; | 295 | bool was_scanning = local->scanning; |
296 | struct cfg80211_scan_request *scan_req; | ||
293 | 297 | ||
294 | lockdep_assert_held(&local->mtx); | 298 | lockdep_assert_held(&local->mtx); |
295 | 299 | ||
@@ -322,9 +326,12 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
322 | kfree(local->hw_scan_req); | 326 | kfree(local->hw_scan_req); |
323 | local->hw_scan_req = NULL; | 327 | local->hw_scan_req = NULL; |
324 | 328 | ||
325 | if (local->scan_req != local->int_scan_req) | 329 | scan_req = rcu_dereference_protected(local->scan_req, |
326 | cfg80211_scan_done(local->scan_req, aborted); | 330 | lockdep_is_held(&local->mtx)); |
327 | local->scan_req = NULL; | 331 | |
332 | if (scan_req != local->int_scan_req) | ||
333 | cfg80211_scan_done(scan_req, aborted); | ||
334 | RCU_INIT_POINTER(local->scan_req, NULL); | ||
328 | RCU_INIT_POINTER(local->scan_sdata, NULL); | 335 | RCU_INIT_POINTER(local->scan_sdata, NULL); |
329 | 336 | ||
330 | local->scanning = 0; | 337 | local->scanning = 0; |
@@ -440,23 +447,26 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
440 | { | 447 | { |
441 | int i; | 448 | int i; |
442 | struct ieee80211_sub_if_data *sdata; | 449 | struct ieee80211_sub_if_data *sdata; |
450 | struct cfg80211_scan_request *scan_req; | ||
443 | enum ieee80211_band band = local->hw.conf.chandef.chan->band; | 451 | enum ieee80211_band band = local->hw.conf.chandef.chan->band; |
444 | u32 tx_flags; | 452 | u32 tx_flags; |
445 | 453 | ||
454 | scan_req = rcu_dereference_protected(local->scan_req, | ||
455 | lockdep_is_held(&local->mtx)); | ||
456 | |||
446 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | 457 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; |
447 | if (local->scan_req->no_cck) | 458 | if (scan_req->no_cck) |
448 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 459 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
449 | 460 | ||
450 | sdata = rcu_dereference_protected(local->scan_sdata, | 461 | sdata = rcu_dereference_protected(local->scan_sdata, |
451 | lockdep_is_held(&local->mtx)); | 462 | lockdep_is_held(&local->mtx)); |
452 | 463 | ||
453 | for (i = 0; i < local->scan_req->n_ssids; i++) | 464 | for (i = 0; i < scan_req->n_ssids; i++) |
454 | ieee80211_send_probe_req( | 465 | ieee80211_send_probe_req( |
455 | sdata, NULL, | 466 | sdata, NULL, |
456 | local->scan_req->ssids[i].ssid, | 467 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, |
457 | local->scan_req->ssids[i].ssid_len, | 468 | scan_req->ie, scan_req->ie_len, |
458 | local->scan_req->ie, local->scan_req->ie_len, | 469 | scan_req->rates[band], false, |
459 | local->scan_req->rates[band], false, | ||
460 | tx_flags, local->hw.conf.chandef.chan, true); | 470 | tx_flags, local->hw.conf.chandef.chan, true); |
461 | 471 | ||
462 | /* | 472 | /* |
@@ -480,7 +490,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
480 | 490 | ||
481 | if (!ieee80211_can_scan(local, sdata)) { | 491 | if (!ieee80211_can_scan(local, sdata)) { |
482 | /* wait for the work to finish/time out */ | 492 | /* wait for the work to finish/time out */ |
483 | local->scan_req = req; | 493 | rcu_assign_pointer(local->scan_req, req); |
484 | rcu_assign_pointer(local->scan_sdata, sdata); | 494 | rcu_assign_pointer(local->scan_sdata, sdata); |
485 | return 0; | 495 | return 0; |
486 | } | 496 | } |
@@ -530,7 +540,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
530 | */ | 540 | */ |
531 | } | 541 | } |
532 | 542 | ||
533 | local->scan_req = req; | 543 | rcu_assign_pointer(local->scan_req, req); |
534 | rcu_assign_pointer(local->scan_sdata, sdata); | 544 | rcu_assign_pointer(local->scan_sdata, sdata); |
535 | 545 | ||
536 | if (local->ops->hw_scan) { | 546 | if (local->ops->hw_scan) { |
@@ -558,7 +568,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
558 | 568 | ||
559 | if ((req->channels[0]->flags & | 569 | if ((req->channels[0]->flags & |
560 | IEEE80211_CHAN_NO_IR) || | 570 | IEEE80211_CHAN_NO_IR) || |
561 | !local->scan_req->n_ssids) { | 571 | !req->n_ssids) { |
562 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 572 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
563 | } else { | 573 | } else { |
564 | ieee80211_scan_state_send_probe(local, &next_delay); | 574 | ieee80211_scan_state_send_probe(local, &next_delay); |
@@ -617,6 +627,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
617 | struct ieee80211_sub_if_data *sdata; | 627 | struct ieee80211_sub_if_data *sdata; |
618 | struct ieee80211_channel *next_chan; | 628 | struct ieee80211_channel *next_chan; |
619 | enum mac80211_scan_state next_scan_state; | 629 | enum mac80211_scan_state next_scan_state; |
630 | struct cfg80211_scan_request *scan_req; | ||
620 | 631 | ||
621 | /* | 632 | /* |
622 | * check if at least one STA interface is associated, | 633 | * check if at least one STA interface is associated, |
@@ -641,7 +652,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
641 | } | 652 | } |
642 | mutex_unlock(&local->iflist_mtx); | 653 | mutex_unlock(&local->iflist_mtx); |
643 | 654 | ||
644 | next_chan = local->scan_req->channels[local->scan_channel_idx]; | 655 | scan_req = rcu_dereference_protected(local->scan_req, |
656 | lockdep_is_held(&local->mtx)); | ||
657 | |||
658 | next_chan = scan_req->channels[local->scan_channel_idx]; | ||
645 | 659 | ||
646 | /* | 660 | /* |
647 | * we're currently scanning a different channel, let's | 661 | * we're currently scanning a different channel, let's |
@@ -656,7 +670,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
656 | local->leave_oper_channel_time + HZ / 8); | 670 | local->leave_oper_channel_time + HZ / 8); |
657 | 671 | ||
658 | if (associated && !tx_empty) { | 672 | if (associated && !tx_empty) { |
659 | if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) | 673 | if (scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) |
660 | next_scan_state = SCAN_ABORT; | 674 | next_scan_state = SCAN_ABORT; |
661 | else | 675 | else |
662 | next_scan_state = SCAN_SUSPEND; | 676 | next_scan_state = SCAN_SUSPEND; |
@@ -677,14 +691,18 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
677 | int skip; | 691 | int skip; |
678 | struct ieee80211_channel *chan; | 692 | struct ieee80211_channel *chan; |
679 | enum nl80211_bss_scan_width oper_scan_width; | 693 | enum nl80211_bss_scan_width oper_scan_width; |
694 | struct cfg80211_scan_request *scan_req; | ||
695 | |||
696 | scan_req = rcu_dereference_protected(local->scan_req, | ||
697 | lockdep_is_held(&local->mtx)); | ||
680 | 698 | ||
681 | skip = 0; | 699 | skip = 0; |
682 | chan = local->scan_req->channels[local->scan_channel_idx]; | 700 | chan = scan_req->channels[local->scan_channel_idx]; |
683 | 701 | ||
684 | local->scan_chandef.chan = chan; | 702 | local->scan_chandef.chan = chan; |
685 | local->scan_chandef.center_freq1 = chan->center_freq; | 703 | local->scan_chandef.center_freq1 = chan->center_freq; |
686 | local->scan_chandef.center_freq2 = 0; | 704 | local->scan_chandef.center_freq2 = 0; |
687 | switch (local->scan_req->scan_width) { | 705 | switch (scan_req->scan_width) { |
688 | case NL80211_BSS_CHAN_WIDTH_5: | 706 | case NL80211_BSS_CHAN_WIDTH_5: |
689 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; | 707 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; |
690 | break; | 708 | break; |
@@ -698,7 +716,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
698 | oper_scan_width = cfg80211_chandef_to_scan_width( | 716 | oper_scan_width = cfg80211_chandef_to_scan_width( |
699 | &local->_oper_chandef); | 717 | &local->_oper_chandef); |
700 | if (chan == local->_oper_chandef.chan && | 718 | if (chan == local->_oper_chandef.chan && |
701 | oper_scan_width == local->scan_req->scan_width) | 719 | oper_scan_width == scan_req->scan_width) |
702 | local->scan_chandef = local->_oper_chandef; | 720 | local->scan_chandef = local->_oper_chandef; |
703 | else | 721 | else |
704 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | 722 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
@@ -727,8 +745,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
727 | * | 745 | * |
728 | * In any case, it is not necessary for a passive scan. | 746 | * In any case, it is not necessary for a passive scan. |
729 | */ | 747 | */ |
730 | if (chan->flags & IEEE80211_CHAN_NO_IR || | 748 | if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) { |
731 | !local->scan_req->n_ssids) { | ||
732 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 749 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
733 | local->next_scan_state = SCAN_DECISION; | 750 | local->next_scan_state = SCAN_DECISION; |
734 | return; | 751 | return; |
@@ -777,6 +794,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
777 | struct ieee80211_local *local = | 794 | struct ieee80211_local *local = |
778 | container_of(work, struct ieee80211_local, scan_work.work); | 795 | container_of(work, struct ieee80211_local, scan_work.work); |
779 | struct ieee80211_sub_if_data *sdata; | 796 | struct ieee80211_sub_if_data *sdata; |
797 | struct cfg80211_scan_request *scan_req; | ||
780 | unsigned long next_delay = 0; | 798 | unsigned long next_delay = 0; |
781 | bool aborted; | 799 | bool aborted; |
782 | 800 | ||
@@ -784,6 +802,8 @@ void ieee80211_scan_work(struct work_struct *work) | |||
784 | 802 | ||
785 | sdata = rcu_dereference_protected(local->scan_sdata, | 803 | sdata = rcu_dereference_protected(local->scan_sdata, |
786 | lockdep_is_held(&local->mtx)); | 804 | lockdep_is_held(&local->mtx)); |
805 | scan_req = rcu_dereference_protected(local->scan_req, | ||
806 | lockdep_is_held(&local->mtx)); | ||
787 | 807 | ||
788 | /* When scanning on-channel, the first-callback means completed. */ | 808 | /* When scanning on-channel, the first-callback means completed. */ |
789 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { | 809 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { |
@@ -796,20 +816,19 @@ void ieee80211_scan_work(struct work_struct *work) | |||
796 | goto out_complete; | 816 | goto out_complete; |
797 | } | 817 | } |
798 | 818 | ||
799 | if (!sdata || !local->scan_req) | 819 | if (!sdata || !scan_req) |
800 | goto out; | 820 | goto out; |
801 | 821 | ||
802 | if (!local->scanning) { | 822 | if (!local->scanning) { |
803 | struct cfg80211_scan_request *req = local->scan_req; | ||
804 | int rc; | 823 | int rc; |
805 | 824 | ||
806 | local->scan_req = NULL; | 825 | RCU_INIT_POINTER(local->scan_req, NULL); |
807 | RCU_INIT_POINTER(local->scan_sdata, NULL); | 826 | RCU_INIT_POINTER(local->scan_sdata, NULL); |
808 | 827 | ||
809 | rc = __ieee80211_start_scan(sdata, req); | 828 | rc = __ieee80211_start_scan(sdata, scan_req); |
810 | if (rc) { | 829 | if (rc) { |
811 | /* need to complete scan in cfg80211 */ | 830 | /* need to complete scan in cfg80211 */ |
812 | local->scan_req = req; | 831 | rcu_assign_pointer(local->scan_req, scan_req); |
813 | aborted = true; | 832 | aborted = true; |
814 | goto out_complete; | 833 | goto out_complete; |
815 | } else | 834 | } else |
@@ -829,7 +848,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
829 | switch (local->next_scan_state) { | 848 | switch (local->next_scan_state) { |
830 | case SCAN_DECISION: | 849 | case SCAN_DECISION: |
831 | /* if no more bands/channels left, complete scan */ | 850 | /* if no more bands/channels left, complete scan */ |
832 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 851 | if (local->scan_channel_idx >= scan_req->n_channels) { |
833 | aborted = false; | 852 | aborted = false; |
834 | goto out_complete; | 853 | goto out_complete; |
835 | } | 854 | } |
@@ -1043,7 +1062,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1043 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1062 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1044 | if (ret == 0) { | 1063 | if (ret == 0) { |
1045 | rcu_assign_pointer(local->sched_scan_sdata, sdata); | 1064 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
1046 | local->sched_scan_req = req; | 1065 | rcu_assign_pointer(local->sched_scan_req, req); |
1047 | } | 1066 | } |
1048 | 1067 | ||
1049 | kfree(ie); | 1068 | kfree(ie); |
@@ -1052,7 +1071,7 @@ out: | |||
1052 | if (ret) { | 1071 | if (ret) { |
1053 | /* Clean in case of failure after HW restart or upon resume. */ | 1072 | /* Clean in case of failure after HW restart or upon resume. */ |
1054 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | 1073 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); |
1055 | local->sched_scan_req = NULL; | 1074 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1056 | } | 1075 | } |
1057 | 1076 | ||
1058 | return ret; | 1077 | return ret; |
@@ -1090,7 +1109,7 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
1090 | } | 1109 | } |
1091 | 1110 | ||
1092 | /* We don't want to restart sched scan anymore. */ | 1111 | /* We don't want to restart sched scan anymore. */ |
1093 | local->sched_scan_req = NULL; | 1112 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1094 | 1113 | ||
1095 | if (rcu_access_pointer(local->sched_scan_sdata)) { | 1114 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
1096 | ret = drv_sched_scan_stop(local, sdata); | 1115 | ret = drv_sched_scan_stop(local, sdata); |
@@ -1125,7 +1144,7 @@ void ieee80211_sched_scan_end(struct ieee80211_local *local) | |||
1125 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | 1144 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); |
1126 | 1145 | ||
1127 | /* If sched scan was aborted by the driver. */ | 1146 | /* If sched scan was aborted by the driver. */ |
1128 | local->sched_scan_req = NULL; | 1147 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1129 | 1148 | ||
1130 | mutex_unlock(&local->mtx); | 1149 | mutex_unlock(&local->mtx); |
1131 | 1150 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 745a8a9cbbb5..0ad534abc008 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1721,6 +1721,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1721 | int res, i; | 1721 | int res, i; |
1722 | bool reconfig_due_to_wowlan = false; | 1722 | bool reconfig_due_to_wowlan = false; |
1723 | struct ieee80211_sub_if_data *sched_scan_sdata; | 1723 | struct ieee80211_sub_if_data *sched_scan_sdata; |
1724 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
1724 | bool sched_scan_stopped = false; | 1725 | bool sched_scan_stopped = false; |
1725 | 1726 | ||
1726 | #ifdef CONFIG_PM | 1727 | #ifdef CONFIG_PM |
@@ -2011,13 +2012,15 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2011 | mutex_lock(&local->mtx); | 2012 | mutex_lock(&local->mtx); |
2012 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | 2013 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, |
2013 | lockdep_is_held(&local->mtx)); | 2014 | lockdep_is_held(&local->mtx)); |
2014 | if (sched_scan_sdata && local->sched_scan_req) | 2015 | sched_scan_req = rcu_dereference_protected(local->sched_scan_req, |
2016 | lockdep_is_held(&local->mtx)); | ||
2017 | if (sched_scan_sdata && sched_scan_req) | ||
2015 | /* | 2018 | /* |
2016 | * Sched scan stopped, but we don't want to report it. Instead, | 2019 | * Sched scan stopped, but we don't want to report it. Instead, |
2017 | * we're trying to reschedule. | 2020 | * we're trying to reschedule. |
2018 | */ | 2021 | */ |
2019 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | 2022 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, |
2020 | local->sched_scan_req)) | 2023 | sched_scan_req)) |
2021 | sched_scan_stopped = true; | 2024 | sched_scan_stopped = true; |
2022 | mutex_unlock(&local->mtx); | 2025 | mutex_unlock(&local->mtx); |
2023 | 2026 | ||