diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 51 |
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 | |||
1156 | void 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 | |||
1178 | void 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 | |||
1184 | void 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 | } | ||