Skip to content

Commit a439909

Browse files
dberlinjannau
authored andcommitted
[brcmfmac] Add support for more rate info in station dumps
We try to retrieve a newer sta_info structure that has both rx and tx ratespecs, but if we don't get the structure we are expecting we fall back to tx rate info only. Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1 parent 3459b70 commit a439909

3 files changed

Lines changed: 355 additions & 2 deletions

File tree

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

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "feature.h"
3636
#include "fwvid.h"
3737
#include "xtlv.h"
38+
#include "ratespec.h"
3839

3940
#define BRCMF_SCAN_IE_LEN_MAX 2048
4041

@@ -3168,6 +3169,70 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
31683169
return 0;
31693170
}
31703171

3172+
static void brcmf_convert_ratespec_to_rateinfo(u32 ratespec,
3173+
struct rate_info *rateinfo)
3174+
{
3175+
/* First extract the bandwidth info */
3176+
switch (ratespec & BRCMF_RSPEC_BW_MASK) {
3177+
case BRCMF_RSPEC_BW_20MHZ:
3178+
rateinfo->bw = RATE_INFO_BW_20;
3179+
break;
3180+
case BRCMF_RSPEC_BW_40MHZ:
3181+
rateinfo->bw = RATE_INFO_BW_40;
3182+
break;
3183+
case BRCMF_RSPEC_BW_80MHZ:
3184+
rateinfo->bw = RATE_INFO_BW_80;
3185+
break;
3186+
case BRCMF_RSPEC_BW_160MHZ:
3187+
rateinfo->bw = RATE_INFO_BW_160;
3188+
break;
3189+
case BRCMF_RSPEC_BW_320MHZ:
3190+
rateinfo->bw = RATE_INFO_BW_320;
3191+
break;
3192+
default:
3193+
/* Fill in nothing */
3194+
break;
3195+
}
3196+
if (BRCMF_RSPEC_ISHT(ratespec)) {
3197+
rateinfo->flags |= RATE_INFO_FLAGS_MCS;
3198+
rateinfo->mcs = ratespec & BRCMF_RSPEC_HT_MCS_MASK;
3199+
} else if (BRCMF_RSPEC_ISVHT(ratespec)) {
3200+
rateinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
3201+
rateinfo->mcs = ratespec & BRCMF_RSPEC_VHT_MCS_MASK;
3202+
rateinfo->nss = (ratespec & BRCMF_RSPEC_VHT_NSS_MASK) >>
3203+
BRCMF_RSPEC_VHT_NSS_SHIFT;
3204+
} else if (BRCMF_RSPEC_ISHE(ratespec)) {
3205+
u32 ltf_gi = BRCMF_RSPEC_HE_LTF_GI(ratespec);
3206+
3207+
rateinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
3208+
rateinfo->mcs = ratespec & BRCMF_RSPEC_HE_MCS_MASK;
3209+
rateinfo->nss = (ratespec & BRCMF_RSPEC_HE_NSS_MASK) >>
3210+
BRCMF_RSPEC_HE_NSS_SHIFT;
3211+
rateinfo->he_dcm = BRCMF_RSPEC_HE_DCM(ratespec);
3212+
if (HE_IS_GI_0_8us(ltf_gi)) {
3213+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
3214+
} else if (HE_IS_GI_1_6us(ltf_gi)) {
3215+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
3216+
} else if (HE_IS_GI_3_2us(ltf_gi)) {
3217+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
3218+
}
3219+
} else if (BRCMF_RSPEC_ISEHT(ratespec)) {
3220+
u32 ltf_gi = BRCMF_RSPEC_EHT_LTF_GI(ratespec);
3221+
3222+
rateinfo->flags |= RATE_INFO_FLAGS_EHT_MCS;
3223+
rateinfo->mcs = ratespec & BRCMF_RSPEC_EHT_MCS_MASK;
3224+
rateinfo->nss = (ratespec & BRCMF_RSPEC_EHT_NSS_MASK) >>
3225+
BRCMF_RSPEC_EHT_NSS_SHIFT;
3226+
if (EHT_IS_GI_0_8us(ltf_gi)) {
3227+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_0_8;
3228+
} else if (EHT_IS_GI_1_6us(ltf_gi)) {
3229+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_1_6;
3230+
} else if (EHT_IS_GI_3_2us(ltf_gi)) {
3231+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_3_2;
3232+
}
3233+
}
3234+
}
3235+
31713236
static s32
31723237
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
31733238
const u8 *mac, struct station_info *sinfo)
@@ -3185,6 +3250,8 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
31853250
s32 count_rssi = 0;
31863251
int rssi;
31873252
u32 i;
3253+
u16 struct_ver;
3254+
u16 info_len;
31883255

31893256
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
31903257
if (!check_vif_up(ifp->vif))
@@ -3208,7 +3275,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32083275
goto done;
32093276
}
32103277
}
3211-
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
3278+
info_len = le16_to_cpu(sta_info_le.len);
3279+
struct_ver = le16_to_cpu(sta_info_le.ver);
3280+
brcmf_dbg(TRACE, "version %d\n", struct_ver);
32123281
sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
32133282
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
32143283
sta_flags = le32_to_cpu(sta_info_le.flags);
@@ -3242,12 +3311,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32423311
sinfo->rxrate.legacy =
32433312
le32_to_cpu(sta_info_le.rx_rate) / 100;
32443313
}
3245-
if (le16_to_cpu(sta_info_le.ver) >= 4) {
3314+
if (struct_ver >= 4) {
32463315
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
32473316
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
32483317
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
32493318
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
32503319
}
3320+
32513321
for (i = 0; i < BRCMF_ANT_MAX; i++) {
32523322
if (sta_info_le.rssi[i] == 0 ||
32533323
sta_info_le.rx_lastpkt_rssi[i] == 0)
@@ -3286,6 +3356,25 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32863356
}
32873357
}
32883358
}
3359+
/* Some version 7 structs have ratespecs from the last packet. */
3360+
if (struct_ver >= 7) {
3361+
if (info_len >= sizeof(sta_info_le)) {
3362+
brcmf_convert_ratespec_to_rateinfo(
3363+
le32_to_cpu(sta_info_le.v7.tx_rspec),
3364+
&sinfo->txrate);
3365+
brcmf_convert_ratespec_to_rateinfo(
3366+
le32_to_cpu(sta_info_le.v7.rx_rspec),
3367+
&sinfo->rxrate);
3368+
} else {
3369+
/* We didn't get the fields we were expecting, fallback to nrate */
3370+
u32 nrate = 0;
3371+
err = brcmf_fil_iovar_int_get(ifp, "nrate", &nrate);
3372+
if (!err) {
3373+
brcmf_convert_ratespec_to_rateinfo(
3374+
nrate, &sinfo->txrate);
3375+
}
3376+
}
3377+
}
32893378
done:
32903379
brcmf_dbg(TRACE, "Exit\n");
32913380
return err;

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,17 @@ struct brcmf_channel_info_le {
824824
__le32 scan_channel;
825825
};
826826

827+
#define BRCMF_MAX_ASSOC_OUI_NUM 6
828+
#define BRCMF_ASSOC_OUI_LEN 3
827829
struct brcmf_sta_info_le {
828830
__le16 ver; /* version of this struct */
829831
__le16 len; /* length in bytes of this structure */
830832
__le16 cap; /* sta's advertised capabilities */
833+
u16 PAD;
831834
__le32 flags; /* flags defined below */
832835
__le32 idle; /* time since data pkt rx'd from sta */
833836
u8 ea[ETH_ALEN]; /* Station address */
837+
u16 PAD2;
834838
__le32 count; /* # rates in this set */
835839
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
836840
/* w/hi bit set if basic */
@@ -862,6 +866,7 @@ struct brcmf_sta_info_le {
862866
__le16 aid; /* association ID */
863867
__le16 ht_capabilities; /* advertised ht caps */
864868
__le16 vht_flags; /* converted vht flags */
869+
u16 PAD3;
865870
__le32 tx_pkts_retry_cnt; /* # of frames where a retry was
866871
* exhausted.
867872
*/
@@ -914,6 +919,13 @@ struct brcmf_sta_info_le {
914919
__le32 tx_rspec; /* Rate of last successful tx frame */
915920
__le32 rx_rspec; /* Rate of last successful rx frame */
916921
__le32 wnm_cap; /* wnm capabilities */
922+
__le16 he_flags; /* converted he flags */
923+
u16 PAD;
924+
struct {
925+
u8 count;
926+
u8 oui[BRCMF_MAX_ASSOC_OUI_NUM][BRCMF_ASSOC_OUI_LEN];
927+
} vendor_oui;
928+
u8 link_bw;
917929
} v7;
918930
};
919931
};

0 commit comments

Comments
 (0)