aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-02-10 05:49:39 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-03-09 13:16:48 -0400
commit91b80256b6ef64c3ec21210f7b4a0256c2c47f64 (patch)
tree7c12c6c536ad95746a9cd1a1d9ab946bb882411c /drivers/net
parent33ea27f66afa9ca3e130bd00c595dca509152fd7 (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.c25
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c18
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;
1733out: 1750out:
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);
805int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, 805int 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);
807void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); 807int iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
808 808
809/* Scheduled scan */ 809/* Scheduled scan */
810int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, 810int 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
469void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) 472int 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
504out_remove_notif: 503out_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
508int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, 508int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,