Skip to content

Commit 6c9ed31

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 a2b6bfe commit 6c9ed31

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

@@ -3161,6 +3162,70 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
31613162
return 0;
31623163
}
31633164

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

31823249
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
31833250
if (!check_vif_up(ifp->vif))
@@ -3201,7 +3268,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32013268
goto done;
32023269
}
32033270
}
3204-
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
3271+
info_len = le16_to_cpu(sta_info_le.len);
3272+
struct_ver = le16_to_cpu(sta_info_le.ver);
3273+
brcmf_dbg(TRACE, "version %d\n", struct_ver);
32053274
sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
32063275
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
32073276
sta_flags = le32_to_cpu(sta_info_le.flags);
@@ -3235,12 +3304,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32353304
sinfo->rxrate.legacy =
32363305
le32_to_cpu(sta_info_le.rx_rate) / 100;
32373306
}
3238-
if (le16_to_cpu(sta_info_le.ver) >= 4) {
3307+
if (struct_ver >= 4) {
32393308
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
32403309
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
32413310
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
32423311
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
32433312
}
3313+
32443314
for (i = 0; i < BRCMF_ANT_MAX; i++) {
32453315
if (sta_info_le.rssi[i] == 0 ||
32463316
sta_info_le.rx_lastpkt_rssi[i] == 0)
@@ -3279,6 +3349,25 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32793349
}
32803350
}
32813351
}
3352+
/* Some version 7 structs have ratespecs from the last packet. */
3353+
if (struct_ver >= 7) {
3354+
if (info_len >= sizeof(sta_info_le)) {
3355+
brcmf_convert_ratespec_to_rateinfo(
3356+
le32_to_cpu(sta_info_le.v7.tx_rspec),
3357+
&sinfo->txrate);
3358+
brcmf_convert_ratespec_to_rateinfo(
3359+
le32_to_cpu(sta_info_le.v7.rx_rspec),
3360+
&sinfo->rxrate);
3361+
} else {
3362+
/* We didn't get the fields we were expecting, fallback to nrate */
3363+
u32 nrate = 0;
3364+
err = brcmf_fil_iovar_int_get(ifp, "nrate", &nrate);
3365+
if (!err) {
3366+
brcmf_convert_ratespec_to_rateinfo(
3367+
nrate, &sinfo->txrate);
3368+
}
3369+
}
3370+
}
32823371
done:
32833372
brcmf_dbg(TRACE, "Exit\n");
32843373
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)