1 /* 2 * Copyright (c) 2016 Broadcom 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #include <linux/netdevice.h> 17 #include <linux/gcd.h> 18 #include <net/cfg80211.h> 19 20 #include "core.h" 21 #include "debug.h" 22 #include "fwil.h" 23 #include "fwil_types.h" 24 #include "cfg80211.h" 25 #include "pno.h" 26 27 #define BRCMF_PNO_VERSION 2 28 #define BRCMF_PNO_REPEAT 4 29 #define BRCMF_PNO_FREQ_EXPO_MAX 3 30 #define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3 31 #define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5 32 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 33 #define BRCMF_PNO_REPORT_SEPARATELY_BIT 11 34 #define BRCMF_PNO_SCAN_INCOMPLETE 0 35 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF 36 #define BRCMF_PNO_HIDDEN_BIT 2 37 #define BRCMF_PNO_SCHED_SCAN_PERIOD 30 38 39 #define BRCMF_PNO_MAX_BUCKETS 16 40 #define GSCAN_BATCH_NO_THR_SET 101 41 #define GSCAN_RETRY_THRESHOLD 3 42 43 struct brcmf_pno_info { 44 int n_reqs; 45 struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS]; 46 struct mutex req_lock; 47 }; 48 49 #define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno) 50 51 static int brcmf_pno_store_request(struct brcmf_pno_info *pi, 52 struct cfg80211_sched_scan_request *req) 53 { 54 if (WARN(pi->n_reqs == BRCMF_PNO_MAX_BUCKETS, 55 "pno request storage full\n")) 56 return -ENOSPC; 57 58 brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid); 59 mutex_lock(&pi->req_lock); 60 pi->reqs[pi->n_reqs++] = req; 61 mutex_unlock(&pi->req_lock); 62 return 0; 63 } 64 65 static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid) 66 { 67 int i, err = 0; 68 69 mutex_lock(&pi->req_lock); 70 71 /* find request */ 72 for (i = 0; i < pi->n_reqs; i++) { 73 if (pi->reqs[i]->reqid == reqid) 74 break; 75 } 76 /* request not found */ 77 if (WARN(i == pi->n_reqs, "reqid not found\n")) { 78 err = -ENOENT; 79 goto done; 80 } 81 82 brcmf_dbg(SCAN, "reqid=%llu\n", reqid); 83 pi->n_reqs--; 84 85 /* if last we are done */ 86 if (!pi->n_reqs || i == pi->n_reqs) 87 goto done; 88 89 /* fill the gap with remaining requests */ 90 while (i <= pi->n_reqs - 1) { 91 pi->reqs[i] = pi->reqs[i + 1]; 92 i++; 93 } 94 95 done: 96 mutex_unlock(&pi->req_lock); 97 return err; 98 } 99 100 static int brcmf_pno_channel_config(struct brcmf_if *ifp, 101 struct brcmf_pno_config_le *cfg) 102 { 103 cfg->reporttype = 0; 104 cfg->flags = 0; 105 106 return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg)); 107 } 108 109 static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, 110 u32 mscan, u32 bestn) 111 { 112 struct brcmf_pno_param_le pfn_param; 113 u16 flags; 114 u32 pfnmem; 115 s32 err; 116 117 memset(&pfn_param, 0, sizeof(pfn_param)); 118 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); 119 120 /* set extra pno params */ 121 flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) | 122 BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); 123 pfn_param.repeat = BRCMF_PNO_REPEAT; 124 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; 125 126 /* set up pno scan fr */ 127 pfn_param.scan_freq = cpu_to_le32(scan_freq); 128 129 if (mscan) { 130 pfnmem = bestn; 131 132 /* set bestn in firmware */ 133 err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem); 134 if (err < 0) { 135 brcmf_err("failed to set pfnmem\n"); 136 goto exit; 137 } 138 /* get max mscan which the firmware supports */ 139 err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem); 140 if (err < 0) { 141 brcmf_err("failed to get pfnmem\n"); 142 goto exit; 143 } 144 mscan = min_t(u32, mscan, pfnmem); 145 pfn_param.mscan = mscan; 146 pfn_param.bestn = bestn; 147 flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT); 148 brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn); 149 } 150 151 pfn_param.flags = cpu_to_le16(flags); 152 err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, 153 sizeof(pfn_param)); 154 if (err) 155 brcmf_err("pfn_set failed, err=%d\n", err); 156 157 exit: 158 return err; 159 } 160 161 static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) 162 { 163 struct brcmf_pno_macaddr_le pfn_mac; 164 u8 *mac_addr = NULL; 165 u8 *mac_mask = NULL; 166 int err, i; 167 168 for (i = 0; i < pi->n_reqs; i++) 169 if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { 170 mac_addr = pi->reqs[i]->mac_addr; 171 mac_mask = pi->reqs[i]->mac_addr_mask; 172 break; 173 } 174 175 /* no random mac requested */ 176 if (!mac_addr) 177 return 0; 178 179 pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; 180 pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; 181 182 memcpy(pfn_mac.mac, mac_addr, ETH_ALEN); 183 for (i = 0; i < ETH_ALEN; i++) { 184 pfn_mac.mac[i] &= mac_mask[i]; 185 pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); 186 } 187 /* Clear multi bit */ 188 pfn_mac.mac[0] &= 0xFE; 189 /* Set locally administered */ 190 pfn_mac.mac[0] |= 0x02; 191 192 brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n", 193 pi->reqs[i]->reqid, pfn_mac.mac); 194 err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, 195 sizeof(pfn_mac)); 196 if (err) 197 brcmf_err("pfn_macaddr failed, err=%d\n", err); 198 199 return err; 200 } 201 202 static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, 203 bool active) 204 { 205 struct brcmf_pno_net_param_le pfn; 206 int err; 207 208 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); 209 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); 210 pfn.wsec = cpu_to_le32(0); 211 pfn.infra = cpu_to_le32(1); 212 pfn.flags = 0; 213 if (active) 214 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); 215 pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len); 216 memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len); 217 218 brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active); 219 err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); 220 if (err < 0) 221 brcmf_err("adding failed: err=%d\n", err); 222 return err; 223 } 224 225 static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid) 226 { 227 struct brcmf_pno_bssid_le bssid_cfg; 228 int err; 229 230 memcpy(bssid_cfg.bssid, bssid, ETH_ALEN); 231 bssid_cfg.flags = 0; 232 233 brcmf_dbg(SCAN, "adding bssid=%pM\n", bssid); 234 err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg, 235 sizeof(bssid_cfg)); 236 if (err < 0) 237 brcmf_err("adding failed: err=%d\n", err); 238 return err; 239 } 240 241 static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, 242 struct cfg80211_sched_scan_request *req) 243 { 244 int i; 245 246 if (!ssid || !req->ssids || !req->n_ssids) 247 return false; 248 249 for (i = 0; i < req->n_ssids; i++) { 250 if (ssid->ssid_len == req->ssids[i].ssid_len) { 251 if (!strncmp(ssid->ssid, req->ssids[i].ssid, 252 ssid->ssid_len)) 253 return true; 254 } 255 } 256 return false; 257 } 258 259 static int brcmf_pno_clean(struct brcmf_if *ifp) 260 { 261 int ret; 262 263 /* Disable pfn */ 264 ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); 265 if (ret == 0) { 266 /* clear pfn */ 267 ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); 268 } 269 if (ret < 0) 270 brcmf_err("failed code %d\n", ret); 271 272 return ret; 273 } 274 275 static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request *r, 276 struct brcmf_pno_config_le *pno_cfg) 277 { 278 u32 n_chan = le32_to_cpu(pno_cfg->channel_num); 279 u16 chan; 280 int i, err = 0; 281 282 for (i = 0; i < r->n_channels; i++) { 283 if (n_chan >= BRCMF_NUMCHANNELS) { 284 err = -ENOSPC; 285 goto done; 286 } 287 chan = r->channels[i]->hw_value; 288 brcmf_dbg(SCAN, "[%d] Chan : %u\n", n_chan, chan); 289 pno_cfg->channel_list[n_chan++] = cpu_to_le16(chan); 290 } 291 /* return number of channels */ 292 err = n_chan; 293 done: 294 pno_cfg->channel_num = cpu_to_le32(n_chan); 295 return err; 296 } 297 298 static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info *pi, 299 struct brcmf_pno_config_le *pno_cfg, 300 struct brcmf_gscan_bucket_config **buckets, 301 u32 *scan_freq) 302 { 303 struct cfg80211_sched_scan_request *sr; 304 struct brcmf_gscan_bucket_config *fw_buckets; 305 int i, err, chidx; 306 307 brcmf_dbg(SCAN, "n_reqs=%d\n", pi->n_reqs); 308 if (WARN_ON(!pi->n_reqs)) 309 return -ENODATA; 310 311 /* 312 * actual scan period is determined using gcd() for each 313 * scheduled scan period. 314 */ 315 *scan_freq = pi->reqs[0]->scan_plans[0].interval; 316 for (i = 1; i < pi->n_reqs; i++) { 317 sr = pi->reqs[i]; 318 *scan_freq = gcd(sr->scan_plans[0].interval, *scan_freq); 319 } 320 if (*scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) { 321 brcmf_dbg(SCAN, "scan period too small, using minimum\n"); 322 *scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD; 323 } 324 325 *buckets = NULL; 326 fw_buckets = kcalloc(pi->n_reqs, sizeof(*fw_buckets), GFP_KERNEL); 327 if (!fw_buckets) 328 return -ENOMEM; 329 330 memset(pno_cfg, 0, sizeof(*pno_cfg)); 331 for (i = 0; i < pi->n_reqs; i++) { 332 sr = pi->reqs[i]; 333 chidx = brcmf_pno_get_bucket_channels(sr, pno_cfg); 334 if (chidx < 0) { 335 err = chidx; 336 goto fail; 337 } 338 fw_buckets[i].bucket_end_index = chidx - 1; 339 fw_buckets[i].bucket_freq_multiple = 340 sr->scan_plans[0].interval / *scan_freq; 341 /* assure period is non-zero */ 342 if (!fw_buckets[i].bucket_freq_multiple) 343 fw_buckets[i].bucket_freq_multiple = 1; 344 fw_buckets[i].flag = BRCMF_PNO_REPORT_NO_BATCH; 345 } 346 347 if (BRCMF_SCAN_ON()) { 348 brcmf_err("base period=%u\n", *scan_freq); 349 for (i = 0; i < pi->n_reqs; i++) { 350 brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n", 351 i, fw_buckets[i].bucket_freq_multiple, 352 le16_to_cpu(fw_buckets[i].max_freq_multiple), 353 fw_buckets[i].repeat, fw_buckets[i].flag, 354 fw_buckets[i].bucket_end_index); 355 } 356 } 357 *buckets = fw_buckets; 358 return pi->n_reqs; 359 360 fail: 361 kfree(fw_buckets); 362 return err; 363 } 364 365 static int brcmf_pno_config_networks(struct brcmf_if *ifp, 366 struct brcmf_pno_info *pi) 367 { 368 struct cfg80211_sched_scan_request *r; 369 struct cfg80211_match_set *ms; 370 bool active; 371 int i, j, err = 0; 372 373 for (i = 0; i < pi->n_reqs; i++) { 374 r = pi->reqs[i]; 375 376 for (j = 0; j < r->n_match_sets; j++) { 377 ms = &r->match_sets[j]; 378 if (ms->ssid.ssid_len) { 379 active = brcmf_is_ssid_active(&ms->ssid, r); 380 err = brcmf_pno_add_ssid(ifp, &ms->ssid, 381 active); 382 } 383 if (!err && is_valid_ether_addr(ms->bssid)) 384 err = brcmf_pno_add_bssid(ifp, ms->bssid); 385 386 if (err < 0) 387 return err; 388 } 389 } 390 return 0; 391 } 392 393 static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp) 394 { 395 struct brcmf_pno_info *pi; 396 struct brcmf_gscan_config *gscan_cfg; 397 struct brcmf_gscan_bucket_config *buckets; 398 struct brcmf_pno_config_le pno_cfg; 399 size_t gsz; 400 u32 scan_freq; 401 int err, n_buckets; 402 403 pi = ifp_to_pno(ifp); 404 n_buckets = brcmf_pno_prep_fwconfig(pi, &pno_cfg, &buckets, 405 &scan_freq); 406 if (n_buckets < 0) 407 return n_buckets; 408 409 gsz = sizeof(*gscan_cfg) + (n_buckets - 1) * sizeof(*buckets); 410 gscan_cfg = kzalloc(gsz, GFP_KERNEL); 411 if (!gscan_cfg) { 412 err = -ENOMEM; 413 goto free_buckets; 414 } 415 416 /* clean up everything */ 417 err = brcmf_pno_clean(ifp); 418 if (err < 0) { 419 brcmf_err("failed error=%d\n", err); 420 goto free_gscan; 421 } 422 423 /* configure pno */ 424 err = brcmf_pno_config(ifp, scan_freq, 0, 0); 425 if (err < 0) 426 goto free_gscan; 427 428 err = brcmf_pno_channel_config(ifp, &pno_cfg); 429 if (err < 0) 430 goto clean; 431 432 gscan_cfg->version = cpu_to_le16(BRCMF_GSCAN_CFG_VERSION); 433 gscan_cfg->retry_threshold = GSCAN_RETRY_THRESHOLD; 434 gscan_cfg->buffer_threshold = GSCAN_BATCH_NO_THR_SET; 435 gscan_cfg->flags = BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN; 436 437 gscan_cfg->count_of_channel_buckets = n_buckets; 438 memcpy(&gscan_cfg->bucket[0], buckets, 439 n_buckets * sizeof(*buckets)); 440 441 err = brcmf_fil_iovar_data_set(ifp, "pfn_gscan_cfg", gscan_cfg, gsz); 442 443 if (err < 0) 444 goto clean; 445 446 /* configure random mac */ 447 err = brcmf_pno_set_random(ifp, pi); 448 if (err < 0) 449 goto clean; 450 451 err = brcmf_pno_config_networks(ifp, pi); 452 if (err < 0) 453 goto clean; 454 455 /* Enable the PNO */ 456 err = brcmf_fil_iovar_int_set(ifp, "pfn", 1); 457 458 clean: 459 if (err < 0) 460 brcmf_pno_clean(ifp); 461 free_gscan: 462 kfree(gscan_cfg); 463 free_buckets: 464 kfree(buckets); 465 return err; 466 } 467 468 int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, 469 struct cfg80211_sched_scan_request *req) 470 { 471 struct brcmf_pno_info *pi; 472 int ret; 473 474 brcmf_dbg(TRACE, "reqid=%llu\n", req->reqid); 475 476 pi = ifp_to_pno(ifp); 477 ret = brcmf_pno_store_request(pi, req); 478 if (ret < 0) 479 return ret; 480 481 ret = brcmf_pno_config_sched_scans(ifp); 482 if (ret < 0) { 483 brcmf_pno_remove_request(pi, req->reqid); 484 if (pi->n_reqs) 485 (void)brcmf_pno_config_sched_scans(ifp); 486 return ret; 487 } 488 return 0; 489 } 490 491 int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid) 492 { 493 struct brcmf_pno_info *pi; 494 int err; 495 496 brcmf_dbg(TRACE, "reqid=%llu\n", reqid); 497 498 pi = ifp_to_pno(ifp); 499 err = brcmf_pno_remove_request(pi, reqid); 500 if (err) 501 return err; 502 503 brcmf_pno_clean(ifp); 504 505 if (pi->n_reqs) 506 (void)brcmf_pno_config_sched_scans(ifp); 507 508 return 0; 509 } 510 511 int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg) 512 { 513 struct brcmf_pno_info *pi; 514 515 brcmf_dbg(TRACE, "enter\n"); 516 pi = kzalloc(sizeof(*pi), GFP_KERNEL); 517 if (!pi) 518 return -ENOMEM; 519 520 cfg->pno = pi; 521 mutex_init(&pi->req_lock); 522 return 0; 523 } 524 525 void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg) 526 { 527 struct brcmf_pno_info *pi; 528 529 brcmf_dbg(TRACE, "enter\n"); 530 pi = cfg->pno; 531 cfg->pno = NULL; 532 533 WARN_ON(pi->n_reqs); 534 mutex_destroy(&pi->req_lock); 535 kfree(pi); 536 } 537 538 void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan) 539 { 540 /* scheduled scan settings */ 541 wiphy->max_sched_scan_reqs = gscan ? BRCMF_PNO_MAX_BUCKETS : 1; 542 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; 543 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; 544 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; 545 wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD; 546 } 547 548 u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket) 549 { 550 u64 reqid = 0; 551 552 mutex_lock(&pi->req_lock); 553 554 if (bucket < pi->n_reqs) 555 reqid = pi->reqs[bucket]->reqid; 556 557 mutex_unlock(&pi->req_lock); 558 return reqid; 559 } 560 561 u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi, 562 struct brcmf_pno_net_info_le *ni) 563 { 564 struct cfg80211_sched_scan_request *req; 565 struct cfg80211_match_set *ms; 566 u32 bucket_map = 0; 567 int i, j; 568 569 mutex_lock(&pi->req_lock); 570 for (i = 0; i < pi->n_reqs; i++) { 571 req = pi->reqs[i]; 572 573 if (!req->n_match_sets) 574 continue; 575 for (j = 0; j < req->n_match_sets; j++) { 576 ms = &req->match_sets[j]; 577 if (ms->ssid.ssid_len == ni->SSID_len && 578 !memcmp(ms->ssid.ssid, ni->SSID, ni->SSID_len)) { 579 bucket_map |= BIT(i); 580 break; 581 } 582 if (is_valid_ether_addr(ms->bssid) && 583 !memcmp(ms->bssid, ni->bssid, ETH_ALEN)) { 584 bucket_map |= BIT(i); 585 break; 586 } 587 } 588 } 589 mutex_unlock(&pi->req_lock); 590 return bucket_map; 591 } 592