Merge branch 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / net / wireless / wl12xx / wl1271_scan.c
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 static int wl1271_get_scan_channels(struct wl1271 *wl,
32                                     struct cfg80211_scan_request *req,
33                                     struct basic_scan_channel_params *channels,
34                                     enum ieee80211_band band, bool passive)
35 {
36         int i, j;
37         u32 flags;
38
39         for (i = 0, j = 0;
40              i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
41              i++) {
42
43                 flags = req->channels[i]->flags;
44
45                 if (!wl->scan.scanned_ch[i] &&
46                     !(flags & IEEE80211_CHAN_DISABLED) &&
47                     ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) &&
48                     (req->channels[i]->band == band)) {
49
50                         wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
51                                      req->channels[i]->band,
52                                      req->channels[i]->center_freq);
53                         wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X",
54                                      req->channels[i]->hw_value,
55                                      req->channels[i]->flags);
56                         wl1271_debug(DEBUG_SCAN,
57                                      "max_antenna_gain %d, max_power %d",
58                                      req->channels[i]->max_antenna_gain,
59                                      req->channels[i]->max_power);
60                         wl1271_debug(DEBUG_SCAN, "beacon_found %d",
61                                      req->channels[i]->beacon_found);
62
63                         channels[j].min_duration =
64                                 cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
65                         channels[j].max_duration =
66                                 cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
67                         channels[j].early_termination = 0;
68                         channels[j].tx_power_att = req->channels[i]->max_power;
69                         channels[j].channel = req->channels[i]->hw_value;
70
71                         memset(&channels[j].bssid_lsb, 0xff, 4);
72                         memset(&channels[j].bssid_msb, 0xff, 2);
73
74                         /* Mark the channels we already used */
75                         wl->scan.scanned_ch[i] = true;
76
77                         j++;
78                 }
79         }
80
81         return j;
82 }
83
84 #define WL1271_NOTHING_TO_SCAN 1
85
86 static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
87                              bool passive, u32 basic_rate)
88 {
89         struct wl1271_cmd_scan *cmd;
90         struct wl1271_cmd_trigger_scan_to *trigger;
91         int ret;
92         u16 scan_options = 0;
93
94         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
95         trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
96         if (!cmd || !trigger) {
97                 ret = -ENOMEM;
98                 goto out;
99         }
100
101         /* We always use high priority scans */
102         scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
103         if(passive)
104                 scan_options |= WL1271_SCAN_OPT_PASSIVE;
105         cmd->params.scan_options = cpu_to_le16(scan_options);
106
107         cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
108                                                     cmd->channels,
109                                                     band, passive);
110         if (cmd->params.n_ch == 0) {
111                 ret = WL1271_NOTHING_TO_SCAN;
112                 goto out;
113         }
114
115         cmd->params.tx_rate = cpu_to_le32(basic_rate);
116         cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
117         cmd->params.rx_filter_options =
118                 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
119
120         cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
121         cmd->params.tx_rate = cpu_to_le32(basic_rate);
122         cmd->params.tid_trigger = 0;
123         cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
124
125         if (band == IEEE80211_BAND_2GHZ)
126                 cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ;
127         else
128                 cmd->params.band = WL1271_SCAN_BAND_5_GHZ;
129
130         if (wl->scan.ssid_len && wl->scan.ssid) {
131                 cmd->params.ssid_len = wl->scan.ssid_len;
132                 memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
133         }
134
135         ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
136                                          wl->scan.req->ie, wl->scan.req->ie_len,
137                                          band);
138         if (ret < 0) {
139                 wl1271_error("PROBE request template failed");
140                 goto out;
141         }
142
143         /* disable the timeout */
144         trigger->timeout = 0;
145         ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
146                               sizeof(*trigger), 0);
147         if (ret < 0) {
148                 wl1271_error("trigger scan to failed for hw scan");
149                 goto out;
150         }
151
152         wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
153
154         ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
155         if (ret < 0) {
156                 wl1271_error("SCAN failed");
157                 goto out;
158         }
159
160 out:
161         kfree(cmd);
162         kfree(trigger);
163         return ret;
164 }
165
166 void wl1271_scan_stm(struct wl1271 *wl)
167 {
168         int ret;
169
170         switch (wl->scan.state) {
171         case WL1271_SCAN_STATE_IDLE:
172                 break;
173
174         case WL1271_SCAN_STATE_2GHZ_ACTIVE:
175                 ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false,
176                                        wl->conf.tx.basic_rate);
177                 if (ret == WL1271_NOTHING_TO_SCAN) {
178                         wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
179                         wl1271_scan_stm(wl);
180                 }
181
182                 break;
183
184         case WL1271_SCAN_STATE_2GHZ_PASSIVE:
185                 ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
186                                        wl->conf.tx.basic_rate);
187                 if (ret == WL1271_NOTHING_TO_SCAN) {
188                         if (wl1271_11a_enabled())
189                                 wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
190                         else
191                                 wl->scan.state = WL1271_SCAN_STATE_DONE;
192                         wl1271_scan_stm(wl);
193                 }
194
195                 break;
196
197         case WL1271_SCAN_STATE_5GHZ_ACTIVE:
198                 ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false,
199                                        wl->conf.tx.basic_rate_5);
200                 if (ret == WL1271_NOTHING_TO_SCAN) {
201                         wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
202                         wl1271_scan_stm(wl);
203                 }
204
205                 break;
206
207         case WL1271_SCAN_STATE_5GHZ_PASSIVE:
208                 ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true,
209                                        wl->conf.tx.basic_rate_5);
210                 if (ret == WL1271_NOTHING_TO_SCAN) {
211                         wl->scan.state = WL1271_SCAN_STATE_DONE;
212                         wl1271_scan_stm(wl);
213                 }
214
215                 break;
216
217         case WL1271_SCAN_STATE_DONE:
218                 mutex_unlock(&wl->mutex);
219                 ieee80211_scan_completed(wl->hw, false);
220                 mutex_lock(&wl->mutex);
221
222                 kfree(wl->scan.scanned_ch);
223                 wl->scan.scanned_ch = NULL;
224
225                 wl->scan.state = WL1271_SCAN_STATE_IDLE;
226                 break;
227
228         default:
229                 wl1271_error("invalid scan state");
230                 break;
231         }
232 }
233
234 int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
235                 struct cfg80211_scan_request *req)
236 {
237         if (wl->scan.state != WL1271_SCAN_STATE_IDLE)
238                 return -EBUSY;
239
240         wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE;
241
242         if (ssid_len && ssid) {
243                 wl->scan.ssid_len = ssid_len;
244                 memcpy(wl->scan.ssid, ssid, ssid_len);
245         } else {
246                 wl->scan.ssid_len = 0;
247         }
248
249         wl->scan.req = req;
250
251         wl->scan.scanned_ch = kzalloc(req->n_channels *
252                                       sizeof(*wl->scan.scanned_ch),
253                                       GFP_KERNEL);
254         wl1271_scan_stm(wl);
255
256         return 0;
257 }