aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c154
1 files changed, 86 insertions, 68 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 5171a958163..fb274db77e3 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -249,12 +249,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
249 return true; 249 return true;
250} 250}
251 251
252static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 252static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
253 bool was_hw_scan)
253{ 254{
254 struct ieee80211_local *local = hw_to_local(hw); 255 struct ieee80211_local *local = hw_to_local(hw);
255 bool was_hw_scan;
256 256
257 mutex_lock(&local->mtx); 257 lockdep_assert_held(&local->mtx);
258 258
259 /* 259 /*
260 * It's ok to abort a not-yet-running scan (that 260 * It's ok to abort a not-yet-running scan (that
@@ -265,17 +265,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
265 if (WARN_ON(!local->scanning && !aborted)) 265 if (WARN_ON(!local->scanning && !aborted))
266 aborted = true; 266 aborted = true;
267 267
268 if (WARN_ON(!local->scan_req)) { 268 if (WARN_ON(!local->scan_req))
269 mutex_unlock(&local->mtx); 269 return false;
270 return;
271 }
272 270
273 was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
274 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { 271 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
275 ieee80211_queue_delayed_work(&local->hw, 272 int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
276 &local->scan_work, 0); 273 if (rc == 0)
277 mutex_unlock(&local->mtx); 274 return false;
278 return;
279 } 275 }
280 276
281 kfree(local->hw_scan_req); 277 kfree(local->hw_scan_req);
@@ -289,23 +285,25 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
289 local->scanning = 0; 285 local->scanning = 0;
290 local->scan_channel = NULL; 286 local->scan_channel = NULL;
291 287
292 /* we only have to protect scan_req and hw/sw scan */ 288 return true;
293 mutex_unlock(&local->mtx); 289}
294
295 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
296 if (was_hw_scan)
297 goto done;
298
299 ieee80211_configure_filter(local);
300 290
301 drv_sw_scan_complete(local); 291static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
292 bool was_hw_scan)
293{
294 struct ieee80211_local *local = hw_to_local(hw);
302 295
303 ieee80211_offchannel_return(local, true); 296 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
297 if (!was_hw_scan) {
298 ieee80211_configure_filter(local);
299 drv_sw_scan_complete(local);
300 ieee80211_offchannel_return(local, true);
301 }
304 302
305 done:
306 mutex_lock(&local->mtx); 303 mutex_lock(&local->mtx);
307 ieee80211_recalc_idle(local); 304 ieee80211_recalc_idle(local);
308 mutex_unlock(&local->mtx); 305 mutex_unlock(&local->mtx);
306
309 ieee80211_mlme_notify_scan_completed(local); 307 ieee80211_mlme_notify_scan_completed(local);
310 ieee80211_ibss_notify_scan_completed(local); 308 ieee80211_ibss_notify_scan_completed(local);
311 ieee80211_mesh_notify_scan_completed(local); 309 ieee80211_mesh_notify_scan_completed(local);
@@ -366,6 +364,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
366 struct ieee80211_local *local = sdata->local; 364 struct ieee80211_local *local = sdata->local;
367 int rc; 365 int rc;
368 366
367 lockdep_assert_held(&local->mtx);
368
369 if (local->scan_req) 369 if (local->scan_req)
370 return -EBUSY; 370 return -EBUSY;
371 371
@@ -447,8 +447,8 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
447 return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; 447 return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
448} 448}
449 449
450static int ieee80211_scan_state_decision(struct ieee80211_local *local, 450static void ieee80211_scan_state_decision(struct ieee80211_local *local,
451 unsigned long *next_delay) 451 unsigned long *next_delay)
452{ 452{
453 bool associated = false; 453 bool associated = false;
454 bool tx_empty = true; 454 bool tx_empty = true;
@@ -458,12 +458,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
458 struct ieee80211_sub_if_data *sdata; 458 struct ieee80211_sub_if_data *sdata;
459 struct ieee80211_channel *next_chan; 459 struct ieee80211_channel *next_chan;
460 460
461 /* if no more bands/channels left, complete scan and advance to the idle state */
462 if (local->scan_channel_idx >= local->scan_req->n_channels) {
463 __ieee80211_scan_completed(&local->hw, false);
464 return 1;
465 }
466
467 /* 461 /*
468 * check if at least one STA interface is associated, 462 * check if at least one STA interface is associated,
469 * check if at least one STA interface has pending tx frames 463 * check if at least one STA interface has pending tx frames
@@ -535,7 +529,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
535 } 529 }
536 530
537 *next_delay = 0; 531 *next_delay = 0;
538 return 0;
539} 532}
540 533
541static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, 534static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
@@ -651,28 +644,17 @@ void ieee80211_scan_work(struct work_struct *work)
651 container_of(work, struct ieee80211_local, scan_work.work); 644 container_of(work, struct ieee80211_local, scan_work.work);
652 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 645 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
653 unsigned long next_delay = 0; 646 unsigned long next_delay = 0;
647 bool aborted, hw_scan, finish;
654 648
655 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { 649 mutex_lock(&local->mtx);
656 bool aborted;
657 650
651 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
658 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); 652 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
659 __ieee80211_scan_completed(&local->hw, aborted); 653 goto out_complete;
660 return;
661 }
662
663 mutex_lock(&local->mtx);
664 if (!sdata || !local->scan_req) {
665 mutex_unlock(&local->mtx);
666 return;
667 } 654 }
668 655
669 if (local->hw_scan_req) { 656 if (!sdata || !local->scan_req)
670 int rc = drv_hw_scan(local, sdata, local->hw_scan_req); 657 goto out;
671 mutex_unlock(&local->mtx);
672 if (rc)
673 __ieee80211_scan_completed(&local->hw, true);
674 return;
675 }
676 658
677 if (local->scan_req && !local->scanning) { 659 if (local->scan_req && !local->scanning) {
678 struct cfg80211_scan_request *req = local->scan_req; 660 struct cfg80211_scan_request *req = local->scan_req;
@@ -682,21 +664,21 @@ void ieee80211_scan_work(struct work_struct *work)
682 local->scan_sdata = NULL; 664 local->scan_sdata = NULL;
683 665
684 rc = __ieee80211_start_scan(sdata, req); 666 rc = __ieee80211_start_scan(sdata, req);
685 mutex_unlock(&local->mtx); 667 if (rc) {
686 668 /* need to complete scan in cfg80211 */
687 if (rc) 669 local->scan_req = req;
688 __ieee80211_scan_completed(&local->hw, true); 670 aborted = true;
689 return; 671 goto out_complete;
672 } else
673 goto out;
690 } 674 }
691 675
692 mutex_unlock(&local->mtx);
693
694 /* 676 /*
695 * Avoid re-scheduling when the sdata is going away. 677 * Avoid re-scheduling when the sdata is going away.
696 */ 678 */
697 if (!ieee80211_sdata_running(sdata)) { 679 if (!ieee80211_sdata_running(sdata)) {
698 __ieee80211_scan_completed(&local->hw, true); 680 aborted = true;
699 return; 681 goto out_complete;
700 } 682 }
701 683
702 /* 684 /*
@@ -706,8 +688,12 @@ void ieee80211_scan_work(struct work_struct *work)
706 do { 688 do {
707 switch (local->next_scan_state) { 689 switch (local->next_scan_state) {
708 case SCAN_DECISION: 690 case SCAN_DECISION:
709 if (ieee80211_scan_state_decision(local, &next_delay)) 691 /* if no more bands/channels left, complete scan */
710 return; 692 if (local->scan_channel_idx >= local->scan_req->n_channels) {
693 aborted = false;
694 goto out_complete;
695 }
696 ieee80211_scan_state_decision(local, &next_delay);
711 break; 697 break;
712 case SCAN_SET_CHANNEL: 698 case SCAN_SET_CHANNEL:
713 ieee80211_scan_state_set_channel(local, &next_delay); 699 ieee80211_scan_state_set_channel(local, &next_delay);
@@ -725,6 +711,19 @@ void ieee80211_scan_work(struct work_struct *work)
725 } while (next_delay == 0); 711 } while (next_delay == 0);
726 712
727 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); 713 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
714 mutex_unlock(&local->mtx);
715 return;
716
717out_complete:
718 hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
719 finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
720 mutex_unlock(&local->mtx);
721 if (finish)
722 __ieee80211_scan_completed_finish(&local->hw, hw_scan);
723 return;
724
725out:
726 mutex_unlock(&local->mtx);
728} 727}
729 728
730int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, 729int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
@@ -786,21 +785,40 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
786 return ret; 785 return ret;
787} 786}
788 787
788/*
789 * Only call this function when a scan can't be queued -- under RTNL.
790 */
789void ieee80211_scan_cancel(struct ieee80211_local *local) 791void ieee80211_scan_cancel(struct ieee80211_local *local)
790{ 792{
791 bool abortscan; 793 bool abortscan;
792 794 bool finish = false;
793 cancel_delayed_work_sync(&local->scan_work);
794 795
795 /* 796 /*
796 * Only call this function when a scan can't be 797 * We are only canceling software scan, or deferred scan that was not
797 * queued -- mostly at suspend under RTNL. 798 * yet really started (see __ieee80211_start_scan ).
799 *
800 * Regarding hardware scan:
801 * - we can not call __ieee80211_scan_completed() as when
802 * SCAN_HW_SCANNING bit is set this function change
803 * local->hw_scan_req to operate on 5G band, what race with
804 * driver which can use local->hw_scan_req
805 *
806 * - we can not cancel scan_work since driver can schedule it
807 * by ieee80211_scan_completed(..., true) to finish scan
808 *
809 * Hence low lever driver is responsible for canceling HW scan.
798 */ 810 */
811
799 mutex_lock(&local->mtx); 812 mutex_lock(&local->mtx);
800 abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || 813 abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
801 (!local->scanning && local->scan_req); 814 if (abortscan)
815 finish = __ieee80211_scan_completed(&local->hw, true, false);
802 mutex_unlock(&local->mtx); 816 mutex_unlock(&local->mtx);
803 817
804 if (abortscan) 818 if (abortscan) {
805 __ieee80211_scan_completed(&local->hw, true); 819 /* The scan is canceled, but stop work from being pending */
820 cancel_delayed_work_sync(&local->scan_work);
821 }
822 if (finish)
823 __ieee80211_scan_completed_finish(&local->hw, false);
806} 824}