xref: /openbmc/linux/drivers/net/wireless/ti/wlcore/scan.c (revision c94e3690)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * This file is part of wl1271
4  *
5  * Copyright (C) 2009-2010 Nokia Corporation
6  *
7  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8  */
9 
10 #include <linux/ieee80211.h>
11 #include <linux/pm_runtime.h>
12 
13 #include "wlcore.h"
14 #include "debug.h"
15 #include "cmd.h"
16 #include "scan.h"
17 #include "acx.h"
18 #include "tx.h"
19 
wl1271_scan_complete_work(struct work_struct * work)20 void wl1271_scan_complete_work(struct work_struct *work)
21 {
22 	struct delayed_work *dwork;
23 	struct wl1271 *wl;
24 	struct wl12xx_vif *wlvif;
25 	struct cfg80211_scan_info info = {
26 		.aborted = false,
27 	};
28 	int ret;
29 
30 	dwork = to_delayed_work(work);
31 	wl = container_of(dwork, struct wl1271, scan_complete_work);
32 
33 	wl1271_debug(DEBUG_SCAN, "Scanning complete");
34 
35 	mutex_lock(&wl->mutex);
36 
37 	if (unlikely(wl->state != WLCORE_STATE_ON))
38 		goto out;
39 
40 	if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
41 		goto out;
42 
43 	wlvif = wl->scan_wlvif;
44 
45 	/*
46 	 * Rearm the tx watchdog just before idling scan. This
47 	 * prevents just-finished scans from triggering the watchdog
48 	 */
49 	wl12xx_rearm_tx_watchdog_locked(wl);
50 
51 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
52 	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
53 	wl->scan.req = NULL;
54 	wl->scan_wlvif = NULL;
55 
56 	ret = pm_runtime_resume_and_get(wl->dev);
57 	if (ret < 0)
58 		goto out;
59 
60 	if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
61 		/* restore hardware connection monitoring template */
62 		wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
63 	}
64 
65 	if (wl->scan.failed) {
66 		wl1271_info("Scan completed due to error.");
67 		wl12xx_queue_recovery_work(wl);
68 	}
69 
70 	wlcore_cmd_regdomain_config_locked(wl);
71 
72 	pm_runtime_mark_last_busy(wl->dev);
73 	pm_runtime_put_autosuspend(wl->dev);
74 
75 	ieee80211_scan_completed(wl->hw, &info);
76 
77 out:
78 	mutex_unlock(&wl->mutex);
79 
80 }
81 
wlcore_started_vifs_iter(void * data,u8 * mac,struct ieee80211_vif * vif)82 static void wlcore_started_vifs_iter(void *data, u8 *mac,
83 				     struct ieee80211_vif *vif)
84 {
85 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
86 	bool active = false;
87 	int *count = (int *)data;
88 
89 	/*
90 	 * count active interfaces according to interface type.
91 	 * checking only bss_conf.idle is bad for some cases, e.g.
92 	 * we don't want to count sta in p2p_find as active interface.
93 	 */
94 	switch (wlvif->bss_type) {
95 	case BSS_TYPE_STA_BSS:
96 		if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
97 			active = true;
98 		break;
99 
100 	case BSS_TYPE_AP_BSS:
101 		if (wlvif->wl->active_sta_count > 0)
102 			active = true;
103 		break;
104 
105 	default:
106 		break;
107 	}
108 
109 	if (active)
110 		(*count)++;
111 }
112 
wlcore_count_started_vifs(struct wl1271 * wl)113 static int wlcore_count_started_vifs(struct wl1271 *wl)
114 {
115 	int count = 0;
116 
117 	ieee80211_iterate_active_interfaces_atomic(wl->hw,
118 					IEEE80211_IFACE_ITER_RESUME_ALL,
119 					wlcore_started_vifs_iter, &count);
120 	return count;
121 }
122 
123 static int
wlcore_scan_get_channels(struct wl1271 * wl,struct ieee80211_channel * req_channels[],u32 n_channels,u32 n_ssids,struct conn_scan_ch_params * channels,u32 band,bool radar,bool passive,int start,int max_channels,u8 * n_pactive_ch,int scan_type)124 wlcore_scan_get_channels(struct wl1271 *wl,
125 			 struct ieee80211_channel *req_channels[],
126 			 u32 n_channels,
127 			 u32 n_ssids,
128 			 struct conn_scan_ch_params *channels,
129 			 u32 band, bool radar, bool passive,
130 			 int start, int max_channels,
131 			 u8 *n_pactive_ch,
132 			 int scan_type)
133 {
134 	int i, j;
135 	u32 flags;
136 	bool force_passive = !n_ssids;
137 	u32 min_dwell_time_active, max_dwell_time_active;
138 	u32 dwell_time_passive, dwell_time_dfs;
139 
140 	/* configure dwell times according to scan type */
141 	if (scan_type == SCAN_TYPE_SEARCH) {
142 		struct conf_scan_settings *c = &wl->conf.scan;
143 		bool active_vif_exists = !!wlcore_count_started_vifs(wl);
144 
145 		min_dwell_time_active = active_vif_exists ?
146 			c->min_dwell_time_active :
147 			c->min_dwell_time_active_long;
148 		max_dwell_time_active = active_vif_exists ?
149 			c->max_dwell_time_active :
150 			c->max_dwell_time_active_long;
151 		dwell_time_passive = c->dwell_time_passive;
152 		dwell_time_dfs = c->dwell_time_dfs;
153 	} else {
154 		struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
155 		u32 delta_per_probe;
156 
157 		if (band == NL80211_BAND_5GHZ)
158 			delta_per_probe = c->dwell_time_delta_per_probe_5;
159 		else
160 			delta_per_probe = c->dwell_time_delta_per_probe;
161 
162 		min_dwell_time_active = c->base_dwell_time +
163 			 n_ssids * c->num_probe_reqs * delta_per_probe;
164 
165 		max_dwell_time_active = min_dwell_time_active +
166 					c->max_dwell_time_delta;
167 		dwell_time_passive = c->dwell_time_passive;
168 		dwell_time_dfs = c->dwell_time_dfs;
169 	}
170 	min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000);
171 	max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000);
172 	dwell_time_passive = DIV_ROUND_UP(dwell_time_passive, 1000);
173 	dwell_time_dfs = DIV_ROUND_UP(dwell_time_dfs, 1000);
174 
175 	for (i = 0, j = start;
176 	     i < n_channels && j < max_channels;
177 	     i++) {
178 		flags = req_channels[i]->flags;
179 
180 		if (force_passive)
181 			flags |= IEEE80211_CHAN_NO_IR;
182 
183 		if ((req_channels[i]->band == band) &&
184 		    !(flags & IEEE80211_CHAN_DISABLED) &&
185 		    (!!(flags & IEEE80211_CHAN_RADAR) == radar) &&
186 		    /* if radar is set, we ignore the passive flag */
187 		    (radar ||
188 		     !!(flags & IEEE80211_CHAN_NO_IR) == passive)) {
189 			if (flags & IEEE80211_CHAN_RADAR) {
190 				channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
191 
192 				channels[j].passive_duration =
193 					cpu_to_le16(dwell_time_dfs);
194 			} else {
195 				channels[j].passive_duration =
196 					cpu_to_le16(dwell_time_passive);
197 			}
198 
199 			channels[j].min_duration =
200 				cpu_to_le16(min_dwell_time_active);
201 			channels[j].max_duration =
202 				cpu_to_le16(max_dwell_time_active);
203 
204 			channels[j].tx_power_att = req_channels[i]->max_power;
205 			channels[j].channel = req_channels[i]->hw_value;
206 
207 			if (n_pactive_ch &&
208 			    (band == NL80211_BAND_2GHZ) &&
209 			    (channels[j].channel >= 12) &&
210 			    (channels[j].channel <= 14) &&
211 			    (flags & IEEE80211_CHAN_NO_IR) &&
212 			    !force_passive) {
213 				/* pactive channels treated as DFS */
214 				channels[j].flags = SCAN_CHANNEL_FLAGS_DFS;
215 
216 				/*
217 				 * n_pactive_ch is counted down from the end of
218 				 * the passive channel list
219 				 */
220 				(*n_pactive_ch)++;
221 				wl1271_debug(DEBUG_SCAN, "n_pactive_ch = %d",
222 					     *n_pactive_ch);
223 			}
224 
225 			wl1271_debug(DEBUG_SCAN, "freq %d, ch. %d, flags 0x%x, power %d, min/max_dwell %d/%d%s%s",
226 				     req_channels[i]->center_freq,
227 				     req_channels[i]->hw_value,
228 				     req_channels[i]->flags,
229 				     req_channels[i]->max_power,
230 				     min_dwell_time_active,
231 				     max_dwell_time_active,
232 				     flags & IEEE80211_CHAN_RADAR ?
233 					", DFS" : "",
234 				     flags & IEEE80211_CHAN_NO_IR ?
235 					", NO-IR" : "");
236 			j++;
237 		}
238 	}
239 
240 	return j - start;
241 }
242 
243 bool
wlcore_set_scan_chan_params(struct wl1271 * wl,struct wlcore_scan_channels * cfg,struct ieee80211_channel * channels[],u32 n_channels,u32 n_ssids,int scan_type)244 wlcore_set_scan_chan_params(struct wl1271 *wl,
245 			    struct wlcore_scan_channels *cfg,
246 			    struct ieee80211_channel *channels[],
247 			    u32 n_channels,
248 			    u32 n_ssids,
249 			    int scan_type)
250 {
251 	u8 n_pactive_ch = 0;
252 
253 	cfg->passive[0] =
254 		wlcore_scan_get_channels(wl,
255 					 channels,
256 					 n_channels,
257 					 n_ssids,
258 					 cfg->channels_2,
259 					 NL80211_BAND_2GHZ,
260 					 false, true, 0,
261 					 MAX_CHANNELS_2GHZ,
262 					 &n_pactive_ch,
263 					 scan_type);
264 	cfg->active[0] =
265 		wlcore_scan_get_channels(wl,
266 					 channels,
267 					 n_channels,
268 					 n_ssids,
269 					 cfg->channels_2,
270 					 NL80211_BAND_2GHZ,
271 					 false, false,
272 					 cfg->passive[0],
273 					 MAX_CHANNELS_2GHZ,
274 					 &n_pactive_ch,
275 					 scan_type);
276 	cfg->passive[1] =
277 		wlcore_scan_get_channels(wl,
278 					 channels,
279 					 n_channels,
280 					 n_ssids,
281 					 cfg->channels_5,
282 					 NL80211_BAND_5GHZ,
283 					 false, true, 0,
284 					 wl->max_channels_5,
285 					 &n_pactive_ch,
286 					 scan_type);
287 	cfg->dfs =
288 		wlcore_scan_get_channels(wl,
289 					 channels,
290 					 n_channels,
291 					 n_ssids,
292 					 cfg->channels_5,
293 					 NL80211_BAND_5GHZ,
294 					 true, true,
295 					 cfg->passive[1],
296 					 wl->max_channels_5,
297 					 &n_pactive_ch,
298 					 scan_type);
299 	cfg->active[1] =
300 		wlcore_scan_get_channels(wl,
301 					 channels,
302 					 n_channels,
303 					 n_ssids,
304 					 cfg->channels_5,
305 					 NL80211_BAND_5GHZ,
306 					 false, false,
307 					 cfg->passive[1] + cfg->dfs,
308 					 wl->max_channels_5,
309 					 &n_pactive_ch,
310 					 scan_type);
311 
312 	/* 802.11j channels are not supported yet */
313 	cfg->passive[2] = 0;
314 	cfg->active[2] = 0;
315 
316 	cfg->passive_active = n_pactive_ch;
317 
318 	wl1271_debug(DEBUG_SCAN, "    2.4GHz: active %d passive %d",
319 		     cfg->active[0], cfg->passive[0]);
320 	wl1271_debug(DEBUG_SCAN, "    5GHz: active %d passive %d",
321 		     cfg->active[1], cfg->passive[1]);
322 	wl1271_debug(DEBUG_SCAN, "    DFS: %d", cfg->dfs);
323 
324 	return  cfg->passive[0] || cfg->active[0] ||
325 		cfg->passive[1] || cfg->active[1] || cfg->dfs ||
326 		cfg->passive[2] || cfg->active[2];
327 }
328 EXPORT_SYMBOL_GPL(wlcore_set_scan_chan_params);
329 
wlcore_scan(struct wl1271 * wl,struct ieee80211_vif * vif,const u8 * ssid,size_t ssid_len,struct cfg80211_scan_request * req)330 int wlcore_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
331 		const u8 *ssid, size_t ssid_len,
332 		struct cfg80211_scan_request *req)
333 {
334 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
335 
336 	/*
337 	 * cfg80211 should guarantee that we don't get more channels
338 	 * than what we have registered.
339 	 */
340 	BUG_ON(req->n_channels > WL1271_MAX_CHANNELS);
341 
342 	if (wl->scan.state != WL1271_SCAN_STATE_IDLE)
343 		return -EBUSY;
344 
345 	wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE;
346 
347 	if (ssid_len && ssid) {
348 		wl->scan.ssid_len = ssid_len;
349 		memcpy(wl->scan.ssid, ssid, ssid_len);
350 	} else {
351 		wl->scan.ssid_len = 0;
352 	}
353 
354 	wl->scan_wlvif = wlvif;
355 	wl->scan.req = req;
356 	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
357 
358 	/* we assume failure so that timeout scenarios are handled correctly */
359 	wl->scan.failed = true;
360 	ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
361 				     msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
362 
363 	wl->ops->scan_start(wl, wlvif, req);
364 
365 	return 0;
366 }
367 /* Returns the scan type to be used or a negative value on error */
368 int
wlcore_scan_sched_scan_ssid_list(struct wl1271 * wl,struct wl12xx_vif * wlvif,struct cfg80211_sched_scan_request * req)369 wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl,
370 				 struct wl12xx_vif *wlvif,
371 				 struct cfg80211_sched_scan_request *req)
372 {
373 	struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
374 	struct cfg80211_match_set *sets = req->match_sets;
375 	struct cfg80211_ssid *ssids = req->ssids;
376 	int ret = 0, type, i, j, n_match_ssids = 0;
377 
378 	wl1271_debug((DEBUG_CMD | DEBUG_SCAN), "cmd sched scan ssid list");
379 
380 	/* count the match sets that contain SSIDs */
381 	for (i = 0; i < req->n_match_sets; i++)
382 		if (sets[i].ssid.ssid_len > 0)
383 			n_match_ssids++;
384 
385 	/* No filter, no ssids or only bcast ssid */
386 	if (!n_match_ssids &&
387 	    (!req->n_ssids ||
388 	     (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
389 		type = SCAN_SSID_FILTER_ANY;
390 		goto out;
391 	}
392 
393 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
394 	if (!cmd) {
395 		ret = -ENOMEM;
396 		goto out;
397 	}
398 
399 	cmd->role_id = wlvif->role_id;
400 	if (!n_match_ssids) {
401 		/* No filter, with ssids */
402 		type = SCAN_SSID_FILTER_DISABLED;
403 
404 		for (i = 0; i < req->n_ssids; i++) {
405 			cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
406 				SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
407 			cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
408 			memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
409 			       ssids[i].ssid_len);
410 			cmd->n_ssids++;
411 		}
412 	} else {
413 		type = SCAN_SSID_FILTER_LIST;
414 
415 		/* Add all SSIDs from the filters */
416 		for (i = 0; i < req->n_match_sets; i++) {
417 			/* ignore sets without SSIDs */
418 			if (!sets[i].ssid.ssid_len)
419 				continue;
420 
421 			cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
422 			cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
423 			memcpy(cmd->ssids[cmd->n_ssids].ssid,
424 			       sets[i].ssid.ssid, sets[i].ssid.ssid_len);
425 			cmd->n_ssids++;
426 		}
427 		if ((req->n_ssids > 1) ||
428 		    (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
429 			/*
430 			 * Mark all the SSIDs passed in the SSID list as HIDDEN,
431 			 * so they're used in probe requests.
432 			 */
433 			for (i = 0; i < req->n_ssids; i++) {
434 				if (!req->ssids[i].ssid_len)
435 					continue;
436 
437 				for (j = 0; j < cmd->n_ssids; j++)
438 					if ((req->ssids[i].ssid_len ==
439 					     cmd->ssids[j].len) &&
440 					    !memcmp(req->ssids[i].ssid,
441 						   cmd->ssids[j].ssid,
442 						   req->ssids[i].ssid_len)) {
443 						cmd->ssids[j].type =
444 							SCAN_SSID_TYPE_HIDDEN;
445 						break;
446 					}
447 				/* Fail if SSID isn't present in the filters */
448 				if (j == cmd->n_ssids) {
449 					ret = -EINVAL;
450 					goto out_free;
451 				}
452 			}
453 		}
454 	}
455 
456 	ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
457 			      sizeof(*cmd), 0);
458 	if (ret < 0) {
459 		wl1271_error("cmd sched scan ssid list failed");
460 		goto out_free;
461 	}
462 
463 out_free:
464 	kfree(cmd);
465 out:
466 	if (ret < 0)
467 		return ret;
468 	return type;
469 }
470 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_ssid_list);
471 
wlcore_scan_sched_scan_results(struct wl1271 * wl)472 void wlcore_scan_sched_scan_results(struct wl1271 *wl)
473 {
474 	wl1271_debug(DEBUG_SCAN, "got periodic scan results");
475 
476 	ieee80211_sched_scan_results(wl->hw);
477 }
478 EXPORT_SYMBOL_GPL(wlcore_scan_sched_scan_results);
479