Commit 3344b99d authored by Wen Gong's avatar Wen Gong Committed by Kalle Valo
Browse files

ath10k: add bitrate parse for peer stats info



The rate code and rate kbps report by WMI_TLV_PEER_STATS_INFO_EVENTID
from firmware contains all the bitrate info which include OFDM, CCK,
HT/VHT, and mac80211 need the struct rate_info which include below
parameters:

flags: bitflag of flags from &enum rate_info_flags
mcs: mcs index if struct describes an HT/VHT/HE rate
legacy: bitrate in 100kbit/s for 802.11abg
nss: number of streams (VHT & HE only)
bw: bandwidth (from &enum rate_info_bw)

For OFDM/CCK, its rate kbps indicate the bitrate, for HT/VHT, mac80211
need the above 5 parameters to cacluate the bitrate and show by iw.

After parse the bitrate info, iw show the correct rx bitrate:

localhost ~ # iw wlan0 link
	rx bitrate: 234.0 MBit/s VHT-MCS 3 80MHz VHT-NSS 2
	rx bitrate: 40.5 MBit/s MCS 2 40MHz
	rx bitrate: 72.2 MBit/s MCS 7 short GI
	rx bitrate: 54.0 MBit/s
	rx bitrate: 48.0 MBit/s

Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00042.

Signed-off-by: default avatarWen Gong <wgong@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200427080416.8265-4-wgong@codeaurora.org
parent 0f7cb268
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -149,6 +149,26 @@ static inline u32 host_interest_item_address(u32 item_offset)
	return QCA988X_HOST_INTEREST_ADDRESS + item_offset;
}

enum ath10k_phy_mode {
	ATH10K_PHY_MODE_LEGACY = 0,
	ATH10K_PHY_MODE_HT = 1,
	ATH10K_PHY_MODE_VHT = 2,
};

/* Data rate 100KBPS based on IE Index */
struct ath10k_index_ht_data_rate_type {
	u8   beacon_rate_index;
	u16  supported_rate[4];
};

/* Data rate 100KBPS based on IE Index */
struct ath10k_index_vht_data_rate_type {
	u8   beacon_rate_index;
	u16  supported_VHT80_rate[2];
	u16  supported_VHT40_rate[2];
	u16  supported_VHT20_rate[2];
};

struct ath10k_bmi {
	bool done_sent;
};
+161 −0
Original line number Diff line number Diff line
@@ -8305,6 +8305,157 @@ static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
			peer->removed = true;
}

/* HT MCS parameters with Nss = 1 */
static const struct ath10k_index_ht_data_rate_type supported_ht_mcs_rate_nss1[] = {
	/* MCS  L20   L40   S20  S40 */
	{0,  { 65,  135,  72,  150} },
	{1,  { 130, 270,  144, 300} },
	{2,  { 195, 405,  217, 450} },
	{3,  { 260, 540,  289, 600} },
	{4,  { 390, 810,  433, 900} },
	{5,  { 520, 1080, 578, 1200} },
	{6,  { 585, 1215, 650, 1350} },
	{7,  { 650, 1350, 722, 1500} }
};

/* HT MCS parameters with Nss = 2 */
static const struct ath10k_index_ht_data_rate_type supported_ht_mcs_rate_nss2[] = {
	/* MCS  L20    L40   S20   S40 */
	{0,  {130,  270,  144,  300} },
	{1,  {260,  540,  289,  600} },
	{2,  {390,  810,  433,  900} },
	{3,  {520,  1080, 578,  1200} },
	{4,  {780,  1620, 867,  1800} },
	{5,  {1040, 2160, 1156, 2400} },
	{6,  {1170, 2430, 1300, 2700} },
	{7,  {1300, 2700, 1444, 3000} }
};

/* MCS parameters with Nss = 1 */
static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = {
	/* MCS  L80    S80     L40   S40    L20   S20 */
	{0,  {293,  325},  {135,  150},  {65,   72} },
	{1,  {585,  650},  {270,  300},  {130,  144} },
	{2,  {878,  975},  {405,  450},  {195,  217} },
	{3,  {1170, 1300}, {540,  600},  {260,  289} },
	{4,  {1755, 1950}, {810,  900},  {390,  433} },
	{5,  {2340, 2600}, {1080, 1200}, {520,  578} },
	{6,  {2633, 2925}, {1215, 1350}, {585,  650} },
	{7,  {2925, 3250}, {1350, 1500}, {650,  722} },
	{8,  {3510, 3900}, {1620, 1800}, {780,  867} },
	{9,  {3900, 4333}, {1800, 2000}, {780,  867} }
};

/*MCS parameters with Nss = 2 */
static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = {
	/* MCS  L80    S80     L40   S40    L20   S20 */
	{0,  {585,  650},  {270,  300},  {130,  144} },
	{1,  {1170, 1300}, {540,  600},  {260,  289} },
	{2,  {1755, 1950}, {810,  900},  {390,  433} },
	{3,  {2340, 2600}, {1080, 1200}, {520,  578} },
	{4,  {3510, 3900}, {1620, 1800}, {780,  867} },
	{5,  {4680, 5200}, {2160, 2400}, {1040, 1156} },
	{6,  {5265, 5850}, {2430, 2700}, {1170, 1300} },
	{7,  {5850, 6500}, {2700, 3000}, {1300, 1444} },
	{8,  {7020, 7800}, {3240, 3600}, {1560, 1733} },
	{9,  {7800, 8667}, {3600, 4000}, {1560, 1733} }
};

static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs,
					 u8 *flags, u8 *bw)
{
	struct ath10k_index_ht_data_rate_type *mcs_rate;

	mcs_rate = (struct ath10k_index_ht_data_rate_type *)
		   ((nss == 1) ? &supported_ht_mcs_rate_nss1 :
		   &supported_ht_mcs_rate_nss2);

	if (rate == mcs_rate[mcs].supported_rate[0]) {
		*bw = RATE_INFO_BW_20;
	} else if (rate == mcs_rate[mcs].supported_rate[1]) {
		*bw |= RATE_INFO_BW_40;
	} else if (rate == mcs_rate[mcs].supported_rate[2]) {
		*bw |= RATE_INFO_BW_20;
		*flags |= RATE_INFO_FLAGS_SHORT_GI;
	} else if (rate == mcs_rate[mcs].supported_rate[3]) {
		*bw |= RATE_INFO_BW_40;
		*flags |= RATE_INFO_FLAGS_SHORT_GI;
	} else {
		ath10k_warn(ar, "invalid ht params rate %d 100kbps nss %d mcs %d",
			    rate, nss, mcs);
	}
}

static void ath10k_mac_get_rate_flags_vht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs,
					  u8 *flags, u8 *bw)
{
	struct ath10k_index_vht_data_rate_type *mcs_rate;

	mcs_rate = (struct ath10k_index_vht_data_rate_type *)
		   ((nss == 1) ? &supported_vht_mcs_rate_nss1 :
		   &supported_vht_mcs_rate_nss2);

	if (rate == mcs_rate[mcs].supported_VHT80_rate[0]) {
		*bw = RATE_INFO_BW_80;
	} else if (rate == mcs_rate[mcs].supported_VHT80_rate[1]) {
		*bw = RATE_INFO_BW_80;
		*flags |= RATE_INFO_FLAGS_SHORT_GI;
	} else if (rate == mcs_rate[mcs].supported_VHT40_rate[0]) {
		*bw = RATE_INFO_BW_40;
	} else if (rate == mcs_rate[mcs].supported_VHT40_rate[1]) {
		*bw = RATE_INFO_BW_40;
		*flags |= RATE_INFO_FLAGS_SHORT_GI;
	} else if (rate == mcs_rate[mcs].supported_VHT20_rate[0]) {
		*bw = RATE_INFO_BW_20;
	} else if (rate == mcs_rate[mcs].supported_VHT20_rate[1]) {
		*bw = RATE_INFO_BW_20;
		*flags |= RATE_INFO_FLAGS_SHORT_GI;
	} else {
		ath10k_warn(ar, "invalid vht params rate %d 100kbps nss %d mcs %d",
			    rate, nss, mcs);
	}
}

static void ath10k_mac_get_rate_flags(struct ath10k *ar, u32 rate,
				      enum ath10k_phy_mode mode, u8 nss, u8 mcs,
				      u8 *flags, u8 *bw)
{
	if (mode == ATH10K_PHY_MODE_HT) {
		*flags = RATE_INFO_FLAGS_MCS;
		ath10k_mac_get_rate_flags_ht(ar, rate, nss, mcs, flags, bw);
	} else if (mode == ATH10K_PHY_MODE_VHT) {
		*flags = RATE_INFO_FLAGS_VHT_MCS;
		ath10k_mac_get_rate_flags_vht(ar, rate, nss, mcs, flags, bw);
	}
}

static void ath10k_mac_parse_bitrate(struct ath10k *ar, u32 rate_code,
				     u32 bitrate_kbps, struct rate_info *rate)
{
	enum ath10k_phy_mode mode = ATH10K_PHY_MODE_LEGACY;
	enum wmi_rate_preamble preamble = WMI_TLV_GET_HW_RC_PREAM_V1(rate_code);
	u8 nss = WMI_TLV_GET_HW_RC_NSS_V1(rate_code) + 1;
	u8 mcs = WMI_TLV_GET_HW_RC_RATE_V1(rate_code);
	u8 flags = 0, bw = 0;

	if (preamble == WMI_RATE_PREAMBLE_HT)
		mode = ATH10K_PHY_MODE_HT;
	else if (preamble == WMI_RATE_PREAMBLE_VHT)
		mode = ATH10K_PHY_MODE_VHT;

	ath10k_mac_get_rate_flags(ar, bitrate_kbps / 100, mode, nss, mcs, &flags, &bw);

	ath10k_dbg(ar, ATH10K_DBG_MAC,
		   "mac parse bitrate preamble %d mode %d nss %d mcs %d flags %x bw %d\n",
		   preamble, mode, nss, mcs, flags, bw);

	rate->flags = flags;
	rate->bw = bw;
	rate->legacy = bitrate_kbps / 100;
	rate->nss = nss;
	rate->mcs = mcs;
}

static void ath10k_mac_sta_get_peer_stats_info(struct ath10k *ar,
					       struct ieee80211_sta *sta,
					       struct station_info *sinfo)
@@ -8341,6 +8492,16 @@ static void ath10k_mac_sta_get_peer_stats_info(struct ath10k *ar,
		ath10k_warn(ar, "timed out waiting peer stats info\n");
		return;
	}

	if (arsta->rx_rate_code != 0 && arsta->rx_bitrate_kbps != 0) {
		ath10k_mac_parse_bitrate(ar, arsta->rx_rate_code,
					 arsta->rx_bitrate_kbps,
					 &sinfo->rxrate);

		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
		arsta->rx_rate_code = 0;
		arsta->rx_bitrate_kbps = 0;
	}
}

static void ath10k_sta_statistics(struct ieee80211_hw *hw,
+9 −0
Original line number Diff line number Diff line
@@ -2174,6 +2174,15 @@ struct wmi_tlv_peer_stats_info {
	__le32 peer_rssi_per_chain[WMI_TLV_MAX_CHAINS];
} __packed;

#define HW_RATECODE_PREAM_V1_MASK GENMASK(10, 8)
#define WMI_TLV_GET_HW_RC_PREAM_V1(rc) FIELD_GET(HW_RATECODE_PREAM_V1_MASK, rc)

#define HW_RATECODE_NSS_V1_MASK GENMASK(7, 5)
#define WMI_TLV_GET_HW_RC_NSS_V1(rc) FIELD_GET(HW_RATECODE_NSS_V1_MASK, rc)

#define HW_RATECODE_RATE_V1_MASK GENMASK(4, 0)
#define WMI_TLV_GET_HW_RC_RATE_V1(rc) FIELD_GET(HW_RATECODE_RATE_V1_MASK, rc)

struct wmi_tlv_p2p_noa_ev {
	__le32 vdev_id;
} __packed;