Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+11 −53
Original line number Diff line number Diff line
@@ -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:
+33 −4
Original line number Diff line number Diff line
@@ -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 */
/**********/
+2 −0
Original line number Diff line number Diff line
@@ -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)
{