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
;
39 struct cfg80211_scan_info info
= {
44 dwork
= to_delayed_work(work
);
45 wl
= container_of(dwork
, struct wl1271
, scan_complete_work
);
47 wl1271_debug(DEBUG_SCAN
, "Scanning complete");
49 mutex_lock(&wl
->mutex
);
51 if (unlikely(wl
->state
!= WLCORE_STATE_ON
))
54 if (wl
->scan
.state
== WL1271_SCAN_STATE_IDLE
)
57 wlvif
= wl
->scan_wlvif
;
60 * Rearm the tx watchdog just before idling scan. This
61 * prevents just-finished scans from triggering the watchdog
63 wl12xx_rearm_tx_watchdog_locked(wl
);
65 wl
->scan
.state
= WL1271_SCAN_STATE_IDLE
;
66 memset(wl
->scan
.scanned_ch
, 0, sizeof(wl
->scan
.scanned_ch
));
68 wl
->scan_wlvif
= NULL
;
70 ret
= wl1271_ps_elp_wakeup(wl
);
74 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED
, &wlvif
->flags
)) {
75 /* restore hardware connection monitoring template */
76 wl1271_cmd_build_ap_probe_req(wl
, wlvif
, wlvif
->probereq
);
79 wl1271_ps_elp_sleep(wl
);
81 if (wl
->scan
.failed
) {
82 wl1271_info("Scan completed due to error.");
83 wl12xx_queue_recovery_work(wl
);
86 wlcore_cmd_regdomain_config_locked(wl
);
88 ieee80211_scan_completed(wl
->hw
, &info
);
91 mutex_unlock(&wl
->mutex
);
95 static void wlcore_started_vifs_iter(void *data
, u8
*mac
,
96 struct ieee80211_vif
*vif
)
98 struct wl12xx_vif
*wlvif
= wl12xx_vif_to_data(vif
);
100 int *count
= (int *)data
;
103 * count active interfaces according to interface type.
104 * checking only bss_conf.idle is bad for some cases, e.g.
105 * we don't want to count sta in p2p_find as active interface.
107 switch (wlvif
->bss_type
) {
108 case BSS_TYPE_STA_BSS
:
109 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED
, &wlvif
->flags
))
113 case BSS_TYPE_AP_BSS
:
114 if (wlvif
->wl
->active_sta_count
> 0)
126 static int wlcore_count_started_vifs(struct wl1271
*wl
)
130 ieee80211_iterate_active_interfaces_atomic(wl
->hw
,
131 IEEE80211_IFACE_ITER_RESUME_ALL
,
132 wlcore_started_vifs_iter
, &count
);
137 wlcore_scan_get_channels(struct wl1271
*wl
,
138 struct ieee80211_channel
*req_channels
[],
141 struct conn_scan_ch_params
*channels
,
142 u32 band
, bool radar
, bool passive
,
143 int start
, int max_channels
,
149 bool force_passive
= !n_ssids
;
150 u32 min_dwell_time_active
, max_dwell_time_active
;
151 u32 dwell_time_passive
, dwell_time_dfs
;
153 /* configure dwell times according to scan type */
154 if (scan_type
== SCAN_TYPE_SEARCH
) {
155 struct conf_scan_settings
*c
= &wl
->conf
.scan
;
156 bool active_vif_exists
= !!wlcore_count_started_vifs(wl
);
158 min_dwell_time_active
= active_vif_exists
?
159 c
->min_dwell_time_active
:
160 c
->min_dwell_time_active_long
;
161 max_dwell_time_active
= active_vif_exists
?
162 c
->max_dwell_time_active
:
163 c
->max_dwell_time_active_long
;
164 dwell_time_passive
= c
->dwell_time_passive
;
165 dwell_time_dfs
= c
->dwell_time_dfs
;
167 struct conf_sched_scan_settings
*c
= &wl
->conf
.sched_scan
;
170 if (band
== NL80211_BAND_5GHZ
)
171 delta_per_probe
= c
->dwell_time_delta_per_probe_5
;
173 delta_per_probe
= c
->dwell_time_delta_per_probe
;
175 min_dwell_time_active
= c
->base_dwell_time
+
176 n_ssids
* c
->num_probe_reqs
* delta_per_probe
;
178 max_dwell_time_active
= min_dwell_time_active
+
179 c
->max_dwell_time_delta
;
180 dwell_time_passive
= c
->dwell_time_passive
;
181 dwell_time_dfs
= c
->dwell_time_dfs
;
183 min_dwell_time_active
= DIV_ROUND_UP(min_dwell_time_active
, 1000);
184 max_dwell_time_active
= DIV_ROUND_UP(max_dwell_time_active
, 1000);
185 dwell_time_passive
= DIV_ROUND_UP(dwell_time_passive
, 1000);
186 dwell_time_dfs
= DIV_ROUND_UP(dwell_time_dfs
, 1000);
188 for (i
= 0, j
= start
;
189 i
< n_channels
&& j
< max_channels
;
191 flags
= req_channels
[i
]->flags
;
194 flags
|= IEEE80211_CHAN_NO_IR
;
196 if ((req_channels
[i
]->band
== band
) &&
197 !(flags
& IEEE80211_CHAN_DISABLED
) &&
198 (!!(flags
& IEEE80211_CHAN_RADAR
) == radar
) &&
199 /* if radar is set, we ignore the passive flag */
201 !!(flags
& IEEE80211_CHAN_NO_IR
) == passive
)) {
202 if (flags
& IEEE80211_CHAN_RADAR
) {
203 channels
[j
].flags
|= SCAN_CHANNEL_FLAGS_DFS
;
205 channels
[j
].passive_duration
=
206 cpu_to_le16(dwell_time_dfs
);
208 channels
[j
].passive_duration
=
209 cpu_to_le16(dwell_time_passive
);
212 channels
[j
].min_duration
=
213 cpu_to_le16(min_dwell_time_active
);
214 channels
[j
].max_duration
=
215 cpu_to_le16(max_dwell_time_active
);
217 channels
[j
].tx_power_att
= req_channels
[i
]->max_power
;
218 channels
[j
].channel
= req_channels
[i
]->hw_value
;
221 (band
== NL80211_BAND_2GHZ
) &&
222 (channels
[j
].channel
>= 12) &&
223 (channels
[j
].channel
<= 14) &&
224 (flags
& IEEE80211_CHAN_NO_IR
) &&
226 /* pactive channels treated as DFS */
227 channels
[j
].flags
= SCAN_CHANNEL_FLAGS_DFS
;
230 * n_pactive_ch is counted down from the end of
231 * the passive channel list
234 wl1271_debug(DEBUG_SCAN
, "n_pactive_ch = %d",
238 wl1271_debug(DEBUG_SCAN
, "freq %d, ch. %d, flags 0x%x, power %d, min/max_dwell %d/%d%s%s",
239 req_channels
[i
]->center_freq
,
240 req_channels
[i
]->hw_value
,
241 req_channels
[i
]->flags
,
242 req_channels
[i
]->max_power
,
243 min_dwell_time_active
,
244 max_dwell_time_active
,
245 flags
& IEEE80211_CHAN_RADAR
?
247 flags
& IEEE80211_CHAN_NO_IR
?
257 wlcore_set_scan_chan_params(struct wl1271
*wl
,
258 struct wlcore_scan_channels
*cfg
,
259 struct ieee80211_channel
*channels
[],
267 wlcore_scan_get_channels(wl
,
278 wlcore_scan_get_channels(wl
,
290 wlcore_scan_get_channels(wl
,
301 wlcore_scan_get_channels(wl
,
313 wlcore_scan_get_channels(wl
,
320 cfg
->passive
[1] + cfg
->dfs
,
325 /* 802.11j channels are not supported yet */
329 cfg
->passive_active
= n_pactive_ch
;
331 wl1271_debug(DEBUG_SCAN
, " 2.4GHz: active %d passive %d",
332 cfg
->active
[0], cfg
->passive
[0]);
333 wl1271_debug(DEBUG_SCAN
, " 5GHz: active %d passive %d",
334 cfg
->active
[1], cfg
->passive
[1]);
335 wl1271_debug(DEBUG_SCAN
, " DFS: %d", cfg
->dfs
);
337 return cfg
->passive
[0] || cfg
->active
[0] ||
338 cfg
->passive
[1] || cfg
->active
[1] || cfg
->dfs
||
339 cfg
->passive
[2] || cfg
->active
[2];
341 EXPORT_SYMBOL_GPL(wlcore_set_scan_chan_params
);
343 int wlcore_scan(struct wl1271
*wl
, struct ieee80211_vif
*vif
,
344 const u8
*ssid
, size_t ssid_len
,
345 struct cfg80211_scan_request
*req
)
347 struct wl12xx_vif
*wlvif
= wl12xx_vif_to_data(vif
);
350 * cfg80211 should guarantee that we don't get more channels
351 * than what we have registered.
353 BUG_ON(req
->n_channels
> WL1271_MAX_CHANNELS
);
355 if (wl
->scan
.state
!= WL1271_SCAN_STATE_IDLE
)
358 wl
->scan
.state
= WL1271_SCAN_STATE_2GHZ_ACTIVE
;
360 if (ssid_len
&& ssid
) {
361 wl
->scan
.ssid_len
= ssid_len
;
362 memcpy(wl
->scan
.ssid
, ssid
, ssid_len
);
364 wl
->scan
.ssid_len
= 0;
367 wl
->scan_wlvif
= wlvif
;
369 memset(wl
->scan
.scanned_ch
, 0, sizeof(wl
->scan
.scanned_ch
));
371 /* we assume failure so that timeout scenarios are handled correctly */
372 wl
->scan
.failed
= true;
373 ieee80211_queue_delayed_work(wl
->hw
, &wl
->scan_complete_work
,
374 msecs_to_jiffies(WL1271_SCAN_TIMEOUT
));
376 wl
->ops
->scan_start(wl
, wlvif
, req
);
380 /* Returns the scan type to be used or a negative value on error */
382 wlcore_scan_sched_scan_ssid_list(struct wl1271
*wl
,
383 struct wl12xx_vif
*wlvif
,
384 struct cfg80211_sched_scan_request
*req
)
386 struct wl1271_cmd_sched_scan_ssid_list
*cmd
= NULL
;
387 struct cfg80211_match_set
*sets
= req
->match_sets
;
388 struct cfg80211_ssid
*ssids
= req
->ssids
;
389 int ret
= 0, type
, i
, j
, n_match_ssids
= 0;
391 wl1271_debug((DEBUG_CMD
| DEBUG_SCAN
), "cmd sched scan ssid list");
393 /* count the match sets that contain SSIDs */
394 for (i
= 0; i
< req
->n_match_sets
; i
++)
395 if (sets
[i
].ssid
.ssid_len
> 0)
398 /* No filter, no ssids or only bcast ssid */
399 if (!n_match_ssids
&&
401 (req
->n_ssids
== 1 && req
->ssids
[0].ssid_len
== 0))) {
402 type
= SCAN_SSID_FILTER_ANY
;
406 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
412 cmd
->role_id
= wlvif
->role_id
;
413 if (!n_match_ssids
) {
414 /* No filter, with ssids */
415 type
= SCAN_SSID_FILTER_DISABLED
;
417 for (i
= 0; i
< req
->n_ssids
; i
++) {
418 cmd
->ssids
[cmd
->n_ssids
].type
= (ssids
[i
].ssid_len
) ?
419 SCAN_SSID_TYPE_HIDDEN
: SCAN_SSID_TYPE_PUBLIC
;
420 cmd
->ssids
[cmd
->n_ssids
].len
= ssids
[i
].ssid_len
;
421 memcpy(cmd
->ssids
[cmd
->n_ssids
].ssid
, ssids
[i
].ssid
,
426 type
= SCAN_SSID_FILTER_LIST
;
428 /* Add all SSIDs from the filters */
429 for (i
= 0; i
< req
->n_match_sets
; i
++) {
430 /* ignore sets without SSIDs */
431 if (!sets
[i
].ssid
.ssid_len
)
434 cmd
->ssids
[cmd
->n_ssids
].type
= SCAN_SSID_TYPE_PUBLIC
;
435 cmd
->ssids
[cmd
->n_ssids
].len
= sets
[i
].ssid
.ssid_len
;
436 memcpy(cmd
->ssids
[cmd
->n_ssids
].ssid
,
437 sets
[i
].ssid
.ssid
, sets
[i
].ssid
.ssid_len
);
440 if ((req
->n_ssids
> 1) ||
441 (req
->n_ssids
== 1 && req
->ssids
[0].ssid_len
> 0)) {
443 * Mark all the SSIDs passed in the SSID list as HIDDEN,
444 * so they're used in probe requests.
446 for (i
= 0; i
< req
->n_ssids
; i
++) {
447 if (!req
->ssids
[i
].ssid_len
)
450 for (j
= 0; j
< cmd
->n_ssids
; j
++)
451 if ((req
->ssids
[i
].ssid_len
==
452 cmd
->ssids
[j
].len
) &&
453 !memcmp(req
->ssids
[i
].ssid
,
455 req
->ssids
[i
].ssid_len
)) {
457 SCAN_SSID_TYPE_HIDDEN
;
460 /* Fail if SSID isn't present in the filters */
461 if (j
== cmd
->n_ssids
) {
469 ret
= wl1271_cmd_send(wl
, CMD_CONNECTION_SCAN_SSID_CFG
, cmd
,
472 wl1271_error("cmd sched scan ssid list failed");
483 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_ssid_list
);
485 void wlcore_scan_sched_scan_results(struct wl1271
*wl
)
487 wl1271_debug(DEBUG_SCAN
, "got periodic scan results");
489 ieee80211_sched_scan_results(wl
->hw
);
491 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_results
);