Skip to content

Commit dc17820

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 289c740 commit dc17820

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

@@ -3183,6 +3184,70 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
31833184
return 0;
31843185
}
31853186

3187+
static void brcmf_convert_ratespec_to_rateinfo(u32 ratespec,
3188+
struct rate_info *rateinfo)
3189+
{
3190+
/* First extract the bandwidth info */
3191+
switch (ratespec & BRCMF_RSPEC_BW_MASK) {
3192+
case BRCMF_RSPEC_BW_20MHZ:
3193+
rateinfo->bw = RATE_INFO_BW_20;
3194+
break;
3195+
case BRCMF_RSPEC_BW_40MHZ:
3196+
rateinfo->bw = RATE_INFO_BW_40;
3197+
break;
3198+
case BRCMF_RSPEC_BW_80MHZ:
3199+
rateinfo->bw = RATE_INFO_BW_80;
3200+
break;
3201+
case BRCMF_RSPEC_BW_160MHZ:
3202+
rateinfo->bw = RATE_INFO_BW_160;
3203+
break;
3204+
case BRCMF_RSPEC_BW_320MHZ:
3205+
rateinfo->bw = RATE_INFO_BW_320;
3206+
break;
3207+
default:
3208+
/* Fill in nothing */
3209+
break;
3210+
}
3211+
if (BRCMF_RSPEC_ISHT(ratespec)) {
3212+
rateinfo->flags |= RATE_INFO_FLAGS_MCS;
3213+
rateinfo->mcs = ratespec & BRCMF_RSPEC_HT_MCS_MASK;
3214+
} else if (BRCMF_RSPEC_ISVHT(ratespec)) {
3215+
rateinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
3216+
rateinfo->mcs = ratespec & BRCMF_RSPEC_VHT_MCS_MASK;
3217+
rateinfo->nss = (ratespec & BRCMF_RSPEC_VHT_NSS_MASK) >>
3218+
BRCMF_RSPEC_VHT_NSS_SHIFT;
3219+
} else if (BRCMF_RSPEC_ISHE(ratespec)) {
3220+
u32 ltf_gi = BRCMF_RSPEC_HE_LTF_GI(ratespec);
3221+
3222+
rateinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
3223+
rateinfo->mcs = ratespec & BRCMF_RSPEC_HE_MCS_MASK;
3224+
rateinfo->nss = (ratespec & BRCMF_RSPEC_HE_NSS_MASK) >>
3225+
BRCMF_RSPEC_HE_NSS_SHIFT;
3226+
rateinfo->he_dcm = BRCMF_RSPEC_HE_DCM(ratespec);
3227+
if (HE_IS_GI_0_8us(ltf_gi)) {
3228+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
3229+
} else if (HE_IS_GI_1_6us(ltf_gi)) {
3230+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
3231+
} else if (HE_IS_GI_3_2us(ltf_gi)) {
3232+
rateinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
3233+
}
3234+
} else if (BRCMF_RSPEC_ISEHT(ratespec)) {
3235+
u32 ltf_gi = BRCMF_RSPEC_EHT_LTF_GI(ratespec);
3236+
3237+
rateinfo->flags |= RATE_INFO_FLAGS_EHT_MCS;
3238+
rateinfo->mcs = ratespec & BRCMF_RSPEC_EHT_MCS_MASK;
3239+
rateinfo->nss = (ratespec & BRCMF_RSPEC_EHT_NSS_MASK) >>
3240+
BRCMF_RSPEC_EHT_NSS_SHIFT;
3241+
if (EHT_IS_GI_0_8us(ltf_gi)) {
3242+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_0_8;
3243+
} else if (EHT_IS_GI_1_6us(ltf_gi)) {
3244+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_1_6;
3245+
} else if (EHT_IS_GI_3_2us(ltf_gi)) {
3246+
rateinfo->eht_gi = NL80211_RATE_INFO_EHT_GI_3_2;
3247+
}
3248+
}
3249+
}
3250+
31863251
static s32
31873252
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
31883253
const u8 *mac, struct station_info *sinfo)
@@ -3200,6 +3265,8 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32003265
s32 count_rssi = 0;
32013266
int rssi;
32023267
u32 i;
3268+
u16 struct_ver;
3269+
u16 info_len;
32033270

32043271
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
32053272
if (!check_vif_up(ifp->vif))
@@ -3223,7 +3290,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32233290
goto done;
32243291
}
32253292
}
3226-
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
3293+
info_len = le16_to_cpu(sta_info_le.len);
3294+
struct_ver = le16_to_cpu(sta_info_le.ver);
3295+
brcmf_dbg(TRACE, "version %d\n", struct_ver);
32273296
sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
32283297
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
32293298
sta_flags = le32_to_cpu(sta_info_le.flags);
@@ -3257,12 +3326,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
32573326
sinfo->rxrate.legacy =
32583327
le32_to_cpu(sta_info_le.rx_rate) / 100;
32593328
}
3260-
if (le16_to_cpu(sta_info_le.ver) >= 4) {
3329+
if (struct_ver >= 4) {
32613330
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
32623331
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
32633332
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
32643333
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
32653334
}
3335+
32663336
for (i = 0; i < BRCMF_ANT_MAX; i++) {
32673337
if (sta_info_le.rssi[i] == 0 ||
32683338
sta_info_le.rx_lastpkt_rssi[i] == 0)
@@ -3301,6 +3371,25 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
33013371
}
33023372
}
33033373
}
3374+
/* Some version 7 structs have ratespecs from the last packet. */
3375+
if (struct_ver >= 7) {
3376+
if (info_len >= sizeof(sta_info_le)) {
3377+
brcmf_convert_ratespec_to_rateinfo(
3378+
le32_to_cpu(sta_info_le.v7.tx_rspec),
3379+
&sinfo->txrate);
3380+
brcmf_convert_ratespec_to_rateinfo(
3381+
le32_to_cpu(sta_info_le.v7.rx_rspec),
3382+
&sinfo->rxrate);
3383+
} else {
3384+
/* We didn't get the fields we were expecting, fallback to nrate */
3385+
u32 nrate = 0;
3386+
err = brcmf_fil_iovar_int_get(ifp, "nrate", &nrate);
3387+
if (!err) {
3388+
brcmf_convert_ratespec_to_rateinfo(
3389+
nrate, &sinfo->txrate);
3390+
}
3391+
}
3392+
}
33043393
done:
33053394
brcmf_dbg(TRACE, "Exit\n");
33063395
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)