diff options
author | Arik Nemtsov <arik@wizery.com> | 2014-02-10 05:49:39 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-03-09 13:16:48 -0400 |
commit | 91b80256b6ef64c3ec21210f7b4a0256c2c47f64 (patch) | |
tree | 7c12c6c536ad95746a9cd1a1d9ab946bb882411c /drivers/net | |
parent | 33ea27f66afa9ca3e130bd00c595dca509152fd7 (diff) |
iwlwifi: mvm: abort scan on sched_scan request
A scheduled scan is a more persistent setting and should take priority
over temporary regular scans. Abort the regular when a sched_scan
request arrives and then request the sched_scan.
The kernel API allows sending a sched_scan without canceling a regular
scan in progress, so this is our way to abstract the FW's limitations.
Make the scan-cancel Rx handler async and flush after invocation to
ensure new scans can't creep in before it.
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 18 |
4 files changed, 33 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index fff66ab2cfda..a6df00d675b7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1708,9 +1708,26 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
1708 | 1708 | ||
1709 | mutex_lock(&mvm->mutex); | 1709 | mutex_lock(&mvm->mutex); |
1710 | 1710 | ||
1711 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | 1711 | switch (mvm->scan_status) { |
1712 | IWL_DEBUG_SCAN(mvm, | 1712 | case IWL_MVM_SCAN_OS: |
1713 | "SCHED SCAN request during internal scan - abort\n"); | 1713 | IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n"); |
1714 | ret = iwl_mvm_cancel_scan(mvm); | ||
1715 | if (ret) { | ||
1716 | ret = -EBUSY; | ||
1717 | goto out; | ||
1718 | } | ||
1719 | |||
1720 | /* | ||
1721 | * iwl_mvm_rx_scan_complete() will be called soon but will | ||
1722 | * not reset the scan status as it won't be IWL_MVM_SCAN_OS | ||
1723 | * any more since we queue the next scan immediately (below). | ||
1724 | * We make sure it is called before the next scan starts by | ||
1725 | * flushing the async-handlers work. | ||
1726 | */ | ||
1727 | break; | ||
1728 | case IWL_MVM_SCAN_NONE: | ||
1729 | break; | ||
1730 | default: | ||
1714 | ret = -EBUSY; | 1731 | ret = -EBUSY; |
1715 | goto out; | 1732 | goto out; |
1716 | } | 1733 | } |
@@ -1732,6 +1749,8 @@ err: | |||
1732 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 1749 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
1733 | out: | 1750 | out: |
1734 | mutex_unlock(&mvm->mutex); | 1751 | mutex_unlock(&mvm->mutex); |
1752 | /* make sure to flush the Rx handler before the next scan arrives */ | ||
1753 | iwl_mvm_wait_for_async_handlers(mvm); | ||
1735 | return ret; | 1754 | return ret; |
1736 | } | 1755 | } |
1737 | 1756 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4da53c395ad3..e5c1db97acf4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -804,7 +804,7 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
804 | struct iwl_device_cmd *cmd); | 804 | struct iwl_device_cmd *cmd); |
805 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 805 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
806 | struct iwl_device_cmd *cmd); | 806 | struct iwl_device_cmd *cmd); |
807 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); | 807 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm); |
808 | 808 | ||
809 | /* Scheduled scan */ | 809 | /* Scheduled scan */ |
810 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | 810 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 05f635572063..39279e1d6ad4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -226,7 +226,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
226 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), | 226 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), |
227 | 227 | ||
228 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 228 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
229 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 229 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true), |
230 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, | 230 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, |
231 | iwl_mvm_rx_scan_offload_complete_notif, true), | 231 | iwl_mvm_rx_scan_offload_complete_notif, true), |
232 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, | 232 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index a2cd54b57e67..945398ba39b4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -402,10 +402,13 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
402 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 402 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
403 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; | 403 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; |
404 | 404 | ||
405 | lockdep_assert_held(&mvm->mutex); | ||
406 | |||
405 | IWL_DEBUG_SCAN(mvm, "Scan complete: status=0x%x scanned channels=%d\n", | 407 | IWL_DEBUG_SCAN(mvm, "Scan complete: status=0x%x scanned channels=%d\n", |
406 | notif->status, notif->scanned_channels); | 408 | notif->status, notif->scanned_channels); |
407 | 409 | ||
408 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 410 | if (mvm->scan_status == IWL_MVM_SCAN_OS) |
411 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
409 | ieee80211_scan_completed(mvm->hw, notif->status != SCAN_COMP_STATUS_OK); | 412 | ieee80211_scan_completed(mvm->hw, notif->status != SCAN_COMP_STATUS_OK); |
410 | 413 | ||
411 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 414 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
@@ -466,7 +469,7 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, | |||
466 | }; | 469 | }; |
467 | } | 470 | } |
468 | 471 | ||
469 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | 472 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) |
470 | { | 473 | { |
471 | struct iwl_notification_wait wait_scan_abort; | 474 | struct iwl_notification_wait wait_scan_abort; |
472 | static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD, | 475 | static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD, |
@@ -474,13 +477,13 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
474 | int ret; | 477 | int ret; |
475 | 478 | ||
476 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | 479 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) |
477 | return; | 480 | return 0; |
478 | 481 | ||
479 | if (iwl_mvm_is_radio_killed(mvm)) { | 482 | if (iwl_mvm_is_radio_killed(mvm)) { |
480 | ieee80211_scan_completed(mvm->hw, true); | 483 | ieee80211_scan_completed(mvm->hw, true); |
481 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 484 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
482 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 485 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
483 | return; | 486 | return 0; |
484 | } | 487 | } |
485 | 488 | ||
486 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, | 489 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, |
@@ -495,14 +498,11 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
495 | goto out_remove_notif; | 498 | goto out_remove_notif; |
496 | } | 499 | } |
497 | 500 | ||
498 | ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_abort, 1 * HZ); | 501 | return iwl_wait_notification(&mvm->notif_wait, &wait_scan_abort, HZ); |
499 | if (ret) | ||
500 | IWL_ERR(mvm, "%s - failed on timeout\n", __func__); | ||
501 | |||
502 | return; | ||
503 | 502 | ||
504 | out_remove_notif: | 503 | out_remove_notif: |
505 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); | 504 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); |
505 | return ret; | ||
506 | } | 506 | } |
507 | 507 | ||
508 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | 508 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, |