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+
31643229static s32
31653230brcmf_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+ }
32823371done :
32833372 brcmf_dbg (TRACE , "Exit\n" );
32843373 return err ;
0 commit comments