GNU Linux-libre 4.19.207-gnu1
[releases.git] / drivers / net / wireless / broadcom / brcm80211 / brcmfmac / pno.c
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 }