Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2016 Broadcom
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     /* Nothing to do if we have no requests */
0061     if (pi->n_reqs == 0)
0062         goto done;
0063 
0064     /* find request */
0065     for (i = 0; i < pi->n_reqs; i++) {
0066         if (pi->reqs[i]->reqid == reqid)
0067             break;
0068     }
0069     /* request not found */
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     /* if last we are done */
0079     if (!pi->n_reqs || i == pi->n_reqs)
0080         goto done;
0081 
0082     /* fill the gap with remaining requests */
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     /* set extra pno params */
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     /* set up pno scan fr */
0121     pfn_param.scan_freq = cpu_to_le32(scan_freq);
0122 
0123     if (mscan) {
0124         pfnmem = bestn;
0125 
0126         /* set bestn in firmware */
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         /* get max mscan which the firmware supports */
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     /* no random mac requested */
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     /* Clear multi bit */
0183     pfn_mac.mac[0] &= 0xFE;
0184     /* Set locally administered */
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     /* Disable pfn */
0262     ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
0263     if (ret == 0) {
0264         /* clear pfn */
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     /* return number of channels */
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      * actual scan period is determined using gcd() for each
0311      * scheduled scan period.
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         /* assure period is non-zero */
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     /* clean up everything */
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     /* configure pno */
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     /* configure random mac */
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     /* Enable the PNO */
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     /* No PNO request */
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     /* scheduled scan settings */
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 }