Skip to content

Commit e7bdb5a

Browse files
committed
wifi: brcmfmac: Support join_params_v1
The new assoc params structure is the same as the old, except for a field which materialized where a padding byte was (which is compatible), and extra version and flags field at the top. To ease supporting both versions, implement this by embedding the old structure into the new one. Then the code that actually uses these structures can directly copy around the inner v0 subset, or pass around pointers, to avoid excess code duplication. Drive-by fix: Always count the assoc_params length even if no bssid is provided. It doesn't make sense to truncate it off, since we need to set the bssid to the broadcast addr anyway in that case. Signed-off-by: Hector Martin <[email protected]>
1 parent 9faff37 commit e7bdb5a

4 files changed

Lines changed: 113 additions & 40 deletions

File tree

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

Lines changed: 85 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@
101101
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
102102
(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
103103

104+
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE_V1 \
105+
(sizeof(struct brcmf_assoc_params_v1_le) - sizeof(u16))
106+
104107
#define BRCMF_MAX_CHANSPEC_LIST \
105108
(BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1)
106109

@@ -1781,7 +1784,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
17811784
struct brcmf_if *ifp = netdev_priv(ndev);
17821785
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
17831786
struct brcmf_pub *drvr = cfg->pub;
1784-
struct brcmf_join_params join_params;
1787+
struct brcmf_join_params_v1 join_params;
17851788
size_t join_params_size = 0;
17861789
s32 err = 0;
17871790
s32 wsec = 0;
@@ -1868,15 +1871,14 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
18681871
ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);
18691872
memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);
18701873
join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
1871-
join_params_size = sizeof(join_params.ssid_le);
1874+
join_params_size = sizeof(join_params.ssid_le) + BRCMF_ASSOC_PARAMS_FIXED_SIZE_V1;
18721875

18731876
/* BSSID */
18741877
if (params->bssid) {
1875-
memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1876-
join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1878+
memcpy(join_params.params_le.v0.bssid, params->bssid, ETH_ALEN);
18771879
memcpy(profile->bssid, params->bssid, ETH_ALEN);
18781880
} else {
1879-
eth_broadcast_addr(join_params.params_le.bssid);
1881+
eth_broadcast_addr(join_params.params_le.v0.bssid);
18801882
eth_zero_addr(profile->bssid);
18811883
}
18821884

@@ -1891,10 +1893,10 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
18911893
/* adding chanspec */
18921894
chanspec = chandef_to_chanspec(&cfg->d11inf,
18931895
&params->chandef);
1894-
join_params.params_le.chanspec_list[0] =
1896+
join_params.params_le.v0.chanspec_list[0] =
18951897
cpu_to_le16(chanspec);
1896-
join_params.params_le.chanspec_num = cpu_to_le32(1);
1897-
join_params_size += sizeof(join_params.params_le);
1898+
join_params.params_le.v0.chanspec_num = cpu_to_le32(1);
1899+
join_params_size += sizeof(u16);
18981900
}
18991901

19001902
/* set channel for starter */
@@ -1910,9 +1912,19 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
19101912

19111913
cfg->ibss_starter = false;
19121914

1913-
1914-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1915-
&join_params, join_params_size);
1915+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_JOIN_V1)) {
1916+
struct brcmf_join_params join_params_v0 = {
1917+
.ssid_le = join_params.ssid_le,
1918+
.params_le = join_params.params_le.v0,
1919+
};
1920+
join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1921+
join_params_size -= BRCMF_ASSOC_PARAMS_FIXED_SIZE_V1;
1922+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1923+
&join_params_v0, join_params_size);
1924+
} else {
1925+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1926+
&join_params, join_params_size);
1927+
}
19161928
if (err) {
19171929
bphy_err(drvr, "WLC_SET_SSID failed (%d)\n", err);
19181930
goto done;
@@ -2373,13 +2385,16 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
23732385
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
23742386
struct ieee80211_channel *chan = sme->channel;
23752387
struct brcmf_pub *drvr = ifp->drvr;
2376-
struct brcmf_join_params join_params;
2388+
struct brcmf_join_params_v1 join_params;
2389+
struct brcmf_ssid_le *ssid_le;
2390+
struct brcmf_join_scan_params_le *scan_le;
2391+
struct brcmf_assoc_params_le *assoc_v0;
23772392
size_t join_params_size;
23782393
const struct brcmf_tlv *rsn_ie;
23792394
const struct brcmf_vs_tlv *wpa_ie;
23802395
const void *ie;
23812396
u32 ie_len;
2382-
struct brcmf_ext_join_params_le *ext_join_params;
2397+
void *ext_join_params;
23832398
u16 chanspec;
23842399
s32 err = 0;
23852400
u32 ssid_len;
@@ -2515,55 +2530,74 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
25152530
/* Join with specific BSSID and cached SSID
25162531
* If SSID is zero join based on BSSID only
25172532
*/
2518-
join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) +
2533+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_JOIN_V1)) {
2534+
struct brcmf_ext_join_params_v1_le *ext_v1;
2535+
2536+
join_params_size = offsetof(struct brcmf_ext_join_params_v1_le, assoc_le) +
2537+
offsetof(struct brcmf_assoc_params_v1_le, v0.chanspec_list);
2538+
ext_v1 = kzalloc(sizeof(*ext_v1), GFP_KERNEL);
2539+
ssid_le = &ext_v1->ssid_le;
2540+
scan_le = &ext_v1->scan_le;
2541+
assoc_v0 = &ext_v1->assoc_le.v0;
2542+
ext_join_params = ext_v1;
2543+
} else {
2544+
struct brcmf_ext_join_params_le *ext_v0;
2545+
2546+
join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) +
25192547
offsetof(struct brcmf_assoc_params_le, chanspec_list);
2520-
if (cfg->channel)
2521-
join_params_size += sizeof(u16);
2522-
ext_join_params = kzalloc(sizeof(*ext_join_params), GFP_KERNEL);
2548+
ext_v0 = kzalloc(sizeof(*ext_v0), GFP_KERNEL);
2549+
ssid_le = &ext_v0->ssid_le;
2550+
scan_le = &ext_v0->scan_le;
2551+
assoc_v0 = &ext_v0->assoc_le;
2552+
ext_join_params = ext_v0;
2553+
}
25232554
if (ext_join_params == NULL) {
25242555
err = -ENOMEM;
25252556
goto done;
25262557
}
2558+
2559+
if (cfg->channel)
2560+
join_params_size += sizeof(u16);
25272561
ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);
2528-
ext_join_params->ssid_le.SSID_len = cpu_to_le32(ssid_len);
2529-
memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ssid_len);
2562+
ssid_le->SSID_len = cpu_to_le32(ssid_len);
2563+
memcpy(&ssid_le->SSID, sme->ssid, ssid_len);
25302564
if (ssid_len < IEEE80211_MAX_SSID_LEN)
25312565
brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n",
2532-
ext_join_params->ssid_le.SSID, ssid_len);
2566+
ssid_le->SSID, ssid_len);
25332567

25342568
/* Set up join scan parameters */
2535-
ext_join_params->scan_le.scan_type = -1;
2536-
ext_join_params->scan_le.home_time = cpu_to_le32(-1);
2569+
scan_le->scan_type = -1;
2570+
scan_le->home_time = cpu_to_le32(-1);
25372571

25382572
if (sme->bssid)
2539-
memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN);
2573+
memcpy(&assoc_v0->bssid, sme->bssid, ETH_ALEN);
25402574
else
2541-
eth_broadcast_addr(ext_join_params->assoc_le.bssid);
2575+
eth_broadcast_addr(assoc_v0->bssid);
25422576

25432577
if (cfg->channel) {
2544-
ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1);
2578+
assoc_v0->chanspec_num = cpu_to_le32(1);
25452579

2546-
ext_join_params->assoc_le.chanspec_list[0] =
2580+
assoc_v0->chanspec_list[0] =
25472581
cpu_to_le16(chanspec);
25482582
/* Increase dwell time to receive probe response or detect
25492583
* beacon from target AP at a noisy air only during connect
25502584
* command.
25512585
*/
2552-
ext_join_params->scan_le.active_time =
2586+
scan_le->active_time =
25532587
cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);
2554-
ext_join_params->scan_le.passive_time =
2588+
scan_le->passive_time =
25552589
cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);
25562590
/* To sync with presence period of VSDB GO send probe request
25572591
* more frequently. Probe request will be stopped when it gets
25582592
* probe response from target AP/GO.
25592593
*/
2560-
ext_join_params->scan_le.nprobes =
2594+
scan_le->nprobes =
25612595
cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /
25622596
BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);
25632597
} else {
2564-
ext_join_params->scan_le.active_time = cpu_to_le32(-1);
2565-
ext_join_params->scan_le.passive_time = cpu_to_le32(-1);
2566-
ext_join_params->scan_le.nprobes = cpu_to_le32(-1);
2598+
scan_le->active_time = cpu_to_le32(-1);
2599+
scan_le->passive_time = cpu_to_le32(-1);
2600+
scan_le->nprobes = cpu_to_le32(-1);
25672601
}
25682602

25692603
brcmf_set_join_pref(ifp, &sme->bss_select);
@@ -2577,23 +2611,34 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
25772611

25782612
/* join command failed, fallback to set ssid */
25792613
memset(&join_params, 0, sizeof(join_params));
2580-
join_params_size = sizeof(join_params.ssid_le);
2614+
join_params_size = sizeof(join_params.ssid_le) + BRCMF_ASSOC_PARAMS_FIXED_SIZE_V1;
25812615

25822616
memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);
25832617
join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
25842618

25852619
if (sme->bssid)
2586-
memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
2620+
memcpy(join_params.params_le.v0.bssid, sme->bssid, ETH_ALEN);
25872621
else
2588-
eth_broadcast_addr(join_params.params_le.bssid);
2622+
eth_broadcast_addr(join_params.params_le.v0.bssid);
25892623

25902624
if (cfg->channel) {
2591-
join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec);
2592-
join_params.params_le.chanspec_num = cpu_to_le32(1);
2593-
join_params_size += sizeof(join_params.params_le);
2625+
join_params.params_le.v0.chanspec_list[0] = cpu_to_le16(chanspec);
2626+
join_params.params_le.v0.chanspec_num = cpu_to_le32(1);
2627+
join_params_size += sizeof(u16);
2628+
}
2629+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_JOIN_V1)) {
2630+
struct brcmf_join_params join_params_v0 = {
2631+
.ssid_le = join_params.ssid_le,
2632+
.params_le = join_params.params_le.v0,
2633+
};
2634+
join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
2635+
join_params_size -= BRCMF_ASSOC_PARAMS_FIXED_SIZE_V1;
2636+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
2637+
&join_params_v0, join_params_size);
2638+
} else {
2639+
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
2640+
&join_params, join_params_size);
25942641
}
2595-
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
2596-
&join_params, join_params_size);
25972642
if (err)
25982643
bphy_err(drvr, "BRCMF_C_SET_SSID failed (%d)\n", err);
25992644

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct brcmf_feat_wlcfeat {
135135
static const struct brcmf_feat_wlcfeat brcmf_feat_wlcfeat_map[] = {
136136
{ 12, 0, BIT(BRCMF_FEAT_PMKID_V2) },
137137
{ 13, 0, BIT(BRCMF_FEAT_PMKID_V3) },
138+
{ 17, 0, BIT(BRCMF_FEAT_JOIN_V1) },
138139
};
139140

140141
static void brcmf_feat_wlc_version_overrides(struct brcmf_pub *drv)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
BRCMF_FEAT_DEF(PMKID_V2) \
6161
BRCMF_FEAT_DEF(PMKID_V3) \
6262
BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \
63+
BRCMF_FEAT_DEF(JOIN_V1)
6364

6465
/*
6566
* Quirks:

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,27 @@ struct brcmf_escan_result_le {
508508
struct brcmf_assoc_params_le {
509509
/* 00:00:00:00:00:00: broadcast scan */
510510
u8 bssid[ETH_ALEN];
511+
/* 0: use chanspec_num, and the single bssid,
512+
* otherwise count of chanspecs in chanspec_list
513+
* AND paired bssids following chanspec_list
514+
* also, chanspec_num has to be set to zero
515+
* for bssid list to be used
516+
*/
517+
__le16 bssid_cnt;
511518
/* 0: all available channels, otherwise count of chanspecs in
512519
* chanspec_list */
513520
__le32 chanspec_num;
514521
/* list of chanspecs */
515522
__le16 chanspec_list[1];
516523
};
517524

525+
struct brcmf_assoc_params_v1_le {
526+
__le16 version;
527+
__le16 flags;
528+
/* Embed the old structure to ease supporting both */
529+
struct brcmf_assoc_params_le v0;
530+
};
531+
518532
/**
519533
* struct join_pref params - parameters for preferred join selection.
520534
*
@@ -537,6 +551,11 @@ struct brcmf_join_params {
537551
struct brcmf_assoc_params_le params_le;
538552
};
539553

554+
struct brcmf_join_params_v1 {
555+
struct brcmf_ssid_le ssid_le;
556+
struct brcmf_assoc_params_v1_le params_le;
557+
};
558+
540559
/* scan params for extended join */
541560
struct brcmf_join_scan_params_le {
542561
u8 scan_type; /* 0 use default, active or passive scan */
@@ -559,6 +578,13 @@ struct brcmf_ext_join_params_le {
559578
struct brcmf_assoc_params_le assoc_le;
560579
};
561580

581+
/* extended join params */
582+
struct brcmf_ext_join_params_v1_le {
583+
struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */
584+
struct brcmf_join_scan_params_le scan_le;
585+
struct brcmf_assoc_params_v1_le assoc_le;
586+
};
587+
562588
struct brcmf_wsec_key {
563589
u32 index; /* key index */
564590
u32 len; /* key length */

0 commit comments

Comments
 (0)