diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-11-20 16:09:30 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-11-20 16:09:30 -0500 |
commit | 9a638ddfb09e5aa17158842c95526e1aa79f92e6 (patch) | |
tree | 7edf2e128b23f711cf28273dca3ff69f3706925a /net/mac80211/scan.c | |
parent | b4c1b70823721e9edb19a839188e4dae50ce878d (diff) | |
parent | 75769c80e381653994293b5aa5a8cfec50088f9f (diff) |
Merge tag 'mac80211-next-for-john-2014-11-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg <johannes@sipsolutions.net> says:
"It has been a while since my last pull request, so we accumulated
another relatively large set of changes:
* TDLS off-channel support set from Arik/Liad, with some support
patches I did
* custom regulatory fixes from Arik
* minstrel VHT fix (and a small optimisation) from Felix
* add back radiotap vendor namespace support (myself)
* random MAC address scanning for cfg80211/mac80211/hwsim (myself)
* CSA improvements (Luca)
* WoWLAN Net Detect (wake on network found) support (Luca)
* and lots of other smaller changes from many people"
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r-- | net/mac80211/scan.c | 129 |
1 files changed, 88 insertions, 41 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index af0d094b2f2f..ae842678b629 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
184 | return; | 184 | return; |
185 | 185 | ||
186 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { | 186 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { |
187 | /* ignore ProbeResp to foreign address */ | 187 | struct cfg80211_scan_request *scan_req; |
188 | if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && | 188 | struct cfg80211_sched_scan_request *sched_scan_req; |
189 | (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr))) | 189 | |
190 | scan_req = rcu_dereference(local->scan_req); | ||
191 | sched_scan_req = rcu_dereference(local->sched_scan_req); | ||
192 | |||
193 | /* ignore ProbeResp to foreign address unless scanning | ||
194 | * with randomised address | ||
195 | */ | ||
196 | if (!(sdata1 && | ||
197 | (ether_addr_equal(mgmt->da, sdata1->vif.addr) || | ||
198 | scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) && | ||
199 | !(sdata2 && | ||
200 | (ether_addr_equal(mgmt->da, sdata2->vif.addr) || | ||
201 | sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))) | ||
190 | return; | 202 | return; |
191 | 203 | ||
192 | elements = mgmt->u.probe_resp.variable; | 204 | elements = mgmt->u.probe_resp.variable; |
@@ -234,11 +246,14 @@ ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef, | |||
234 | /* return false if no more work */ | 246 | /* return false if no more work */ |
235 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | 247 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) |
236 | { | 248 | { |
237 | struct cfg80211_scan_request *req = local->scan_req; | 249 | struct cfg80211_scan_request *req; |
238 | struct cfg80211_chan_def chandef; | 250 | struct cfg80211_chan_def chandef; |
239 | u8 bands_used = 0; | 251 | u8 bands_used = 0; |
240 | int i, ielen, n_chans; | 252 | int i, ielen, n_chans; |
241 | 253 | ||
254 | req = rcu_dereference_protected(local->scan_req, | ||
255 | lockdep_is_held(&local->mtx)); | ||
256 | |||
242 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) | 257 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) |
243 | return false; | 258 | return false; |
244 | 259 | ||
@@ -281,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
281 | bands_used, req->rates, &chandef); | 296 | bands_used, req->rates, &chandef); |
282 | local->hw_scan_req->req.ie_len = ielen; | 297 | local->hw_scan_req->req.ie_len = ielen; |
283 | local->hw_scan_req->req.no_cck = req->no_cck; | 298 | local->hw_scan_req->req.no_cck = req->no_cck; |
299 | ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); | ||
300 | ether_addr_copy(local->hw_scan_req->req.mac_addr_mask, | ||
301 | req->mac_addr_mask); | ||
284 | 302 | ||
285 | return true; | 303 | return true; |
286 | } | 304 | } |
@@ -290,6 +308,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
290 | struct ieee80211_local *local = hw_to_local(hw); | 308 | struct ieee80211_local *local = hw_to_local(hw); |
291 | bool hw_scan = local->ops->hw_scan; | 309 | bool hw_scan = local->ops->hw_scan; |
292 | bool was_scanning = local->scanning; | 310 | bool was_scanning = local->scanning; |
311 | struct cfg80211_scan_request *scan_req; | ||
312 | struct ieee80211_sub_if_data *scan_sdata; | ||
293 | 313 | ||
294 | lockdep_assert_held(&local->mtx); | 314 | lockdep_assert_held(&local->mtx); |
295 | 315 | ||
@@ -322,9 +342,15 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
322 | kfree(local->hw_scan_req); | 342 | kfree(local->hw_scan_req); |
323 | local->hw_scan_req = NULL; | 343 | local->hw_scan_req = NULL; |
324 | 344 | ||
325 | if (local->scan_req != local->int_scan_req) | 345 | scan_req = rcu_dereference_protected(local->scan_req, |
326 | cfg80211_scan_done(local->scan_req, aborted); | 346 | lockdep_is_held(&local->mtx)); |
327 | local->scan_req = NULL; | 347 | |
348 | if (scan_req != local->int_scan_req) | ||
349 | cfg80211_scan_done(scan_req, aborted); | ||
350 | RCU_INIT_POINTER(local->scan_req, NULL); | ||
351 | |||
352 | scan_sdata = rcu_dereference_protected(local->scan_sdata, | ||
353 | lockdep_is_held(&local->mtx)); | ||
328 | RCU_INIT_POINTER(local->scan_sdata, NULL); | 354 | RCU_INIT_POINTER(local->scan_sdata, NULL); |
329 | 355 | ||
330 | local->scanning = 0; | 356 | local->scanning = 0; |
@@ -335,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
335 | 361 | ||
336 | if (!hw_scan) { | 362 | if (!hw_scan) { |
337 | ieee80211_configure_filter(local); | 363 | ieee80211_configure_filter(local); |
338 | drv_sw_scan_complete(local); | 364 | drv_sw_scan_complete(local, scan_sdata); |
339 | ieee80211_offchannel_return(local); | 365 | ieee80211_offchannel_return(local); |
340 | } | 366 | } |
341 | 367 | ||
@@ -361,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
361 | } | 387 | } |
362 | EXPORT_SYMBOL(ieee80211_scan_completed); | 388 | EXPORT_SYMBOL(ieee80211_scan_completed); |
363 | 389 | ||
364 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) | 390 | static int ieee80211_start_sw_scan(struct ieee80211_local *local, |
391 | struct ieee80211_sub_if_data *sdata) | ||
365 | { | 392 | { |
366 | /* Software scan is not supported in multi-channel cases */ | 393 | /* Software scan is not supported in multi-channel cases */ |
367 | if (local->use_chanctx) | 394 | if (local->use_chanctx) |
@@ -380,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
380 | * nullfunc frames and probe requests will be dropped in | 407 | * nullfunc frames and probe requests will be dropped in |
381 | * ieee80211_tx_h_check_assoc(). | 408 | * ieee80211_tx_h_check_assoc(). |
382 | */ | 409 | */ |
383 | drv_sw_scan_start(local); | 410 | drv_sw_scan_start(local, sdata, local->scan_addr); |
384 | 411 | ||
385 | local->leave_oper_channel_time = jiffies; | 412 | local->leave_oper_channel_time = jiffies; |
386 | local->next_scan_state = SCAN_DECISION; | 413 | local->next_scan_state = SCAN_DECISION; |
@@ -440,23 +467,26 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
440 | { | 467 | { |
441 | int i; | 468 | int i; |
442 | struct ieee80211_sub_if_data *sdata; | 469 | struct ieee80211_sub_if_data *sdata; |
470 | struct cfg80211_scan_request *scan_req; | ||
443 | enum ieee80211_band band = local->hw.conf.chandef.chan->band; | 471 | enum ieee80211_band band = local->hw.conf.chandef.chan->band; |
444 | u32 tx_flags; | 472 | u32 tx_flags; |
445 | 473 | ||
474 | scan_req = rcu_dereference_protected(local->scan_req, | ||
475 | lockdep_is_held(&local->mtx)); | ||
476 | |||
446 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | 477 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; |
447 | if (local->scan_req->no_cck) | 478 | if (scan_req->no_cck) |
448 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 479 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
449 | 480 | ||
450 | sdata = rcu_dereference_protected(local->scan_sdata, | 481 | sdata = rcu_dereference_protected(local->scan_sdata, |
451 | lockdep_is_held(&local->mtx)); | 482 | lockdep_is_held(&local->mtx)); |
452 | 483 | ||
453 | for (i = 0; i < local->scan_req->n_ssids; i++) | 484 | for (i = 0; i < scan_req->n_ssids; i++) |
454 | ieee80211_send_probe_req( | 485 | ieee80211_send_probe_req( |
455 | sdata, NULL, | 486 | sdata, local->scan_addr, NULL, |
456 | local->scan_req->ssids[i].ssid, | 487 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, |
457 | local->scan_req->ssids[i].ssid_len, | 488 | scan_req->ie, scan_req->ie_len, |
458 | local->scan_req->ie, local->scan_req->ie_len, | 489 | scan_req->rates[band], false, |
459 | local->scan_req->rates[band], false, | ||
460 | tx_flags, local->hw.conf.chandef.chan, true); | 490 | tx_flags, local->hw.conf.chandef.chan, true); |
461 | 491 | ||
462 | /* | 492 | /* |
@@ -480,7 +510,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
480 | 510 | ||
481 | if (!ieee80211_can_scan(local, sdata)) { | 511 | if (!ieee80211_can_scan(local, sdata)) { |
482 | /* wait for the work to finish/time out */ | 512 | /* wait for the work to finish/time out */ |
483 | local->scan_req = req; | 513 | rcu_assign_pointer(local->scan_req, req); |
484 | rcu_assign_pointer(local->scan_sdata, sdata); | 514 | rcu_assign_pointer(local->scan_sdata, sdata); |
485 | return 0; | 515 | return 0; |
486 | } | 516 | } |
@@ -530,9 +560,16 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
530 | */ | 560 | */ |
531 | } | 561 | } |
532 | 562 | ||
533 | local->scan_req = req; | 563 | rcu_assign_pointer(local->scan_req, req); |
534 | rcu_assign_pointer(local->scan_sdata, sdata); | 564 | rcu_assign_pointer(local->scan_sdata, sdata); |
535 | 565 | ||
566 | if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) | ||
567 | get_random_mask_addr(local->scan_addr, | ||
568 | req->mac_addr, | ||
569 | req->mac_addr_mask); | ||
570 | else | ||
571 | memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN); | ||
572 | |||
536 | if (local->ops->hw_scan) { | 573 | if (local->ops->hw_scan) { |
537 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 574 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
538 | } else if ((req->n_channels == 1) && | 575 | } else if ((req->n_channels == 1) && |
@@ -549,7 +586,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
549 | 586 | ||
550 | /* Notify driver scan is starting, keep order of operations | 587 | /* Notify driver scan is starting, keep order of operations |
551 | * same as normal software scan, in case that matters. */ | 588 | * same as normal software scan, in case that matters. */ |
552 | drv_sw_scan_start(local); | 589 | drv_sw_scan_start(local, sdata, local->scan_addr); |
553 | 590 | ||
554 | ieee80211_configure_filter(local); /* accept probe-responses */ | 591 | ieee80211_configure_filter(local); /* accept probe-responses */ |
555 | 592 | ||
@@ -558,7 +595,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
558 | 595 | ||
559 | if ((req->channels[0]->flags & | 596 | if ((req->channels[0]->flags & |
560 | IEEE80211_CHAN_NO_IR) || | 597 | IEEE80211_CHAN_NO_IR) || |
561 | !local->scan_req->n_ssids) { | 598 | !req->n_ssids) { |
562 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 599 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
563 | } else { | 600 | } else { |
564 | ieee80211_scan_state_send_probe(local, &next_delay); | 601 | ieee80211_scan_state_send_probe(local, &next_delay); |
@@ -579,8 +616,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
579 | if (local->ops->hw_scan) { | 616 | if (local->ops->hw_scan) { |
580 | WARN_ON(!ieee80211_prep_hw_scan(local)); | 617 | WARN_ON(!ieee80211_prep_hw_scan(local)); |
581 | rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 618 | rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
582 | } else | 619 | } else { |
583 | rc = ieee80211_start_sw_scan(local); | 620 | rc = ieee80211_start_sw_scan(local, sdata); |
621 | } | ||
584 | 622 | ||
585 | if (rc) { | 623 | if (rc) { |
586 | kfree(local->hw_scan_req); | 624 | kfree(local->hw_scan_req); |
@@ -617,6 +655,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
617 | struct ieee80211_sub_if_data *sdata; | 655 | struct ieee80211_sub_if_data *sdata; |
618 | struct ieee80211_channel *next_chan; | 656 | struct ieee80211_channel *next_chan; |
619 | enum mac80211_scan_state next_scan_state; | 657 | enum mac80211_scan_state next_scan_state; |
658 | struct cfg80211_scan_request *scan_req; | ||
620 | 659 | ||
621 | /* | 660 | /* |
622 | * check if at least one STA interface is associated, | 661 | * check if at least one STA interface is associated, |
@@ -641,7 +680,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
641 | } | 680 | } |
642 | mutex_unlock(&local->iflist_mtx); | 681 | mutex_unlock(&local->iflist_mtx); |
643 | 682 | ||
644 | next_chan = local->scan_req->channels[local->scan_channel_idx]; | 683 | scan_req = rcu_dereference_protected(local->scan_req, |
684 | lockdep_is_held(&local->mtx)); | ||
685 | |||
686 | next_chan = scan_req->channels[local->scan_channel_idx]; | ||
645 | 687 | ||
646 | /* | 688 | /* |
647 | * we're currently scanning a different channel, let's | 689 | * we're currently scanning a different channel, let's |
@@ -656,7 +698,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
656 | local->leave_oper_channel_time + HZ / 8); | 698 | local->leave_oper_channel_time + HZ / 8); |
657 | 699 | ||
658 | if (associated && !tx_empty) { | 700 | if (associated && !tx_empty) { |
659 | if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) | 701 | if (scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) |
660 | next_scan_state = SCAN_ABORT; | 702 | next_scan_state = SCAN_ABORT; |
661 | else | 703 | else |
662 | next_scan_state = SCAN_SUSPEND; | 704 | next_scan_state = SCAN_SUSPEND; |
@@ -677,14 +719,18 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
677 | int skip; | 719 | int skip; |
678 | struct ieee80211_channel *chan; | 720 | struct ieee80211_channel *chan; |
679 | enum nl80211_bss_scan_width oper_scan_width; | 721 | enum nl80211_bss_scan_width oper_scan_width; |
722 | struct cfg80211_scan_request *scan_req; | ||
723 | |||
724 | scan_req = rcu_dereference_protected(local->scan_req, | ||
725 | lockdep_is_held(&local->mtx)); | ||
680 | 726 | ||
681 | skip = 0; | 727 | skip = 0; |
682 | chan = local->scan_req->channels[local->scan_channel_idx]; | 728 | chan = scan_req->channels[local->scan_channel_idx]; |
683 | 729 | ||
684 | local->scan_chandef.chan = chan; | 730 | local->scan_chandef.chan = chan; |
685 | local->scan_chandef.center_freq1 = chan->center_freq; | 731 | local->scan_chandef.center_freq1 = chan->center_freq; |
686 | local->scan_chandef.center_freq2 = 0; | 732 | local->scan_chandef.center_freq2 = 0; |
687 | switch (local->scan_req->scan_width) { | 733 | switch (scan_req->scan_width) { |
688 | case NL80211_BSS_CHAN_WIDTH_5: | 734 | case NL80211_BSS_CHAN_WIDTH_5: |
689 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; | 735 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; |
690 | break; | 736 | break; |
@@ -698,7 +744,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
698 | oper_scan_width = cfg80211_chandef_to_scan_width( | 744 | oper_scan_width = cfg80211_chandef_to_scan_width( |
699 | &local->_oper_chandef); | 745 | &local->_oper_chandef); |
700 | if (chan == local->_oper_chandef.chan && | 746 | if (chan == local->_oper_chandef.chan && |
701 | oper_scan_width == local->scan_req->scan_width) | 747 | oper_scan_width == scan_req->scan_width) |
702 | local->scan_chandef = local->_oper_chandef; | 748 | local->scan_chandef = local->_oper_chandef; |
703 | else | 749 | else |
704 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | 750 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
@@ -727,8 +773,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
727 | * | 773 | * |
728 | * In any case, it is not necessary for a passive scan. | 774 | * In any case, it is not necessary for a passive scan. |
729 | */ | 775 | */ |
730 | if (chan->flags & IEEE80211_CHAN_NO_IR || | 776 | if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) { |
731 | !local->scan_req->n_ssids) { | ||
732 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 777 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
733 | local->next_scan_state = SCAN_DECISION; | 778 | local->next_scan_state = SCAN_DECISION; |
734 | return; | 779 | return; |
@@ -777,6 +822,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
777 | struct ieee80211_local *local = | 822 | struct ieee80211_local *local = |
778 | container_of(work, struct ieee80211_local, scan_work.work); | 823 | container_of(work, struct ieee80211_local, scan_work.work); |
779 | struct ieee80211_sub_if_data *sdata; | 824 | struct ieee80211_sub_if_data *sdata; |
825 | struct cfg80211_scan_request *scan_req; | ||
780 | unsigned long next_delay = 0; | 826 | unsigned long next_delay = 0; |
781 | bool aborted; | 827 | bool aborted; |
782 | 828 | ||
@@ -784,6 +830,8 @@ void ieee80211_scan_work(struct work_struct *work) | |||
784 | 830 | ||
785 | sdata = rcu_dereference_protected(local->scan_sdata, | 831 | sdata = rcu_dereference_protected(local->scan_sdata, |
786 | lockdep_is_held(&local->mtx)); | 832 | lockdep_is_held(&local->mtx)); |
833 | scan_req = rcu_dereference_protected(local->scan_req, | ||
834 | lockdep_is_held(&local->mtx)); | ||
787 | 835 | ||
788 | /* When scanning on-channel, the first-callback means completed. */ | 836 | /* When scanning on-channel, the first-callback means completed. */ |
789 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { | 837 | if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { |
@@ -796,20 +844,19 @@ void ieee80211_scan_work(struct work_struct *work) | |||
796 | goto out_complete; | 844 | goto out_complete; |
797 | } | 845 | } |
798 | 846 | ||
799 | if (!sdata || !local->scan_req) | 847 | if (!sdata || !scan_req) |
800 | goto out; | 848 | goto out; |
801 | 849 | ||
802 | if (local->scan_req && !local->scanning) { | 850 | if (!local->scanning) { |
803 | struct cfg80211_scan_request *req = local->scan_req; | ||
804 | int rc; | 851 | int rc; |
805 | 852 | ||
806 | local->scan_req = NULL; | 853 | RCU_INIT_POINTER(local->scan_req, NULL); |
807 | RCU_INIT_POINTER(local->scan_sdata, NULL); | 854 | RCU_INIT_POINTER(local->scan_sdata, NULL); |
808 | 855 | ||
809 | rc = __ieee80211_start_scan(sdata, req); | 856 | rc = __ieee80211_start_scan(sdata, scan_req); |
810 | if (rc) { | 857 | if (rc) { |
811 | /* need to complete scan in cfg80211 */ | 858 | /* need to complete scan in cfg80211 */ |
812 | local->scan_req = req; | 859 | rcu_assign_pointer(local->scan_req, scan_req); |
813 | aborted = true; | 860 | aborted = true; |
814 | goto out_complete; | 861 | goto out_complete; |
815 | } else | 862 | } else |
@@ -829,7 +876,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
829 | switch (local->next_scan_state) { | 876 | switch (local->next_scan_state) { |
830 | case SCAN_DECISION: | 877 | case SCAN_DECISION: |
831 | /* if no more bands/channels left, complete scan */ | 878 | /* if no more bands/channels left, complete scan */ |
832 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 879 | if (local->scan_channel_idx >= scan_req->n_channels) { |
833 | aborted = false; | 880 | aborted = false; |
834 | goto out_complete; | 881 | goto out_complete; |
835 | } | 882 | } |
@@ -1043,7 +1090,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); | 1090 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1044 | if (ret == 0) { | 1091 | if (ret == 0) { |
1045 | rcu_assign_pointer(local->sched_scan_sdata, sdata); | 1092 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
1046 | local->sched_scan_req = req; | 1093 | rcu_assign_pointer(local->sched_scan_req, req); |
1047 | } | 1094 | } |
1048 | 1095 | ||
1049 | kfree(ie); | 1096 | kfree(ie); |
@@ -1052,7 +1099,7 @@ out: | |||
1052 | if (ret) { | 1099 | if (ret) { |
1053 | /* Clean in case of failure after HW restart or upon resume. */ | 1100 | /* Clean in case of failure after HW restart or upon resume. */ |
1054 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | 1101 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); |
1055 | local->sched_scan_req = NULL; | 1102 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1056 | } | 1103 | } |
1057 | 1104 | ||
1058 | return ret; | 1105 | return ret; |
@@ -1090,7 +1137,7 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
1090 | } | 1137 | } |
1091 | 1138 | ||
1092 | /* We don't want to restart sched scan anymore. */ | 1139 | /* We don't want to restart sched scan anymore. */ |
1093 | local->sched_scan_req = NULL; | 1140 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1094 | 1141 | ||
1095 | if (rcu_access_pointer(local->sched_scan_sdata)) { | 1142 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
1096 | ret = drv_sched_scan_stop(local, sdata); | 1143 | ret = drv_sched_scan_stop(local, sdata); |
@@ -1125,7 +1172,7 @@ void ieee80211_sched_scan_end(struct ieee80211_local *local) | |||
1125 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | 1172 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); |
1126 | 1173 | ||
1127 | /* If sched scan was aborted by the driver. */ | 1174 | /* If sched scan was aborted by the driver. */ |
1128 | local->sched_scan_req = NULL; | 1175 | RCU_INIT_POINTER(local->sched_scan_req, NULL); |
1129 | 1176 | ||
1130 | mutex_unlock(&local->mtx); | 1177 | mutex_unlock(&local->mtx); |
1131 | 1178 | ||