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+
31863251static s32
31873252brcmf_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+ }
33043393done :
33053394 brcmf_dbg (TRACE , "Exit\n" );
33063395 return err ;
0 commit comments