1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2016 Broadcom
5 #include <linux/netdevice.h>
7 #include <net/cfg80211.h>
12 #include "fwil_types.h"
16 #define BRCMF_PNO_VERSION 2
17 #define BRCMF_PNO_REPEAT 4
18 #define BRCMF_PNO_FREQ_EXPO_MAX 3
19 #define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3
20 #define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5
21 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
22 #define BRCMF_PNO_REPORT_SEPARATELY_BIT 11
23 #define BRCMF_PNO_SCAN_INCOMPLETE 0
24 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
25 #define BRCMF_PNO_HIDDEN_BIT 2
26 #define BRCMF_PNO_SCHED_SCAN_PERIOD 30
28 #define BRCMF_PNO_MAX_BUCKETS 16
29 #define GSCAN_BATCH_NO_THR_SET 101
30 #define GSCAN_RETRY_THRESHOLD 3
32 struct brcmf_pno_info
{
34 struct cfg80211_sched_scan_request
*reqs
[BRCMF_PNO_MAX_BUCKETS
];
35 struct mutex req_lock
;
38 #define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno)
40 static int brcmf_pno_store_request(struct brcmf_pno_info
*pi
,
41 struct cfg80211_sched_scan_request
*req
)
43 if (WARN(pi
->n_reqs
== BRCMF_PNO_MAX_BUCKETS
,
44 "pno request storage full\n"))
47 brcmf_dbg(SCAN
, "reqid=%llu\n", req
->reqid
);
48 mutex_lock(&pi
->req_lock
);
49 pi
->reqs
[pi
->n_reqs
++] = req
;
50 mutex_unlock(&pi
->req_lock
);
54 static int brcmf_pno_remove_request(struct brcmf_pno_info
*pi
, u64 reqid
)
58 mutex_lock(&pi
->req_lock
);
60 /* Nothing to do if we have no requests */
65 for (i
= 0; i
< pi
->n_reqs
; i
++) {
66 if (pi
->reqs
[i
]->reqid
== reqid
)
69 /* request not found */
70 if (WARN(i
== pi
->n_reqs
, "reqid not found\n")) {
75 brcmf_dbg(SCAN
, "reqid=%llu\n", reqid
);
78 /* if last we are done */
79 if (!pi
->n_reqs
|| i
== pi
->n_reqs
)
82 /* fill the gap with remaining requests */
83 while (i
<= pi
->n_reqs
- 1) {
84 pi
->reqs
[i
] = pi
->reqs
[i
+ 1];
89 mutex_unlock(&pi
->req_lock
);
93 static int brcmf_pno_channel_config(struct brcmf_if
*ifp
,
94 struct brcmf_pno_config_le
*cfg
)
99 return brcmf_fil_iovar_data_set(ifp
, "pfn_cfg", cfg
, sizeof(*cfg
));
102 static int brcmf_pno_config(struct brcmf_if
*ifp
, u32 scan_freq
,
103 u32 mscan
, u32 bestn
)
105 struct brcmf_pub
*drvr
= ifp
->drvr
;
106 struct brcmf_pno_param_le pfn_param
;
111 memset(&pfn_param
, 0, sizeof(pfn_param
));
112 pfn_param
.version
= cpu_to_le32(BRCMF_PNO_VERSION
);
114 /* set extra pno params */
115 flags
= BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT
) |
116 BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT
);
117 pfn_param
.repeat
= BRCMF_PNO_REPEAT
;
118 pfn_param
.exp
= BRCMF_PNO_FREQ_EXPO_MAX
;
120 /* set up pno scan fr */
121 pfn_param
.scan_freq
= cpu_to_le32(scan_freq
);
126 /* set bestn in firmware */
127 err
= brcmf_fil_iovar_int_set(ifp
, "pfnmem", pfnmem
);
129 bphy_err(drvr
, "failed to set pfnmem\n");
132 /* get max mscan which the firmware supports */
133 err
= brcmf_fil_iovar_int_get(ifp
, "pfnmem", &pfnmem
);
135 bphy_err(drvr
, "failed to get pfnmem\n");
138 mscan
= min_t(u32
, mscan
, pfnmem
);
139 pfn_param
.mscan
= mscan
;
140 pfn_param
.bestn
= bestn
;
141 flags
|= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT
);
142 brcmf_dbg(INFO
, "mscan=%d, bestn=%d\n", mscan
, bestn
);
145 pfn_param
.flags
= cpu_to_le16(flags
);
146 err
= brcmf_fil_iovar_data_set(ifp
, "pfn_set", &pfn_param
,
149 bphy_err(drvr
, "pfn_set failed, err=%d\n", err
);
155 static int brcmf_pno_set_random(struct brcmf_if
*ifp
, struct brcmf_pno_info
*pi
)
157 struct brcmf_pub
*drvr
= ifp
->drvr
;
158 struct brcmf_pno_macaddr_le pfn_mac
;
163 for (i
= 0; i
< pi
->n_reqs
; i
++)
164 if (pi
->reqs
[i
]->flags
& NL80211_SCAN_FLAG_RANDOM_ADDR
) {
165 mac_addr
= pi
->reqs
[i
]->mac_addr
;
166 mac_mask
= pi
->reqs
[i
]->mac_addr_mask
;
170 /* no random mac requested */
174 pfn_mac
.version
= BRCMF_PFN_MACADDR_CFG_VER
;
175 pfn_mac
.flags
= BRCMF_PFN_MAC_OUI_ONLY
| BRCMF_PFN_SET_MAC_UNASSOC
;
177 memcpy(pfn_mac
.mac
, mac_addr
, ETH_ALEN
);
178 for (i
= 0; i
< ETH_ALEN
; i
++) {
179 pfn_mac
.mac
[i
] &= mac_mask
[i
];
180 pfn_mac
.mac
[i
] |= get_random_int() & ~(mac_mask
[i
]);
182 /* Clear multi bit */
183 pfn_mac
.mac
[0] &= 0xFE;
184 /* Set locally administered */
185 pfn_mac
.mac
[0] |= 0x02;
187 brcmf_dbg(SCAN
, "enabling random mac: reqid=%llu mac=%pM\n",
188 pi
->reqs
[i
]->reqid
, pfn_mac
.mac
);
189 err
= brcmf_fil_iovar_data_set(ifp
, "pfn_macaddr", &pfn_mac
,
192 bphy_err(drvr
, "pfn_macaddr failed, err=%d\n", err
);
197 static int brcmf_pno_add_ssid(struct brcmf_if
*ifp
, struct cfg80211_ssid
*ssid
,
200 struct brcmf_pub
*drvr
= ifp
->drvr
;
201 struct brcmf_pno_net_param_le pfn
;
204 pfn
.auth
= cpu_to_le32(WLAN_AUTH_OPEN
);
205 pfn
.wpa_auth
= cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY
);
206 pfn
.wsec
= cpu_to_le32(0);
207 pfn
.infra
= cpu_to_le32(1);
210 pfn
.flags
= cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT
);
211 pfn
.ssid
.SSID_len
= cpu_to_le32(ssid
->ssid_len
);
212 memcpy(pfn
.ssid
.SSID
, ssid
->ssid
, ssid
->ssid_len
);
214 brcmf_dbg(SCAN
, "adding ssid=%.32s (active=%d)\n", ssid
->ssid
, active
);
215 err
= brcmf_fil_iovar_data_set(ifp
, "pfn_add", &pfn
, sizeof(pfn
));
217 bphy_err(drvr
, "adding failed: err=%d\n", err
);
221 static int brcmf_pno_add_bssid(struct brcmf_if
*ifp
, const u8
*bssid
)
223 struct brcmf_pub
*drvr
= ifp
->drvr
;
224 struct brcmf_pno_bssid_le bssid_cfg
;
227 memcpy(bssid_cfg
.bssid
, bssid
, ETH_ALEN
);
230 brcmf_dbg(SCAN
, "adding bssid=%pM\n", bssid
);
231 err
= brcmf_fil_iovar_data_set(ifp
, "pfn_add_bssid", &bssid_cfg
,
234 bphy_err(drvr
, "adding failed: err=%d\n", err
);
238 static bool brcmf_is_ssid_active(struct cfg80211_ssid
*ssid
,
239 struct cfg80211_sched_scan_request
*req
)
243 if (!ssid
|| !req
->ssids
|| !req
->n_ssids
)
246 for (i
= 0; i
< req
->n_ssids
; i
++) {
247 if (ssid
->ssid_len
== req
->ssids
[i
].ssid_len
) {
248 if (!strncmp(ssid
->ssid
, req
->ssids
[i
].ssid
,
256 static int brcmf_pno_clean(struct brcmf_if
*ifp
)
258 struct brcmf_pub
*drvr
= ifp
->drvr
;
262 ret
= brcmf_fil_iovar_int_set(ifp
, "pfn", 0);
265 ret
= brcmf_fil_iovar_data_set(ifp
, "pfnclear", NULL
, 0);
268 bphy_err(drvr
, "failed code %d\n", ret
);
273 static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request
*r
,
274 struct brcmf_pno_config_le
*pno_cfg
)
276 u32 n_chan
= le32_to_cpu(pno_cfg
->channel_num
);
280 for (i
= 0; i
< r
->n_channels
; i
++) {
281 if (n_chan
>= BRCMF_NUMCHANNELS
) {
285 chan
= r
->channels
[i
]->hw_value
;
286 brcmf_dbg(SCAN
, "[%d] Chan : %u\n", n_chan
, chan
);
287 pno_cfg
->channel_list
[n_chan
++] = cpu_to_le16(chan
);
289 /* return number of channels */
292 pno_cfg
->channel_num
= cpu_to_le32(n_chan
);
296 static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info
*pi
,
297 struct brcmf_pno_config_le
*pno_cfg
,
298 struct brcmf_gscan_bucket_config
**buckets
,
301 struct cfg80211_sched_scan_request
*sr
;
302 struct brcmf_gscan_bucket_config
*fw_buckets
;
305 brcmf_dbg(SCAN
, "n_reqs=%d\n", pi
->n_reqs
);
306 if (WARN_ON(!pi
->n_reqs
))
310 * actual scan period is determined using gcd() for each
311 * scheduled scan period.
313 *scan_freq
= pi
->reqs
[0]->scan_plans
[0].interval
;
314 for (i
= 1; i
< pi
->n_reqs
; i
++) {
316 *scan_freq
= gcd(sr
->scan_plans
[0].interval
, *scan_freq
);
318 if (*scan_freq
< BRCMF_PNO_SCHED_SCAN_MIN_PERIOD
) {
319 brcmf_dbg(SCAN
, "scan period too small, using minimum\n");
320 *scan_freq
= BRCMF_PNO_SCHED_SCAN_MIN_PERIOD
;
324 fw_buckets
= kcalloc(pi
->n_reqs
, sizeof(*fw_buckets
), GFP_KERNEL
);
328 memset(pno_cfg
, 0, sizeof(*pno_cfg
));
329 for (i
= 0; i
< pi
->n_reqs
; i
++) {
331 chidx
= brcmf_pno_get_bucket_channels(sr
, pno_cfg
);
336 fw_buckets
[i
].bucket_end_index
= chidx
- 1;
337 fw_buckets
[i
].bucket_freq_multiple
=
338 sr
->scan_plans
[0].interval
/ *scan_freq
;
339 /* assure period is non-zero */
340 if (!fw_buckets
[i
].bucket_freq_multiple
)
341 fw_buckets
[i
].bucket_freq_multiple
= 1;
342 fw_buckets
[i
].flag
= BRCMF_PNO_REPORT_NO_BATCH
;
345 if (BRCMF_SCAN_ON()) {
346 brcmf_err("base period=%u\n", *scan_freq
);
347 for (i
= 0; i
< pi
->n_reqs
; i
++) {
348 brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n",
349 i
, fw_buckets
[i
].bucket_freq_multiple
,
350 le16_to_cpu(fw_buckets
[i
].max_freq_multiple
),
351 fw_buckets
[i
].repeat
, fw_buckets
[i
].flag
,
352 fw_buckets
[i
].bucket_end_index
);
355 *buckets
= fw_buckets
;
363 static int brcmf_pno_config_networks(struct brcmf_if
*ifp
,
364 struct brcmf_pno_info
*pi
)
366 struct cfg80211_sched_scan_request
*r
;
367 struct cfg80211_match_set
*ms
;
371 for (i
= 0; i
< pi
->n_reqs
; i
++) {
374 for (j
= 0; j
< r
->n_match_sets
; j
++) {
375 ms
= &r
->match_sets
[j
];
376 if (ms
->ssid
.ssid_len
) {
377 active
= brcmf_is_ssid_active(&ms
->ssid
, r
);
378 err
= brcmf_pno_add_ssid(ifp
, &ms
->ssid
,
381 if (!err
&& is_valid_ether_addr(ms
->bssid
))
382 err
= brcmf_pno_add_bssid(ifp
, ms
->bssid
);
391 static int brcmf_pno_config_sched_scans(struct brcmf_if
*ifp
)
393 struct brcmf_pub
*drvr
= ifp
->drvr
;
394 struct brcmf_pno_info
*pi
;
395 struct brcmf_gscan_config
*gscan_cfg
;
396 struct brcmf_gscan_bucket_config
*buckets
;
397 struct brcmf_pno_config_le pno_cfg
;
402 pi
= ifp_to_pno(ifp
);
403 n_buckets
= brcmf_pno_prep_fwconfig(pi
, &pno_cfg
, &buckets
,
408 gsz
= sizeof(*gscan_cfg
) + (n_buckets
- 1) * sizeof(*buckets
);
409 gscan_cfg
= kzalloc(gsz
, GFP_KERNEL
);
415 /* clean up everything */
416 err
= brcmf_pno_clean(ifp
);
418 bphy_err(drvr
, "failed error=%d\n", err
);
423 err
= brcmf_pno_config(ifp
, scan_freq
, 0, 0);
427 err
= brcmf_pno_channel_config(ifp
, &pno_cfg
);
431 gscan_cfg
->version
= cpu_to_le16(BRCMF_GSCAN_CFG_VERSION
);
432 gscan_cfg
->retry_threshold
= GSCAN_RETRY_THRESHOLD
;
433 gscan_cfg
->buffer_threshold
= GSCAN_BATCH_NO_THR_SET
;
434 gscan_cfg
->flags
= BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN
;
436 gscan_cfg
->count_of_channel_buckets
= n_buckets
;
437 memcpy(&gscan_cfg
->bucket
[0], buckets
,
438 n_buckets
* sizeof(*buckets
));
440 err
= brcmf_fil_iovar_data_set(ifp
, "pfn_gscan_cfg", gscan_cfg
, gsz
);
445 /* configure random mac */
446 err
= brcmf_pno_set_random(ifp
, pi
);
450 err
= brcmf_pno_config_networks(ifp
, pi
);
455 err
= brcmf_fil_iovar_int_set(ifp
, "pfn", 1);
459 brcmf_pno_clean(ifp
);
467 int brcmf_pno_start_sched_scan(struct brcmf_if
*ifp
,
468 struct cfg80211_sched_scan_request
*req
)
470 struct brcmf_pno_info
*pi
;
473 brcmf_dbg(TRACE
, "reqid=%llu\n", req
->reqid
);
475 pi
= ifp_to_pno(ifp
);
476 ret
= brcmf_pno_store_request(pi
, req
);
480 ret
= brcmf_pno_config_sched_scans(ifp
);
482 brcmf_pno_remove_request(pi
, req
->reqid
);
484 (void)brcmf_pno_config_sched_scans(ifp
);
490 int brcmf_pno_stop_sched_scan(struct brcmf_if
*ifp
, u64 reqid
)
492 struct brcmf_pno_info
*pi
;
495 brcmf_dbg(TRACE
, "reqid=%llu\n", reqid
);
497 pi
= ifp_to_pno(ifp
);
503 err
= brcmf_pno_remove_request(pi
, reqid
);
507 brcmf_pno_clean(ifp
);
510 (void)brcmf_pno_config_sched_scans(ifp
);
515 int brcmf_pno_attach(struct brcmf_cfg80211_info
*cfg
)
517 struct brcmf_pno_info
*pi
;
519 brcmf_dbg(TRACE
, "enter\n");
520 pi
= kzalloc(sizeof(*pi
), GFP_KERNEL
);
525 mutex_init(&pi
->req_lock
);
529 void brcmf_pno_detach(struct brcmf_cfg80211_info
*cfg
)
531 struct brcmf_pno_info
*pi
;
533 brcmf_dbg(TRACE
, "enter\n");
538 mutex_destroy(&pi
->req_lock
);
542 void brcmf_pno_wiphy_params(struct wiphy
*wiphy
, bool gscan
)
544 /* scheduled scan settings */
545 wiphy
->max_sched_scan_reqs
= gscan
? BRCMF_PNO_MAX_BUCKETS
: 1;
546 wiphy
->max_sched_scan_ssids
= BRCMF_PNO_MAX_PFN_COUNT
;
547 wiphy
->max_match_sets
= BRCMF_PNO_MAX_PFN_COUNT
;
548 wiphy
->max_sched_scan_ie_len
= BRCMF_SCAN_IE_LEN_MAX
;
549 wiphy
->max_sched_scan_plan_interval
= BRCMF_PNO_SCHED_SCAN_MAX_PERIOD
;
552 u64
brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info
*pi
, u32 bucket
)
556 mutex_lock(&pi
->req_lock
);
558 if (bucket
< pi
->n_reqs
)
559 reqid
= pi
->reqs
[bucket
]->reqid
;
561 mutex_unlock(&pi
->req_lock
);
565 u32
brcmf_pno_get_bucket_map(struct brcmf_pno_info
*pi
,
566 struct brcmf_pno_net_info_le
*ni
)
568 struct cfg80211_sched_scan_request
*req
;
569 struct cfg80211_match_set
*ms
;
573 mutex_lock(&pi
->req_lock
);
574 for (i
= 0; i
< pi
->n_reqs
; i
++) {
577 if (!req
->n_match_sets
)
579 for (j
= 0; j
< req
->n_match_sets
; j
++) {
580 ms
= &req
->match_sets
[j
];
581 if (ms
->ssid
.ssid_len
== ni
->SSID_len
&&
582 !memcmp(ms
->ssid
.ssid
, ni
->SSID
, ni
->SSID_len
)) {
583 bucket_map
|= BIT(i
);
586 if (is_valid_ether_addr(ms
->bssid
) &&
587 !memcmp(ms
->bssid
, ni
->bssid
, ETH_ALEN
)) {
588 bucket_map
|= BIT(i
);
593 mutex_unlock(&pi
->req_lock
);