aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/scan.c')
-rw-r--r--drivers/net/wireless/wl12xx/scan.c102
1 files changed, 64 insertions, 38 deletions
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index fc29c671cf3b..8599dab1fe2a 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -24,6 +24,7 @@
24#include <linux/ieee80211.h> 24#include <linux/ieee80211.h>
25 25
26#include "wl12xx.h" 26#include "wl12xx.h"
27#include "debug.h"
27#include "cmd.h" 28#include "cmd.h"
28#include "scan.h" 29#include "scan.h"
29#include "acx.h" 30#include "acx.h"
@@ -34,6 +35,8 @@ void wl1271_scan_complete_work(struct work_struct *work)
34{ 35{
35 struct delayed_work *dwork; 36 struct delayed_work *dwork;
36 struct wl1271 *wl; 37 struct wl1271 *wl;
38 struct ieee80211_vif *vif;
39 struct wl12xx_vif *wlvif;
37 int ret; 40 int ret;
38 bool is_sta, is_ibss; 41 bool is_sta, is_ibss;
39 42
@@ -50,28 +53,31 @@ void wl1271_scan_complete_work(struct work_struct *work)
50 if (wl->scan.state == WL1271_SCAN_STATE_IDLE) 53 if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
51 goto out; 54 goto out;
52 55
56 vif = wl->scan_vif;
57 wlvif = wl12xx_vif_to_data(vif);
58
53 wl->scan.state = WL1271_SCAN_STATE_IDLE; 59 wl->scan.state = WL1271_SCAN_STATE_IDLE;
54 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 60 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
55 wl->scan.req = NULL; 61 wl->scan.req = NULL;
62 wl->scan_vif = NULL;
56 63
57 ret = wl1271_ps_elp_wakeup(wl); 64 ret = wl1271_ps_elp_wakeup(wl);
58 if (ret < 0) 65 if (ret < 0)
59 goto out; 66 goto out;
60 67
61 if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { 68 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
62 /* restore hardware connection monitoring template */ 69 /* restore hardware connection monitoring template */
63 wl1271_cmd_build_ap_probe_req(wl, wl->probereq); 70 wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
64 } 71 }
65 72
66 /* return to ROC if needed */ 73 /* return to ROC if needed */
67 is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); 74 is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
68 is_ibss = (wl->bss_type == BSS_TYPE_IBSS); 75 is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
69 if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || 76 if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
70 (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && 77 (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) &&
71 !test_bit(wl->dev_role_id, wl->roc_map)) { 78 !test_bit(wlvif->dev_role_id, wl->roc_map)) {
72 /* restore remain on channel */ 79 /* restore remain on channel */
73 wl12xx_cmd_role_start_dev(wl); 80 wl12xx_start_dev(wl, wlvif);
74 wl12xx_roc(wl, wl->dev_role_id);
75 } 81 }
76 wl1271_ps_elp_sleep(wl); 82 wl1271_ps_elp_sleep(wl);
77 83
@@ -155,9 +161,11 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
155 161
156#define WL1271_NOTHING_TO_SCAN 1 162#define WL1271_NOTHING_TO_SCAN 1
157 163
158static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, 164static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
159 bool passive, u32 basic_rate) 165 enum ieee80211_band band,
166 bool passive, u32 basic_rate)
160{ 167{
168 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
161 struct wl1271_cmd_scan *cmd; 169 struct wl1271_cmd_scan *cmd;
162 struct wl1271_cmd_trigger_scan_to *trigger; 170 struct wl1271_cmd_trigger_scan_to *trigger;
163 int ret; 171 int ret;
@@ -177,11 +185,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
177 if (passive) 185 if (passive)
178 scan_options |= WL1271_SCAN_OPT_PASSIVE; 186 scan_options |= WL1271_SCAN_OPT_PASSIVE;
179 187
180 if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { 188 if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) {
181 ret = -EINVAL; 189 ret = -EINVAL;
182 goto out; 190 goto out;
183 } 191 }
184 cmd->params.role_id = wl->role_id; 192 cmd->params.role_id = wlvif->role_id;
185 cmd->params.scan_options = cpu_to_le16(scan_options); 193 cmd->params.scan_options = cpu_to_le16(scan_options);
186 194
187 cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, 195 cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@@ -194,7 +202,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
194 202
195 cmd->params.tx_rate = cpu_to_le32(basic_rate); 203 cmd->params.tx_rate = cpu_to_le32(basic_rate);
196 cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; 204 cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
197 cmd->params.tx_rate = cpu_to_le32(basic_rate);
198 cmd->params.tid_trigger = 0; 205 cmd->params.tid_trigger = 0;
199 cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; 206 cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
200 207
@@ -208,11 +215,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
208 memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); 215 memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
209 } 216 }
210 217
211 memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); 218 memcpy(cmd->addr, vif->addr, ETH_ALEN);
212 219
213 ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, 220 ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid,
214 wl->scan.req->ie, wl->scan.req->ie_len, 221 wl->scan.ssid_len, wl->scan.req->ie,
215 band); 222 wl->scan.req->ie_len, band);
216 if (ret < 0) { 223 if (ret < 0) {
217 wl1271_error("PROBE request template failed"); 224 wl1271_error("PROBE request template failed");
218 goto out; 225 goto out;
@@ -241,11 +248,12 @@ out:
241 return ret; 248 return ret;
242} 249}
243 250
244void wl1271_scan_stm(struct wl1271 *wl) 251void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
245{ 252{
253 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
246 int ret = 0; 254 int ret = 0;
247 enum ieee80211_band band; 255 enum ieee80211_band band;
248 u32 rate; 256 u32 rate, mask;
249 257
250 switch (wl->scan.state) { 258 switch (wl->scan.state) {
251 case WL1271_SCAN_STATE_IDLE: 259 case WL1271_SCAN_STATE_IDLE:
@@ -253,47 +261,59 @@ void wl1271_scan_stm(struct wl1271 *wl)
253 261
254 case WL1271_SCAN_STATE_2GHZ_ACTIVE: 262 case WL1271_SCAN_STATE_2GHZ_ACTIVE:
255 band = IEEE80211_BAND_2GHZ; 263 band = IEEE80211_BAND_2GHZ;
256 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); 264 mask = wlvif->bitrate_masks[band];
257 ret = wl1271_scan_send(wl, band, false, rate); 265 if (wl->scan.req->no_cck) {
266 mask &= ~CONF_TX_CCK_RATES;
267 if (!mask)
268 mask = CONF_TX_RATE_MASK_BASIC_P2P;
269 }
270 rate = wl1271_tx_min_rate_get(wl, mask);
271 ret = wl1271_scan_send(wl, vif, band, false, rate);
258 if (ret == WL1271_NOTHING_TO_SCAN) { 272 if (ret == WL1271_NOTHING_TO_SCAN) {
259 wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; 273 wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
260 wl1271_scan_stm(wl); 274 wl1271_scan_stm(wl, vif);
261 } 275 }
262 276
263 break; 277 break;
264 278
265 case WL1271_SCAN_STATE_2GHZ_PASSIVE: 279 case WL1271_SCAN_STATE_2GHZ_PASSIVE:
266 band = IEEE80211_BAND_2GHZ; 280 band = IEEE80211_BAND_2GHZ;
267 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); 281 mask = wlvif->bitrate_masks[band];
268 ret = wl1271_scan_send(wl, band, true, rate); 282 if (wl->scan.req->no_cck) {
283 mask &= ~CONF_TX_CCK_RATES;
284 if (!mask)
285 mask = CONF_TX_RATE_MASK_BASIC_P2P;
286 }
287 rate = wl1271_tx_min_rate_get(wl, mask);
288 ret = wl1271_scan_send(wl, vif, band, true, rate);
269 if (ret == WL1271_NOTHING_TO_SCAN) { 289 if (ret == WL1271_NOTHING_TO_SCAN) {
270 if (wl->enable_11a) 290 if (wl->enable_11a)
271 wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; 291 wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
272 else 292 else
273 wl->scan.state = WL1271_SCAN_STATE_DONE; 293 wl->scan.state = WL1271_SCAN_STATE_DONE;
274 wl1271_scan_stm(wl); 294 wl1271_scan_stm(wl, vif);
275 } 295 }
276 296
277 break; 297 break;
278 298
279 case WL1271_SCAN_STATE_5GHZ_ACTIVE: 299 case WL1271_SCAN_STATE_5GHZ_ACTIVE:
280 band = IEEE80211_BAND_5GHZ; 300 band = IEEE80211_BAND_5GHZ;
281 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); 301 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
282 ret = wl1271_scan_send(wl, band, false, rate); 302 ret = wl1271_scan_send(wl, vif, band, false, rate);
283 if (ret == WL1271_NOTHING_TO_SCAN) { 303 if (ret == WL1271_NOTHING_TO_SCAN) {
284 wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; 304 wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
285 wl1271_scan_stm(wl); 305 wl1271_scan_stm(wl, vif);
286 } 306 }
287 307
288 break; 308 break;
289 309
290 case WL1271_SCAN_STATE_5GHZ_PASSIVE: 310 case WL1271_SCAN_STATE_5GHZ_PASSIVE:
291 band = IEEE80211_BAND_5GHZ; 311 band = IEEE80211_BAND_5GHZ;
292 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); 312 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
293 ret = wl1271_scan_send(wl, band, true, rate); 313 ret = wl1271_scan_send(wl, vif, band, true, rate);
294 if (ret == WL1271_NOTHING_TO_SCAN) { 314 if (ret == WL1271_NOTHING_TO_SCAN) {
295 wl->scan.state = WL1271_SCAN_STATE_DONE; 315 wl->scan.state = WL1271_SCAN_STATE_DONE;
296 wl1271_scan_stm(wl); 316 wl1271_scan_stm(wl, vif);
297 } 317 }
298 318
299 break; 319 break;
@@ -317,7 +337,8 @@ void wl1271_scan_stm(struct wl1271 *wl)
317 } 337 }
318} 338}
319 339
320int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, 340int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
341 const u8 *ssid, size_t ssid_len,
321 struct cfg80211_scan_request *req) 342 struct cfg80211_scan_request *req)
322{ 343{
323 /* 344 /*
@@ -338,6 +359,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
338 wl->scan.ssid_len = 0; 359 wl->scan.ssid_len = 0;
339 } 360 }
340 361
362 wl->scan_vif = vif;
341 wl->scan.req = req; 363 wl->scan.req = req;
342 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 364 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
343 365
@@ -346,7 +368,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
346 ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, 368 ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
347 msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); 369 msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
348 370
349 wl1271_scan_stm(wl); 371 wl1271_scan_stm(wl, vif);
350 372
351 return 0; 373 return 0;
352} 374}
@@ -550,6 +572,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
550 * so they're used in probe requests. 572 * so they're used in probe requests.
551 */ 573 */
552 for (i = 0; i < req->n_ssids; i++) { 574 for (i = 0; i < req->n_ssids; i++) {
575 if (!req->ssids[i].ssid_len)
576 continue;
577
553 for (j = 0; j < cmd->n_ssids; j++) 578 for (j = 0; j < cmd->n_ssids; j++)
554 if (!memcmp(req->ssids[i].ssid, 579 if (!memcmp(req->ssids[i].ssid,
555 cmd->ssids[j].ssid, 580 cmd->ssids[j].ssid,
@@ -585,6 +610,7 @@ out:
585} 610}
586 611
587int wl1271_scan_sched_scan_config(struct wl1271 *wl, 612int wl1271_scan_sched_scan_config(struct wl1271 *wl,
613 struct wl12xx_vif *wlvif,
588 struct cfg80211_sched_scan_request *req, 614 struct cfg80211_sched_scan_request *req,
589 struct ieee80211_sched_scan_ies *ies) 615 struct ieee80211_sched_scan_ies *ies)
590{ 616{
@@ -631,7 +657,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
631 } 657 }
632 658
633 if (!force_passive && cfg->active[0]) { 659 if (!force_passive && cfg->active[0]) {
634 ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, 660 ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
635 req->ssids[0].ssid_len, 661 req->ssids[0].ssid_len,
636 ies->ie[IEEE80211_BAND_2GHZ], 662 ies->ie[IEEE80211_BAND_2GHZ],
637 ies->len[IEEE80211_BAND_2GHZ], 663 ies->len[IEEE80211_BAND_2GHZ],
@@ -643,7 +669,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
643 } 669 }
644 670
645 if (!force_passive && cfg->active[1]) { 671 if (!force_passive && cfg->active[1]) {
646 ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, 672 ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
647 req->ssids[0].ssid_len, 673 req->ssids[0].ssid_len,
648 ies->ie[IEEE80211_BAND_5GHZ], 674 ies->ie[IEEE80211_BAND_5GHZ],
649 ies->len[IEEE80211_BAND_5GHZ], 675 ies->len[IEEE80211_BAND_5GHZ],
@@ -667,14 +693,14 @@ out:
667 return ret; 693 return ret;
668} 694}
669 695
670int wl1271_scan_sched_scan_start(struct wl1271 *wl) 696int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
671{ 697{
672 struct wl1271_cmd_sched_scan_start *start; 698 struct wl1271_cmd_sched_scan_start *start;
673 int ret = 0; 699 int ret = 0;
674 700
675 wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); 701 wl1271_debug(DEBUG_CMD, "cmd periodic scan start");
676 702
677 if (wl->bss_type != BSS_TYPE_STA_BSS) 703 if (wlvif->bss_type != BSS_TYPE_STA_BSS)
678 return -EOPNOTSUPP; 704 return -EOPNOTSUPP;
679 705
680 if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) 706 if (!test_bit(WL1271_FLAG_IDLE, &wl->flags))