Blob Blame History Raw
From 7005eafc1f1cb0a525631c2214f760d6fb636ebb Mon Sep 17 00:00:00 2001
From: Wen Gong <wgong@codeaurora.org>
Date: Thu, 14 Nov 2019 19:19:31 +0800
Subject: [PATCH] ath10k: report rssi of each chain to mac80211 for sdio
Git-commit: 7005eafc1f1cb0a525631c2214f760d6fb636ebb
Patch-mainline: v5.6-rc1
References: jsc#SLE-13430

iw command only show rssi without each chain's rssi on sdio
iw wlan0 station dump
Station a0:40:a0:93:3e:de (on wlan0)
Signal: -82 dBm
signal avg:     -82 dBm

after this patch, it will show each chain's rssi on sdio
Station a0:40:a0:93:3e:de (on wlan0)
Signal: -82 [-84, -88] dBm
signal avg:     -82 [-84, -87] dBm

For QCA6174 PCIe, the ppdu have the correct rssi of each chain, it
indicate rssi of rx data by ath10k_htt_rx_h_signal. For sdio chip, the
rssi of each chain stored in rx management reported by firmware, the
ath10k_wmi_tlv_op_pull_mgmt_rx_ev which used for tlv wmi will get the
rssi of each chain and stored them in wmi_mgmt_rx_ev_arg, then indicate
them to mac80211. For non-tlv wmi chip, it will not get the rssi of each
chain and not indicate to mac80211, for non-tlv wmi chip, this patch will
not have impact. For tlv wmi chip, if the rssi of chain in mgmt is valid,
it will be indicate to mac80211, tested with QCA6174 PCIe/SDIO, the rssi
of 2 chain in mgmt is valid.

rssi of chains in mgmt of QCA6174 SDIO:
92096.652780: ath10k:ath10k_log_warn: ath10k_sdio mmc1:0001:1 rssi[0]:70
92096.657324: ath10k:ath10k_log_warn: ath10k_sdio mmc1:0001:1 rssi[1]:68
92096.662009: ath10k:ath10k_log_warn: ath10k_sdio mmc1:0001:1 rssi[2]:128
92096.666647: ath10k:ath10k_log_warn: ath10k_sdio mmc1:0001:1 rssi[3]:128

rssi of chains in mgmt of QCA6174 PCIe:
[ 1581.049816] ath10k_pci 0000:02:00.0: mgmt rssi[0]:17
[ 1581.049818] ath10k_pci 0000:02:00.0: mgmt rssi[1]:22
[ 1581.049821] ath10k_pci 0000:02:00.0: mgmt rssi[2]:128
[ 1581.049823] ath10k_pci 0000:02:00.0: mgmt rssi[3]:128

after apply this patch, the iw's rssi of PCIe do not changed, result is
same with before.

iw wlan0 station dump of QCA6174 PCIe:
Station 6c:e8:73:b8:92:dc (on wlan0)
        signal:         -70 [-77, -72] dBm
        signal avg:     -69 [-78, -72] dBm

iw wlan-5000mhz station dump of QCA9984 PCIe
connected with 2 client which has 2 chain:
Station 70:48:0f:1f:1a:b2 (on wlan-5000mhz)
        signal:         -47 [-55, -48, -87, -88] dBm
        signal avg:     -42 [-50, -43, -83, -86] dBm
Station ac:c1:ee:39:e3:83 (on wlan-5000mhz)
        signal:         -43 [-46, -45, -79, -84] dBm
        signal avg:     -43 [-46, -46, -82, -83] dBm

Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00017-QCARMSWP-1.
Tested with QCA6174 PCIe with firmware WLAN.RM.4.4.1-00110-QCARMSWP-1.
Tested with QCA9984 PCIe with firmware 10.4-3.9.0.2-00040.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/net/wireless/ath/ath10k/htt_rx.c  |  1 -
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |  5 ++++-
 drivers/net/wireless/ath/ath10k/wmi.c     | 18 ++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi.h     |  2 ++
 4 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index edda6dd93476..0f1f71e43b9b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2239,7 +2239,6 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
 	rx_status = IEEE80211_SKB_RXCB(skb);
 	memset(rx_status, 0, sizeof(*rx_status));
 
-	rx_status->chains |= BIT(0);
 	if (rx->ppdu.combined_rssi == 0) {
 		/* SDIO firmware does not provide signal */
 		rx_status->signal = 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 7b358484940e..4e68debda9bf 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -841,7 +841,7 @@ static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
 	const struct wmi_tlv_mgmt_rx_ev *ev;
 	const u8 *frame;
 	u32 msdu_len;
-	int ret;
+	int ret, i;
 
 	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
 	if (IS_ERR(tb)) {
@@ -865,6 +865,9 @@ static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
 	arg->phy_mode = ev->phy_mode;
 	arg->rate = ev->rate;
 
+	for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
+		arg->rssi[i] = ev->rssi[i];
+
 	msdu_len = __le32_to_cpu(arg->buf_len);
 
 	if (skb->len < (frame - skb->data) + msdu_len) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 9f564e2b7a14..13f7531d945d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2463,10 +2463,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 	u32 rx_status;
 	u32 channel;
 	u32 phy_mode;
-	u32 snr;
+	u32 snr, rssi;
 	u32 rate;
 	u16 fc;
-	int ret;
+	int ret, i;
 
 	ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
 	if (ret) {
@@ -2525,6 +2525,20 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 
 	status->freq = ieee80211_channel_to_frequency(channel, status->band);
 	status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
+
+	BUILD_BUG_ON(ARRAY_SIZE(status->chain_signal) != ARRAY_SIZE(arg.rssi));
+
+	for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
+		status->chains &= ~BIT(i);
+		rssi = __le32_to_cpu(arg.rssi[i]);
+		ath10k_dbg(ar, ATH10K_DBG_MGMT, "mgmt rssi[%d]:%d\n", i, arg.rssi[i]);
+
+		if (rssi != ATH10K_INVALID_RSSI && rssi != 0) {
+			status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR + rssi;
+			status->chains |= BIT(i);
+		}
+	}
+
 	status->rate_idx = ath10k_mac_bitrate_to_idx(sband, rate / 100);
 
 	hdr = (struct ieee80211_hdr *)skb->data;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 74adce1dd3a9..972d53d77654 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6786,6 +6786,7 @@ struct wmi_peer_delete_resp_ev_arg {
 	struct wmi_mac_addr peer_addr;
 };
 
+#define WMI_MGMT_RX_NUM_RSSI 4
 struct wmi_mgmt_rx_ev_arg {
 	__le32 channel;
 	__le32 snr;
@@ -6794,6 +6795,7 @@ struct wmi_mgmt_rx_ev_arg {
 	__le32 buf_len;
 	__le32 status; /* %WMI_RX_STATUS_ */
 	struct wmi_mgmt_rx_ext_info ext_info;
+	__le32 rssi[WMI_MGMT_RX_NUM_RSSI];
 };
 
 struct wmi_ch_info_ev_arg {
-- 
2.16.4