Yu Wang <yyuwang@xxxxxxxxxxxxxx> writes: > When working in station mode, after connected to a legacy > AP, 11g only, for example, the tx bitrate is incorrect in > output of command 'iw wlan0 link'. > > That's because the legacy tx bitrate value reported by > firmware is not well handled: > For QCA6174, the value represents rate index, but treated > as a real rate; > For QCA9888, the value is real rate, with unit 'Mbps', but > treated as '100kbps'. > > To fix this issue: > 1. Translate the rate index to real rate for QCA6174; > 2. Translate the rate from 'Mbps' to 'kbps' for QCA9888. > > Tested with: > QCA6174 PCIe with firmware WLAN.RM.4.4.1.c3-00031. > QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00029. > QCA9888 PCIe with firmware 10.4-3.9.0.2-00040. > > Signed-off-by: Yu Wang <yyuwang@xxxxxxxxxxxxxx> [...] > @@ -3723,6 +3729,74 @@ static void ath10k_htt_rx_sec_ind_handler(struct ath10k *ar, > spin_unlock_bh(&ar->data_lock); > } > > +static int > +ath10k_htt_update_ratecode(struct ath10k *ar, struct ath10k_sta *arsta, > + u8 *ratecode) > +{ > + u8 hw_rate, preamble; > + u16 bitrate; > + int i; > + const struct ieee80211_rate *bitrates; > + bool cck; > + struct ieee80211_chanctx_conf *conf = NULL; > + enum nl80211_band band; > + struct ieee80211_supported_band *sband; > + > + if (!ratecode) > + return -EINVAL; > + > + /* only for legacy ratecode */ > + preamble = ATH10K_HW_PREAMBLE(*ratecode); > + if (preamble != WMI_RATE_PREAMBLE_CCK && > + preamble != WMI_RATE_PREAMBLE_OFDM) > + return 0; > + > + if (!arsta->arvif || !arsta->arvif->vif) > + return -EINVAL; > + > + WARN_ON(!rcu_read_lock_held()); > + conf = rcu_dereference(arsta->arvif->vif->chanctx_conf); > + if (!conf) > + return -EINVAL; > + > + band = conf->def.chan->band; > + sband = &ar->mac.sbands[band]; > + if (!sband->bitrates) > + return -EINVAL; > + > + if (WARN_ON_ONCE(sband->n_bitrates > S8_MAX)) > + return -EINVAL; > + > + cck = (preamble == WMI_RATE_PREAMBLE_CCK); > + hw_rate = ATH10K_HW_LEGACY_RATE(*ratecode); > + for (i = 0; i < sband->n_bitrates; i++) { > + bitrates = &sband->bitrates[i]; > + if (ath10k_mac_bitrate_is_cck(bitrates->bitrate) != cck) > + continue; > + > + if (bitrates->hw_value == hw_rate || > + (bitrates->flags & IEEE80211_RATE_SHORT_PREAMBLE && > + bitrates->hw_value_short == hw_rate)) { > + bitrate = bitrates->bitrate; > + > + /* The bitrate will be recovered in > + * ath10k_update_per_peer_tx_stats(). > + */ > + if (bitrate == 55) > + bitrate = 60; > + > + bitrate = bitrate / 10; Here you use magic value 60 but in ath10k_update_per_peer_tx_stats() you use magic value 50: > + /* from 1Mbps to 100Kbps */ > + rate = rate * 10; > + if (rate == 50) > + rate = 55; Am I missing something or how is this supposed to work? -- https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches