0001
0002
0003
0004
0005 #include <linux/netdevice.h>
0006 #include <linux/gcd.h>
0007 #include <net/cfg80211.h>
0008
0009 #include "core.h"
0010 #include "debug.h"
0011 #include "fwil.h"
0012 #include "fwil_types.h"
0013 #include "cfg80211.h"
0014 #include "pno.h"
0015
0016 #define BRCMF_PNO_VERSION 2
0017 #define BRCMF_PNO_REPEAT 4
0018 #define BRCMF_PNO_FREQ_EXPO_MAX 3
0019 #define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3
0020 #define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5
0021 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
0022 #define BRCMF_PNO_REPORT_SEPARATELY_BIT 11
0023 #define BRCMF_PNO_SCAN_INCOMPLETE 0
0024 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
0025 #define BRCMF_PNO_HIDDEN_BIT 2
0026 #define BRCMF_PNO_SCHED_SCAN_PERIOD 30
0027
0028 #define BRCMF_PNO_MAX_BUCKETS 16
0029 #define GSCAN_BATCH_NO_THR_SET 101
0030 #define GSCAN_RETRY_THRESHOLD 3
0031
0032 struct brcmf_pno_info {
0033 int n_reqs;
0034 struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS];
0035 struct mutex req_lock;
0036 };
0037
0038 #define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno)
0039
0040 static int brcmf_pno_store_request(struct brcmf_pno_info *pi,
0041 struct cfg80211_sched_scan_request *req)
0042 {
0043 if (WARN(pi->n_reqs == BRCMF_PNO_MAX_BUCKETS,
0044 "pno request storage full\n"))
0045 return -ENOSPC;
0046
0047 brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid);
0048 mutex_lock(&pi->req_lock);
0049 pi->reqs[pi->n_reqs++] = req;
0050 mutex_unlock(&pi->req_lock);
0051 return 0;
0052 }
0053
0054 static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
0055 {
0056 int i, err = 0;
0057
0058 mutex_lock(&pi->req_lock);
0059
0060
0061 if (pi->n_reqs == 0)
0062 goto done;
0063
0064
0065 for (i = 0; i < pi->n_reqs; i++) {
0066 if (pi->reqs[i]->reqid == reqid)
0067 break;
0068 }
0069
0070 if (WARN(i == pi->n_reqs, "reqid not found\n")) {
0071 err = -ENOENT;
0072 goto done;
0073 }
0074
0075 brcmf_dbg(SCAN, "reqid=%llu\n", reqid);
0076 pi->n_reqs--;
0077
0078
0079 if (!pi->n_reqs || i == pi->n_reqs)
0080 goto done;
0081
0082
0083 while (i <= pi->n_reqs - 1) {
0084 pi->reqs[i] = pi->reqs[i + 1];
0085 i++;
0086 }
0087
0088 done:
0089 mutex_unlock(&pi->req_lock);
0090 return err;
0091 }
0092
0093 static int brcmf_pno_channel_config(struct brcmf_if *ifp,
0094 struct brcmf_pno_config_le *cfg)
0095 {
0096 cfg->reporttype = 0;
0097 cfg->flags = 0;
0098
0099 return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg));
0100 }
0101
0102 static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
0103 u32 mscan, u32 bestn)
0104 {
0105 struct brcmf_pub *drvr = ifp->drvr;
0106 struct brcmf_pno_param_le pfn_param;
0107 u16 flags;
0108 u32 pfnmem;
0109 s32 err;
0110
0111 memset(&pfn_param, 0, sizeof(pfn_param));
0112 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
0113
0114
0115 flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
0116 BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
0117 pfn_param.repeat = BRCMF_PNO_REPEAT;
0118 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
0119
0120
0121 pfn_param.scan_freq = cpu_to_le32(scan_freq);
0122
0123 if (mscan) {
0124 pfnmem = bestn;
0125
0126
0127 err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem);
0128 if (err < 0) {
0129 bphy_err(drvr, "failed to set pfnmem\n");
0130 goto exit;
0131 }
0132
0133 err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem);
0134 if (err < 0) {
0135 bphy_err(drvr, "failed to get pfnmem\n");
0136 goto exit;
0137 }
0138 mscan = min_t(u32, mscan, pfnmem);
0139 pfn_param.mscan = mscan;
0140 pfn_param.bestn = bestn;
0141 flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT);
0142 brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn);
0143 }
0144
0145 pfn_param.flags = cpu_to_le16(flags);
0146 err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
0147 sizeof(pfn_param));
0148 if (err)
0149 bphy_err(drvr, "pfn_set failed, err=%d\n", err);
0150
0151 exit:
0152 return err;
0153 }
0154
0155 static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
0156 {
0157 struct brcmf_pub *drvr = ifp->drvr;
0158 struct brcmf_pno_macaddr_le pfn_mac;
0159 u8 *mac_addr = NULL;
0160 u8 *mac_mask = NULL;
0161 int err, i;
0162
0163 for (i = 0; i < pi->n_reqs; i++)
0164 if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
0165 mac_addr = pi->reqs[i]->mac_addr;
0166 mac_mask = pi->reqs[i]->mac_addr_mask;
0167 break;
0168 }
0169
0170
0171 if (!mac_addr)
0172 return 0;
0173
0174 pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
0175 pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
0176
0177 memcpy(pfn_mac.mac, mac_addr, ETH_ALEN);
0178 for (i = 0; i < ETH_ALEN; i++) {
0179 pfn_mac.mac[i] &= mac_mask[i];
0180 pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
0181 }
0182
0183 pfn_mac.mac[0] &= 0xFE;
0184
0185 pfn_mac.mac[0] |= 0x02;
0186
0187 brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
0188 pi->reqs[i]->reqid, pfn_mac.mac);
0189 err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
0190 sizeof(pfn_mac));
0191 if (err)
0192 bphy_err(drvr, "pfn_macaddr failed, err=%d\n", err);
0193
0194 return err;
0195 }
0196
0197 static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
0198 bool active)
0199 {
0200 struct brcmf_pub *drvr = ifp->drvr;
0201 struct brcmf_pno_net_param_le pfn;
0202 int err;
0203
0204 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
0205 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
0206 pfn.wsec = cpu_to_le32(0);
0207 pfn.infra = cpu_to_le32(1);
0208 pfn.flags = 0;
0209 if (active)
0210 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
0211 pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
0212 memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
0213
0214 brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active);
0215 err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
0216 if (err < 0)
0217 bphy_err(drvr, "adding failed: err=%d\n", err);
0218 return err;
0219 }
0220
0221 static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
0222 {
0223 struct brcmf_pub *drvr = ifp->drvr;
0224 struct brcmf_pno_bssid_le bssid_cfg;
0225 int err;
0226
0227 memcpy(bssid_cfg.bssid, bssid, ETH_ALEN);
0228 bssid_cfg.flags = 0;
0229
0230 brcmf_dbg(SCAN, "adding bssid=%pM\n", bssid);
0231 err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg,
0232 sizeof(bssid_cfg));
0233 if (err < 0)
0234 bphy_err(drvr, "adding failed: err=%d\n", err);
0235 return err;
0236 }
0237
0238 static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
0239 struct cfg80211_sched_scan_request *req)
0240 {
0241 int i;
0242
0243 if (!ssid || !req->ssids || !req->n_ssids)
0244 return false;
0245
0246 for (i = 0; i < req->n_ssids; i++) {
0247 if (ssid->ssid_len == req->ssids[i].ssid_len) {
0248 if (!strncmp(ssid->ssid, req->ssids[i].ssid,
0249 ssid->ssid_len))
0250 return true;
0251 }
0252 }
0253 return false;
0254 }
0255
0256 static int brcmf_pno_clean(struct brcmf_if *ifp)
0257 {
0258 struct brcmf_pub *drvr = ifp->drvr;
0259 int ret;
0260
0261
0262 ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
0263 if (ret == 0) {
0264
0265 ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
0266 }
0267 if (ret < 0)
0268 bphy_err(drvr, "failed code %d\n", ret);
0269
0270 return ret;
0271 }
0272
0273 static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request *r,
0274 struct brcmf_pno_config_le *pno_cfg)
0275 {
0276 u32 n_chan = le32_to_cpu(pno_cfg->channel_num);
0277 u16 chan;
0278 int i, err = 0;
0279
0280 for (i = 0; i < r->n_channels; i++) {
0281 if (n_chan >= BRCMF_NUMCHANNELS) {
0282 err = -ENOSPC;
0283 goto done;
0284 }
0285 chan = r->channels[i]->hw_value;
0286 brcmf_dbg(SCAN, "[%d] Chan : %u\n", n_chan, chan);
0287 pno_cfg->channel_list[n_chan++] = cpu_to_le16(chan);
0288 }
0289
0290 err = n_chan;
0291 done:
0292 pno_cfg->channel_num = cpu_to_le32(n_chan);
0293 return err;
0294 }
0295
0296 static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info *pi,
0297 struct brcmf_pno_config_le *pno_cfg,
0298 struct brcmf_gscan_bucket_config **buckets,
0299 u32 *scan_freq)
0300 {
0301 struct cfg80211_sched_scan_request *sr;
0302 struct brcmf_gscan_bucket_config *fw_buckets;
0303 int i, err, chidx;
0304
0305 brcmf_dbg(SCAN, "n_reqs=%d\n", pi->n_reqs);
0306 if (WARN_ON(!pi->n_reqs))
0307 return -ENODATA;
0308
0309
0310
0311
0312
0313 *scan_freq = pi->reqs[0]->scan_plans[0].interval;
0314 for (i = 1; i < pi->n_reqs; i++) {
0315 sr = pi->reqs[i];
0316 *scan_freq = gcd(sr->scan_plans[0].interval, *scan_freq);
0317 }
0318 if (*scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
0319 brcmf_dbg(SCAN, "scan period too small, using minimum\n");
0320 *scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
0321 }
0322
0323 *buckets = NULL;
0324 fw_buckets = kcalloc(pi->n_reqs, sizeof(*fw_buckets), GFP_KERNEL);
0325 if (!fw_buckets)
0326 return -ENOMEM;
0327
0328 memset(pno_cfg, 0, sizeof(*pno_cfg));
0329 for (i = 0; i < pi->n_reqs; i++) {
0330 sr = pi->reqs[i];
0331 chidx = brcmf_pno_get_bucket_channels(sr, pno_cfg);
0332 if (chidx < 0) {
0333 err = chidx;
0334 goto fail;
0335 }
0336 fw_buckets[i].bucket_end_index = chidx - 1;
0337 fw_buckets[i].bucket_freq_multiple =
0338 sr->scan_plans[0].interval / *scan_freq;
0339
0340 if (!fw_buckets[i].bucket_freq_multiple)
0341 fw_buckets[i].bucket_freq_multiple = 1;
0342 fw_buckets[i].flag = BRCMF_PNO_REPORT_NO_BATCH;
0343 }
0344
0345 if (BRCMF_SCAN_ON()) {
0346 brcmf_err("base period=%u\n", *scan_freq);
0347 for (i = 0; i < pi->n_reqs; i++) {
0348 brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n",
0349 i, fw_buckets[i].bucket_freq_multiple,
0350 le16_to_cpu(fw_buckets[i].max_freq_multiple),
0351 fw_buckets[i].repeat, fw_buckets[i].flag,
0352 fw_buckets[i].bucket_end_index);
0353 }
0354 }
0355 *buckets = fw_buckets;
0356 return pi->n_reqs;
0357
0358 fail:
0359 kfree(fw_buckets);
0360 return err;
0361 }
0362
0363 static int brcmf_pno_config_networks(struct brcmf_if *ifp,
0364 struct brcmf_pno_info *pi)
0365 {
0366 struct cfg80211_sched_scan_request *r;
0367 struct cfg80211_match_set *ms;
0368 bool active;
0369 int i, j, err = 0;
0370
0371 for (i = 0; i < pi->n_reqs; i++) {
0372 r = pi->reqs[i];
0373
0374 for (j = 0; j < r->n_match_sets; j++) {
0375 ms = &r->match_sets[j];
0376 if (ms->ssid.ssid_len) {
0377 active = brcmf_is_ssid_active(&ms->ssid, r);
0378 err = brcmf_pno_add_ssid(ifp, &ms->ssid,
0379 active);
0380 }
0381 if (!err && is_valid_ether_addr(ms->bssid))
0382 err = brcmf_pno_add_bssid(ifp, ms->bssid);
0383
0384 if (err < 0)
0385 return err;
0386 }
0387 }
0388 return 0;
0389 }
0390
0391 static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
0392 {
0393 struct brcmf_pub *drvr = ifp->drvr;
0394 struct brcmf_pno_info *pi;
0395 struct brcmf_gscan_config *gscan_cfg;
0396 struct brcmf_gscan_bucket_config *buckets;
0397 struct brcmf_pno_config_le pno_cfg;
0398 size_t gsz;
0399 u32 scan_freq;
0400 int err, n_buckets;
0401
0402 pi = ifp_to_pno(ifp);
0403 n_buckets = brcmf_pno_prep_fwconfig(pi, &pno_cfg, &buckets,
0404 &scan_freq);
0405 if (n_buckets < 0)
0406 return n_buckets;
0407
0408 gsz = sizeof(*gscan_cfg) + (n_buckets - 1) * sizeof(*buckets);
0409 gscan_cfg = kzalloc(gsz, GFP_KERNEL);
0410 if (!gscan_cfg) {
0411 err = -ENOMEM;
0412 goto free_buckets;
0413 }
0414
0415
0416 err = brcmf_pno_clean(ifp);
0417 if (err < 0) {
0418 bphy_err(drvr, "failed error=%d\n", err);
0419 goto free_gscan;
0420 }
0421
0422
0423 err = brcmf_pno_config(ifp, scan_freq, 0, 0);
0424 if (err < 0)
0425 goto free_gscan;
0426
0427 err = brcmf_pno_channel_config(ifp, &pno_cfg);
0428 if (err < 0)
0429 goto clean;
0430
0431 gscan_cfg->version = cpu_to_le16(BRCMF_GSCAN_CFG_VERSION);
0432 gscan_cfg->retry_threshold = GSCAN_RETRY_THRESHOLD;
0433 gscan_cfg->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
0434 gscan_cfg->flags = BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN;
0435
0436 gscan_cfg->count_of_channel_buckets = n_buckets;
0437 memcpy(&gscan_cfg->bucket[0], buckets,
0438 n_buckets * sizeof(*buckets));
0439
0440 err = brcmf_fil_iovar_data_set(ifp, "pfn_gscan_cfg", gscan_cfg, gsz);
0441
0442 if (err < 0)
0443 goto clean;
0444
0445
0446 err = brcmf_pno_set_random(ifp, pi);
0447 if (err < 0)
0448 goto clean;
0449
0450 err = brcmf_pno_config_networks(ifp, pi);
0451 if (err < 0)
0452 goto clean;
0453
0454
0455 err = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
0456
0457 clean:
0458 if (err < 0)
0459 brcmf_pno_clean(ifp);
0460 free_gscan:
0461 kfree(gscan_cfg);
0462 free_buckets:
0463 kfree(buckets);
0464 return err;
0465 }
0466
0467 int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
0468 struct cfg80211_sched_scan_request *req)
0469 {
0470 struct brcmf_pno_info *pi;
0471 int ret;
0472
0473 brcmf_dbg(TRACE, "reqid=%llu\n", req->reqid);
0474
0475 pi = ifp_to_pno(ifp);
0476 ret = brcmf_pno_store_request(pi, req);
0477 if (ret < 0)
0478 return ret;
0479
0480 ret = brcmf_pno_config_sched_scans(ifp);
0481 if (ret < 0) {
0482 brcmf_pno_remove_request(pi, req->reqid);
0483 if (pi->n_reqs)
0484 (void)brcmf_pno_config_sched_scans(ifp);
0485 return ret;
0486 }
0487 return 0;
0488 }
0489
0490 int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
0491 {
0492 struct brcmf_pno_info *pi;
0493 int err;
0494
0495 brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
0496
0497 pi = ifp_to_pno(ifp);
0498
0499
0500 if (!pi->n_reqs)
0501 return 0;
0502
0503 err = brcmf_pno_remove_request(pi, reqid);
0504 if (err)
0505 return err;
0506
0507 brcmf_pno_clean(ifp);
0508
0509 if (pi->n_reqs)
0510 (void)brcmf_pno_config_sched_scans(ifp);
0511
0512 return 0;
0513 }
0514
0515 int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg)
0516 {
0517 struct brcmf_pno_info *pi;
0518
0519 brcmf_dbg(TRACE, "enter\n");
0520 pi = kzalloc(sizeof(*pi), GFP_KERNEL);
0521 if (!pi)
0522 return -ENOMEM;
0523
0524 cfg->pno = pi;
0525 mutex_init(&pi->req_lock);
0526 return 0;
0527 }
0528
0529 void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg)
0530 {
0531 struct brcmf_pno_info *pi;
0532
0533 brcmf_dbg(TRACE, "enter\n");
0534 pi = cfg->pno;
0535 cfg->pno = NULL;
0536
0537 WARN_ON(pi->n_reqs);
0538 mutex_destroy(&pi->req_lock);
0539 kfree(pi);
0540 }
0541
0542 void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
0543 {
0544
0545 wiphy->max_sched_scan_reqs = gscan ? BRCMF_PNO_MAX_BUCKETS : 1;
0546 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
0547 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
0548 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
0549 wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
0550 }
0551
0552 u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket)
0553 {
0554 u64 reqid = 0;
0555
0556 mutex_lock(&pi->req_lock);
0557
0558 if (bucket < pi->n_reqs)
0559 reqid = pi->reqs[bucket]->reqid;
0560
0561 mutex_unlock(&pi->req_lock);
0562 return reqid;
0563 }
0564
0565 u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
0566 struct brcmf_pno_net_info_le *ni)
0567 {
0568 struct cfg80211_sched_scan_request *req;
0569 struct cfg80211_match_set *ms;
0570 u32 bucket_map = 0;
0571 int i, j;
0572
0573 mutex_lock(&pi->req_lock);
0574 for (i = 0; i < pi->n_reqs; i++) {
0575 req = pi->reqs[i];
0576
0577 if (!req->n_match_sets)
0578 continue;
0579 for (j = 0; j < req->n_match_sets; j++) {
0580 ms = &req->match_sets[j];
0581 if (ms->ssid.ssid_len == ni->SSID_len &&
0582 !memcmp(ms->ssid.ssid, ni->SSID, ni->SSID_len)) {
0583 bucket_map |= BIT(i);
0584 break;
0585 }
0586 if (is_valid_ether_addr(ms->bssid) &&
0587 !memcmp(ms->bssid, ni->bssid, ETH_ALEN)) {
0588 bucket_map |= BIT(i);
0589 break;
0590 }
0591 }
0592 }
0593 mutex_unlock(&pi->req_lock);
0594 return bucket_map;
0595 }