Skip to content

Commit 78b96c0

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 0ae6f22 commit 78b96c0

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

@@ -3166,6 +3167,70 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
31663167
return 0;
31673168
}
31683169

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

31873254
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
31883255
if (!check_vif_up(ifp->vif))
@@ -3206,7 +3273,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32063273
goto done;
32073274
}
32083275
}
3209-
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
3276+
info_len = le16_to_cpu(sta_info_le.len);
3277+
struct_ver = le16_to_cpu(sta_info_le.ver);
3278+
brcmf_dbg(TRACE, "version %d\n", struct_ver);
32103279
sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
32113280
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
32123281
sta_flags = le32_to_cpu(sta_info_le.flags);
@@ -3240,12 +3309,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32403309
sinfo->rxrate.legacy =
32413310
le32_to_cpu(sta_info_le.rx_rate) / 100;
32423311
}
3243-
if (le16_to_cpu(sta_info_le.ver) >= 4) {
3312+
if (struct_ver >= 4) {
32443313
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
32453314
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
32463315
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
32473316
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
32483317
}
3318+
32493319
for (i = 0; i < BRCMF_ANT_MAX; i++) {
32503320
if (sta_info_le.rssi[i] == 0 ||
32513321
sta_info_le.rx_lastpkt_rssi[i] == 0)
@@ -3284,6 +3354,25 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32843354
}
32853355
}
32863356
}
3357+
/* Some version 7 structs have ratespecs from the last packet. */
3358+
if (struct_ver >= 7) {
3359+
if (info_len >= sizeof(sta_info_le)) {
3360+
brcmf_convert_ratespec_to_rateinfo(
3361+
le32_to_cpu(sta_info_le.v7.tx_rspec),
3362+
&sinfo->txrate);
3363+
brcmf_convert_ratespec_to_rateinfo(
3364+
le32_to_cpu(sta_info_le.v7.rx_rspec),
3365+
&sinfo->rxrate);
3366+
} else {
3367+
/* We didn't get the fields we were expecting, fallback to nrate */
3368+
u32 nrate = 0;
3369+
err = brcmf_fil_iovar_int_get(ifp, "nrate", &nrate);
3370+
if (!err) {
3371+
brcmf_convert_ratespec_to_rateinfo(
3372+
nrate, &sinfo->txrate);
3373+
}
3374+
}
3375+
}
32873376
done:
32883377
brcmf_dbg(TRACE, "Exit\n");
32893378
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)