aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 031d8e21f82f..eb0ded7a8a99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -101,11 +101,8 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
101 ieee80211_scan_completed(priv->hw, aborted); 101 ieee80211_scan_completed(priv->hw, aborted);
102 } 102 }
103 103
104 if (priv->scan_type == IWL_SCAN_ROC) { 104 if (priv->scan_type == IWL_SCAN_ROC)
105 ieee80211_remain_on_channel_expired(priv->hw); 105 iwl_scan_roc_expired(priv);
106 priv->hw_roc_channel = NULL;
107 schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
108 }
109 106
110 priv->scan_type = IWL_SCAN_NORMAL; 107 priv->scan_type = IWL_SCAN_NORMAL;
111 priv->scan_vif = NULL; 108 priv->scan_vif = NULL;
@@ -134,11 +131,8 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
134 goto out_settings; 131 goto out_settings;
135 } 132 }
136 133
137 if (priv->scan_type == IWL_SCAN_ROC) { 134 if (priv->scan_type == IWL_SCAN_ROC)
138 ieee80211_remain_on_channel_expired(priv->hw); 135 iwl_scan_roc_expired(priv);
139 priv->hw_roc_channel = NULL;
140 schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
141 }
142 136
143 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { 137 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
144 int err; 138 int err;
@@ -1158,3 +1152,40 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
1158 mutex_unlock(&priv->mutex); 1152 mutex_unlock(&priv->mutex);
1159 } 1153 }
1160} 1154}
1155
1156void iwl_scan_roc_expired(struct iwl_priv *priv)
1157{
1158 /*
1159 * The status bit should be set here, to prevent a race
1160 * where the atomic_read returns 1, but before the execution continues
1161 * iwl_scan_offchannel_skb_status() checks if the status bit is set
1162 */
1163 set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
1164
1165 if (atomic_read(&priv->num_aux_in_flight) == 0) {
1166 ieee80211_remain_on_channel_expired(priv->hw);
1167 priv->hw_roc_channel = NULL;
1168 schedule_delayed_work(&priv->hw_roc_disable_work,
1169 10 * HZ);
1170
1171 clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
1172 } else {
1173 IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n",
1174 atomic_read(&priv->num_aux_in_flight));
1175 }
1176}
1177
1178void iwl_scan_offchannel_skb(struct iwl_priv *priv)
1179{
1180 WARN_ON(!priv->hw_roc_start_notified);
1181 atomic_inc(&priv->num_aux_in_flight);
1182}
1183
1184void iwl_scan_offchannel_skb_status(struct iwl_priv *priv)
1185{
1186 if (atomic_dec_return(&priv->num_aux_in_flight) == 0 &&
1187 test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) {
1188 IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n");
1189 iwl_scan_roc_expired(priv);
1190 }
1191}