diff options
-rw-r--r-- | include/net/mac80211.h | 10 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 10 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 6 | ||||
-rw-r--r-- | net/mac80211/scan.c | 37 |
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 | ||
221 | static 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 | |||
221 | static inline int | 231 | static inline int |
222 | drv_sched_scan_start(struct ieee80211_local *local, | 232 | drv_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 | ||
463 | DEFINE_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 | |||
463 | DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, | 469 | DEFINE_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 | */ |
822 | void ieee80211_scan_cancel(struct ieee80211_local *local) | 822 | void 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); | ||
860 | out: | ||
856 | mutex_unlock(&local->mtx); | 861 | mutex_unlock(&local->mtx); |
857 | } | 862 | } |
858 | 863 | ||