Skip to content

Commit 33b9aa5

Browse files
dberlinjannau
authored andcommitted
[brcmfmac] Structurize PNF scan and add support for latest version
This patch structurizes PNF scan handling, adding support for netinfo v3 and PNO v3 structures. This in turn, enables the chip to tell us about 6G scan results, as the results contain chanspecs and not just channels. Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1 parent 49f4510 commit 33b9aa5

7 files changed

Lines changed: 456 additions & 90 deletions

File tree

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

Lines changed: 45 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -3984,17 +3984,11 @@ brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
39843984
}
39853985

39863986
static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
3987-
u8 *ssid, u8 ssid_len, u8 channel)
3987+
u8 *ssid, u8 ssid_len, u8 channel, enum nl80211_band band)
39883988
{
39893989
struct ieee80211_channel *chan;
3990-
enum nl80211_band band;
39913990
int freq, i;
39923991

3993-
if (channel <= CH_MAX_2G_CHANNEL)
3994-
band = NL80211_BAND_2GHZ;
3995-
else
3996-
band = NL80211_BAND_5GHZ;
3997-
39983992
freq = ieee80211_channel_to_frequency(channel, band);
39993993
if (!freq)
40003994
return -EINVAL;
@@ -4050,53 +4044,30 @@ static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,
40504044
return 0;
40514045
}
40524046

4053-
static struct brcmf_pno_net_info_le *
4054-
brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
4055-
{
4056-
struct brcmf_pno_scanresults_v2_le *pfn_v2;
4057-
struct brcmf_pno_net_info_le *netinfo;
4058-
4059-
switch (pfn_v1->version) {
4060-
default:
4061-
WARN_ON(1);
4062-
fallthrough;
4063-
case cpu_to_le32(1):
4064-
netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);
4065-
break;
4066-
case cpu_to_le32(2):
4067-
pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
4068-
netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
4069-
break;
4070-
}
4071-
4072-
return netinfo;
4073-
}
4074-
40754047
/* PFN result doesn't have all the info which are required by the supplicant
40764048
* (For e.g IEs) Do a target Escan so that sched scan results are reported
40774049
* via wl_inform_single_bss in the required format. Escan does require the
40784050
* scan request in the form of cfg80211_scan_request. For timebeing, create
40794051
* cfg80211_scan_request one out of the received PNO event.
40804052
*/
4081-
static s32
4082-
brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
4083-
const struct brcmf_event_msg *e, void *data)
4053+
static s32 brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
4054+
const struct brcmf_event_msg *e,
4055+
void *data)
40844056
{
40854057
struct brcmf_pub *drvr = ifp->drvr;
40864058
struct brcmf_cfg80211_info *cfg = drvr->config;
4087-
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
40884059
struct cfg80211_scan_request *request = NULL;
40894060
struct wiphy *wiphy = cfg_to_wiphy(cfg);
40904061
int i, err = 0;
4091-
struct brcmf_pno_scanresults_le *pfn_result;
40924062
u32 bucket_map;
40934063
u32 result_count;
40944064
u32 status;
4095-
u32 datalen;
4065+
u32 min_data_len;
40964066

40974067
brcmf_dbg(SCAN, "Enter\n");
4068+
min_data_len = drvr->pno_handler.get_min_data_len();
40984069

4099-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4070+
if (e->datalen < min_data_len) {
41004071
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
41014072
return 0;
41024073
}
@@ -4106,9 +4077,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
41064077
return 0;
41074078
}
41084079

4109-
pfn_result = (struct brcmf_pno_scanresults_le *)data;
4110-
result_count = le32_to_cpu(pfn_result->count);
4111-
status = le32_to_cpu(pfn_result->status);
4080+
result_count = drvr->pno_handler.get_result_count(data);
4081+
status = drvr->pno_handler.get_result_status(data);
41124082

41134083
/* PFN event is limited to fit 512 bytes so we may get
41144084
* multiple NET_FOUND events. For now place a warning here.
@@ -4119,38 +4089,33 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
41194089
bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n");
41204090
goto out_err;
41214091
}
4122-
4123-
netinfo_start = brcmf_get_netinfo_array(pfn_result);
4124-
datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
4125-
if (datalen < result_count * sizeof(*netinfo)) {
4126-
bphy_err(drvr, "insufficient event data\n");
4092+
err = drvr->pno_handler.validate_pfn_results(data, e->datalen);
4093+
if (err) {
4094+
bphy_err(drvr, "Invalid escan results (%d)", err);
41274095
goto out_err;
41284096
}
4129-
4130-
request = brcmf_alloc_internal_escan_request(wiphy,
4131-
result_count);
4097+
request = brcmf_alloc_internal_escan_request(wiphy, result_count);
41324098
if (!request) {
41334099
err = -ENOMEM;
41344100
goto out_err;
41354101
}
4136-
41374102
bucket_map = 0;
41384103
for (i = 0; i < result_count; i++) {
4139-
netinfo = &netinfo_start[i];
4140-
4141-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4142-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4143-
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
4144-
netinfo->SSID, netinfo->channel);
4145-
bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
4146-
err = brcmf_internal_escan_add_info(request,
4147-
netinfo->SSID,
4148-
netinfo->SSID_len,
4149-
netinfo->channel);
4104+
u8 channel;
4105+
enum nl80211_band band;
4106+
u8 ssid[IEEE80211_MAX_SSID_LEN];
4107+
u8 ssid_len;
4108+
4109+
drvr->pno_handler.get_result_info(data, i, &ssid, &ssid_len,
4110+
&channel, &band);
4111+
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d Band:%d\n", ssid,
4112+
channel, band);
4113+
bucket_map |= drvr->pno_handler.get_bucket_map(data, i, cfg->pno);
4114+
err = brcmf_internal_escan_add_info(request, ssid, ssid_len,
4115+
channel, band);
41504116
if (err)
41514117
goto out_err;
41524118
}
4153-
41544119
if (!bucket_map)
41554120
goto free_req;
41564121

@@ -4253,48 +4218,50 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
42534218
return ret;
42544219
}
42554220

4256-
static s32
4257-
brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
4258-
void *data)
4221+
static s32 brcmf_wowl_nd_results(struct brcmf_if *ifp,
4222+
const struct brcmf_event_msg *e, void *data)
42594223
{
42604224
struct brcmf_pub *drvr = ifp->drvr;
42614225
struct brcmf_cfg80211_info *cfg = drvr->config;
4262-
struct brcmf_pno_scanresults_le *pfn_result;
4263-
struct brcmf_pno_net_info_le *netinfo;
4226+
u32 min_data_len;
4227+
u8 channel;
4228+
enum nl80211_band band;
4229+
u8 ssid[IEEE80211_MAX_SSID_LEN];
4230+
u8 ssid_len;
4231+
u32 result_count;
42644232

42654233
brcmf_dbg(SCAN, "Enter\n");
42664234

4267-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4235+
min_data_len = drvr->pno_handler.get_min_data_len();
4236+
4237+
if (e->datalen < min_data_len) {
42684238
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
42694239
return 0;
42704240
}
42714241

4272-
pfn_result = (struct brcmf_pno_scanresults_le *)data;
42734242

42744243
if (e->event_code == BRCMF_E_PFN_NET_LOST) {
42754244
brcmf_dbg(SCAN, "PFN NET LOST event. Ignore\n");
42764245
return 0;
42774246
}
42784247

4279-
if (le32_to_cpu(pfn_result->count) < 1) {
4248+
result_count = drvr->pno_handler.get_result_count(data);
4249+
if (result_count < 1) {
42804250
bphy_err(drvr, "Invalid result count, expected 1 (%d)\n",
4281-
le32_to_cpu(pfn_result->count));
4251+
result_count);
42824252
return -EINVAL;
42834253
}
42844254

4285-
netinfo = brcmf_get_netinfo_array(pfn_result);
4286-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4287-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4288-
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
4289-
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
4255+
drvr->pno_handler.get_result_info(data, 0, &ssid, &ssid_len, &channel,
4256+
&band);
4257+
memcpy(cfg->wowl.nd->ssid.ssid, ssid, ssid_len);
4258+
cfg->wowl.nd->ssid.ssid_len = ssid_len;
42904259
cfg->wowl.nd->n_channels = 1;
42914260
cfg->wowl.nd->channels[0] =
4292-
ieee80211_channel_to_frequency(netinfo->channel,
4293-
netinfo->channel <= CH_MAX_2G_CHANNEL ?
4294-
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
4261+
ieee80211_channel_to_frequency(channel, band);
4262+
42954263
cfg->wowl.nd_info->n_matches = 1;
42964264
cfg->wowl.nd_info->matches[0] = cfg->wowl.nd;
4297-
42984265
/* Inform (the resume task) that the net detect information was recvd */
42994266
cfg->wowl.nd_data_completed = true;
43004267
wake_up(&cfg->wowl.nd_data_wait);

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* for brcmu_d11inf */
1010
#include <brcmu_d11.h>
11+
#include <brcmu_wifi.h>
1112

1213
#include "core.h"
1314
#include "fwil_types.h"
@@ -388,6 +389,22 @@ struct brcmf_tlv {
388389
u8 data[];
389390
};
390391

392+
static inline enum nl80211_band fwil_band_to_nl80211(u16 band)
393+
{
394+
switch (band) {
395+
case WLC_BAND_2G:
396+
return NL80211_BAND_2GHZ;
397+
case WLC_BAND_5G:
398+
return NL80211_BAND_5GHZ;
399+
case WLC_BAND_6G:
400+
return NL80211_BAND_6GHZ;
401+
default:
402+
WARN_ON(1);
403+
break;
404+
}
405+
return 0;
406+
}
407+
391408
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
392409
{
393410
return cfg->wiphy;

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ struct brcmf_rev_info {
9797
u32 nvramrev;
9898
};
9999

100+
struct brcmf_pno_info;
101+
/**
102+
* struct pno_struct_handler
103+
*/
104+
struct pno_struct_handler {
105+
u8 version;
106+
int (*pno_config)(struct brcmf_if *ifp, u32 scan_freq, u32 mscan,
107+
u32 bestn);
108+
u32 (*get_min_data_len)(void);
109+
u32 (*get_result_count)(void *data);
110+
u32 (*get_result_status)(void *data);
111+
int (*validate_pfn_results)(void *data, u32 event_datalen);
112+
u32 (*get_bucket_map)(void *data, int idx, struct brcmf_pno_info *pi);
113+
int (*get_result_info)(void *data, int result_idx,
114+
u8 (*ssid)[IEEE80211_MAX_SSID_LEN], u8 *ssid_len,
115+
u8 *channel, enum nl80211_band *band);
116+
};
117+
100118
/* Common structure for module and instance linkage */
101119
struct brcmf_pub {
102120
/* Linkage ponters */
@@ -145,6 +163,8 @@ struct brcmf_pub {
145163
u8 sta_mac_idx;
146164
const struct brcmf_fwvid_ops *vops;
147165
void *vdata;
166+
u16 cnt_ver;
167+
struct pno_struct_handler pno_handler;
148168
};
149169

150170
/* forward declarations */

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "fwvid.h"
1717
#include "feature.h"
1818
#include "common.h"
19+
#include "pno.h"
1920

2021
#define BRCMF_FW_UNSUPPORTED 23
2122

@@ -290,6 +291,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
290291
{
291292
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
292293
struct brcmf_wl_scan_version_le scan_ver;
294+
struct brcmf_pno_param_v3_le pno_params;
293295
struct brcmf_pno_macaddr_le pfn_mac;
294296
struct brcmf_gscan_config gscan_cfg;
295297
u32 wowl_cap;
@@ -356,6 +358,16 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
356358
}
357359
}
358360

361+
/* See what version of PFN scan is supported*/
362+
err = brcmf_fil_iovar_data_get(ifp, "pno_set", &pno_params,
363+
sizeof(pno_params));
364+
if (!err) {
365+
brcmf_pno_setup_for_version(drvr, le16_to_cpu(pno_params.version));
366+
} else {
367+
/* Default to version 2, supported by all chips we support. */
368+
brcmf_pno_setup_for_version(drvr, 2);
369+
}
370+
359371
brcmf_feat_wlc_version_overrides(drvr);
360372
brcmf_feat_firmware_overrides(drvr);
361373

0 commit comments

Comments
 (0)