2 * This file is part of wl1271
4 * Copyright (C) 2009-2010 Nokia Corporation
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
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.
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.
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
24 #include <linux/ieee80211.h>
34 void wl1271_scan_complete_work(struct work_struct
*work
)
36 struct delayed_work
*dwork
;
38 struct wl12xx_vif
*wlvif
;
41 dwork
= container_of(work
, struct delayed_work
, work
);
42 wl
= container_of(dwork
, struct wl1271
, scan_complete_work
);
44 wl1271_debug(DEBUG_SCAN
, "Scanning complete");
46 mutex_lock(&wl
->mutex
);
48 if (unlikely(wl
->state
!= WLCORE_STATE_ON
))
51 if (wl
->scan
.state
== WL1271_SCAN_STATE_IDLE
)
54 wlvif
= wl
->scan_wlvif
;
57 * Rearm the tx watchdog just before idling scan. This
58 * prevents just-finished scans from triggering the watchdog
60 wl12xx_rearm_tx_watchdog_locked(wl
);
62 wl
->scan
.state
= WL1271_SCAN_STATE_IDLE
;
63 memset(wl
->scan
.scanned_ch
, 0, sizeof(wl
->scan
.scanned_ch
));
65 wl
->scan_wlvif
= NULL
;
67 ret
= wl1271_ps_elp_wakeup(wl
);
71 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED
, &wlvif
->flags
)) {
72 /* restore hardware connection monitoring template */
73 wl1271_cmd_build_ap_probe_req(wl
, wlvif
, wlvif
->probereq
);
76 wl1271_ps_elp_sleep(wl
);
78 if (wl
->scan
.failed
) {
79 wl1271_info("Scan completed due to error.");
80 wl12xx_queue_recovery_work(wl
);
83 wlcore_cmd_regdomain_config_locked(wl
);
85 ieee80211_scan_completed(wl
->hw
, false);
88 mutex_unlock(&wl
->mutex
);
92 static void wlcore_started_vifs_iter(void *data
, u8
*mac
,
93 struct ieee80211_vif
*vif
)
95 struct wl12xx_vif
*wlvif
= wl12xx_vif_to_data(vif
);
97 int *count
= (int *)data
;
100 * count active interfaces according to interface type.
101 * checking only bss_conf.idle is bad for some cases, e.g.
102 * we don't want to count sta in p2p_find as active interface.
104 switch (wlvif
->bss_type
) {
105 case BSS_TYPE_STA_BSS
:
106 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED
, &wlvif
->flags
))
110 case BSS_TYPE_AP_BSS
:
111 if (wlvif
->wl
->active_sta_count
> 0)
123 static int wlcore_count_started_vifs(struct wl1271
*wl
)
127 ieee80211_iterate_active_interfaces_atomic(wl
->hw
,
128 IEEE80211_IFACE_ITER_RESUME_ALL
,
129 wlcore_started_vifs_iter
, &count
);
134 wlcore_scan_get_channels(struct wl1271
*wl
,
135 struct ieee80211_channel
*req_channels
[],
138 struct conn_scan_ch_params
*channels
,
139 u32 band
, bool radar
, bool passive
,
140 int start
, int max_channels
,
146 bool force_passive
= !n_ssids
;
147 u32 min_dwell_time_active
, max_dwell_time_active
;
148 u32 dwell_time_passive
, dwell_time_dfs
;
150 /* configure dwell times according to scan type */
151 if (scan_type
== SCAN_TYPE_SEARCH
) {
152 struct conf_scan_settings
*c
= &wl
->conf
.scan
;
153 bool active_vif_exists
= !!wlcore_count_started_vifs(wl
);
155 min_dwell_time_active
= active_vif_exists
?
156 c
->min_dwell_time_active
:
157 c
->min_dwell_time_active_long
;
158 max_dwell_time_active
= active_vif_exists
?
159 c
->max_dwell_time_active
:
160 c
->max_dwell_time_active_long
;
161 dwell_time_passive
= c
->dwell_time_passive
;
162 dwell_time_dfs
= c
->dwell_time_dfs
;
164 struct conf_sched_scan_settings
*c
= &wl
->conf
.sched_scan
;
167 if (band
== IEEE80211_BAND_5GHZ
)
168 delta_per_probe
= c
->dwell_time_delta_per_probe_5
;
170 delta_per_probe
= c
->dwell_time_delta_per_probe
;
172 min_dwell_time_active
= c
->base_dwell_time
+
173 n_ssids
* c
->num_probe_reqs
* delta_per_probe
;
175 max_dwell_time_active
= min_dwell_time_active
+
176 c
->max_dwell_time_delta
;
177 dwell_time_passive
= c
->dwell_time_passive
;
178 dwell_time_dfs
= c
->dwell_time_dfs
;
180 min_dwell_time_active
= DIV_ROUND_UP(min_dwell_time_active
, 1000);
181 max_dwell_time_active
= DIV_ROUND_UP(max_dwell_time_active
, 1000);
182 dwell_time_passive
= DIV_ROUND_UP(dwell_time_passive
, 1000);
183 dwell_time_dfs
= DIV_ROUND_UP(dwell_time_dfs
, 1000);
185 for (i
= 0, j
= start
;
186 i
< n_channels
&& j
< max_channels
;
188 flags
= req_channels
[i
]->flags
;
191 flags
|= IEEE80211_CHAN_NO_IR
;
193 if ((req_channels
[i
]->band
== band
) &&
194 !(flags
& IEEE80211_CHAN_DISABLED
) &&
195 (!!(flags
& IEEE80211_CHAN_RADAR
) == radar
) &&
196 /* if radar is set, we ignore the passive flag */
198 !!(flags
& IEEE80211_CHAN_NO_IR
) == passive
)) {
199 if (flags
& IEEE80211_CHAN_RADAR
) {
200 channels
[j
].flags
|= SCAN_CHANNEL_FLAGS_DFS
;
202 channels
[j
].passive_duration
=
203 cpu_to_le16(dwell_time_dfs
);
205 channels
[j
].passive_duration
=
206 cpu_to_le16(dwell_time_passive
);
209 channels
[j
].min_duration
=
210 cpu_to_le16(min_dwell_time_active
);
211 channels
[j
].max_duration
=
212 cpu_to_le16(max_dwell_time_active
);
214 channels
[j
].tx_power_att
= req_channels
[i
]->max_power
;
215 channels
[j
].channel
= req_channels
[i
]->hw_value
;
218 (band
== IEEE80211_BAND_2GHZ
) &&
219 (channels
[j
].channel
>= 12) &&
220 (channels
[j
].channel
<= 14) &&
221 (flags
& IEEE80211_CHAN_NO_IR
) &&
223 /* pactive channels treated as DFS */
224 channels
[j
].flags
= SCAN_CHANNEL_FLAGS_DFS
;
227 * n_pactive_ch is counted down from the end of
228 * the passive channel list
231 wl1271_debug(DEBUG_SCAN
, "n_pactive_ch = %d",
235 wl1271_debug(DEBUG_SCAN
, "freq %d, ch. %d, flags 0x%x, power %d, min/max_dwell %d/%d%s%s",
236 req_channels
[i
]->center_freq
,
237 req_channels
[i
]->hw_value
,
238 req_channels
[i
]->flags
,
239 req_channels
[i
]->max_power
,
240 min_dwell_time_active
,
241 max_dwell_time_active
,
242 flags
& IEEE80211_CHAN_RADAR
?
244 flags
& IEEE80211_CHAN_NO_IR
?
254 wlcore_set_scan_chan_params(struct wl1271
*wl
,
255 struct wlcore_scan_channels
*cfg
,
256 struct ieee80211_channel
*channels
[],
264 wlcore_scan_get_channels(wl
,
275 wlcore_scan_get_channels(wl
,
287 wlcore_scan_get_channels(wl
,
298 wlcore_scan_get_channels(wl
,
310 wlcore_scan_get_channels(wl
,
317 cfg
->passive
[1] + cfg
->dfs
,
322 /* 802.11j channels are not supported yet */
326 cfg
->passive_active
= n_pactive_ch
;
328 wl1271_debug(DEBUG_SCAN
, " 2.4GHz: active %d passive %d",
329 cfg
->active
[0], cfg
->passive
[0]);
330 wl1271_debug(DEBUG_SCAN
, " 5GHz: active %d passive %d",
331 cfg
->active
[1], cfg
->passive
[1]);
332 wl1271_debug(DEBUG_SCAN
, " DFS: %d", cfg
->dfs
);
334 return cfg
->passive
[0] || cfg
->active
[0] ||
335 cfg
->passive
[1] || cfg
->active
[1] || cfg
->dfs
||
336 cfg
->passive
[2] || cfg
->active
[2];
338 EXPORT_SYMBOL_GPL(wlcore_set_scan_chan_params
);
340 int wlcore_scan(struct wl1271
*wl
, struct ieee80211_vif
*vif
,
341 const u8
*ssid
, size_t ssid_len
,
342 struct cfg80211_scan_request
*req
)
344 struct wl12xx_vif
*wlvif
= wl12xx_vif_to_data(vif
);
347 * cfg80211 should guarantee that we don't get more channels
348 * than what we have registered.
350 BUG_ON(req
->n_channels
> WL1271_MAX_CHANNELS
);
352 if (wl
->scan
.state
!= WL1271_SCAN_STATE_IDLE
)
355 wl
->scan
.state
= WL1271_SCAN_STATE_2GHZ_ACTIVE
;
357 if (ssid_len
&& ssid
) {
358 wl
->scan
.ssid_len
= ssid_len
;
359 memcpy(wl
->scan
.ssid
, ssid
, ssid_len
);
361 wl
->scan
.ssid_len
= 0;
364 wl
->scan_wlvif
= wlvif
;
366 memset(wl
->scan
.scanned_ch
, 0, sizeof(wl
->scan
.scanned_ch
));
368 /* we assume failure so that timeout scenarios are handled correctly */
369 wl
->scan
.failed
= true;
370 ieee80211_queue_delayed_work(wl
->hw
, &wl
->scan_complete_work
,
371 msecs_to_jiffies(WL1271_SCAN_TIMEOUT
));
373 wl
->ops
->scan_start(wl
, wlvif
, req
);
377 /* Returns the scan type to be used or a negative value on error */
379 wlcore_scan_sched_scan_ssid_list(struct wl1271
*wl
,
380 struct wl12xx_vif
*wlvif
,
381 struct cfg80211_sched_scan_request
*req
)
383 struct wl1271_cmd_sched_scan_ssid_list
*cmd
= NULL
;
384 struct cfg80211_match_set
*sets
= req
->match_sets
;
385 struct cfg80211_ssid
*ssids
= req
->ssids
;
386 int ret
= 0, type
, i
, j
, n_match_ssids
= 0;
388 wl1271_debug((DEBUG_CMD
| DEBUG_SCAN
), "cmd sched scan ssid list");
390 /* count the match sets that contain SSIDs */
391 for (i
= 0; i
< req
->n_match_sets
; i
++)
392 if (sets
[i
].ssid
.ssid_len
> 0)
395 /* No filter, no ssids or only bcast ssid */
396 if (!n_match_ssids
&&
398 (req
->n_ssids
== 1 && req
->ssids
[0].ssid_len
== 0))) {
399 type
= SCAN_SSID_FILTER_ANY
;
403 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
409 cmd
->role_id
= wlvif
->role_id
;
410 if (!n_match_ssids
) {
411 /* No filter, with ssids */
412 type
= SCAN_SSID_FILTER_DISABLED
;
414 for (i
= 0; i
< req
->n_ssids
; i
++) {
415 cmd
->ssids
[cmd
->n_ssids
].type
= (ssids
[i
].ssid_len
) ?
416 SCAN_SSID_TYPE_HIDDEN
: SCAN_SSID_TYPE_PUBLIC
;
417 cmd
->ssids
[cmd
->n_ssids
].len
= ssids
[i
].ssid_len
;
418 memcpy(cmd
->ssids
[cmd
->n_ssids
].ssid
, ssids
[i
].ssid
,
423 type
= SCAN_SSID_FILTER_LIST
;
425 /* Add all SSIDs from the filters */
426 for (i
= 0; i
< req
->n_match_sets
; i
++) {
427 /* ignore sets without SSIDs */
428 if (!sets
[i
].ssid
.ssid_len
)
431 cmd
->ssids
[cmd
->n_ssids
].type
= SCAN_SSID_TYPE_PUBLIC
;
432 cmd
->ssids
[cmd
->n_ssids
].len
= sets
[i
].ssid
.ssid_len
;
433 memcpy(cmd
->ssids
[cmd
->n_ssids
].ssid
,
434 sets
[i
].ssid
.ssid
, sets
[i
].ssid
.ssid_len
);
437 if ((req
->n_ssids
> 1) ||
438 (req
->n_ssids
== 1 && req
->ssids
[0].ssid_len
> 0)) {
440 * Mark all the SSIDs passed in the SSID list as HIDDEN,
441 * so they're used in probe requests.
443 for (i
= 0; i
< req
->n_ssids
; i
++) {
444 if (!req
->ssids
[i
].ssid_len
)
447 for (j
= 0; j
< cmd
->n_ssids
; j
++)
448 if ((req
->ssids
[i
].ssid_len
==
449 cmd
->ssids
[j
].len
) &&
450 !memcmp(req
->ssids
[i
].ssid
,
452 req
->ssids
[i
].ssid_len
)) {
454 SCAN_SSID_TYPE_HIDDEN
;
457 /* Fail if SSID isn't present in the filters */
458 if (j
== cmd
->n_ssids
) {
466 ret
= wl1271_cmd_send(wl
, CMD_CONNECTION_SCAN_SSID_CFG
, cmd
,
469 wl1271_error("cmd sched scan ssid list failed");
480 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_ssid_list
);
482 void wlcore_scan_sched_scan_results(struct wl1271
*wl
)
484 wl1271_debug(DEBUG_SCAN
, "got periodic scan results");
486 ieee80211_sched_scan_results(wl
->hw
);
488 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_results
);