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+
31693234static s32
31703235brcmf_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+ }
32873376done :
32883377 brcmf_dbg (TRACE , "Exit\n" );
32893378 return err ;
0 commit comments