aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-02-10 08:34:29 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-03-09 13:16:48 -0400
commit33ea27f66afa9ca3e130bd00c595dca509152fd7 (patch)
tree6fd5a2d075e9aaef96638d4d8b04c2508100f5d8 /drivers/net/wireless
parent7bb426ea36f143459895de0cf11f0f0a7cfa396a (diff)
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c24
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c42
3 files changed, 46 insertions, 27 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 41b9e65f6a3f..fff66ab2cfda 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1419,8 +1419,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1419 struct cfg80211_scan_request *req) 1419 struct cfg80211_scan_request *req)
1420{ 1420{
1421 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1421 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1422 struct iwl_notification_wait wait_scan_done;
1423 static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
1424 int ret; 1422 int ret;
1425 1423
1426 if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) 1424 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,
1430 1428
1431 switch (mvm->scan_status) { 1429 switch (mvm->scan_status) {
1432 case IWL_MVM_SCAN_SCHED: 1430 case IWL_MVM_SCAN_SCHED:
1433 iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done, 1431 ret = iwl_mvm_sched_scan_stop(mvm);
1434 scan_done_notif,
1435 ARRAY_SIZE(scan_done_notif),
1436 NULL, NULL);
1437 iwl_mvm_sched_scan_stop(mvm);
1438 ret = iwl_wait_notification(&mvm->notif_wait,
1439 &wait_scan_done, HZ);
1440 if (ret) { 1432 if (ret) {
1441 ret = -EBUSY; 1433 ret = -EBUSY;
1442 goto out; 1434 goto out;
1443 } 1435 }
1444 /* iwl_mvm_rx_scan_offload_complete_notif() will be called
1445 * soon but will not reset the scan status as it won't be
1446 * IWL_MVM_SCAN_SCHED any more since we queue the next scan
1447 * immediately (below)
1448 */
1449 break; 1436 break;
1450 case IWL_MVM_SCAN_NONE: 1437 case IWL_MVM_SCAN_NONE:
1451 break; 1438 break;
@@ -1461,7 +1448,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1461 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1448 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1462out: 1449out:
1463 mutex_unlock(&mvm->mutex); 1450 mutex_unlock(&mvm->mutex);
1464 1451 /* make sure to flush the Rx handler before the next scan arrives */
1452 iwl_mvm_wait_for_async_handlers(mvm);
1465 return ret; 1453 return ret;
1466} 1454}
1467 1455
@@ -1751,12 +1739,14 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
1751 struct ieee80211_vif *vif) 1739 struct ieee80211_vif *vif)
1752{ 1740{
1753 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1741 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1742 int ret;
1754 1743
1755 mutex_lock(&mvm->mutex); 1744 mutex_lock(&mvm->mutex);
1756 iwl_mvm_sched_scan_stop(mvm); 1745 ret = iwl_mvm_sched_scan_stop(mvm);
1757 mutex_unlock(&mvm->mutex); 1746 mutex_unlock(&mvm->mutex);
1747 iwl_mvm_wait_for_async_handlers(mvm);
1758 1748
1759 return 0; 1749 return ret;
1760} 1750}
1761 1751
1762static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, 1752static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 3511bf79abcd..4da53c395ad3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -712,6 +712,11 @@ static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
712int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); 712int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync);
713void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); 713void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
714 714
715static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)
716{
717 flush_work(&mvm->async_handlers_wk);
718}
719
715/* Statistics */ 720/* Statistics */
716int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm, 721int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm,
717 struct iwl_rx_cmd_buffer *rxb, 722 struct iwl_rx_cmd_buffer *rxb,
@@ -813,7 +818,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
813 struct cfg80211_sched_scan_request *req); 818 struct cfg80211_sched_scan_request *req);
814int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, 819int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
815 struct cfg80211_sched_scan_request *req); 820 struct cfg80211_sched_scan_request *req);
816void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); 821int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
817int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, 822int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
818 struct iwl_rx_cmd_buffer *rxb, 823 struct iwl_rx_cmd_buffer *rxb,
819 struct iwl_device_cmd *cmd); 824 struct iwl_device_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index b4c9fb649976..a2cd54b57e67 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -519,10 +519,11 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
519 scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? 519 scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
520 "completed" : "aborted"); 520 "completed" : "aborted");
521 521
522 /* might already be something else again, don't reset if so */ 522 /* only call mac80211 completion if the stop was initiated by FW */
523 if (mvm->scan_status == IWL_MVM_SCAN_SCHED) 523 if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
524 mvm->scan_status = IWL_MVM_SCAN_NONE; 524 mvm->scan_status = IWL_MVM_SCAN_NONE;
525 ieee80211_sched_scan_stopped(mvm->hw); 525 ieee80211_sched_scan_stopped(mvm->hw);
526 }
526 527
527 return 0; 528 return 0;
528} 529}
@@ -894,26 +895,49 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
894 * microcode has notified us that a scan is completed. 895 * microcode has notified us that a scan is completed.
895 */ 896 */
896 IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status); 897 IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status);
897 ret = -EIO; 898 ret = -ENOENT;
898 } 899 }
899 900
900 return ret; 901 return ret;
901} 902}
902 903
903void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) 904int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm)
904{ 905{
905 int ret; 906 int ret;
907 struct iwl_notification_wait wait_scan_done;
908 static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
906 909
907 lockdep_assert_held(&mvm->mutex); 910 lockdep_assert_held(&mvm->mutex);
908 911
909 if (mvm->scan_status != IWL_MVM_SCAN_SCHED) { 912 if (mvm->scan_status != IWL_MVM_SCAN_SCHED) {
910 IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n"); 913 IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n");
911 return; 914 return 0;
912 } 915 }
913 916
917 iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
918 scan_done_notif,
919 ARRAY_SIZE(scan_done_notif),
920 NULL, NULL);
921
914 ret = iwl_mvm_send_sched_scan_abort(mvm); 922 ret = iwl_mvm_send_sched_scan_abort(mvm);
915 if (ret) 923 if (ret) {
916 IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret); 924 IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret);
917 else 925 iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
918 IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n"); 926 return ret;
927 }
928
929 IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n");
930
931 ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
932 if (ret)
933 return ret;
934
935 /*
936 * Clear the scan status so the next scan requests will succeed. This
937 * also ensures the Rx handler doesn't do anything, as the scan was
938 * stopped from above.
939 */
940 mvm->scan_status = IWL_MVM_SCAN_NONE;
941
942 return 0;
919} 943}