aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h10
-rw-r--r--net/mac80211/driver-ops.h10
-rw-r--r--net/mac80211/driver-trace.h6
-rw-r--r--net/mac80211/scan.c37
4 files changed, 47 insertions, 16 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e33fe795a3a4..120f102814b6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1708,6 +1708,14 @@ enum ieee80211_ampdu_mlme_action {
1708 * any error unless this callback returned a negative error code. 1708 * any error unless this callback returned a negative error code.
1709 * The callback can sleep. 1709 * The callback can sleep.
1710 * 1710 *
1711 * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
1712 * The driver should ask the hardware to cancel the scan (if possible),
1713 * but the scan will be completed only after the driver will call
1714 * ieee80211_scan_completed().
1715 * This callback is needed for wowlan, to prevent enqueueing a new
1716 * scan_work after the low-level driver was already suspended.
1717 * The callback can sleep.
1718 *
1711 * @sched_scan_start: Ask the hardware to start scanning repeatedly at 1719 * @sched_scan_start: Ask the hardware to start scanning repeatedly at
1712 * specific intervals. The driver must call the 1720 * specific intervals. The driver must call the
1713 * ieee80211_sched_scan_results() function whenever it finds results. 1721 * ieee80211_sched_scan_results() function whenever it finds results.
@@ -1900,6 +1908,8 @@ struct ieee80211_ops {
1900 u32 iv32, u16 *phase1key); 1908 u32 iv32, u16 *phase1key);
1901 int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1909 int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1902 struct cfg80211_scan_request *req); 1910 struct cfg80211_scan_request *req);
1911 void (*cancel_hw_scan)(struct ieee80211_hw *hw,
1912 struct ieee80211_vif *vif);
1903 int (*sched_scan_start)(struct ieee80211_hw *hw, 1913 int (*sched_scan_start)(struct ieee80211_hw *hw,
1904 struct ieee80211_vif *vif, 1914 struct ieee80211_vif *vif,
1905 struct cfg80211_sched_scan_request *req, 1915 struct cfg80211_sched_scan_request *req,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index eebf7a67daf7..0e7e4268ddf6 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -218,6 +218,16 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
218 return ret; 218 return ret;
219} 219}
220 220
221static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
222 struct ieee80211_sub_if_data *sdata)
223{
224 might_sleep();
225
226 trace_drv_cancel_hw_scan(local, sdata);
227 local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
228 trace_drv_return_void(local);
229}
230
221static inline int 231static inline int
222drv_sched_scan_start(struct ieee80211_local *local, 232drv_sched_scan_start(struct ieee80211_local *local,
223 struct ieee80211_sub_if_data *sdata, 233 struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ed9edcbd9aa5..3cb6795e926d 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -460,6 +460,12 @@ DEFINE_EVENT(local_sdata_evt, drv_hw_scan,
460 TP_ARGS(local, sdata) 460 TP_ARGS(local, sdata)
461); 461);
462 462
463DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
464 TP_PROTO(struct ieee80211_local *local,
465 struct ieee80211_sub_if_data *sdata),
466 TP_ARGS(local, sdata)
467);
468
463DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, 469DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
464 TP_PROTO(struct ieee80211_local *local, 470 TP_PROTO(struct ieee80211_local *local,
465 struct ieee80211_sub_if_data *sdata), 471 struct ieee80211_sub_if_data *sdata),
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 58ffa7d069c7..1758b463c583 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -821,10 +821,8 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
821 */ 821 */
822void ieee80211_scan_cancel(struct ieee80211_local *local) 822void ieee80211_scan_cancel(struct ieee80211_local *local)
823{ 823{
824 bool abortscan;
825
826 /* 824 /*
827 * We are only canceling software scan, or deferred scan that was not 825 * We are canceling software scan, or deferred scan that was not
828 * yet really started (see __ieee80211_start_scan ). 826 * yet really started (see __ieee80211_start_scan ).
829 * 827 *
830 * Regarding hardware scan: 828 * Regarding hardware scan:
@@ -836,23 +834,30 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
836 * - we can not cancel scan_work since driver can schedule it 834 * - we can not cancel scan_work since driver can schedule it
837 * by ieee80211_scan_completed(..., true) to finish scan 835 * by ieee80211_scan_completed(..., true) to finish scan
838 * 836 *
839 * Hence low lever driver is responsible for canceling HW scan. 837 * Hence we only call the cancel_hw_scan() callback, but the low-level
838 * driver is still responsible for calling ieee80211_scan_completed()
839 * after the scan was completed/aborted.
840 */ 840 */
841 841
842 mutex_lock(&local->mtx); 842 mutex_lock(&local->mtx);
843 abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning); 843 if (!local->scan_req)
844 if (abortscan) { 844 goto out;
845 /* 845
846 * The scan is canceled, but stop work from being pending. 846 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
847 * 847 if (local->ops->cancel_hw_scan)
848 * If the work is currently running, it must be blocked on 848 drv_cancel_hw_scan(local, local->scan_sdata);
849 * the mutex, but we'll set scan_sdata = NULL and it'll 849 goto out;
850 * simply exit once it acquires the mutex.
851 */
852 cancel_delayed_work(&local->scan_work);
853 /* and clean up */
854 __ieee80211_scan_completed(&local->hw, true, false);
855 } 850 }
851
852 /*
853 * If the work is currently running, it must be blocked on
854 * the mutex, but we'll set scan_sdata = NULL and it'll
855 * simply exit once it acquires the mutex.
856 */
857 cancel_delayed_work(&local->scan_work);
858 /* and clean up */
859 __ieee80211_scan_completed(&local->hw, true, false);
860out:
856 mutex_unlock(&local->mtx); 861 mutex_unlock(&local->mtx);
857} 862}
858 863