aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-scan.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-06-11 21:47:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-14 12:18:08 -0400
commit2a421b91d6fe89e27ded7544a25449c0b050098f (patch)
treea1e0ba54c0457c20d1ac7b8b765899d695d796f6 /drivers/net/wireless/iwlwifi/iwl-scan.c
parent4564ce8b0e17d91d047aa875843deb2cccf3f268 (diff)
iwlwifi: move scan to iwl-scan.c iwlcore
This patch moves scan code to iwl-scan.c file in iwlcore module. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c896
1 files changed, 896 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
new file mode 100644
index 000000000000..c2ed7c17ea1f
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -0,0 +1,896 @@
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 Intel Corporation. All rights reserved.
6 *
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
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Tomas Winkler <tomas.winkler@intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
28#include <net/mac80211.h>
29#include <linux/etherdevice.h>
30
31#include "iwl-eeprom.h"
32#include "iwl-dev.h"
33#include "iwl-core.h"
34#include "iwl-sta.h"
35#include "iwl-io.h"
36#include "iwl-helpers.h"
37
38/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
39 * sending probe req. This should be set long enough to hear probe responses
40 * from more than one AP. */
41#define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */
42#define IWL_ACTIVE_DWELL_TIME_52 (10)
43
44/* For faster active scanning, scan will move to the next channel if fewer than
45 * PLCP_QUIET_THRESH packets are heard on this channel within
46 * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
47 * time if it's a quiet channel (nothing responded to our probe, and there's
48 * no other traffic).
49 * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
50#define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */
51#define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */
52
53/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
54 * Must be set longer than active dwell time.
55 * For the most reliable scan, set > AP beacon interval (typically 100msec). */
56#define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */
57#define IWL_PASSIVE_DWELL_TIME_52 (10)
58#define IWL_PASSIVE_DWELL_BASE (100)
59#define IWL_CHANNEL_TUNE_TIME 5
60
61
62
63static int iwl_is_empty_essid(const char *essid, int essid_len)
64{
65 /* Single white space is for Linksys APs */
66 if (essid_len == 1 && essid[0] == ' ')
67 return 1;
68
69 /* Otherwise, if the entire essid is 0, we assume it is hidden */
70 while (essid_len) {
71 essid_len--;
72 if (essid[essid_len] != '\0')
73 return 0;
74 }
75
76 return 1;
77}
78
79
80
81const char *iwl_escape_essid(const char *essid, u8 essid_len)
82{
83 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
84 const char *s = essid;
85 char *d = escaped;
86
87 if (iwl_is_empty_essid(essid, essid_len)) {
88 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
89 return escaped;
90 }
91
92 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
93 while (essid_len--) {
94 if (*s == '\0') {
95 *d++ = '\\';
96 *d++ = '0';
97 s++;
98 } else
99 *d++ = *s++;
100 }
101 *d = '\0';
102 return escaped;
103}
104EXPORT_SYMBOL(iwl_escape_essid);
105
106/**
107 * iwl_scan_cancel - Cancel any currently executing HW scan
108 *
109 * NOTE: priv->mutex is not required before calling this function
110 */
111int iwl_scan_cancel(struct iwl_priv *priv)
112{
113 if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
114 clear_bit(STATUS_SCANNING, &priv->status);
115 return 0;
116 }
117
118 if (test_bit(STATUS_SCANNING, &priv->status)) {
119 if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
120 IWL_DEBUG_SCAN("Queuing scan abort.\n");
121 set_bit(STATUS_SCAN_ABORTING, &priv->status);
122 queue_work(priv->workqueue, &priv->abort_scan);
123
124 } else
125 IWL_DEBUG_SCAN("Scan abort already in progress.\n");
126
127 return test_bit(STATUS_SCANNING, &priv->status);
128 }
129
130 return 0;
131}
132EXPORT_SYMBOL(iwl_scan_cancel);
133/**
134 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
135 * @ms: amount of time to wait (in milliseconds) for scan to abort
136 *
137 * NOTE: priv->mutex must be held before calling this function
138 */
139int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
140{
141 unsigned long now = jiffies;
142 int ret;
143
144 ret = iwl_scan_cancel(priv);
145 if (ret && ms) {
146 mutex_unlock(&priv->mutex);
147 while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
148 test_bit(STATUS_SCANNING, &priv->status))
149 msleep(1);
150 mutex_lock(&priv->mutex);
151
152 return test_bit(STATUS_SCANNING, &priv->status);
153 }
154
155 return ret;
156}
157EXPORT_SYMBOL(iwl_scan_cancel_timeout);
158
159static int iwl_send_scan_abort(struct iwl_priv *priv)
160{
161 int ret = 0;
162 struct iwl_rx_packet *res;
163 struct iwl_host_cmd cmd = {
164 .id = REPLY_SCAN_ABORT_CMD,
165 .meta.flags = CMD_WANT_SKB,
166 };
167
168 /* If there isn't a scan actively going on in the hardware
169 * then we are in between scan bands and not actually
170 * actively scanning, so don't send the abort command */
171 if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
172 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
173 return 0;
174 }
175
176 ret = iwl_send_cmd_sync(priv, &cmd);
177 if (ret) {
178 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
179 return ret;
180 }
181
182 res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
183 if (res->u.status != CAN_ABORT_STATUS) {
184 /* The scan abort will return 1 for success or
185 * 2 for "failure". A failure condition can be
186 * due to simply not being in an active scan which
187 * can occur if we send the scan abort before we
188 * the microcode has notified us that a scan is
189 * completed. */
190 IWL_DEBUG_INFO("SCAN_ABORT returned %d.\n", res->u.status);
191 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
192 clear_bit(STATUS_SCAN_HW, &priv->status);
193 }
194
195 dev_kfree_skb_any(cmd.meta.u.skb);
196
197 return ret;
198}
199
200
201/* Service response to REPLY_SCAN_CMD (0x80) */
202static void iwl_rx_reply_scan(struct iwl_priv *priv,
203 struct iwl_rx_mem_buffer *rxb)
204{
205#ifdef CONFIG_IWLWIFI_DEBUG
206 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
207 struct iwl_scanreq_notification *notif =
208 (struct iwl_scanreq_notification *)pkt->u.raw;
209
210 IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
211#endif
212}
213
214/* Service SCAN_START_NOTIFICATION (0x82) */
215static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
216 struct iwl_rx_mem_buffer *rxb)
217{
218 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
219 struct iwl_scanstart_notification *notif =
220 (struct iwl_scanstart_notification *)pkt->u.raw;
221 priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
222 IWL_DEBUG_SCAN("Scan start: "
223 "%d [802.11%s] "
224 "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
225 notif->channel,
226 notif->band ? "bg" : "a",
227 notif->tsf_high,
228 notif->tsf_low, notif->status, notif->beacon_timer);
229}
230
231/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
232static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
233 struct iwl_rx_mem_buffer *rxb)
234{
235#ifdef CONFIG_IWLWIFI_DEBUG
236 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
237 struct iwl_scanresults_notification *notif =
238 (struct iwl_scanresults_notification *)pkt->u.raw;
239
240 IWL_DEBUG_SCAN("Scan ch.res: "
241 "%d [802.11%s] "
242 "(TSF: 0x%08X:%08X) - %d "
243 "elapsed=%lu usec (%dms since last)\n",
244 notif->channel,
245 notif->band ? "bg" : "a",
246 le32_to_cpu(notif->tsf_high),
247 le32_to_cpu(notif->tsf_low),
248 le32_to_cpu(notif->statistics[0]),
249 le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf,
250 jiffies_to_msecs(elapsed_jiffies
251 (priv->last_scan_jiffies, jiffies)));
252#endif
253
254 priv->last_scan_jiffies = jiffies;
255 priv->next_scan_jiffies = 0;
256}
257
258/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
259static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
260 struct iwl_rx_mem_buffer *rxb)
261{
262 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
263 struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
264
265 IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
266 scan_notif->scanned_channels,
267 scan_notif->tsf_low,
268 scan_notif->tsf_high, scan_notif->status);
269
270 /* The HW is no longer scanning */
271 clear_bit(STATUS_SCAN_HW, &priv->status);
272
273 /* The scan completion notification came in, so kill that timer... */
274 cancel_delayed_work(&priv->scan_check);
275
276 IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
277 (priv->scan_bands == 2) ? "2.4" : "5.2",
278 jiffies_to_msecs(elapsed_jiffies
279 (priv->scan_pass_start, jiffies)));
280
281 /* Remove this scanned band from the list
282 * of pending bands to scan */
283 priv->scan_bands--;
284
285 /* If a request to abort was given, or the scan did not succeed
286 * then we reset the scan state machine and terminate,
287 * re-queuing another scan if one has been requested */
288 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
289 IWL_DEBUG_INFO("Aborted scan completed.\n");
290 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
291 } else {
292 /* If there are more bands on this scan pass reschedule */
293 if (priv->scan_bands > 0)
294 goto reschedule;
295 }
296
297 priv->last_scan_jiffies = jiffies;
298 priv->next_scan_jiffies = 0;
299 IWL_DEBUG_INFO("Setting scan to off\n");
300
301 clear_bit(STATUS_SCANNING, &priv->status);
302
303 IWL_DEBUG_INFO("Scan took %dms\n",
304 jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
305
306 queue_work(priv->workqueue, &priv->scan_completed);
307
308 return;
309
310reschedule:
311 priv->scan_pass_start = jiffies;
312 queue_work(priv->workqueue, &priv->request_scan);
313}
314
315void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
316{
317 /* scan handlers */
318 priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
319 priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
320 priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
321 iwl_rx_scan_results_notif;
322 priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
323 iwl_rx_scan_complete_notif;
324}
325EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
326
327static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
328 enum ieee80211_band band)
329{
330 if (band == IEEE80211_BAND_5GHZ)
331 return IWL_ACTIVE_DWELL_TIME_52;
332 else
333 return IWL_ACTIVE_DWELL_TIME_24;
334}
335
336static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
337 enum ieee80211_band band)
338{
339 u16 active = iwl_get_active_dwell_time(priv, band);
340 u16 passive = (band != IEEE80211_BAND_5GHZ) ?
341 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
342 IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
343
344 if (iwl_is_associated(priv)) {
345 /* If we're associated, we clamp the maximum passive
346 * dwell time to be 98% of the beacon interval (minus
347 * 2 * channel tune time) */
348 passive = priv->beacon_int;
349 if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
350 passive = IWL_PASSIVE_DWELL_BASE;
351 passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
352 }
353
354 if (passive <= active)
355 passive = active + 1;
356
357 return passive;
358}
359
360static int iwl_get_channels_for_scan(struct iwl_priv *priv,
361 enum ieee80211_band band,
362 u8 is_active, u8 direct_mask,
363 struct iwl_scan_channel *scan_ch)
364{
365 const struct ieee80211_channel *channels = NULL;
366 const struct ieee80211_supported_band *sband;
367 const struct iwl_channel_info *ch_info;
368 u16 passive_dwell = 0;
369 u16 active_dwell = 0;
370 int added, i;
371
372 sband = iwl_get_hw_mode(priv, band);
373 if (!sband)
374 return 0;
375
376 channels = sband->channels;
377
378 active_dwell = iwl_get_active_dwell_time(priv, band);
379 passive_dwell = iwl_get_passive_dwell_time(priv, band);
380
381 for (i = 0, added = 0; i < sband->n_channels; i++) {
382 if (channels[i].flags & IEEE80211_CHAN_DISABLED)
383 continue;
384
385 scan_ch->channel =
386 ieee80211_frequency_to_channel(channels[i].center_freq);
387
388 ch_info = iwl_get_channel_info(priv, band,
389 scan_ch->channel);
390 if (!is_channel_valid(ch_info)) {
391 IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
392 scan_ch->channel);
393 continue;
394 }
395
396 if (!is_active || is_channel_passive(ch_info) ||
397 (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
398 scan_ch->type = 0; /* passive */
399 else
400 scan_ch->type = 1; /* active */
401
402 if (scan_ch->type & 1)
403 scan_ch->type |= (direct_mask << 1);
404
405 scan_ch->active_dwell = cpu_to_le16(active_dwell);
406 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
407
408 /* Set txpower levels to defaults */
409 scan_ch->tpc.dsp_atten = 110;
410 /* scan_pwr_info->tpc.dsp_atten; */
411
412 /*scan_pwr_info->tpc.tx_gain; */
413 if (band == IEEE80211_BAND_5GHZ)
414 scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
415 else {
416 scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
417 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
418 * power level:
419 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
420 */
421 }
422
423 IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
424 scan_ch->channel,
425 (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
426 (scan_ch->type & 1) ?
427 active_dwell : passive_dwell);
428
429 scan_ch++;
430 added++;
431 }
432
433 IWL_DEBUG_SCAN("total channels to scan %d \n", added);
434 return added;
435}
436
437int iwl_scan_initiate(struct iwl_priv *priv)
438{
439 if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
440 IWL_ERROR("APs don't scan.\n");
441 return 0;
442 }
443
444 if (!iwl_is_ready_rf(priv)) {
445 IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
446 return -EIO;
447 }
448
449 if (test_bit(STATUS_SCANNING, &priv->status)) {
450 IWL_DEBUG_SCAN("Scan already in progress.\n");
451 return -EAGAIN;
452 }
453
454 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
455 IWL_DEBUG_SCAN("Scan request while abort pending. "
456 "Queuing.\n");
457 return -EAGAIN;
458 }
459
460 IWL_DEBUG_INFO("Starting scan...\n");
461 priv->scan_bands = 2;
462 set_bit(STATUS_SCANNING, &priv->status);
463 priv->scan_start = jiffies;
464 priv->scan_pass_start = priv->scan_start;
465
466 queue_work(priv->workqueue, &priv->request_scan);
467
468 return 0;
469}
470EXPORT_SYMBOL(iwl_scan_initiate);
471
472#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
473
474static void iwl_bg_scan_check(struct work_struct *data)
475{
476 struct iwl_priv *priv =
477 container_of(data, struct iwl_priv, scan_check.work);
478
479 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
480 return;
481
482 mutex_lock(&priv->mutex);
483 if (test_bit(STATUS_SCANNING, &priv->status) ||
484 test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
485 IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting "
486 "adapter (%dms)\n",
487 jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
488
489 if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
490 iwl_send_scan_abort(priv);
491 }
492 mutex_unlock(&priv->mutex);
493}
494/**
495 * iwl_supported_rate_to_ie - fill in the supported rate in IE field
496 *
497 * return : set the bit for each supported rate insert in ie
498 */
499static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
500 u16 basic_rate, int *left)
501{
502 u16 ret_rates = 0, bit;
503 int i;
504 u8 *cnt = ie;
505 u8 *rates = ie + 1;
506
507 for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
508 if (bit & supported_rate) {
509 ret_rates |= bit;
510 rates[*cnt] = iwl_rates[i].ieee |
511 ((bit & basic_rate) ? 0x80 : 0x00);
512 (*cnt)++;
513 (*left)--;
514 if ((*left <= 0) ||
515 (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
516 break;
517 }
518 }
519
520 return ret_rates;
521}
522
523
524static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
525 u8 *pos, int *left)
526{
527 struct ieee80211_ht_cap *ht_cap;
528
529 if (!sband || !sband->ht_info.ht_supported)
530 return;
531
532 if (*left < sizeof(struct ieee80211_ht_cap))
533 return;
534
535 *pos++ = sizeof(struct ieee80211_ht_cap);
536 ht_cap = (struct ieee80211_ht_cap *) pos;
537
538 ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
539 memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
540 ht_cap->ampdu_params_info =
541 (sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
542 ((sband->ht_info.ampdu_density << 2) &
543 IEEE80211_HT_CAP_AMPDU_DENSITY);
544 *left -= sizeof(struct ieee80211_ht_cap);
545}
546
547/**
548 * iwl_fill_probe_req - fill in all required fields and IE for probe request
549 */
550static u16 iwl_fill_probe_req(struct iwl_priv *priv,
551 enum ieee80211_band band,
552 struct ieee80211_mgmt *frame,
553 int left, int is_direct)
554{
555 int len = 0;
556 u8 *pos = NULL;
557 u16 active_rates, ret_rates, cck_rates, active_rate_basic;
558 const struct ieee80211_supported_band *sband =
559 iwl_get_hw_mode(priv, band);
560
561 /* Make sure there is enough space for the probe request,
562 * two mandatory IEs and the data */
563 left -= 24;
564 if (left < 0)
565 return 0;
566 len += 24;
567
568 frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
569 memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
570 memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
571 memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
572 frame->seq_ctrl = 0;
573
574 /* fill in our indirect SSID IE */
575 /* ...next IE... */
576
577 left -= 2;
578 if (left < 0)
579 return 0;
580 len += 2;
581 pos = &(frame->u.probe_req.variable[0]);
582 *pos++ = WLAN_EID_SSID;
583 *pos++ = 0;
584
585 /* fill in our direct SSID IE... */
586 if (is_direct) {
587 /* ...next IE... */
588 left -= 2 + priv->essid_len;
589 if (left < 0)
590 return 0;
591 /* ... fill it in... */
592 *pos++ = WLAN_EID_SSID;
593 *pos++ = priv->essid_len;
594 memcpy(pos, priv->essid, priv->essid_len);
595 pos += priv->essid_len;
596 len += 2 + priv->essid_len;
597 }
598
599 /* fill in supported rate */
600 /* ...next IE... */
601 left -= 2;
602 if (left < 0)
603 return 0;
604
605 /* ... fill it in... */
606 *pos++ = WLAN_EID_SUPP_RATES;
607 *pos = 0;
608
609 /* exclude 60M rate */
610 active_rates = priv->rates_mask;
611 active_rates &= ~IWL_RATE_60M_MASK;
612
613 active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
614
615 cck_rates = IWL_CCK_RATES_MASK & active_rates;
616 ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
617 active_rate_basic, &left);
618 active_rates &= ~ret_rates;
619
620 ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
621 active_rate_basic, &left);
622 active_rates &= ~ret_rates;
623
624 len += 2 + *pos;
625 pos += (*pos) + 1;
626 if (active_rates == 0)
627 goto fill_end;
628
629 /* fill in supported extended rate */
630 /* ...next IE... */
631 left -= 2;
632 if (left < 0)
633 return 0;
634 /* ... fill it in... */
635 *pos++ = WLAN_EID_EXT_SUPP_RATES;
636 *pos = 0;
637 iwl_supported_rate_to_ie(pos, active_rates,
638 active_rate_basic, &left);
639 if (*pos > 0)
640 len += 2 + *pos;
641
642 fill_end:
643 /* fill in HT IE */
644 left -= 2;
645 if (left < 0)
646 return 0;
647
648 *pos++ = WLAN_EID_HT_CAPABILITY;
649 *pos = 0;
650
651 iwl_ht_cap_to_ie(sband, pos, &left);
652
653 if (*pos > 0)
654 len += 2 + *pos;
655 return (u16)len;
656}
657
658static void iwl_bg_request_scan(struct work_struct *data)
659{
660 struct iwl_priv *priv =
661 container_of(data, struct iwl_priv, request_scan);
662 struct iwl_host_cmd cmd = {
663 .id = REPLY_SCAN_CMD,
664 .len = sizeof(struct iwl_scan_cmd),
665 .meta.flags = CMD_SIZE_HUGE,
666 };
667 struct iwl_scan_cmd *scan;
668 struct ieee80211_conf *conf = NULL;
669 u16 cmd_len;
670 enum ieee80211_band band;
671 u8 direct_mask;
672 int ret = 0;
673
674 conf = ieee80211_get_hw_conf(priv->hw);
675
676 mutex_lock(&priv->mutex);
677
678 if (!iwl_is_ready(priv)) {
679 IWL_WARNING("request scan called when driver not ready.\n");
680 goto done;
681 }
682
683 /* Make sure the scan wasn't cancelled before this queued work
684 * was given the chance to run... */
685 if (!test_bit(STATUS_SCANNING, &priv->status))
686 goto done;
687
688 /* This should never be called or scheduled if there is currently
689 * a scan active in the hardware. */
690 if (test_bit(STATUS_SCAN_HW, &priv->status)) {
691 IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
692 "Ignoring second request.\n");
693 ret = -EIO;
694 goto done;
695 }
696
697 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
698 IWL_DEBUG_SCAN("Aborting scan due to device shutdown\n");
699 goto done;
700 }
701
702 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
703 IWL_DEBUG_HC("Scan request while abort pending. Queuing.\n");
704 goto done;
705 }
706
707 if (iwl_is_rfkill(priv)) {
708 IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
709 goto done;
710 }
711
712 if (!test_bit(STATUS_READY, &priv->status)) {
713 IWL_DEBUG_HC("Scan request while uninitialized. Queuing.\n");
714 goto done;
715 }
716
717 if (!priv->scan_bands) {
718 IWL_DEBUG_HC("Aborting scan due to no requested bands\n");
719 goto done;
720 }
721
722 if (!priv->scan) {
723 priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
724 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
725 if (!priv->scan) {
726 ret = -ENOMEM;
727 goto done;
728 }
729 }
730 scan = priv->scan;
731 memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
732
733 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
734 scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
735
736 if (iwl_is_associated(priv)) {
737 u16 interval = 0;
738 u32 extra;
739 u32 suspend_time = 100;
740 u32 scan_suspend_time = 100;
741 unsigned long flags;
742
743 IWL_DEBUG_INFO("Scanning while associated...\n");
744
745 spin_lock_irqsave(&priv->lock, flags);
746 interval = priv->beacon_int;
747 spin_unlock_irqrestore(&priv->lock, flags);
748
749 scan->suspend_time = 0;
750 scan->max_out_time = cpu_to_le32(200 * 1024);
751 if (!interval)
752 interval = suspend_time;
753
754 extra = (suspend_time / interval) << 22;
755 scan_suspend_time = (extra |
756 ((suspend_time % interval) * 1024));
757 scan->suspend_time = cpu_to_le32(scan_suspend_time);
758 IWL_DEBUG_SCAN("suspend_time 0x%X beacon interval %d\n",
759 scan_suspend_time, interval);
760 }
761
762 /* We should add the ability for user to lock to PASSIVE ONLY */
763 if (priv->one_direct_scan) {
764 IWL_DEBUG_SCAN
765 ("Kicking off one direct scan for '%s'\n",
766 iwl_escape_essid(priv->direct_ssid,
767 priv->direct_ssid_len));
768 scan->direct_scan[0].id = WLAN_EID_SSID;
769 scan->direct_scan[0].len = priv->direct_ssid_len;
770 memcpy(scan->direct_scan[0].ssid,
771 priv->direct_ssid, priv->direct_ssid_len);
772 direct_mask = 1;
773 } else if (!iwl_is_associated(priv) && priv->essid_len) {
774 IWL_DEBUG_SCAN
775 ("Kicking off one direct scan for '%s' when not associated\n",
776 iwl_escape_essid(priv->essid, priv->essid_len));
777 scan->direct_scan[0].id = WLAN_EID_SSID;
778 scan->direct_scan[0].len = priv->essid_len;
779 memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
780 direct_mask = 1;
781 } else {
782 IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
783 direct_mask = 0;
784 }
785
786 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
787 scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
788 scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
789
790
791 switch (priv->scan_bands) {
792 case 2:
793 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
794 scan->tx_cmd.rate_n_flags =
795 iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
796 RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
797
798 scan->good_CRC_th = 0;
799 band = IEEE80211_BAND_2GHZ;
800 break;
801
802 case 1:
803 scan->tx_cmd.rate_n_flags =
804 iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
805 RATE_MCS_ANT_B_MSK);
806 scan->good_CRC_th = IWL_GOOD_CRC_TH;
807 band = IEEE80211_BAND_5GHZ;
808 break;
809
810 default:
811 IWL_WARNING("Invalid scan band count\n");
812 goto done;
813 }
814
815 /* We don't build a direct scan probe request; the uCode will do
816 * that based on the direct_mask added to each channel entry */
817 cmd_len = iwl_fill_probe_req(priv, band,
818 (struct ieee80211_mgmt *)scan->data,
819 IWL_MAX_SCAN_SIZE - sizeof(*scan), 0);
820
821 scan->tx_cmd.len = cpu_to_le16(cmd_len);
822 /* select Rx chains */
823
824 /* Force use of chains B and C (0x6) for scan Rx.
825 * Avoid A (0x1) because of its off-channel reception on A-band.
826 * MIMO is not used here, but value is required to make uCode happy. */
827 scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
828 cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
829 (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
830 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
831
832 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
833 scan->filter_flags = RXON_FILTER_PROMISC_MSK;
834
835 if (direct_mask)
836 scan->channel_count =
837 iwl_get_channels_for_scan(
838 priv, band, 1, /* active */
839 direct_mask,
840 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
841 else
842 scan->channel_count =
843 iwl_get_channels_for_scan(
844 priv, band, 0, /* passive */
845 direct_mask,
846 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
847
848 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
849 RXON_FILTER_BCON_AWARE_MSK);
850 cmd.len += le16_to_cpu(scan->tx_cmd.len) +
851 scan->channel_count * sizeof(struct iwl_scan_channel);
852 cmd.data = scan;
853 scan->len = cpu_to_le16(cmd.len);
854
855 set_bit(STATUS_SCAN_HW, &priv->status);
856 ret = iwl_send_cmd_sync(priv, &cmd);
857 if (ret)
858 goto done;
859
860 queue_delayed_work(priv->workqueue, &priv->scan_check,
861 IWL_SCAN_CHECK_WATCHDOG);
862
863 mutex_unlock(&priv->mutex);
864 return;
865
866 done:
867 /* inform mac80211 scan aborted */
868 queue_work(priv->workqueue, &priv->scan_completed);
869 mutex_unlock(&priv->mutex);
870}
871
872static void iwl_bg_abort_scan(struct work_struct *work)
873{
874 struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
875
876 if (!iwl_is_ready(priv))
877 return;
878
879 mutex_lock(&priv->mutex);
880
881 set_bit(STATUS_SCAN_ABORTING, &priv->status);
882 iwl_send_scan_abort(priv);
883
884 mutex_unlock(&priv->mutex);
885}
886
887void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
888{
889 /* FIXME: move here when resolved PENDING
890 * INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); */
891 INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
892 INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
893 INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
894}
895EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
896