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