Skip to content

Commit 1efbe18

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

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
@@ -1099,170 +1099,13 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
10991099
}
11001100
}
11011101

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

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

12601104
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12611105
struct brcmf_if *ifp, bool aborted,
12621106
bool fw_abort)
12631107
{
12641108
struct brcmf_pub *drvr = cfg->pub;
1265-
struct brcmf_scan_params_v2_le params_v2_le;
12661109
struct cfg80211_scan_request *scan_request;
12671110
u64 reqid;
12681111
u32 bucket;
@@ -1278,25 +1121,16 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12781121
timer_delete_sync(&cfg->escan_timeout);
12791122

12801123
if (fw_abort) {
1124+
u32 len;
1125+
void *data = drvr->scan_param_handler.get_prepped_struct(cfg, &len, NULL);
1126+
if (!data){
1127+
bphy_err(drvr, "Scan abort failed to prepare abort struct\n");
1128+
return 0;
1129+
}
12811130
/* Do a scan abort to stop the driver's scan engine */
12821131
brcmf_dbg(SCAN, "ABORT scan in firmware\n");
1283-
1284-
brcmf_escan_prep(cfg, ifp, &params_v2_le, NULL);
1285-
1286-
/* E-Scan (or anyother type) can be aborted by SCAN */
1287-
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
1288-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
1289-
&params_v2_le,
1290-
sizeof(params_v2_le));
1291-
} else {
1292-
struct brcmf_scan_params_le params_le;
1293-
1294-
brcmf_scan_params_v2_to_v1(&params_v2_le, &params_le);
1295-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
1296-
&params_le,
1297-
sizeof(params_le));
1298-
}
1299-
1132+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, data, len);
1133+
kfree(data);
13001134
if (err)
13011135
bphy_err(drvr, "Scan abort failed\n");
13021136
}
@@ -1520,49 +1354,39 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15201354
struct cfg80211_scan_request *request)
15211355
{
15221356
struct brcmf_pub *drvr = cfg->pub;
1523-
s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
1524-
offsetof(struct brcmf_escan_params_le, params_v2_le);
1357+
u32 struct_size = 0;
1358+
void *prepped_params = NULL;
1359+
u32 params_size = 0;
15251360
struct brcmf_escan_params_le *params;
15261361
s32 err = 0;
15271362

15281363
brcmf_dbg(SCAN, "E-SCAN START\n");
15291364

1530-
if (request != NULL) {
1531-
/* Allocate space for populating ssids in struct */
1532-
params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
1533-
1534-
/* Allocate space for populating ssids in struct */
1535-
params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;
1365+
prepped_params = drvr->scan_param_handler.get_prepped_struct(cfg, &struct_size, request);
1366+
if (!prepped_params) {
1367+
err = -EINVAL;
1368+
goto exit;
1369+
}
1370+
params_size = struct_size +
1371+
offsetof(struct brcmf_escan_params_le, params_v4_le);
1372+
if (!params_size) {
1373+
err = -EINVAL;
1374+
goto exit;
15361375
}
15371376

15381377
params = kzalloc(params_size, GFP_KERNEL);
15391378
if (!params) {
15401379
err = -ENOMEM;
15411380
goto exit;
15421381
}
1543-
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
1544-
brcmf_escan_prep(cfg, ifp, &params->params_v2_le, request);
1545-
1546-
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V3)) {
1547-
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V3);
1548-
} else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {
1549-
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2);
1550-
} else {
1551-
struct brcmf_escan_params_le *params_v1;
1552-
1553-
params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
1554-
params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
1555-
params_v1 = kzalloc(params_size, GFP_KERNEL);
1556-
if (!params_v1) {
1557-
err = -ENOMEM;
1558-
goto exit_params;
1559-
}
1560-
params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
1561-
brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
1562-
kfree(params);
1563-
params = params_v1;
1564-
}
1382+
/* Copy into the largest part */
1383+
unsafe_memcpy(
1384+
&params->params_v4_le, prepped_params, struct_size,
1385+
/* A composite flex-array that is at least as large as the memcpy due to the allocation above */);
15651386

1387+
/* We can now free the original prepped parameters */
1388+
kfree(prepped_params);
1389+
params->version = cpu_to_le32(drvr->scan_param_handler.version);
15661390
params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
15671391
params->sync_id = cpu_to_le16(0x1234);
15681392

@@ -1574,7 +1398,6 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15741398
bphy_err(drvr, "error (%d)\n", err);
15751399
}
15761400

1577-
exit_params:
15781401
kfree(params);
15791402
exit:
15801403
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)