Skip to content

Commit 54b841c

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 63638ac commit 54b841c

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
@@ -3979,17 +3979,11 @@ brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
39793979
}
39803980

39813981
static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
3982-
u8 *ssid, u8 ssid_len, u8 channel)
3982+
u8 *ssid, u8 ssid_len, u8 channel, enum nl80211_band band)
39833983
{
39843984
struct ieee80211_channel *chan;
3985-
enum nl80211_band band;
39863985
int freq, i;
39873986

3988-
if (channel <= CH_MAX_2G_CHANNEL)
3989-
band = NL80211_BAND_2GHZ;
3990-
else
3991-
band = NL80211_BAND_5GHZ;
3992-
39933987
freq = ieee80211_channel_to_frequency(channel, band);
39943988
if (!freq)
39953989
return -EINVAL;
@@ -4045,53 +4039,30 @@ static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,
40454039
return 0;
40464040
}
40474041

4048-
static struct brcmf_pno_net_info_le *
4049-
brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
4050-
{
4051-
struct brcmf_pno_scanresults_v2_le *pfn_v2;
4052-
struct brcmf_pno_net_info_le *netinfo;
4053-
4054-
switch (pfn_v1->version) {
4055-
default:
4056-
WARN_ON(1);
4057-
fallthrough;
4058-
case cpu_to_le32(1):
4059-
netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);
4060-
break;
4061-
case cpu_to_le32(2):
4062-
pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
4063-
netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
4064-
break;
4065-
}
4066-
4067-
return netinfo;
4068-
}
4069-
40704042
/* PFN result doesn't have all the info which are required by the supplicant
40714043
* (For e.g IEs) Do a target Escan so that sched scan results are reported
40724044
* via wl_inform_single_bss in the required format. Escan does require the
40734045
* scan request in the form of cfg80211_scan_request. For timebeing, create
40744046
* cfg80211_scan_request one out of the received PNO event.
40754047
*/
4076-
static s32
4077-
brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
4078-
const struct brcmf_event_msg *e, void *data)
4048+
static s32 brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
4049+
const struct brcmf_event_msg *e,
4050+
void *data)
40794051
{
40804052
struct brcmf_pub *drvr = ifp->drvr;
40814053
struct brcmf_cfg80211_info *cfg = drvr->config;
4082-
struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
40834054
struct cfg80211_scan_request *request = NULL;
40844055
struct wiphy *wiphy = cfg_to_wiphy(cfg);
40854056
int i, err = 0;
4086-
struct brcmf_pno_scanresults_le *pfn_result;
40874057
u32 bucket_map;
40884058
u32 result_count;
40894059
u32 status;
4090-
u32 datalen;
4060+
u32 min_data_len;
40914061

40924062
brcmf_dbg(SCAN, "Enter\n");
4063+
min_data_len = drvr->pno_handler.get_min_data_len();
40934064

4094-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4065+
if (e->datalen < min_data_len) {
40954066
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
40964067
return 0;
40974068
}
@@ -4101,9 +4072,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
41014072
return 0;
41024073
}
41034074

4104-
pfn_result = (struct brcmf_pno_scanresults_le *)data;
4105-
result_count = le32_to_cpu(pfn_result->count);
4106-
status = le32_to_cpu(pfn_result->status);
4075+
result_count = drvr->pno_handler.get_result_count(data);
4076+
status = drvr->pno_handler.get_result_status(data);
41074077

41084078
/* PFN event is limited to fit 512 bytes so we may get
41094079
* multiple NET_FOUND events. For now place a warning here.
@@ -4114,38 +4084,33 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
41144084
bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n");
41154085
goto out_err;
41164086
}
4117-
4118-
netinfo_start = brcmf_get_netinfo_array(pfn_result);
4119-
datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
4120-
if (datalen < result_count * sizeof(*netinfo)) {
4121-
bphy_err(drvr, "insufficient event data\n");
4087+
err = drvr->pno_handler.validate_pfn_results(data, e->datalen);
4088+
if (err) {
4089+
bphy_err(drvr, "Invalid escan results (%d)", err);
41224090
goto out_err;
41234091
}
4124-
4125-
request = brcmf_alloc_internal_escan_request(wiphy,
4126-
result_count);
4092+
request = brcmf_alloc_internal_escan_request(wiphy, result_count);
41274093
if (!request) {
41284094
err = -ENOMEM;
41294095
goto out_err;
41304096
}
4131-
41324097
bucket_map = 0;
41334098
for (i = 0; i < result_count; i++) {
4134-
netinfo = &netinfo_start[i];
4135-
4136-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4137-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4138-
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
4139-
netinfo->SSID, netinfo->channel);
4140-
bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
4141-
err = brcmf_internal_escan_add_info(request,
4142-
netinfo->SSID,
4143-
netinfo->SSID_len,
4144-
netinfo->channel);
4099+
u8 channel;
4100+
enum nl80211_band band;
4101+
u8 ssid[IEEE80211_MAX_SSID_LEN];
4102+
u8 ssid_len;
4103+
4104+
drvr->pno_handler.get_result_info(data, i, &ssid, &ssid_len,
4105+
&channel, &band);
4106+
brcmf_dbg(SCAN, "SSID:%.32s Channel:%d Band:%d\n", ssid,
4107+
channel, band);
4108+
bucket_map |= drvr->pno_handler.get_bucket_map(data, i, cfg->pno);
4109+
err = brcmf_internal_escan_add_info(request, ssid, ssid_len,
4110+
channel, band);
41454111
if (err)
41464112
goto out_err;
41474113
}
4148-
41494114
if (!bucket_map)
41504115
goto free_req;
41514116

@@ -4248,48 +4213,50 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
42484213
return ret;
42494214
}
42504215

4251-
static s32
4252-
brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
4253-
void *data)
4216+
static s32 brcmf_wowl_nd_results(struct brcmf_if *ifp,
4217+
const struct brcmf_event_msg *e, void *data)
42544218
{
42554219
struct brcmf_pub *drvr = ifp->drvr;
42564220
struct brcmf_cfg80211_info *cfg = drvr->config;
4257-
struct brcmf_pno_scanresults_le *pfn_result;
4258-
struct brcmf_pno_net_info_le *netinfo;
4221+
u32 min_data_len;
4222+
u8 channel;
4223+
enum nl80211_band band;
4224+
u8 ssid[IEEE80211_MAX_SSID_LEN];
4225+
u8 ssid_len;
4226+
u32 result_count;
42594227

42604228
brcmf_dbg(SCAN, "Enter\n");
42614229

4262-
if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
4230+
min_data_len = drvr->pno_handler.get_min_data_len();
4231+
4232+
if (e->datalen < min_data_len) {
42634233
brcmf_dbg(SCAN, "Event data to small. Ignore\n");
42644234
return 0;
42654235
}
42664236

4267-
pfn_result = (struct brcmf_pno_scanresults_le *)data;
42684237

42694238
if (e->event_code == BRCMF_E_PFN_NET_LOST) {
42704239
brcmf_dbg(SCAN, "PFN NET LOST event. Ignore\n");
42714240
return 0;
42724241
}
42734242

4274-
if (le32_to_cpu(pfn_result->count) < 1) {
4243+
result_count = drvr->pno_handler.get_result_count(data);
4244+
if (result_count < 1) {
42754245
bphy_err(drvr, "Invalid result count, expected 1 (%d)\n",
4276-
le32_to_cpu(pfn_result->count));
4246+
result_count);
42774247
return -EINVAL;
42784248
}
42794249

4280-
netinfo = brcmf_get_netinfo_array(pfn_result);
4281-
if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
4282-
netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
4283-
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
4284-
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
4250+
drvr->pno_handler.get_result_info(data, 0, &ssid, &ssid_len, &channel,
4251+
&band);
4252+
memcpy(cfg->wowl.nd->ssid.ssid, ssid, ssid_len);
4253+
cfg->wowl.nd->ssid.ssid_len = ssid_len;
42854254
cfg->wowl.nd->n_channels = 1;
42864255
cfg->wowl.nd->channels[0] =
4287-
ieee80211_channel_to_frequency(netinfo->channel,
4288-
netinfo->channel <= CH_MAX_2G_CHANNEL ?
4289-
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
4256+
ieee80211_channel_to_frequency(channel, band);
4257+
42904258
cfg->wowl.nd_info->n_matches = 1;
42914259
cfg->wowl.nd_info->matches[0] = cfg->wowl.nd;
4292-
42934260
/* Inform (the resume task) that the net detect information was recvd */
42944261
cfg->wowl.nd_data_completed = true;
42954262
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)