diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/scan.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/scan.c | 102 |
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 | ||
158 | static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | 164 | static 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 | ||
244 | void wl1271_scan_stm(struct wl1271 *wl) | 251 | void 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 | ||
320 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 340 | int 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 | ||
587 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | 612 | int 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 | ||
670 | int wl1271_scan_sched_scan_start(struct wl1271 *wl) | 696 | int 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)) |