diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 469 |
1 files changed, 268 insertions, 201 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a4b3663a262f..d60d630cb93a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -54,82 +54,28 @@ | |||
54 | #define IWL_PASSIVE_DWELL_BASE (100) | 54 | #define IWL_PASSIVE_DWELL_BASE (100) |
55 | #define IWL_CHANNEL_TUNE_TIME 5 | 55 | #define IWL_CHANNEL_TUNE_TIME 5 |
56 | 56 | ||
57 | |||
58 | |||
59 | /** | ||
60 | * iwl_scan_cancel - Cancel any currently executing HW scan | ||
61 | * | ||
62 | * NOTE: priv->mutex is not required before calling this function | ||
63 | */ | ||
64 | int iwl_scan_cancel(struct iwl_priv *priv) | ||
65 | { | ||
66 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
67 | clear_bit(STATUS_SCANNING, &priv->status); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
72 | if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
73 | IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); | ||
74 | queue_work(priv->workqueue, &priv->abort_scan); | ||
75 | |||
76 | } else | ||
77 | IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n"); | ||
78 | |||
79 | return test_bit(STATUS_SCANNING, &priv->status); | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | EXPORT_SYMBOL(iwl_scan_cancel); | ||
85 | /** | ||
86 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan | ||
87 | * @ms: amount of time to wait (in milliseconds) for scan to abort | ||
88 | * | ||
89 | * NOTE: priv->mutex must be held before calling this function | ||
90 | */ | ||
91 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | ||
92 | { | ||
93 | unsigned long now = jiffies; | ||
94 | int ret; | ||
95 | |||
96 | ret = iwl_scan_cancel(priv); | ||
97 | if (ret && ms) { | ||
98 | mutex_unlock(&priv->mutex); | ||
99 | while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && | ||
100 | test_bit(STATUS_SCANNING, &priv->status)) | ||
101 | msleep(1); | ||
102 | mutex_lock(&priv->mutex); | ||
103 | |||
104 | return test_bit(STATUS_SCANNING, &priv->status); | ||
105 | } | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | EXPORT_SYMBOL(iwl_scan_cancel_timeout); | ||
110 | |||
111 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 57 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
112 | { | 58 | { |
113 | int ret = 0; | 59 | int ret; |
114 | struct iwl_rx_packet *pkt; | 60 | struct iwl_rx_packet *pkt; |
115 | struct iwl_host_cmd cmd = { | 61 | struct iwl_host_cmd cmd = { |
116 | .id = REPLY_SCAN_ABORT_CMD, | 62 | .id = REPLY_SCAN_ABORT_CMD, |
117 | .flags = CMD_WANT_SKB, | 63 | .flags = CMD_WANT_SKB, |
118 | }; | 64 | }; |
119 | 65 | ||
120 | /* If there isn't a scan actively going on in the hardware | 66 | /* Exit instantly with error when device is not ready |
121 | * then we are in between scan bands and not actually | 67 | * to receive scan abort command or it does not perform |
122 | * actively scanning, so don't send the abort command */ | 68 | * hardware scan currently */ |
123 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) { | 69 | if (!test_bit(STATUS_READY, &priv->status) || |
124 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | 70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || |
125 | return 0; | 71 | !test_bit(STATUS_SCAN_HW, &priv->status) || |
126 | } | 72 | test_bit(STATUS_FW_ERROR, &priv->status) || |
73 | test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
74 | return -EIO; | ||
127 | 75 | ||
128 | ret = iwl_send_cmd_sync(priv, &cmd); | 76 | ret = iwl_send_cmd_sync(priv, &cmd); |
129 | if (ret) { | 77 | if (ret) |
130 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
131 | return ret; | 78 | return ret; |
132 | } | ||
133 | 79 | ||
134 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | 80 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
135 | if (pkt->u.status != CAN_ABORT_STATUS) { | 81 | if (pkt->u.status != CAN_ABORT_STATUS) { |
@@ -139,16 +85,101 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
139 | * can occur if we send the scan abort before we | 85 | * can occur if we send the scan abort before we |
140 | * the microcode has notified us that a scan is | 86 | * the microcode has notified us that a scan is |
141 | * completed. */ | 87 | * completed. */ |
142 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status); | 88 | IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status); |
143 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | 89 | ret = -EIO; |
144 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
145 | } | 90 | } |
146 | 91 | ||
147 | iwl_free_pages(priv, cmd.reply_page); | 92 | iwl_free_pages(priv, cmd.reply_page); |
148 | |||
149 | return ret; | 93 | return ret; |
150 | } | 94 | } |
151 | 95 | ||
96 | static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | ||
97 | { | ||
98 | /* check if scan was requested from mac80211 */ | ||
99 | if (priv->scan_request) { | ||
100 | IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n"); | ||
101 | ieee80211_scan_completed(priv->hw, aborted); | ||
102 | } | ||
103 | |||
104 | priv->scan_type = IWL_SCAN_NORMAL; | ||
105 | priv->scan_vif = NULL; | ||
106 | priv->scan_request = NULL; | ||
107 | } | ||
108 | |||
109 | void iwl_force_scan_end(struct iwl_priv *priv) | ||
110 | { | ||
111 | lockdep_assert_held(&priv->mutex); | ||
112 | |||
113 | if (!test_bit(STATUS_SCANNING, &priv->status)) { | ||
114 | IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); | ||
119 | clear_bit(STATUS_SCANNING, &priv->status); | ||
120 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
121 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
122 | iwl_complete_scan(priv, true); | ||
123 | } | ||
124 | |||
125 | static void iwl_do_scan_abort(struct iwl_priv *priv) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | lockdep_assert_held(&priv->mutex); | ||
130 | |||
131 | if (!test_bit(STATUS_SCANNING, &priv->status)) { | ||
132 | IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
137 | IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | ret = iwl_send_scan_abort(priv); | ||
142 | if (ret) { | ||
143 | IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret); | ||
144 | iwl_force_scan_end(priv); | ||
145 | } else | ||
146 | IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n"); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * iwl_scan_cancel - Cancel any currently executing HW scan | ||
151 | */ | ||
152 | int iwl_scan_cancel(struct iwl_priv *priv) | ||
153 | { | ||
154 | IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); | ||
155 | queue_work(priv->workqueue, &priv->abort_scan); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan | ||
161 | * @ms: amount of time to wait (in milliseconds) for scan to abort | ||
162 | * | ||
163 | */ | ||
164 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | ||
165 | { | ||
166 | unsigned long timeout = jiffies + msecs_to_jiffies(ms); | ||
167 | |||
168 | lockdep_assert_held(&priv->mutex); | ||
169 | |||
170 | IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); | ||
171 | |||
172 | iwl_do_scan_abort(priv); | ||
173 | |||
174 | while (time_before_eq(jiffies, timeout)) { | ||
175 | if (!test_bit(STATUS_SCAN_HW, &priv->status)) | ||
176 | break; | ||
177 | msleep(20); | ||
178 | } | ||
179 | |||
180 | return test_bit(STATUS_SCAN_HW, &priv->status); | ||
181 | } | ||
182 | |||
152 | /* Service response to REPLY_SCAN_CMD (0x80) */ | 183 | /* Service response to REPLY_SCAN_CMD (0x80) */ |
153 | static void iwl_rx_reply_scan(struct iwl_priv *priv, | 184 | static void iwl_rx_reply_scan(struct iwl_priv *priv, |
154 | struct iwl_rx_mem_buffer *rxb) | 185 | struct iwl_rx_mem_buffer *rxb) |
@@ -158,7 +189,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
158 | struct iwl_scanreq_notification *notif = | 189 | struct iwl_scanreq_notification *notif = |
159 | (struct iwl_scanreq_notification *)pkt->u.raw; | 190 | (struct iwl_scanreq_notification *)pkt->u.raw; |
160 | 191 | ||
161 | IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status); | 192 | IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); |
162 | #endif | 193 | #endif |
163 | } | 194 | } |
164 | 195 | ||
@@ -206,7 +237,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | |||
206 | static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | 237 | static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, |
207 | struct iwl_rx_mem_buffer *rxb) | 238 | struct iwl_rx_mem_buffer *rxb) |
208 | { | 239 | { |
209 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
210 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 240 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
211 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; | 241 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; |
212 | 242 | ||
@@ -214,29 +244,36 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
214 | scan_notif->scanned_channels, | 244 | scan_notif->scanned_channels, |
215 | scan_notif->tsf_low, | 245 | scan_notif->tsf_low, |
216 | scan_notif->tsf_high, scan_notif->status); | 246 | scan_notif->tsf_high, scan_notif->status); |
217 | #endif | ||
218 | 247 | ||
219 | /* The HW is no longer scanning */ | 248 | /* The HW is no longer scanning */ |
220 | clear_bit(STATUS_SCAN_HW, &priv->status); | 249 | clear_bit(STATUS_SCAN_HW, &priv->status); |
221 | 250 | ||
222 | IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n", | 251 | IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", |
223 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", | 252 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", |
224 | jiffies_to_msecs(elapsed_jiffies | 253 | jiffies_to_msecs(jiffies - priv->scan_start)); |
225 | (priv->scan_start, jiffies))); | ||
226 | |||
227 | /* | ||
228 | * If a request to abort was given, or the scan did not succeed | ||
229 | * then we reset the scan state machine and terminate, | ||
230 | * re-queuing another scan if one has been requested | ||
231 | */ | ||
232 | if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status)) | ||
233 | IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); | ||
234 | |||
235 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | ||
236 | |||
237 | clear_bit(STATUS_SCANNING, &priv->status); | ||
238 | 254 | ||
239 | queue_work(priv->workqueue, &priv->scan_completed); | 255 | queue_work(priv->workqueue, &priv->scan_completed); |
256 | |||
257 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && | ||
258 | iwl_advanced_bt_coexist(priv) && | ||
259 | priv->bt_status != scan_notif->bt_status) { | ||
260 | if (scan_notif->bt_status) { | ||
261 | /* BT on */ | ||
262 | if (!priv->bt_ch_announce) | ||
263 | priv->bt_traffic_load = | ||
264 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH; | ||
265 | /* | ||
266 | * otherwise, no traffic load information provided | ||
267 | * no changes made | ||
268 | */ | ||
269 | } else { | ||
270 | /* BT off */ | ||
271 | priv->bt_traffic_load = | ||
272 | IWL_BT_COEX_TRAFFIC_LOAD_NONE; | ||
273 | } | ||
274 | priv->bt_status = scan_notif->bt_status; | ||
275 | queue_work(priv->workqueue, &priv->bt_traffic_change_work); | ||
276 | } | ||
240 | } | 277 | } |
241 | 278 | ||
242 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | 279 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) |
@@ -249,7 +286,6 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | |||
249 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = | 286 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = |
250 | iwl_rx_scan_complete_notif; | 287 | iwl_rx_scan_complete_notif; |
251 | } | 288 | } |
252 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); | ||
253 | 289 | ||
254 | inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 290 | inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
255 | enum ieee80211_band band, | 291 | enum ieee80211_band band, |
@@ -262,29 +298,37 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
262 | return IWL_ACTIVE_DWELL_TIME_24 + | 298 | return IWL_ACTIVE_DWELL_TIME_24 + |
263 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); | 299 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); |
264 | } | 300 | } |
265 | EXPORT_SYMBOL(iwl_get_active_dwell_time); | ||
266 | 301 | ||
267 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 302 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
268 | enum ieee80211_band band, | 303 | enum ieee80211_band band, |
269 | struct ieee80211_vif *vif) | 304 | struct ieee80211_vif *vif) |
270 | { | 305 | { |
306 | struct iwl_rxon_context *ctx; | ||
271 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? | 307 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? |
272 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : | 308 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : |
273 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; | 309 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; |
274 | 310 | ||
275 | if (iwl_is_associated(priv)) { | 311 | if (iwl_is_any_associated(priv)) { |
276 | /* If we're associated, we clamp the maximum passive | 312 | /* |
277 | * dwell time to be 98% of the beacon interval (minus | 313 | * If we're associated, we clamp the maximum passive |
278 | * 2 * channel tune time) */ | 314 | * dwell time to be 98% of the smallest beacon interval |
279 | passive = vif ? vif->bss_conf.beacon_int : 0; | 315 | * (minus 2 * channel tune time) |
280 | if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) | 316 | */ |
281 | passive = IWL_PASSIVE_DWELL_BASE; | 317 | for_each_context(priv, ctx) { |
282 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 318 | u16 value; |
319 | |||
320 | if (!iwl_is_associated_ctx(ctx)) | ||
321 | continue; | ||
322 | value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; | ||
323 | if ((value > IWL_PASSIVE_DWELL_BASE) || !value) | ||
324 | value = IWL_PASSIVE_DWELL_BASE; | ||
325 | value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | ||
326 | passive = min(value, passive); | ||
327 | } | ||
283 | } | 328 | } |
284 | 329 | ||
285 | return passive; | 330 | return passive; |
286 | } | 331 | } |
287 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | ||
288 | 332 | ||
289 | void iwl_init_scan_params(struct iwl_priv *priv) | 333 | void iwl_init_scan_params(struct iwl_priv *priv) |
290 | { | 334 | { |
@@ -294,21 +338,56 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
294 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 338 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
295 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; | 339 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; |
296 | } | 340 | } |
297 | EXPORT_SYMBOL(iwl_init_scan_params); | ||
298 | 341 | ||
299 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 342 | int __must_check iwl_scan_initiate(struct iwl_priv *priv, |
343 | struct ieee80211_vif *vif, | ||
344 | enum iwl_scan_type scan_type, | ||
345 | enum ieee80211_band band) | ||
300 | { | 346 | { |
347 | int ret; | ||
348 | |||
301 | lockdep_assert_held(&priv->mutex); | 349 | lockdep_assert_held(&priv->mutex); |
302 | 350 | ||
303 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 351 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) |
352 | return -EOPNOTSUPP; | ||
353 | |||
354 | cancel_delayed_work(&priv->scan_check); | ||
355 | |||
356 | if (!iwl_is_ready_rf(priv)) { | ||
357 | IWL_WARN(priv, "Request scan called when driver not ready.\n"); | ||
358 | return -EIO; | ||
359 | } | ||
360 | |||
361 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
362 | IWL_DEBUG_SCAN(priv, | ||
363 | "Multiple concurrent scan requests in parallel.\n"); | ||
364 | return -EBUSY; | ||
365 | } | ||
366 | |||
367 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
368 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); | ||
369 | return -EBUSY; | ||
370 | } | ||
371 | |||
372 | IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", | ||
373 | scan_type == IWL_SCAN_NORMAL ? "" : | ||
374 | scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " : | ||
375 | "internal short "); | ||
376 | |||
304 | set_bit(STATUS_SCANNING, &priv->status); | 377 | set_bit(STATUS_SCANNING, &priv->status); |
305 | priv->is_internal_short_scan = false; | 378 | priv->scan_type = scan_type; |
306 | priv->scan_start = jiffies; | 379 | priv->scan_start = jiffies; |
380 | priv->scan_band = band; | ||
307 | 381 | ||
308 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | 382 | ret = priv->cfg->ops->utils->request_scan(priv, vif); |
309 | return -EOPNOTSUPP; | 383 | if (ret) { |
384 | clear_bit(STATUS_SCANNING, &priv->status); | ||
385 | priv->scan_type = IWL_SCAN_NORMAL; | ||
386 | return ret; | ||
387 | } | ||
310 | 388 | ||
311 | priv->cfg->ops->utils->request_scan(priv, vif); | 389 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
390 | IWL_SCAN_CHECK_WATCHDOG); | ||
312 | 391 | ||
313 | return 0; | 392 | return 0; |
314 | } | 393 | } |
@@ -327,27 +406,14 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
327 | 406 | ||
328 | mutex_lock(&priv->mutex); | 407 | mutex_lock(&priv->mutex); |
329 | 408 | ||
330 | if (!iwl_is_ready_rf(priv)) { | ||
331 | ret = -EIO; | ||
332 | IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); | ||
333 | goto out_unlock; | ||
334 | } | ||
335 | |||
336 | if (test_bit(STATUS_SCANNING, &priv->status) && | 409 | if (test_bit(STATUS_SCANNING, &priv->status) && |
337 | !priv->is_internal_short_scan) { | 410 | priv->scan_type != IWL_SCAN_NORMAL) { |
338 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 411 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
339 | ret = -EAGAIN; | 412 | ret = -EAGAIN; |
340 | goto out_unlock; | 413 | goto out_unlock; |
341 | } | 414 | } |
342 | 415 | ||
343 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
344 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
345 | ret = -EAGAIN; | ||
346 | goto out_unlock; | ||
347 | } | ||
348 | |||
349 | /* mac80211 will only ask for one band at a time */ | 416 | /* mac80211 will only ask for one band at a time */ |
350 | priv->scan_band = req->channels[0]->band; | ||
351 | priv->scan_request = req; | 417 | priv->scan_request = req; |
352 | priv->scan_vif = vif; | 418 | priv->scan_vif = vif; |
353 | 419 | ||
@@ -355,10 +421,12 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
355 | * If an internal scan is in progress, just set | 421 | * If an internal scan is in progress, just set |
356 | * up the scan_request as per above. | 422 | * up the scan_request as per above. |
357 | */ | 423 | */ |
358 | if (priv->is_internal_short_scan) | 424 | if (priv->scan_type != IWL_SCAN_NORMAL) { |
425 | IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); | ||
359 | ret = 0; | 426 | ret = 0; |
360 | else | 427 | } else |
361 | ret = iwl_scan_initiate(priv, vif); | 428 | ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, |
429 | req->channels[0]->band); | ||
362 | 430 | ||
363 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 431 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
364 | 432 | ||
@@ -367,7 +435,6 @@ out_unlock: | |||
367 | 435 | ||
368 | return ret; | 436 | return ret; |
369 | } | 437 | } |
370 | EXPORT_SYMBOL(iwl_mac_hw_scan); | ||
371 | 438 | ||
372 | /* | 439 | /* |
373 | * internal short scan, this function should only been called while associated. | 440 | * internal short scan, this function should only been called while associated. |
@@ -378,68 +445,45 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
378 | queue_work(priv->workqueue, &priv->start_internal_scan); | 445 | queue_work(priv->workqueue, &priv->start_internal_scan); |
379 | } | 446 | } |
380 | 447 | ||
381 | void iwl_bg_start_internal_scan(struct work_struct *work) | 448 | static void iwl_bg_start_internal_scan(struct work_struct *work) |
382 | { | 449 | { |
383 | struct iwl_priv *priv = | 450 | struct iwl_priv *priv = |
384 | container_of(work, struct iwl_priv, start_internal_scan); | 451 | container_of(work, struct iwl_priv, start_internal_scan); |
385 | 452 | ||
453 | IWL_DEBUG_SCAN(priv, "Start internal scan\n"); | ||
454 | |||
386 | mutex_lock(&priv->mutex); | 455 | mutex_lock(&priv->mutex); |
387 | 456 | ||
388 | if (priv->is_internal_short_scan == true) { | 457 | if (priv->scan_type == IWL_SCAN_RADIO_RESET) { |
389 | IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); | 458 | IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); |
390 | goto unlock; | 459 | goto unlock; |
391 | } | 460 | } |
392 | 461 | ||
393 | if (!iwl_is_ready_rf(priv)) { | ||
394 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | ||
395 | goto unlock; | ||
396 | } | ||
397 | |||
398 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 462 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
399 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 463 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
400 | goto unlock; | 464 | goto unlock; |
401 | } | 465 | } |
402 | 466 | ||
403 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 467 | if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) |
404 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | 468 | IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); |
405 | goto unlock; | ||
406 | } | ||
407 | |||
408 | priv->scan_band = priv->band; | ||
409 | |||
410 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | ||
411 | set_bit(STATUS_SCANNING, &priv->status); | ||
412 | priv->is_internal_short_scan = true; | ||
413 | |||
414 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | ||
415 | goto unlock; | ||
416 | |||
417 | priv->cfg->ops->utils->request_scan(priv, NULL); | ||
418 | unlock: | 469 | unlock: |
419 | mutex_unlock(&priv->mutex); | 470 | mutex_unlock(&priv->mutex); |
420 | } | 471 | } |
421 | EXPORT_SYMBOL(iwl_bg_start_internal_scan); | ||
422 | 472 | ||
423 | void iwl_bg_scan_check(struct work_struct *data) | 473 | static void iwl_bg_scan_check(struct work_struct *data) |
424 | { | 474 | { |
425 | struct iwl_priv *priv = | 475 | struct iwl_priv *priv = |
426 | container_of(data, struct iwl_priv, scan_check.work); | 476 | container_of(data, struct iwl_priv, scan_check.work); |
427 | 477 | ||
428 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 478 | IWL_DEBUG_SCAN(priv, "Scan check work\n"); |
429 | return; | ||
430 | 479 | ||
480 | /* Since we are here firmware does not finish scan and | ||
481 | * most likely is in bad shape, so we don't bother to | ||
482 | * send abort command, just force scan complete to mac80211 */ | ||
431 | mutex_lock(&priv->mutex); | 483 | mutex_lock(&priv->mutex); |
432 | if (test_bit(STATUS_SCANNING, &priv->status) && | 484 | iwl_force_scan_end(priv); |
433 | !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
434 | IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", | ||
435 | jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); | ||
436 | |||
437 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
438 | iwl_send_scan_abort(priv); | ||
439 | } | ||
440 | mutex_unlock(&priv->mutex); | 485 | mutex_unlock(&priv->mutex); |
441 | } | 486 | } |
442 | EXPORT_SYMBOL(iwl_bg_scan_check); | ||
443 | 487 | ||
444 | /** | 488 | /** |
445 | * iwl_fill_probe_req - fill in all required fields and IE for probe request | 489 | * iwl_fill_probe_req - fill in all required fields and IE for probe request |
@@ -487,75 +531,87 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
487 | 531 | ||
488 | return (u16)len; | 532 | return (u16)len; |
489 | } | 533 | } |
490 | EXPORT_SYMBOL(iwl_fill_probe_req); | ||
491 | 534 | ||
492 | void iwl_bg_abort_scan(struct work_struct *work) | 535 | static void iwl_bg_abort_scan(struct work_struct *work) |
493 | { | 536 | { |
494 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); | 537 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); |
495 | 538 | ||
496 | if (!test_bit(STATUS_READY, &priv->status) || | 539 | IWL_DEBUG_SCAN(priv, "Abort scan work\n"); |
497 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | ||
498 | return; | ||
499 | |||
500 | cancel_delayed_work(&priv->scan_check); | ||
501 | 540 | ||
541 | /* We keep scan_check work queued in case when firmware will not | ||
542 | * report back scan completed notification */ | ||
502 | mutex_lock(&priv->mutex); | 543 | mutex_lock(&priv->mutex); |
503 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) | 544 | iwl_scan_cancel_timeout(priv, 200); |
504 | iwl_send_scan_abort(priv); | ||
505 | mutex_unlock(&priv->mutex); | 545 | mutex_unlock(&priv->mutex); |
506 | } | 546 | } |
507 | EXPORT_SYMBOL(iwl_bg_abort_scan); | ||
508 | 547 | ||
509 | void iwl_bg_scan_completed(struct work_struct *work) | 548 | static void iwl_bg_scan_completed(struct work_struct *work) |
510 | { | 549 | { |
511 | struct iwl_priv *priv = | 550 | struct iwl_priv *priv = |
512 | container_of(work, struct iwl_priv, scan_completed); | 551 | container_of(work, struct iwl_priv, scan_completed); |
513 | bool internal = false; | 552 | bool aborted; |
514 | 553 | ||
515 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 554 | IWL_DEBUG_SCAN(priv, "Completed scan.\n"); |
516 | 555 | ||
517 | cancel_delayed_work(&priv->scan_check); | 556 | cancel_delayed_work(&priv->scan_check); |
518 | 557 | ||
519 | mutex_lock(&priv->mutex); | 558 | mutex_lock(&priv->mutex); |
520 | if (priv->is_internal_short_scan) { | 559 | |
521 | priv->is_internal_short_scan = false; | 560 | aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); |
522 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 561 | if (aborted) |
523 | internal = true; | 562 | IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); |
524 | } else { | 563 | |
525 | priv->scan_request = NULL; | 564 | if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { |
526 | priv->scan_vif = NULL; | 565 | IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); |
566 | goto out_settings; | ||
527 | } | 567 | } |
528 | 568 | ||
529 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 569 | if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) { |
570 | ieee80211_tx_status_irqsafe(priv->hw, | ||
571 | priv->_agn.offchan_tx_skb); | ||
572 | priv->_agn.offchan_tx_skb = NULL; | ||
573 | } | ||
574 | |||
575 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | ||
576 | int err; | ||
577 | |||
578 | /* Check if mac80211 requested scan during our internal scan */ | ||
579 | if (priv->scan_request == NULL) | ||
580 | goto out_complete; | ||
581 | |||
582 | /* If so request a new scan */ | ||
583 | err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, | ||
584 | priv->scan_request->channels[0]->band); | ||
585 | if (err) { | ||
586 | IWL_DEBUG_SCAN(priv, | ||
587 | "failed to initiate pending scan: %d\n", err); | ||
588 | aborted = true; | ||
589 | goto out_complete; | ||
590 | } | ||
591 | |||
530 | goto out; | 592 | goto out; |
593 | } | ||
531 | 594 | ||
532 | if (internal && priv->scan_request) | 595 | out_complete: |
533 | iwl_scan_initiate(priv, priv->scan_vif); | 596 | iwl_complete_scan(priv, aborted); |
534 | 597 | ||
535 | /* Since setting the TXPOWER may have been deferred while | 598 | out_settings: |
536 | * performing the scan, fire one off */ | 599 | /* Can we still talk to firmware ? */ |
537 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | 600 | if (!iwl_is_ready_rf(priv)) |
601 | goto out; | ||
538 | 602 | ||
539 | /* | 603 | /* |
540 | * Since setting the RXON may have been deferred while | 604 | * We do not commit power settings while scan is pending, |
541 | * performing the scan, fire one off if needed | 605 | * do it now if the settings changed. |
542 | */ | 606 | */ |
543 | if (memcmp(&priv->active_rxon, | 607 | iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); |
544 | &priv->staging_rxon, sizeof(priv->staging_rxon))) | 608 | iwl_set_tx_power(priv, priv->tx_power_next, false); |
545 | iwlcore_commit_rxon(priv); | ||
546 | 609 | ||
547 | out: | 610 | priv->cfg->ops->utils->post_scan(priv); |
548 | mutex_unlock(&priv->mutex); | ||
549 | 611 | ||
550 | /* | 612 | out: |
551 | * Do not hold mutex here since this will cause mac80211 to call | 613 | mutex_unlock(&priv->mutex); |
552 | * into driver again into functions that will attempt to take | ||
553 | * mutex. | ||
554 | */ | ||
555 | if (!internal) | ||
556 | ieee80211_scan_completed(priv->hw, false); | ||
557 | } | 614 | } |
558 | EXPORT_SYMBOL(iwl_bg_scan_completed); | ||
559 | 615 | ||
560 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 616 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
561 | { | 617 | { |
@@ -564,5 +620,16 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | |||
564 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | 620 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); |
565 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 621 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
566 | } | 622 | } |
567 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | ||
568 | 623 | ||
624 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | ||
625 | { | ||
626 | cancel_work_sync(&priv->start_internal_scan); | ||
627 | cancel_work_sync(&priv->abort_scan); | ||
628 | cancel_work_sync(&priv->scan_completed); | ||
629 | |||
630 | if (cancel_delayed_work_sync(&priv->scan_check)) { | ||
631 | mutex_lock(&priv->mutex); | ||
632 | iwl_force_scan_end(priv); | ||
633 | mutex_unlock(&priv->mutex); | ||
634 | } | ||
635 | } | ||