aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@nokia.com>2010-07-08 10:50:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-08 16:41:58 -0400
commit34dd2aaac4a4b908c093980a9894fd878aeb6deb (patch)
tree62bd3f0ee0d56888d0b722648271c3463a6bab19 /drivers/net/wireless/wl12xx
parentf532be6d48a12cd1b27c4efa38d22e0cbfa512d1 (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/Makefile2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c136
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h68
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c36
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c9
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_scan.c191
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_scan.h101
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
10wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ 10wl1271-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
15wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o 15wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
16obj-$(CONFIG_WL1271) += wl1271.o 16obj-$(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
466int 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(&params->channels[j].bssid_lsb, 0xff, 4);
531 memset(&params->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
596out:
597 kfree(params);
598 kfree(trigger);
599 return ret;
600}
601
602int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, 466int 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);
41int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); 41int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
42int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, 42int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
43 size_t len); 43 size_t len);
44int 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);
47int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, 44int 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);
49int wl1271_cmd_build_null_data(struct wl1271 *wl); 46int 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
366struct 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
390struct 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
405struct 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
412struct wl1271_cmd_trigger_scan_to {
413 struct wl1271_cmd_header header;
414
415 __le32 timeout;
416} __attribute__ ((packed));
417
418struct wl1271_cmd_test_header { 350struct 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
31void wl1271_pspoll_work(struct work_struct *work) 32void 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
88static 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
118static int wl1271_event_ps_report(struct wl1271 *wl, 89static 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
31int 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(&params->channels[j].bssid_lsb, 0xff, 4);
96 memset(&params->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
161out:
162 kfree(params);
163 kfree(trigger);
164 return ret;
165}
166
167int 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
29int 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);
32int 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);
35int 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
49struct 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
73struct 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
88struct 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
95struct wl1271_cmd_trigger_scan_to {
96 struct wl1271_cmd_header header;
97
98 __le32 timeout;
99} __attribute__ ((packed));
100
101#endif /* __WL1271_SCAN_H__ */