Commit 5528e032 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: rework legacy rx rate decoding

Instead of using a hacky table and magic values
use supported band information advertised to
mac80211.

This may impact performance a little when dealing
with legacy rx rates depending on system
architecture. It's probably negligible.

This also fixes a highly theoretical corner case
when HT/VHT rates weren't reported correctly if
channel frequency wasn't known.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent af00148f
......@@ -643,44 +643,15 @@ struct amsdu_subframe_hdr {
__be16 len;
} __packed;
static const u8 rx_legacy_rate_idx[] = {
3, /* 0x00 - 11Mbps */
2, /* 0x01 - 5.5Mbps */
1, /* 0x02 - 2Mbps */
0, /* 0x03 - 1Mbps */
3, /* 0x04 - 11Mbps */
2, /* 0x05 - 5.5Mbps */
1, /* 0x06 - 2Mbps */
0, /* 0x07 - 1Mbps */
10, /* 0x08 - 48Mbps */
8, /* 0x09 - 24Mbps */
6, /* 0x0A - 12Mbps */
4, /* 0x0B - 6Mbps */
11, /* 0x0C - 54Mbps */
9, /* 0x0D - 36Mbps */
7, /* 0x0E - 18Mbps */
5, /* 0x0F - 9Mbps */
};
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
{
enum ieee80211_band band;
u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
struct ieee80211_supported_band *sband;
u8 cck, rate, bw, sgi, mcs, nss;
u8 preamble = 0;
u32 info1, info2, info3;
/* Band value can't be set as undefined but freq can be 0 - use that to
* determine whether band is provided.
*
* FIXME: Perhaps this can go away if CCK rate reporting is a little
* reworked?
*/
if (!status->freq)
return;
band = status->band;
info1 = __le32_to_cpu(rxd->ppdu_start.info1);
info2 = __le32_to_cpu(rxd->ppdu_start.info2);
info3 = __le32_to_cpu(rxd->ppdu_start.info3);
......@@ -689,31 +660,18 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
switch (preamble) {
case HTT_RX_LEGACY:
/* To get legacy rate index band is required. Since band can't
* be undefined check if freq is non-zero.
*/
if (!status->freq)
return;
cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
rate_idx = 0;
if (rate < 0x08 || rate > 0x0F)
break;
switch (band) {
case IEEE80211_BAND_2GHZ:
if (cck)
rate &= ~BIT(3);
rate_idx = rx_legacy_rate_idx[rate];
break;
case IEEE80211_BAND_5GHZ:
rate_idx = rx_legacy_rate_idx[rate];
/* We are using same rate table registering
HW - ath10k_rates[]. In case of 5GHz skip
CCK rates, so -4 here */
rate_idx -= 4;
break;
default:
break;
}
rate &= ~RX_PPDU_START_RATE_FLAG;
status->rate_idx = rate_idx;
sband = &ar->mac.sbands[status->band];
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
break;
case HTT_RX_HT:
case HTT_RX_HT_WITH_TXBF:
......
......@@ -36,10 +36,20 @@
/*********/
static struct ieee80211_rate ath10k_rates[] = {
{ .bitrate = 10, .hw_value = ATH10K_HW_RATE_CCK_LP_1M },
{ .bitrate = 20, .hw_value = ATH10K_HW_RATE_CCK_LP_2M },
{ .bitrate = 55, .hw_value = ATH10K_HW_RATE_CCK_LP_5_5M },
{ .bitrate = 110, .hw_value = ATH10K_HW_RATE_CCK_LP_11M },
{ .bitrate = 10,
.hw_value = ATH10K_HW_RATE_CCK_LP_1M },
{ .bitrate = 20,
.hw_value = ATH10K_HW_RATE_CCK_LP_2M,
.hw_value_short = ATH10K_HW_RATE_CCK_SP_2M,
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55,
.hw_value = ATH10K_HW_RATE_CCK_LP_5_5M,
.hw_value_short = ATH10K_HW_RATE_CCK_SP_5_5M,
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110,
.hw_value = ATH10K_HW_RATE_CCK_LP_11M,
.hw_value_short = ATH10K_HW_RATE_CCK_SP_11M,
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
{ .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
......@@ -75,6 +85,25 @@ static u8 ath10k_mac_bitrate_to_rate(int bitrate)
(ath10k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
}
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate)
{
const struct ieee80211_rate *rate;
int i;
for (i = 0; i < sband->n_bitrates; i++) {
rate = &sband->bitrates[i];
if (rate->hw_value == hw_rate)
return i;
else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
rate->hw_value_short == hw_rate)
return i;
}
return 0;
}
/**********/
/* Crypto */
/**********/
......
......@@ -55,6 +55,8 @@ bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
u8 keyidx);
void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment