diff options
author | Luciano Coelho <luciano.coelho@nokia.com> | 2010-07-08 10:50:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-08 16:41:58 -0400 |
commit | 34dd2aaac4a4b908c093980a9894fd878aeb6deb (patch) | |
tree | 62bd3f0ee0d56888d0b722648271c3463a6bab19 /drivers/net/wireless/wl12xx | |
parent | f532be6d48a12cd1b27c4efa38d22e0cbfa512d1 (diff) |
wl1271: moved scan operations to a separate file
The scanning code is going to get a bit more complex, with proper support for
active/passive scans together with 2.4GHz and 5GHz. In the future, also a
new type of scan (periodic scan) will be added. When all this is
implemented, the code is going to be much more complex, so we'd better
separate it into a separate file.
This patch doesn't have any impact on functionality.
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Saravanan Dhanabal <ext-saravanan.dhanabal@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.c | 136 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.h | 68 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_event.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_scan.c | 191 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_scan.h | 101 |
7 files changed, 303 insertions, 240 deletions
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 27ddd2be0a91..078b4398ac1f 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -10,7 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | |||
10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o | 13 | wl1271_init.o wl1271_debugfs.o wl1271_scan.o |
14 | 14 | ||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | 15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o |
16 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 23c75988f082..ce503ddd5a41 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -463,142 +463,6 @@ out: | |||
463 | return ret; | 463 | return ret; |
464 | } | 464 | } |
465 | 465 | ||
466 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
467 | struct cfg80211_scan_request *req, u8 active_scan, | ||
468 | u8 high_prio, u8 band, u8 probe_requests) | ||
469 | { | ||
470 | |||
471 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | ||
472 | struct wl1271_cmd_scan *params = NULL; | ||
473 | struct ieee80211_channel *channels; | ||
474 | u32 rate; | ||
475 | int i, j, n_ch, ret; | ||
476 | u16 scan_options = 0; | ||
477 | u8 ieee_band; | ||
478 | |||
479 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { | ||
480 | ieee_band = IEEE80211_BAND_2GHZ; | ||
481 | rate = wl->conf.tx.basic_rate; | ||
482 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
483 | ieee_band = IEEE80211_BAND_2GHZ; | ||
484 | rate = wl->conf.tx.basic_rate; | ||
485 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
486 | ieee_band = IEEE80211_BAND_5GHZ; | ||
487 | rate = wl->conf.tx.basic_rate_5; | ||
488 | } else | ||
489 | return -EINVAL; | ||
490 | |||
491 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | ||
492 | return -EINVAL; | ||
493 | |||
494 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | ||
495 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | ||
496 | |||
497 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) | ||
498 | return -EINVAL; | ||
499 | |||
500 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
501 | if (!params) | ||
502 | return -ENOMEM; | ||
503 | |||
504 | params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
505 | params->params.rx_filter_options = | ||
506 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
507 | |||
508 | if (!active_scan) | ||
509 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
510 | if (high_prio) | ||
511 | scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; | ||
512 | params->params.scan_options = cpu_to_le16(scan_options); | ||
513 | |||
514 | params->params.num_probe_requests = probe_requests; | ||
515 | params->params.tx_rate = cpu_to_le32(rate); | ||
516 | params->params.tid_trigger = 0; | ||
517 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
518 | |||
519 | if (band == WL1271_SCAN_BAND_DUAL) | ||
520 | params->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
521 | else | ||
522 | params->params.band = band; | ||
523 | |||
524 | for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { | ||
525 | if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { | ||
526 | params->channels[j].min_duration = | ||
527 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | ||
528 | params->channels[j].max_duration = | ||
529 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | ||
530 | memset(¶ms->channels[j].bssid_lsb, 0xff, 4); | ||
531 | memset(¶ms->channels[j].bssid_msb, 0xff, 2); | ||
532 | params->channels[j].early_termination = 0; | ||
533 | params->channels[j].tx_power_att = | ||
534 | WL1271_SCAN_CURRENT_TX_PWR; | ||
535 | params->channels[j].channel = channels[i].hw_value; | ||
536 | j++; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | params->params.num_channels = j; | ||
541 | |||
542 | if (ssid_len && ssid) { | ||
543 | params->params.ssid_len = ssid_len; | ||
544 | memcpy(params->params.ssid, ssid, ssid_len); | ||
545 | } | ||
546 | |||
547 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, | ||
548 | req->ie, req->ie_len, ieee_band); | ||
549 | if (ret < 0) { | ||
550 | wl1271_error("PROBE request template failed"); | ||
551 | goto out; | ||
552 | } | ||
553 | |||
554 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
555 | if (!trigger) { | ||
556 | ret = -ENOMEM; | ||
557 | goto out; | ||
558 | } | ||
559 | |||
560 | /* disable the timeout */ | ||
561 | trigger->timeout = 0; | ||
562 | |||
563 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
564 | sizeof(*trigger), 0); | ||
565 | if (ret < 0) { | ||
566 | wl1271_error("trigger scan to failed for hw scan"); | ||
567 | goto out; | ||
568 | } | ||
569 | |||
570 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | ||
571 | |||
572 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
573 | if (wl1271_11a_enabled()) { | ||
574 | wl->scan.state = band; | ||
575 | if (band == WL1271_SCAN_BAND_DUAL) { | ||
576 | wl->scan.active = active_scan; | ||
577 | wl->scan.high_prio = high_prio; | ||
578 | wl->scan.probe_requests = probe_requests; | ||
579 | if (ssid_len && ssid) { | ||
580 | wl->scan.ssid_len = ssid_len; | ||
581 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
582 | } else | ||
583 | wl->scan.ssid_len = 0; | ||
584 | wl->scan.req = req; | ||
585 | } else | ||
586 | wl->scan.req = NULL; | ||
587 | } | ||
588 | |||
589 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | ||
590 | if (ret < 0) { | ||
591 | wl1271_error("SCAN failed"); | ||
592 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
593 | goto out; | ||
594 | } | ||
595 | |||
596 | out: | ||
597 | kfree(params); | ||
598 | kfree(trigger); | ||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 466 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
603 | void *buf, size_t buf_len, int index, u32 rates) | 467 | void *buf, size_t buf_len, int index, u32 rates) |
604 | { | 468 | { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 68001dffe716..34cd013ae5b0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -41,9 +41,6 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | |||
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
45 | struct cfg80211_scan_request *req, u8 active_scan, | ||
46 | u8 high_prio, u8 band, u8 probe_requests); | ||
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 44 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len, int index, u32 rates); | 45 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 46 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
@@ -350,71 +347,6 @@ struct wl1271_cmd_set_keys { | |||
350 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | 347 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; |
351 | } __attribute__ ((packed)); | 348 | } __attribute__ ((packed)); |
352 | 349 | ||
353 | |||
354 | #define WL1271_SCAN_MAX_CHANNELS 24 | ||
355 | #define WL1271_SCAN_DEFAULT_TAG 1 | ||
356 | #define WL1271_SCAN_CURRENT_TX_PWR 0 | ||
357 | #define WL1271_SCAN_OPT_ACTIVE 0 | ||
358 | #define WL1271_SCAN_OPT_PASSIVE 1 | ||
359 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | ||
360 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | ||
361 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | ||
362 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | ||
363 | #define WL1271_SCAN_BAND_5_GHZ 1 | ||
364 | #define WL1271_SCAN_BAND_DUAL 2 | ||
365 | |||
366 | struct basic_scan_params { | ||
367 | __le32 rx_config_options; | ||
368 | __le32 rx_filter_options; | ||
369 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
370 | __le16 scan_options; | ||
371 | /* Number of scan channels in the list (maximum 30) */ | ||
372 | u8 num_channels; | ||
373 | /* This field indicates the number of probe requests to send | ||
374 | per channel for an active scan */ | ||
375 | u8 num_probe_requests; | ||
376 | /* Rate bit field for sending the probes */ | ||
377 | __le32 tx_rate; | ||
378 | u8 tid_trigger; | ||
379 | u8 ssid_len; | ||
380 | /* in order to align */ | ||
381 | u8 padding1[2]; | ||
382 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
383 | /* Band to scan */ | ||
384 | u8 band; | ||
385 | u8 use_ssid_list; | ||
386 | u8 scan_tag; | ||
387 | u8 padding2; | ||
388 | } __attribute__ ((packed)); | ||
389 | |||
390 | struct basic_scan_channel_params { | ||
391 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
392 | __le32 min_duration; | ||
393 | __le32 max_duration; | ||
394 | __le32 bssid_lsb; | ||
395 | __le16 bssid_msb; | ||
396 | u8 early_termination; | ||
397 | u8 tx_power_att; | ||
398 | u8 channel; | ||
399 | /* FW internal use only! */ | ||
400 | u8 dfs_candidate; | ||
401 | u8 activity_detected; | ||
402 | u8 pad; | ||
403 | } __attribute__ ((packed)); | ||
404 | |||
405 | struct wl1271_cmd_scan { | ||
406 | struct wl1271_cmd_header header; | ||
407 | |||
408 | struct basic_scan_params params; | ||
409 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
410 | } __attribute__ ((packed)); | ||
411 | |||
412 | struct wl1271_cmd_trigger_scan_to { | ||
413 | struct wl1271_cmd_header header; | ||
414 | |||
415 | __le32 timeout; | ||
416 | } __attribute__ ((packed)); | ||
417 | |||
418 | struct wl1271_cmd_test_header { | 350 | struct wl1271_cmd_test_header { |
419 | u8 id; | 351 | u8 id; |
420 | u8 padding[3]; | 352 | u8 padding[3]; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 2d60d225744a..3bdae892c29e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
27 | #include "wl1271_event.h" | 27 | #include "wl1271_event.h" |
28 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
29 | #include "wl1271_scan.h" | ||
29 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
30 | 31 | ||
31 | void wl1271_pspoll_work(struct work_struct *work) | 32 | void wl1271_pspoll_work(struct work_struct *work) |
@@ -85,36 +86,6 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) | |||
85 | */ | 86 | */ |
86 | } | 87 | } |
87 | 88 | ||
88 | static int wl1271_event_scan_complete(struct wl1271 *wl, | ||
89 | struct event_mailbox *mbox) | ||
90 | { | ||
91 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | ||
92 | mbox->scheduled_scan_status); | ||
93 | |||
94 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | ||
95 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | ||
96 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | ||
97 | * to the wl1271_cmd_scan function that we are not | ||
98 | * scanning as it checks that. | ||
99 | */ | ||
100 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
101 | /* FIXME: ie missing! */ | ||
102 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | ||
103 | wl->scan.req, | ||
104 | wl->scan.active, | ||
105 | wl->scan.high_prio, | ||
106 | WL1271_SCAN_BAND_5_GHZ, | ||
107 | wl->scan.probe_requests); | ||
108 | } else { | ||
109 | mutex_unlock(&wl->mutex); | ||
110 | ieee80211_scan_completed(wl->hw, false); | ||
111 | mutex_lock(&wl->mutex); | ||
112 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
113 | } | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int wl1271_event_ps_report(struct wl1271 *wl, | 89 | static int wl1271_event_ps_report(struct wl1271 *wl, |
119 | struct event_mailbox *mbox, | 90 | struct event_mailbox *mbox, |
120 | bool *beacon_loss) | 91 | bool *beacon_loss) |
@@ -220,7 +191,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
220 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); | 191 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); |
221 | 192 | ||
222 | if (vector & SCAN_COMPLETE_EVENT_ID) { | 193 | if (vector & SCAN_COMPLETE_EVENT_ID) { |
223 | ret = wl1271_event_scan_complete(wl, mbox); | 194 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
195 | mbox->scheduled_scan_status); | ||
196 | |||
197 | ret = wl1271_scan_complete(wl); | ||
224 | if (ret < 0) | 198 | if (ret < 0) |
225 | return ret; | 199 | return ret; |
226 | } | 200 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 70c6b0d22353..cdfcc054efe4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "wl1271_cmd.h" | 44 | #include "wl1271_cmd.h" |
45 | #include "wl1271_boot.h" | 45 | #include "wl1271_boot.h" |
46 | #include "wl1271_testmode.h" | 46 | #include "wl1271_testmode.h" |
47 | #include "wl1271_scan.h" | ||
47 | 48 | ||
48 | #define WL1271_BOOT_RETRIES 3 | 49 | #define WL1271_BOOT_RETRIES 3 |
49 | 50 | ||
@@ -1550,11 +1551,11 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1550 | goto out; | 1551 | goto out; |
1551 | 1552 | ||
1552 | if (wl1271_11a_enabled()) | 1553 | if (wl1271_11a_enabled()) |
1553 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, | 1554 | ret = wl1271_scan(hw->priv, ssid, len, req, |
1554 | 1, 0, WL1271_SCAN_BAND_DUAL, 3); | 1555 | 1, 0, WL1271_SCAN_BAND_DUAL, 3); |
1555 | else | 1556 | else |
1556 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, | 1557 | ret = wl1271_scan(hw->priv, ssid, len, req, |
1557 | 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); | 1558 | 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); |
1558 | 1559 | ||
1559 | wl1271_ps_elp_sleep(wl); | 1560 | wl1271_ps_elp_sleep(wl); |
1560 | 1561 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c new file mode 100644 index 000000000000..eb9b4ece4ec3 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/ieee80211.h> | ||
25 | |||
26 | #include "wl1271.h" | ||
27 | #include "wl1271_cmd.h" | ||
28 | #include "wl1271_scan.h" | ||
29 | #include "wl1271_acx.h" | ||
30 | |||
31 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
32 | struct cfg80211_scan_request *req, u8 active_scan, | ||
33 | u8 high_prio, u8 band, u8 probe_requests) | ||
34 | { | ||
35 | |||
36 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | ||
37 | struct wl1271_cmd_scan *params = NULL; | ||
38 | struct ieee80211_channel *channels; | ||
39 | u32 rate; | ||
40 | int i, j, n_ch, ret; | ||
41 | u16 scan_options = 0; | ||
42 | u8 ieee_band; | ||
43 | |||
44 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { | ||
45 | ieee_band = IEEE80211_BAND_2GHZ; | ||
46 | rate = wl->conf.tx.basic_rate; | ||
47 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
48 | ieee_band = IEEE80211_BAND_2GHZ; | ||
49 | rate = wl->conf.tx.basic_rate; | ||
50 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
51 | ieee_band = IEEE80211_BAND_5GHZ; | ||
52 | rate = wl->conf.tx.basic_rate_5; | ||
53 | } else | ||
54 | return -EINVAL; | ||
55 | |||
56 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | ||
57 | return -EINVAL; | ||
58 | |||
59 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | ||
60 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | ||
61 | |||
62 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) | ||
63 | return -EINVAL; | ||
64 | |||
65 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
66 | if (!params) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
70 | params->params.rx_filter_options = | ||
71 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
72 | |||
73 | if (!active_scan) | ||
74 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
75 | if (high_prio) | ||
76 | scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; | ||
77 | params->params.scan_options = cpu_to_le16(scan_options); | ||
78 | |||
79 | params->params.num_probe_requests = probe_requests; | ||
80 | params->params.tx_rate = cpu_to_le32(rate); | ||
81 | params->params.tid_trigger = 0; | ||
82 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
83 | |||
84 | if (band == WL1271_SCAN_BAND_DUAL) | ||
85 | params->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
86 | else | ||
87 | params->params.band = band; | ||
88 | |||
89 | for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { | ||
90 | if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { | ||
91 | params->channels[j].min_duration = | ||
92 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | ||
93 | params->channels[j].max_duration = | ||
94 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | ||
95 | memset(¶ms->channels[j].bssid_lsb, 0xff, 4); | ||
96 | memset(¶ms->channels[j].bssid_msb, 0xff, 2); | ||
97 | params->channels[j].early_termination = 0; | ||
98 | params->channels[j].tx_power_att = | ||
99 | WL1271_SCAN_CURRENT_TX_PWR; | ||
100 | params->channels[j].channel = channels[i].hw_value; | ||
101 | j++; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | params->params.num_channels = j; | ||
106 | |||
107 | if (ssid_len && ssid) { | ||
108 | params->params.ssid_len = ssid_len; | ||
109 | memcpy(params->params.ssid, ssid, ssid_len); | ||
110 | } | ||
111 | |||
112 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, | ||
113 | req->ie, req->ie_len, ieee_band); | ||
114 | if (ret < 0) { | ||
115 | wl1271_error("PROBE request template failed"); | ||
116 | goto out; | ||
117 | } | ||
118 | |||
119 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
120 | if (!trigger) { | ||
121 | ret = -ENOMEM; | ||
122 | goto out; | ||
123 | } | ||
124 | |||
125 | /* disable the timeout */ | ||
126 | trigger->timeout = 0; | ||
127 | |||
128 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
129 | sizeof(*trigger), 0); | ||
130 | if (ret < 0) { | ||
131 | wl1271_error("trigger scan to failed for hw scan"); | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | ||
136 | |||
137 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
138 | if (wl1271_11a_enabled()) { | ||
139 | wl->scan.state = band; | ||
140 | if (band == WL1271_SCAN_BAND_DUAL) { | ||
141 | wl->scan.active = active_scan; | ||
142 | wl->scan.high_prio = high_prio; | ||
143 | wl->scan.probe_requests = probe_requests; | ||
144 | if (ssid_len && ssid) { | ||
145 | wl->scan.ssid_len = ssid_len; | ||
146 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
147 | } else | ||
148 | wl->scan.ssid_len = 0; | ||
149 | wl->scan.req = req; | ||
150 | } else | ||
151 | wl->scan.req = NULL; | ||
152 | } | ||
153 | |||
154 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | ||
155 | if (ret < 0) { | ||
156 | wl1271_error("SCAN failed"); | ||
157 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
158 | goto out; | ||
159 | } | ||
160 | |||
161 | out: | ||
162 | kfree(params); | ||
163 | kfree(trigger); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | int wl1271_scan_complete(struct wl1271 *wl) | ||
168 | { | ||
169 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | ||
170 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | ||
171 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend to | ||
172 | * the wl1271_scan function that we are not scanning | ||
173 | * as it checks that. | ||
174 | */ | ||
175 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
176 | /* FIXME: ie missing! */ | ||
177 | wl1271_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | ||
178 | wl->scan.req, | ||
179 | wl->scan.active, | ||
180 | wl->scan.high_prio, | ||
181 | WL1271_SCAN_BAND_5_GHZ, | ||
182 | wl->scan.probe_requests); | ||
183 | } else { | ||
184 | mutex_unlock(&wl->mutex); | ||
185 | ieee80211_scan_completed(wl->hw, false); | ||
186 | mutex_lock(&wl->mutex); | ||
187 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
188 | } | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h new file mode 100644 index 000000000000..0002e815cb43 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_SCAN_H__ | ||
25 | #define __WL1271_SCAN_H__ | ||
26 | |||
27 | #include "wl1271.h" | ||
28 | |||
29 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
30 | struct cfg80211_scan_request *req, u8 active_scan, | ||
31 | u8 high_prio, u8 band, u8 probe_requests); | ||
32 | int wl1271_scan_build_probe_req(struct wl1271 *wl, | ||
33 | const u8 *ssid, size_t ssid_len, | ||
34 | const u8 *ie, size_t ie_len, u8 band); | ||
35 | int wl1271_scan_complete(struct wl1271 *wl); | ||
36 | |||
37 | #define WL1271_SCAN_MAX_CHANNELS 24 | ||
38 | #define WL1271_SCAN_DEFAULT_TAG 1 | ||
39 | #define WL1271_SCAN_CURRENT_TX_PWR 0 | ||
40 | #define WL1271_SCAN_OPT_ACTIVE 0 | ||
41 | #define WL1271_SCAN_OPT_PASSIVE 1 | ||
42 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | ||
43 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | ||
44 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | ||
45 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | ||
46 | #define WL1271_SCAN_BAND_5_GHZ 1 | ||
47 | #define WL1271_SCAN_BAND_DUAL 2 | ||
48 | |||
49 | struct basic_scan_params { | ||
50 | __le32 rx_config_options; | ||
51 | __le32 rx_filter_options; | ||
52 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
53 | __le16 scan_options; | ||
54 | /* Number of scan channels in the list (maximum 30) */ | ||
55 | u8 num_channels; | ||
56 | /* This field indicates the number of probe requests to send | ||
57 | per channel for an active scan */ | ||
58 | u8 num_probe_requests; | ||
59 | /* Rate bit field for sending the probes */ | ||
60 | __le32 tx_rate; | ||
61 | u8 tid_trigger; | ||
62 | u8 ssid_len; | ||
63 | /* in order to align */ | ||
64 | u8 padding1[2]; | ||
65 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
66 | /* Band to scan */ | ||
67 | u8 band; | ||
68 | u8 use_ssid_list; | ||
69 | u8 scan_tag; | ||
70 | u8 padding2; | ||
71 | } __attribute__ ((packed)); | ||
72 | |||
73 | struct basic_scan_channel_params { | ||
74 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
75 | __le32 min_duration; | ||
76 | __le32 max_duration; | ||
77 | __le32 bssid_lsb; | ||
78 | __le16 bssid_msb; | ||
79 | u8 early_termination; | ||
80 | u8 tx_power_att; | ||
81 | u8 channel; | ||
82 | /* FW internal use only! */ | ||
83 | u8 dfs_candidate; | ||
84 | u8 activity_detected; | ||
85 | u8 pad; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | struct wl1271_cmd_scan { | ||
89 | struct wl1271_cmd_header header; | ||
90 | |||
91 | struct basic_scan_params params; | ||
92 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
93 | } __attribute__ ((packed)); | ||
94 | |||
95 | struct wl1271_cmd_trigger_scan_to { | ||
96 | struct wl1271_cmd_header header; | ||
97 | |||
98 | __le32 timeout; | ||
99 | } __attribute__ ((packed)); | ||
100 | |||
101 | #endif /* __WL1271_SCAN_H__ */ | ||