iwlwifi: mvm: wait for stop sched-scan completion
cfg80211 assumes a scheduled scan is stopped synchronously. Wait for the FW before returning to caller. Don't do anything in the async handler in the stop-from-above flow. There's no need to call the mac80211 sched-scan completion as the cleanup will be automatic. Make sure the async handler is called before the next incoming scan changes the scan_status by flushing the async handlers after all invocations. Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
parent
7bb426ea36
commit
33ea27f66a
@ -1419,8 +1419,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_notification_wait wait_scan_done;
|
||||
static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
|
||||
int ret;
|
||||
|
||||
if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
|
||||
@ -1430,22 +1428,11 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
|
||||
switch (mvm->scan_status) {
|
||||
case IWL_MVM_SCAN_SCHED:
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
|
||||
scan_done_notif,
|
||||
ARRAY_SIZE(scan_done_notif),
|
||||
NULL, NULL);
|
||||
iwl_mvm_sched_scan_stop(mvm);
|
||||
ret = iwl_wait_notification(&mvm->notif_wait,
|
||||
&wait_scan_done, HZ);
|
||||
ret = iwl_mvm_sched_scan_stop(mvm);
|
||||
if (ret) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
/* iwl_mvm_rx_scan_offload_complete_notif() will be called
|
||||
* soon but will not reset the scan status as it won't be
|
||||
* IWL_MVM_SCAN_SCHED any more since we queue the next scan
|
||||
* immediately (below)
|
||||
*/
|
||||
break;
|
||||
case IWL_MVM_SCAN_NONE:
|
||||
break;
|
||||
@ -1461,7 +1448,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
/* make sure to flush the Rx handler before the next scan arrives */
|
||||
iwl_mvm_wait_for_async_handlers(mvm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1751,12 +1739,14 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_sched_scan_stop(mvm);
|
||||
ret = iwl_mvm_sched_scan_stop(mvm);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
iwl_mvm_wait_for_async_handlers(mvm);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
|
@ -712,6 +712,11 @@ static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync);
|
||||
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
|
||||
|
||||
static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
|
||||
{
|
||||
flush_work(&mvm->async_handlers_wk);
|
||||
}
|
||||
|
||||
/* Statistics */
|
||||
int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
@ -813,7 +818,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
|
||||
struct cfg80211_sched_scan_request *req);
|
||||
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
|
||||
struct cfg80211_sched_scan_request *req);
|
||||
void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
@ -519,10 +519,11 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
|
||||
scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
|
||||
"completed" : "aborted");
|
||||
|
||||
/* might already be something else again, don't reset if so */
|
||||
if (mvm->scan_status == IWL_MVM_SCAN_SCHED)
|
||||
/* only call mac80211 completion if the stop was initiated by FW */
|
||||
if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
|
||||
mvm->scan_status = IWL_MVM_SCAN_NONE;
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -894,26 +895,49 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
|
||||
* microcode has notified us that a scan is completed.
|
||||
*/
|
||||
IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status);
|
||||
ret = -EIO;
|
||||
ret = -ENOENT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm)
|
||||
int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_notification_wait wait_scan_done;
|
||||
static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (mvm->scan_status != IWL_MVM_SCAN_SCHED) {
|
||||
IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
|
||||
scan_done_notif,
|
||||
ARRAY_SIZE(scan_done_notif),
|
||||
NULL, NULL);
|
||||
|
||||
ret = iwl_mvm_send_sched_scan_abort(mvm);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret);
|
||||
else
|
||||
IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n");
|
||||
iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n");
|
||||
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Clear the scan status so the next scan requests will succeed. This
|
||||
* also ensures the Rx handler doesn't do anything, as the scan was
|
||||
* stopped from above.
|
||||
*/
|
||||
mvm->scan_status = IWL_MVM_SCAN_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user