diff options
author | Luca Coelho <luciano.coelho@intel.com> | 2016-03-11 02:20:37 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2016-03-30 09:24:48 -0400 |
commit | 728e825f81b1fe29eb177148fcabfa55a7f4c1bb (patch) | |
tree | 487b5ba41dd509dcbd0c3b7036086cf4bfa52bb6 | |
parent | 097129c9e62540122b63cba79c1843a2602bec37 (diff) |
iwlwifi: mvm: add a scan timeout for regular scans
If something goes wrong with the firmware and we never get a scan
complete notification, we stay stuck forever. In order to avoid this
situation, add a timeout and trigger an NMI if it expires before
receiving the notification., so we can clean things up.
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 21 |
3 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index cd5f16e9cab4..2d685e02d488 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
@@ -710,6 +710,7 @@ struct iwl_mvm { | |||
710 | struct iwl_mcast_filter_cmd *mcast_filter_cmd; | 710 | struct iwl_mcast_filter_cmd *mcast_filter_cmd; |
711 | enum iwl_mvm_scan_type scan_type; | 711 | enum iwl_mvm_scan_type scan_type; |
712 | enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all; | 712 | enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all; |
713 | struct timer_list scan_timer; | ||
713 | 714 | ||
714 | /* max number of simultaneous scans the FW supports */ | 715 | /* max number of simultaneous scans the FW supports */ |
715 | unsigned int max_scans; | 716 | unsigned int max_scans; |
@@ -1314,6 +1315,7 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm); | |||
1314 | int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify); | 1315 | int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify); |
1315 | int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); | 1316 | int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); |
1316 | void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); | 1317 | void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); |
1318 | void iwl_mvm_scan_timeout(unsigned long data); | ||
1317 | 1319 | ||
1318 | /* Scheduled scan */ | 1320 | /* Scheduled scan */ |
1319 | void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, | 1321 | void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index cb0092609595..656541c5360a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
@@ -728,6 +728,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
728 | 728 | ||
729 | iwl_mvm_tof_init(mvm); | 729 | iwl_mvm_tof_init(mvm); |
730 | 730 | ||
731 | setup_timer(&mvm->scan_timer, iwl_mvm_scan_timeout, | ||
732 | (unsigned long)mvm); | ||
733 | |||
731 | return op_mode; | 734 | return op_mode; |
732 | 735 | ||
733 | out_unregister: | 736 | out_unregister: |
@@ -783,6 +786,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
783 | 786 | ||
784 | iwl_mvm_tof_clean(mvm); | 787 | iwl_mvm_tof_clean(mvm); |
785 | 788 | ||
789 | del_timer_sync(&mvm->scan_timer); | ||
790 | |||
786 | mutex_destroy(&mvm->mutex); | 791 | mutex_destroy(&mvm->mutex); |
787 | mutex_destroy(&mvm->d0i3_suspend_mutex); | 792 | mutex_destroy(&mvm->d0i3_suspend_mutex); |
788 | 793 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 25b007cf7db7..c1d1be9c5d01 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c | |||
@@ -70,6 +70,7 @@ | |||
70 | 70 | ||
71 | #include "mvm.h" | 71 | #include "mvm.h" |
72 | #include "fw-api-scan.h" | 72 | #include "fw-api-scan.h" |
73 | #include "iwl-io.h" | ||
73 | 74 | ||
74 | #define IWL_DENSE_EBS_SCAN_RATIO 5 | 75 | #define IWL_DENSE_EBS_SCAN_RATIO 5 |
75 | #define IWL_SPARSE_EBS_SCAN_RATIO 1 | 76 | #define IWL_SPARSE_EBS_SCAN_RATIO 1 |
@@ -398,6 +399,10 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, | |||
398 | ieee80211_scan_completed(mvm->hw, | 399 | ieee80211_scan_completed(mvm->hw, |
399 | scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED); | 400 | scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED); |
400 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 401 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
402 | del_timer(&mvm->scan_timer); | ||
403 | } else { | ||
404 | IWL_ERR(mvm, | ||
405 | "got scan complete notification but no scan is running\n"); | ||
401 | } | 406 | } |
402 | 407 | ||
403 | mvm->last_ebs_successful = | 408 | mvm->last_ebs_successful = |
@@ -1217,6 +1222,18 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) | |||
1217 | return -EIO; | 1222 | return -EIO; |
1218 | } | 1223 | } |
1219 | 1224 | ||
1225 | #define SCAN_TIMEOUT (16 * HZ) | ||
1226 | |||
1227 | void iwl_mvm_scan_timeout(unsigned long data) | ||
1228 | { | ||
1229 | struct iwl_mvm *mvm = (struct iwl_mvm *)data; | ||
1230 | |||
1231 | IWL_ERR(mvm, "regular scan timed out\n"); | ||
1232 | |||
1233 | del_timer(&mvm->scan_timer); | ||
1234 | iwl_force_nmi(mvm->trans); | ||
1235 | } | ||
1236 | |||
1220 | int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1237 | int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
1221 | struct cfg80211_scan_request *req, | 1238 | struct cfg80211_scan_request *req, |
1222 | struct ieee80211_scan_ies *ies) | 1239 | struct ieee80211_scan_ies *ies) |
@@ -1296,6 +1313,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1296 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; | 1313 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; |
1297 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); | 1314 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); |
1298 | 1315 | ||
1316 | mod_timer(&mvm->scan_timer, jiffies + SCAN_TIMEOUT); | ||
1317 | |||
1299 | return 0; | 1318 | return 0; |
1300 | } | 1319 | } |
1301 | 1320 | ||
@@ -1413,6 +1432,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, | |||
1413 | if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { | 1432 | if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) { |
1414 | ieee80211_scan_completed(mvm->hw, aborted); | 1433 | ieee80211_scan_completed(mvm->hw, aborted); |
1415 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1434 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
1435 | del_timer(&mvm->scan_timer); | ||
1416 | } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { | 1436 | } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { |
1417 | ieee80211_sched_scan_stopped(mvm->hw); | 1437 | ieee80211_sched_scan_stopped(mvm->hw); |
1418 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | 1438 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; |
@@ -1608,6 +1628,7 @@ out: | |||
1608 | * to release the scan reference here. | 1628 | * to release the scan reference here. |
1609 | */ | 1629 | */ |
1610 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1630 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
1631 | del_timer(&mvm->scan_timer); | ||
1611 | if (notify) | 1632 | if (notify) |
1612 | ieee80211_scan_completed(mvm->hw, true); | 1633 | ieee80211_scan_completed(mvm->hw, true); |
1613 | } else if (notify) { | 1634 | } else if (notify) { |