Skip to content

Commit 3952a7b

Browse files
dberlinmarcan
authored andcommitted
Finish 6G support by supporting new scan structures
Signed-off-by: Daniel Berlin <[email protected]>
1 parent 5f743dd commit 3952a7b

6 files changed

Lines changed: 362 additions & 55 deletions

File tree

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 170 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "vendor.h"
3333
#include "bus.h"
3434
#include "common.h"
35+
#include "feature.h"
3536

3637
#define BRCMF_SCAN_IE_LEN_MAX 2048
3738

@@ -365,6 +366,22 @@ static u8 nl80211_band_to_fwil(enum nl80211_band band)
365366
return 0;
366367
}
367368

369+
static enum nl80211_band fwil_band_to_nl80211(u8 band)
370+
{
371+
switch (band) {
372+
case WLC_BAND_2G:
373+
return NL80211_BAND_2GHZ;
374+
case WLC_BAND_5G:
375+
return NL80211_BAND_5GHZ;
376+
case WLC_BAND_6G:
377+
return NL80211_BAND_6GHZ;
378+
default:
379+
WARN_ON(1);
380+
break;
381+
}
382+
return 0;
383+
}
384+
368385
static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
369386
struct cfg80211_chan_def *ch)
370387
{
@@ -3427,6 +3444,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
34273444
struct cfg80211_bss *bss;
34283445
enum nl80211_band band;
34293446
struct brcmu_chan ch;
3447+
u16 chanspec;
34303448
u16 channel;
34313449
u32 freq;
34323450
u16 notify_capability;
@@ -3440,16 +3458,17 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
34403458
return -EINVAL;
34413459
}
34423460

3461+
chanspec = le16_to_cpu(bi->chanspec);
34433462
if (!bi->ctl_ch) {
3444-
ch.chspec = le16_to_cpu(bi->chanspec);
3463+
ch.chspec = chanspec;
34453464
cfg->d11inf.decchspec(&ch);
34463465
bi->ctl_ch = ch.control_ch_num;
34473466
}
34483467
channel = bi->ctl_ch;
34493468

3450-
if (CHSPEC_IS6G(bi->chanspec))
3469+
if (CHSPEC_IS6G(chanspec))
34513470
band = NL80211_BAND_6GHZ;
3452-
else if (CHSPEC_IS5G(bi->chanspec))
3471+
else if (CHSPEC_IS5G(chanspec))
34533472
band = NL80211_BAND_5GHZ;
34543473
else
34553474
band = NL80211_BAND_2GHZ;
@@ -3943,6 +3962,34 @@ brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
39433962
pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
39443963
netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
39453964
break;
3965+
case cpu_to_le32(3):
3966+
brcmf_err(
3967+
"This should use the brcmf_get_netinfo_v3_array function to retrieve the array\n");
3968+
break;
3969+
}
3970+
3971+
return netinfo;
3972+
}
3973+
3974+
static struct brcmf_pno_net_info_v3_le *
3975+
brcmf_get_netinfo_v3_array(struct brcmf_pno_scanresults_le *pfn_v1)
3976+
{
3977+
struct brcmf_pno_scanresults_v2_le *pfn_v2;
3978+
struct brcmf_pno_net_info_v3_le *netinfo;
3979+
3980+
switch (pfn_v1->version) {
3981+
default:
3982+
WARN_ON(1);
3983+
fallthrough;
3984+
case cpu_to_le32(1):
3985+
case cpu_to_le32(2):
3986+
brcmf_err(
3987+
"This should use the brcmf_get_netinfo_array function to retrieve the array\n");
3988+
break;
3989+
case cpu_to_le32(3):
3990+
pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
3991+
netinfo = (struct brcmf_pno_net_info_v3_le *)(pfn_v2 + 1);
3992+
break;
39463993
}
39473994

39483995
return netinfo;
@@ -3954,13 +4001,12 @@ brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
39544001
* scan request in the form of cfg80211_scan_request. For timebeing, create
39554002
* cfg80211_scan_request one out of the received PNO event.
39564003
*/
3957-
static s32
3958-
brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
3959-
const struct brcmf_event_msg *e, void *data)
4004+
static s32 brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
4005+
const struct brcmf_event_msg *e,
4006+
void *data)
39604007
{
39614008
struct brcmf_pub *drvr = ifp->drvr;
39624009
struct brcmf_cfg80211_info *cfg = drvr->config;
3963-
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
39644010
struct cfg80211_scan_request *request = NULL;
39654011
struct wiphy *wiphy = cfg_to_wiphy(cfg);
39664012
int i, err = 0;
@@ -3969,10 +4015,19 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
39694015
u32 result_count;
39704016
u32 status;
39714017
u32 datalen;
4018+
u32 min_data_len;
39724019

39734020
brcmf_dbg(SCAN, "Enter\n");
39744021

3975-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4022+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PFN_V3)) {
4023+
min_data_len = sizeof(*pfn_result) +
4024+
sizeof(struct brcmf_pno_net_info_v3_le);
4025+
} else {
4026+
min_data_len = sizeof(*pfn_result) +
4027+
sizeof(struct brcmf_pno_net_info_le);
4028+
}
4029+
4030+
if (e->datalen < min_data_len) {
39764031
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
39774032
return 0;
39784033
}
@@ -3995,38 +4050,78 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
39954050
bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n");
39964051
goto out_err;
39974052
}
4053+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PFN_V3)) {
4054+
struct brcmf_pno_net_info_v3_le *netinfo_v3, *netinfo_v3_start;
4055+
netinfo_v3_start = brcmf_get_netinfo_v3_array(pfn_result);
39984056

3999-
netinfo_start = brcmf_get_netinfo_array(pfn_result);
4000-
datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
4001-
if (datalen < result_count * sizeof(*netinfo)) {
4002-
bphy_err(drvr, "insufficient event data\n");
4003-
goto out_err;
4004-
}
4057+
datalen = e->datalen -
4058+
((void *)netinfo_v3_start - (void *)pfn_result);
4059+
if (datalen < result_count * sizeof(*netinfo_v3)) {
4060+
bphy_err(drvr, "insufficient event data\n");
4061+
goto out_err;
4062+
}
40054063

4006-
request = brcmf_alloc_internal_escan_request(wiphy,
4007-
result_count);
4008-
if (!request) {
4009-
err = -ENOMEM;
4010-
goto out_err;
4011-
}
4064+
request =
4065+
brcmf_alloc_internal_escan_request(wiphy, result_count);
4066+
if (!request) {
4067+
err = -ENOMEM;
4068+
goto out_err;
4069+
}
40124070

4013-
bucket_map = 0;
4014-
for (i = 0; i < result_count; i++) {
4015-
netinfo = &netinfo_start[i];
4071+
bucket_map = 0;
4072+
for (i = 0; i < result_count; i++) {
4073+
netinfo_v3 = &netinfo_v3_start[i];
4074+
4075+
if (netinfo_v3->SSID_len > IEEE80211_MAX_SSID_LEN)
4076+
netinfo_v3->SSID_len = IEEE80211_MAX_SSID_LEN;
4077+
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d Band:%d\n",
4078+
netinfo_v3->SSID,
4079+
CHSPEC_CHANNEL(netinfo_v3->chanspec),
4080+
CHSPEC_BAND(netinfo_v3->chanspec));
4081+
bucket_map |= brcmf_pno_get_bucket_map_v3(cfg->pno,
4082+
netinfo_v3);
4083+
err = brcmf_internal_escan_add_info(
4084+
request, netinfo_v3->SSID, netinfo_v3->SSID_len,
4085+
CHSPEC_CHANNEL(netinfo_v3->chanspec));
4086+
if (err)
4087+
goto out_err;
4088+
}
4089+
} else {
4090+
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
40164091

4017-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4018-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4019-
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
4020-
netinfo->SSID, netinfo->channel);
4021-
bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
4022-
err = brcmf_internal_escan_add_info(request,
4023-
netinfo->SSID,
4024-
netinfo->SSID_len,
4025-
netinfo->channel);
4026-
if (err)
4092+
netinfo_start = brcmf_get_netinfo_array(pfn_result);
4093+
datalen = e->datalen -
4094+
((void *)netinfo_start - (void *)pfn_result);
4095+
if (datalen < result_count * sizeof(*netinfo)) {
4096+
bphy_err(drvr, "insufficient event data\n");
40274097
goto out_err;
4028-
}
4098+
}
40294099

4100+
request =
4101+
brcmf_alloc_internal_escan_request(wiphy, result_count);
4102+
if (!request) {
4103+
err = -ENOMEM;
4104+
goto out_err;
4105+
}
4106+
4107+
bucket_map = 0;
4108+
for (i = 0; i < result_count; i++) {
4109+
netinfo = &netinfo_start[i];
4110+
4111+
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4112+
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4113+
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
4114+
netinfo->SSID, netinfo->channel);
4115+
bucket_map |=
4116+
brcmf_pno_get_bucket_map(cfg->pno, netinfo);
4117+
err = brcmf_internal_escan_add_info(request,
4118+
netinfo->SSID,
4119+
netinfo->SSID_len,
4120+
netinfo->channel);
4121+
if (err)
4122+
goto out_err;
4123+
}
4124+
}
40304125
if (!bucket_map)
40314126
goto free_req;
40324127

@@ -4129,18 +4224,25 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
41294224
return ret;
41304225
}
41314226

4132-
static s32
4133-
brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
4134-
void *data)
4227+
static s32 brcmf_wowl_nd_results(struct brcmf_if *ifp,
4228+
const struct brcmf_event_msg *e, void *data)
41354229
{
41364230
struct brcmf_pub *drvr = ifp->drvr;
41374231
struct brcmf_cfg80211_info *cfg = drvr->config;
41384232
struct brcmf_pno_scanresults_le *pfn_result;
4139-
struct brcmf_pno_net_info_le *netinfo;
4233+
u32 min_data_len;
41404234

41414235
brcmf_dbg(SCAN, "Enter\n");
41424236

4143-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4237+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PFN_V3)) {
4238+
min_data_len = sizeof(*pfn_result) +
4239+
sizeof(struct brcmf_pno_net_info_v3_le);
4240+
} else {
4241+
min_data_len = sizeof(*pfn_result) +
4242+
sizeof(struct brcmf_pno_net_info_le);
4243+
}
4244+
4245+
if (e->datalen < min_data_len) {
41444246
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
41454247
return 0;
41464248
}
@@ -4158,20 +4260,38 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
41584260
return -EINVAL;
41594261
}
41604262

4161-
netinfo = brcmf_get_netinfo_array(pfn_result);
4162-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4163-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4164-
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
4165-
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
4166-
cfg->wowl.nd->n_channels = 1;
4167-
/* TODO - need to store band so we can handle 6G */
4168-
cfg->wowl.nd->channels[0] =
4169-
ieee80211_channel_to_frequency(netinfo->channel,
4263+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PFN_V3)) {
4264+
struct brcmf_pno_net_info_v3_le *netinfo_v3;
4265+
netinfo_v3 = brcmf_get_netinfo_v3_array(pfn_result);
4266+
4267+
if (netinfo_v3->SSID_len > IEEE80211_MAX_SSID_LEN)
4268+
netinfo_v3->SSID_len = IEEE80211_MAX_SSID_LEN;
4269+
memcpy(cfg->wowl.nd->ssid.ssid, netinfo_v3->SSID,
4270+
netinfo_v3->SSID_len);
4271+
cfg->wowl.nd->ssid.ssid_len = netinfo_v3->SSID_len;
4272+
cfg->wowl.nd->n_channels = 1;
4273+
/* TODO - need to store band so we can handle 6G */
4274+
cfg->wowl.nd->channels[0] = ieee80211_channel_to_frequency(
4275+
CHSPEC_CHANNEL(netinfo_v3->chanspec),
4276+
fwil_band_to_nl80211(netinfo_v3->chanspec));
4277+
} else {
4278+
struct brcmf_pno_net_info_le *netinfo;
4279+
netinfo = brcmf_get_netinfo_array(pfn_result);
4280+
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4281+
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4282+
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID,
4283+
netinfo->SSID_len);
4284+
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
4285+
cfg->wowl.nd->n_channels = 1;
4286+
/* TODO - need to store band so we can handle 6G */
4287+
cfg->wowl.nd->channels[0] = ieee80211_channel_to_frequency(
4288+
netinfo->channel,
41704289
netinfo->channel <= CH_MAX_2G_CHANNEL ?
4171-
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
4290+
NL80211_BAND_2GHZ :
4291+
NL80211_BAND_5GHZ);
4292+
}
41724293
cfg->wowl.nd_info->n_matches = 1;
41734294
cfg->wowl.nd_info->matches[0] = cfg->wowl.nd;
4174-
41754295
/* Inform (the resume task) that the net detect information was recvd */
41764296
cfg->wowl.nd_data_completed = true;
41774297
wake_up(&cfg->wowl.nd_data_wait);

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
289289
{
290290
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
291291
struct brcmf_wl_scan_version_le scan_ver;
292+
struct brcmf_pno_param_v3_le pno_params;
292293
struct brcmf_pno_macaddr_le pfn_mac;
293294
struct brcmf_gscan_config gscan_cfg;
294295
u32 wowl_cap;
@@ -355,6 +356,15 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
355356
}
356357
}
357358

359+
/* See what version of PFN scan is supported*/
360+
err = brcmf_fil_iovar_data_get(ifp, "pno_set", &pno_params,
361+
sizeof(pno_params));
362+
if (!err) {
363+
if (pno_params.version == 3) {
364+
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_PFN_V3);
365+
}
366+
}
367+
358368
if (drvr->settings->feature_disable) {
359369
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
360370
ifp->drvr->feat_flags,

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
* FWAUTH: Firmware authenticator
3232
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
3333
* SCAN_V2: Version 2 scan params
34+
* SCAN_v3: Version 3 scan params
35+
* PMKID_V2: Version 2 PMKID
36+
* PMKID_V3: Version 3 PMKID
37+
* JOIN_V1: Version 1 join struct
38+
* PFN_V3: Version 3 PNF scan info
3439
*/
3540
#define BRCMF_FEAT_LIST \
3641
BRCMF_FEAT_DEF(MBSS) \
@@ -60,7 +65,8 @@
6065
BRCMF_FEAT_DEF(PMKID_V2) \
6166
BRCMF_FEAT_DEF(PMKID_V3) \
6267
BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \
63-
BRCMF_FEAT_DEF(JOIN_V1)
68+
BRCMF_FEAT_DEF(JOIN_V1) \
69+
BRCMF_FEAT_DEF(PFN_V3)
6470

6571
/*
6672
* Quirks:

0 commit comments

Comments
 (0)