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