Skip to content

Commit 127dfec

Browse files
dberlinjannau
authored andcommitted
[brcmfmac] Structurize scan parameter handling
Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1 parent 33b9aa5 commit 127dfec

8 files changed

Lines changed: 643 additions & 281 deletions

File tree

drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ brcmfmac-objs += \
2525
btcoex.o \
2626
vendor.o \
2727
pno.o \
28+
scan_param.o \
2829
xtlv.o
30+
2931
brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
3032
bcdc.o \
3133
fwsignal.o

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

Lines changed: 28 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,170 +1103,13 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
11031103
}
11041104
}
11051105

1106-
static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le,
1107-
struct brcmf_scan_params_le *params_le)
1108-
{
1109-
size_t params_size;
1110-
u32 ch;
1111-
int n_channels, n_ssids;
1112-
1113-
memcpy(&params_le->ssid_le, &params_v2_le->ssid_le,
1114-
sizeof(params_le->ssid_le));
1115-
memcpy(&params_le->bssid, &params_v2_le->bssid,
1116-
sizeof(params_le->bssid));
1117-
1118-
params_le->bss_type = params_v2_le->bss_type;
1119-
params_le->scan_type = le32_to_cpu(params_v2_le->scan_type);
1120-
params_le->nprobes = params_v2_le->nprobes;
1121-
params_le->active_time = params_v2_le->active_time;
1122-
params_le->passive_time = params_v2_le->passive_time;
1123-
params_le->home_time = params_v2_le->home_time;
1124-
params_le->channel_num = params_v2_le->channel_num;
1125-
1126-
ch = le32_to_cpu(params_v2_le->channel_num);
1127-
n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK;
1128-
n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT;
1129-
1130-
params_size = sizeof(u16) * n_channels;
1131-
if (n_ssids > 0) {
1132-
params_size = roundup(params_size, sizeof(u32));
1133-
params_size += sizeof(struct brcmf_ssid_le) * n_ssids;
1134-
}
1135-
1136-
memcpy(&params_le->channel_list[0],
1137-
&params_v2_le->channel_list[0], params_size);
1138-
}
1139-
1140-
static u32 brcmf_nl80211_scan_flags_to_scan_flags(u32 nl80211_flags)
1141-
{
1142-
u32 scan_flags = 0;
1143-
if (nl80211_flags & NL80211_SCAN_FLAG_LOW_SPAN) {
1144-
scan_flags |= BRCMF_SCANFLAGS_LOW_SPAN;
1145-
brcmf_dbg(SCAN, "requested low span scan\n");
1146-
}
1147-
if (nl80211_flags & NL80211_SCAN_FLAG_HIGH_ACCURACY) {
1148-
scan_flags |= BRCMF_SCANFLAGS_HIGH_ACCURACY;
1149-
brcmf_dbg(SCAN, "requested high accuracy scan\n");
1150-
}
1151-
if (nl80211_flags & NL80211_SCAN_FLAG_LOW_POWER) {
1152-
scan_flags |= BRCMF_SCANFLAGS_LOW_POWER;
1153-
brcmf_dbg(SCAN, "requested low power scan\n");
1154-
}
1155-
if (nl80211_flags & NL80211_SCAN_FLAG_LOW_PRIORITY) {
1156-
scan_flags |= BRCMF_SCANFLAGS_LOW_PRIO;
1157-
brcmf_dbg(SCAN, "requested low priority scan\n");
1158-
}
1159-
return scan_flags;
1160-
}
1161-
1162-
static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
1163-
struct brcmf_if *ifp,
1164-
struct brcmf_scan_params_v2_le *params_le,
1165-
struct cfg80211_scan_request *request)
1166-
{
1167-
u32 n_ssids;
1168-
u32 n_channels;
1169-
s32 i;
1170-
s32 offset;
1171-
u16 chanspec;
1172-
char *ptr;
1173-
int length;
1174-
struct brcmf_ssid_le ssid_le;
1175-
u32 scan_type = BRCMF_SCANTYPE_ACTIVE;
1176-
1177-
eth_broadcast_addr(params_le->bssid);
1178-
1179-
length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
1180-
1181-
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V3))
1182-
params_le->version = cpu_to_le16(BRCMF_SCAN_PARAMS_VERSION_V3);
1183-
else
1184-
params_le->version = cpu_to_le16(BRCMF_SCAN_PARAMS_VERSION_V2);
1185-
1186-
params_le->bss_type = DOT11_BSSTYPE_ANY;
1187-
params_le->ssid_type = 0;
1188-
params_le->channel_num = 0;
1189-
params_le->nprobes = cpu_to_le32(-1);
1190-
params_le->active_time = cpu_to_le32(-1);
1191-
params_le->passive_time = cpu_to_le32(-1);
1192-
params_le->home_time = cpu_to_le32(-1);
1193-
memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
1194-
1195-
/* Scan abort */
1196-
if (!request) {
1197-
length += sizeof(u16);
1198-
params_le->channel_num = cpu_to_le32(1);
1199-
params_le->channel_list[0] = cpu_to_le16(-1);
1200-
params_le->length = cpu_to_le16(length);
1201-
return;
1202-
}
1203-
1204-
n_ssids = request->n_ssids;
1205-
n_channels = request->n_channels;
1206-
1207-
/* Copy channel array if applicable */
1208-
brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
1209-
n_channels);
1210-
if (n_channels > 0) {
1211-
length += roundup(sizeof(u16) * n_channels, sizeof(u32));
1212-
for (i = 0; i < n_channels; i++) {
1213-
chanspec = channel_to_chanspec(&cfg->d11inf,
1214-
request->channels[i]);
1215-
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
1216-
request->channels[i]->hw_value, chanspec);
1217-
params_le->channel_list[i] = cpu_to_le16(chanspec);
1218-
}
1219-
} else {
1220-
brcmf_dbg(SCAN, "Scanning all channels\n");
1221-
}
1222-
1223-
/* Copy ssid array if applicable */
1224-
brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
1225-
if (n_ssids > 0) {
1226-
offset = offsetof(struct brcmf_scan_params_v2_le, channel_list) +
1227-
n_channels * sizeof(u16);
1228-
offset = roundup(offset, sizeof(u32));
1229-
length += sizeof(ssid_le) * n_ssids;
1230-
ptr = (char *)params_le + offset;
1231-
for (i = 0; i < n_ssids; i++) {
1232-
memset(&ssid_le, 0, sizeof(ssid_le));
1233-
ssid_le.SSID_len =
1234-
cpu_to_le32(request->ssids[i].ssid_len);
1235-
memcpy(ssid_le.SSID, request->ssids[i].ssid,
1236-
request->ssids[i].ssid_len);
1237-
if (!ssid_le.SSID_len)
1238-
brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
1239-
else
1240-
brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",
1241-
i, ssid_le.SSID, ssid_le.SSID_len);
1242-
memcpy(ptr, &ssid_le, sizeof(ssid_le));
1243-
ptr += sizeof(ssid_le);
1244-
}
1245-
} else {
1246-
brcmf_dbg(SCAN, "Performing passive scan\n");
1247-
scan_type = BRCMF_SCANTYPE_PASSIVE;
1248-
}
1249-
scan_type |= brcmf_nl80211_scan_flags_to_scan_flags(request->flags);
1250-
params_le->scan_type = cpu_to_le32(scan_type);
1251-
params_le->length = cpu_to_le16(length);
12521106

1253-
/* Include RNR results if requested */
1254-
if (request->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) {
1255-
params_le->ssid_type |= BRCMF_SCANSSID_INC_RNR;
1256-
}
1257-
1258-
/* Adding mask to channel numbers */
1259-
params_le->channel_num =
1260-
cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
1261-
(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
1262-
}
12631107

12641108
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12651109
struct brcmf_if *ifp, bool aborted,
12661110
bool fw_abort)
12671111
{
12681112
struct brcmf_pub *drvr = cfg->pub;
1269-
struct brcmf_scan_params_v2_le params_v2_le;
12701113
struct cfg80211_scan_request *scan_request;
12711114
u64 reqid;
12721115
u32 bucket;
@@ -1282,25 +1125,16 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12821125
timer_delete_sync(&cfg->escan_timeout);
12831126

12841127
if (fw_abort) {
1128+
u32 len;
1129+
void *data = drvr->scan_param_handler.get_prepped_struct(cfg, &len, NULL);
1130+
if (!data){
1131+
bphy_err(drvr, "Scan abort failed to prepare abort struct\n");
1132+
return 0;
1133+
}
12851134
/* Do a scan abort to stop the driver's scan engine */
12861135
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
1287-
1288-
brcmf_escan_prep(cfg, ifp, &params_v2_le, NULL);
1289-
1290-
/* E-Scan (or anyother type) can be aborted by SCAN */
1291-
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
1292-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
1293-
&params_v2_le,
1294-
sizeof(params_v2_le));
1295-
} else {
1296-
struct brcmf_scan_params_le params_le;
1297-
1298-
brcmf_scan_params_v2_to_v1(&params_v2_le, &params_le);
1299-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
1300-
&params_le,
1301-
sizeof(params_le));
1302-
}
1303-
1136+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, data, len);
1137+
kfree(data);
13041138
if (err)
13051139
bphy_err(drvr, "Scan abort failed\n");
13061140
}
@@ -1524,49 +1358,39 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15241358
struct cfg80211_scan_request *request)
15251359
{
15261360
struct brcmf_pub *drvr = cfg->pub;
1527-
s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
1528-
offsetof(struct brcmf_escan_params_le, params_v2_le);
1361+
u32 struct_size = 0;
1362+
void *prepped_params = NULL;
1363+
u32 params_size = 0;
15291364
struct brcmf_escan_params_le *params;
15301365
s32 err = 0;
15311366

15321367
brcmf_dbg(SCAN, "E-SCAN START\n");
15331368

1534-
if (request != NULL) {
1535-
/* Allocate space for populating ssids in struct */
1536-
params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
1537-
1538-
/* Allocate space for populating ssids in struct */
1539-
params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;
1369+
prepped_params = drvr->scan_param_handler.get_prepped_struct(cfg, &struct_size, request);
1370+
if (!prepped_params) {
1371+
err = -EINVAL;
1372+
goto exit;
1373+
}
1374+
params_size = struct_size +
1375+
offsetof(struct brcmf_escan_params_le, params_v4_le);
1376+
if (!params_size) {
1377+
err = -EINVAL;
1378+
goto exit;
15401379
}
15411380

15421381
params = kzalloc(params_size, GFP_KERNEL);
15431382
if (!params) {
15441383
err = -ENOMEM;
15451384
goto exit;
15461385
}
1547-
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
1548-
brcmf_escan_prep(cfg, ifp, &params->params_v2_le, request);
1549-
1550-
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V3)) {
1551-
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V3);
1552-
} else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
1553-
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2);
1554-
} else {
1555-
struct brcmf_escan_params_le *params_v1;
1556-
1557-
params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
1558-
params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
1559-
params_v1 = kzalloc(params_size, GFP_KERNEL);
1560-
if (!params_v1) {
1561-
err = -ENOMEM;
1562-
goto exit_params;
1563-
}
1564-
params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
1565-
brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
1566-
kfree(params);
1567-
params = params_v1;
1568-
}
1386+
/* Copy into the largest part */
1387+
unsafe_memcpy(
1388+
&params->params_v4_le, prepped_params, struct_size,
1389+
/* A composite flex-array that is at least as large as the memcpy due to the allocation above */);
15691390

1391+
/* We can now free the original prepped parameters */
1392+
kfree(prepped_params);
1393+
params->version = cpu_to_le32(drvr->scan_param_handler.version);
15701394
params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
15711395
params->sync_id = cpu_to_le16(0x1234);
15721396

@@ -1578,7 +1402,6 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15781402
bphy_err(drvr, "error (%d)\n", err);
15791403
}
15801404

1581-
exit_params:
15821405
kfree(params);
15831406
exit:
15841407
return err;

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct brcmf_rev_info {
9898
};
9999

100100
struct brcmf_pno_info;
101+
enum nl80211_band;
101102
/**
102103
* struct pno_struct_handler
103104
*/
@@ -114,6 +115,13 @@ struct pno_struct_handler {
114115
u8 (*ssid)[IEEE80211_MAX_SSID_LEN], u8 *ssid_len,
115116
u8 *channel, enum nl80211_band *band);
116117
};
118+
struct cfg80211_scan_request;
119+
struct scan_param_struct_handler {
120+
u8 version;
121+
void *(*get_prepped_struct)(struct brcmf_cfg80211_info *cfg,
122+
u32 *struct_size,
123+
struct cfg80211_scan_request *request);
124+
};
117125

118126
/* Common structure for module and instance linkage */
119127
struct brcmf_pub {
@@ -165,6 +173,7 @@ struct brcmf_pub {
165173
void *vdata;
166174
u16 cnt_ver;
167175
struct pno_struct_handler pno_handler;
176+
struct scan_param_struct_handler scan_param_handler;
168177
};
169178

170179
/* forward declarations */

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

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "feature.h"
1818
#include "common.h"
1919
#include "pno.h"
20+
#include "scan_param.h"
2021

2122
#define BRCMF_FW_UNSUPPORTED 23
2223

@@ -290,7 +291,7 @@ static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data)
290291
void brcmf_feat_attach(struct brcmf_pub *drvr)
291292
{
292293
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
293-
struct brcmf_wl_scan_version_le scan_ver;
294+
struct brcmf_scan_version_le scan_ver;
294295
struct brcmf_pno_param_v3_le pno_params;
295296
struct brcmf_pno_macaddr_le pfn_mac;
296297
struct brcmf_gscan_config gscan_cfg;
@@ -346,16 +347,11 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
346347

347348
err = brcmf_fil_iovar_data_get(ifp, "scan_ver", &scan_ver, sizeof(scan_ver));
348349
if (!err) {
349-
int ver = le16_to_cpu(scan_ver.scan_ver_major);
350-
351-
if (ver == 2) {
352-
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_V2);
353-
} else if (ver == 3) {
354-
/* We consider SCAN_V3 a subtype of SCAN_V2 since the
355-
* structure is essentially the same.
356-
*/
357-
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_V2) | BIT(BRCMF_FEAT_SCAN_V3);
358-
}
350+
u16 ver = le16_to_cpu(scan_ver.scan_ver_major);
351+
brcmf_scan_param_setup_for_version(drvr, ver);
352+
} else {
353+
/* Default tp version 1. */
354+
brcmf_scan_param_setup_for_version(drvr, 1);
359355
}
360356

361357
/* See what version of PFN scan is supported*/

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
* SAE: simultaneous authentication of equals
3131
* FWAUTH: Firmware authenticator
3232
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
33-
* SCAN_V2: Version 2 scan params
34-
* SCAN_v3: Version 3 scan params
3533
* PMKID_V2: Version 2 PMKID
3634
* PMKID_V3: Version 3 PMKID
3735
* EVENT_MSGS_EXT: Event messages extension
@@ -61,8 +59,6 @@
6159
BRCMF_FEAT_DEF(SAE) \
6260
BRCMF_FEAT_DEF(FWAUTH) \
6361
BRCMF_FEAT_DEF(DUMP_OBSS) \
64-
BRCMF_FEAT_DEF(SCAN_V2) \
65-
BRCMF_FEAT_DEF(SCAN_V3) \
6662
BRCMF_FEAT_DEF(PMKID_V2) \
6763
BRCMF_FEAT_DEF(PMKID_V3) \
6864
BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \

0 commit comments

Comments
 (0)