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: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
af00148f63
commit
5528e03270
|
@ -643,44 +643,15 @@ struct amsdu_subframe_hdr {
|
||||||
__be16 len;
|
__be16 len;
|
||||||
} __packed;
|
} __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,
|
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||||
struct ieee80211_rx_status *status,
|
struct ieee80211_rx_status *status,
|
||||||
struct htt_rx_desc *rxd)
|
struct htt_rx_desc *rxd)
|
||||||
{
|
{
|
||||||
enum ieee80211_band band;
|
struct ieee80211_supported_band *sband;
|
||||||
u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
|
u8 cck, rate, bw, sgi, mcs, nss;
|
||||||
u8 preamble = 0;
|
u8 preamble = 0;
|
||||||
u32 info1, info2, info3;
|
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);
|
info1 = __le32_to_cpu(rxd->ppdu_start.info1);
|
||||||
info2 = __le32_to_cpu(rxd->ppdu_start.info2);
|
info2 = __le32_to_cpu(rxd->ppdu_start.info2);
|
||||||
info3 = __le32_to_cpu(rxd->ppdu_start.info3);
|
info3 = __le32_to_cpu(rxd->ppdu_start.info3);
|
||||||
|
@ -689,31 +660,18 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||||
|
|
||||||
switch (preamble) {
|
switch (preamble) {
|
||||||
case HTT_RX_LEGACY:
|
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;
|
cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
|
||||||
rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
|
rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
|
||||||
rate_idx = 0;
|
rate &= ~RX_PPDU_START_RATE_FLAG;
|
||||||
|
|
||||||
if (rate < 0x08 || rate > 0x0F)
|
sband = &ar->mac.sbands[status->band];
|
||||||
break;
|
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
status->rate_idx = rate_idx;
|
|
||||||
break;
|
break;
|
||||||
case HTT_RX_HT:
|
case HTT_RX_HT:
|
||||||
case HTT_RX_HT_WITH_TXBF:
|
case HTT_RX_HT_WITH_TXBF:
|
||||||
|
|
|
@ -36,10 +36,20 @@
|
||||||
/*********/
|
/*********/
|
||||||
|
|
||||||
static struct ieee80211_rate ath10k_rates[] = {
|
static struct ieee80211_rate ath10k_rates[] = {
|
||||||
{ .bitrate = 10, .hw_value = ATH10K_HW_RATE_CCK_LP_1M },
|
{ .bitrate = 10,
|
||||||
{ .bitrate = 20, .hw_value = ATH10K_HW_RATE_CCK_LP_2M },
|
.hw_value = ATH10K_HW_RATE_CCK_LP_1M },
|
||||||
{ .bitrate = 55, .hw_value = ATH10K_HW_RATE_CCK_LP_5_5M },
|
{ .bitrate = 20,
|
||||||
{ .bitrate = 110, .hw_value = ATH10K_HW_RATE_CCK_LP_11M },
|
.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 = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
|
||||||
{ .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
|
{ .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);
|
(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 */
|
/* Crypto */
|
||||||
/**********/
|
/**********/
|
||||||
|
|
|
@ -55,6 +55,8 @@ bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
|
||||||
u8 keyidx);
|
u8 keyidx);
|
||||||
void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
|
void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
|
||||||
void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
|
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)
|
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue