summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Qian <zhangq@codeaurora.org>2019-04-11 16:32:12 +0800
committerZhang Qian <zhangq@codeaurora.org>2019-04-24 13:43:03 +0800
commit91fa1989060fac657ed782bfd168ba09f039fb7a (patch)
tree14f249407271c27fa2cb208f4a4851dc8a93db60
parent11fdab25545b45ce9977d5d49618eaa7f93098ae (diff)
qcacld-2.0: Add RX stats indication to SA
Add RX stats indication to SA Change-Id: I15badd684577a7ff6e7dcb3401e5e57ee63d1ca1 CRs-Fixed: 2407824
-rw-r--r--CORE/CLD_TXRX/HTT/htt_t2h.c29
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_rx.c139
-rw-r--r--CORE/SERVICES/COMMON/ol_htt_rx_api.h17
-rw-r--r--CORE/SERVICES/SA/smart_antenna_apis.h89
4 files changed, 251 insertions, 23 deletions
diff --git a/CORE/CLD_TXRX/HTT/htt_t2h.c b/CORE/CLD_TXRX/HTT/htt_t2h.c
index d6110c366db8..02b8b6a8e1f2 100644
--- a/CORE/CLD_TXRX/HTT/htt_t2h.c
+++ b/CORE/CLD_TXRX/HTT/htt_t2h.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1123,6 +1123,28 @@ htt_rx_ind_noise_floor_chain(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
return noise_floor;
}
+int htt_rx_ind_sig(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
+ uint32_t *sig_a1, uint32_t *sig_a2, uint8_t *type)
+{
+ u_int32_t *msg_word;
+
+ msg_word = (u_int32_t *)
+ (adf_nbuf_data(rx_ind_msg) + HTT_RX_IND_FW_RX_PPDU_DESC_BYTE_OFFSET);
+
+ /* check if the RX_IND message contains valid rx PPDU start info */
+ if (!HTT_RX_IND_START_VALID_GET(*msg_word)) {
+ *sig_a1 = -1;
+ *sig_a2 = -1;
+ *type = -1;
+ return -1;
+ }
+
+ *sig_a1 = *(msg_word + 7);
+ *sig_a2 = *(msg_word + 8);
+ *type = HTT_RX_IND_PREAMBLE_TYPE_GET(*sig_a1);
+ return 0;
+}
+
/**
* htt_rx_ind_legacy_rate() - Return the data rate
* @pdev: the HTT instance the rx data was received on
@@ -1153,7 +1175,7 @@ htt_rx_ind_noise_floor_chain(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
*
* Return the data rate provided in a rx indication message.
*/
-void
+int
htt_rx_ind_legacy_rate(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
uint8_t *legacy_rate, uint8_t *legacy_rate_sel)
{
@@ -1166,11 +1188,12 @@ htt_rx_ind_legacy_rate(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
if (!HTT_RX_IND_START_VALID_GET(*msg_word)) {
*legacy_rate = -1;
*legacy_rate_sel = -1;
- return;
+ return -1;
}
*legacy_rate = HTT_RX_IND_LEGACY_RATE_GET(*msg_word);
*legacy_rate_sel = HTT_RX_IND_LEGACY_RATE_SEL_GET(*msg_word);
+ return 0;
}
/**
diff --git a/CORE/CLD_TXRX/TXRX/ol_rx.c b/CORE/CLD_TXRX/TXRX/ol_rx.c
index b6d2d5b219a2..fed172e93a5f 100644
--- a/CORE/CLD_TXRX/TXRX/ol_rx.c
+++ b/CORE/CLD_TXRX/TXRX/ol_rx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -67,6 +67,8 @@
#include "vos_cnss.h"
#endif
+#include "if_smart_antenna.h"
+
#ifdef OSIF_NEED_RX_PEER_ID
#define OL_RX_OSIF_DELIVER(vdev, peer, msdus) \
vdev->osif_rx(vdev->osif_dev, peer->local_id, msdus)
@@ -338,6 +340,121 @@ ol_rx_mon_mac_header_handler(
}
}
+#ifdef WLAN_SMART_ANTENNA_FEATURE
+static inline void ol_fill_legacy_rate(uint8_t legacy_rate,
+ uint8_t legacy_rate_sel,
+ enum legacy_rate *rate)
+{
+ switch (legacy_rate) {
+ case 0x8:
+ *rate = legacy_rate_sel ? CCK_11M_LONG_PREAMBLE : OFDM_48M;
+ break;
+ case 0x9:
+ *rate = legacy_rate_sel ? CCK_5_5M_LONG_PREAMBLE : OFDM_24M;
+ break;
+ case 0xA:
+ *rate = legacy_rate_sel ? CCK_2M_LONG_PREAMBLE : OFDM_12M;
+ break;
+ case 0xB:
+ *rate = legacy_rate_sel ? CCK_1M_LONG_PREAMBLE : OFDM_6M;
+ break;
+ case 0xC:
+ *rate = legacy_rate_sel ? CCK_11M_SHORT_PREAMBLE : OFDM_54M;
+ break;
+ case 0xD:
+ *rate = legacy_rate_sel ? CCK_5_5M_SHORT_PREAMBLE : OFDM_36M;
+ break;
+ case 0xE:
+ *rate = legacy_rate_sel ? CCK_2M_SHORT_PREAMBLE : OFDM_18M;
+ break;
+ case 0xF:
+ *rate = OFDM_9M;
+ break;
+ default:
+ *rate = INVALID_LEGACY_RATE;
+ break;
+ }
+}
+
+static void ol_pop_rx_stats(htt_pdev_handle htt_pdev,
+ adf_nbuf_t rx_ind_msg,
+ int pkt_num,
+ struct sa_rx_mpdu_stats *fb)
+{
+ uint8_t legacy_rate, legacy_rate_sel, preamble_type, subms;
+ uint32_t vht_sig1, vht_sig2, ms;
+ int i;
+
+ if (!fb)
+ return;
+
+ htt_rx_ind_sig(htt_pdev, rx_ind_msg, &vht_sig1,
+ &vht_sig2, &preamble_type);
+ fb->magic = (vht_sig2 & 0xff000000) >> 24;
+ if (preamble_type == 0x4) {
+ htt_rx_ind_legacy_rate(htt_pdev, rx_ind_msg,
+ &legacy_rate, &legacy_rate_sel);
+ fb->rate.type = LEGACY_RATE;
+ ol_fill_legacy_rate(legacy_rate,
+ legacy_rate_sel, &fb->rate.rate.legacy_rate);
+ } else if (preamble_type != -1) {
+ uint8_t bw = 0;
+ fb->rate.type = HT_VHT_RATE;
+ fb->rate.rate.mcs.mcs_index = vht_sig1 & 0x7f;
+ fb->rate.rate.mcs.nss = (vht_sig2 >> 8) &0x3;
+ bw |= ((vht_sig1 >> 7) & 0x1) ?
+ SMART_ANT_BW_40MHZ : SMART_ANT_BW_20MHZ;
+ if ((preamble_type == 0xC) || (preamble_type == 0xD))
+ bw |= SMART_ANT_NODE_VHT;
+ else
+ bw |= SMART_ANT_NODE_HT;
+ fb->rate.rate.mcs.bw = bw;
+ } else {
+ /* Both legacy and VHT are invalid*/
+ fb->rate.type = LEGACY_RATE;
+ fb->rate.rate.legacy_rate = INVALID_LEGACY_RATE;
+ }
+ fb->tid = htt_rx_ind_ext_tid(htt_pdev, rx_ind_msg);
+ fb->pkt_num = pkt_num;
+ for (i = 0; i < SA_MAX_CHAIN_NUM; i++) {
+ fb->rx_rssi[i] = htt_rx_ind_rssi_dbm_chain(htt_pdev,
+ rx_ind_msg,
+ i);
+ fb->rx_nf[i] = htt_rx_ind_noise_floor_chain(htt_pdev,
+ rx_ind_msg,
+ i);
+ }
+ htt_rx_ind_timestamp(htt_pdev, rx_ind_msg, &ms, &subms);
+ fb->timestamp_microsec = ms;
+ fb->timestamp_submicrosec = (uint32_t)subms;
+}
+
+static struct sa_rx_stats_feedback *ol_rx_feedback_alloc(uint32_t mpdu_num)
+{
+ struct sa_rx_stats_feedback *fb;
+ fb = adf_os_mem_alloc(NULL,
+ sizeof(struct sa_rx_stats_feedback) +
+ mpdu_num * sizeof(struct sa_rx_mpdu_stats));
+
+ if (fb)
+ fb->mpdu_count = mpdu_num;
+ return fb;
+}
+#else
+static inline void ol_pop_rx_stats(htt_pdev_handle htt_pdev,
+ adf_nbuf_t rx_ind_msg,
+ uint32_t pkt_num,
+ struct sa_rx_mpdu_stats *fb)
+{
+}
+
+static inline
+struct sa_rx_stats_feedback *ol_rx_feedback_alloc(uint32_t mpdu_num)
+{
+ return NULL;
+}
+#endif
+
void
ol_rx_indication_handler(
ol_txrx_pdev_handle pdev,
@@ -357,6 +474,7 @@ ol_rx_indication_handler(
uint16_t chan2;
uint8_t phymode;
a_bool_t ret;
+ struct sa_rx_stats_feedback *fb;
htt_pdev = pdev->htt_pdev;
peer = ol_txrx_peer_find_by_id(pdev, peer_id);
@@ -430,6 +548,11 @@ ol_rx_indication_handler(
pdev->htt_pdev->rx_ring.sw_rd_idx.msdu_payld;
#endif
+ if (peer && num_mpdu_ranges)
+ fb = ol_rx_feedback_alloc(num_mpdu_ranges);
+ else
+ fb = NULL;
+
for (mpdu_range = 0; mpdu_range < num_mpdu_ranges; mpdu_range++) {
enum htt_rx_status status;
int i, num_mpdus;
@@ -442,6 +565,9 @@ ol_rx_indication_handler(
htt_rx_ind_mpdu_range_info(
pdev->htt_pdev, rx_ind_msg, mpdu_range, &status, &num_mpdus);
+ if (fb)
+ ol_pop_rx_stats(htt_pdev, rx_ind_msg,
+ num_mpdus, &fb->mpdu_stats[mpdu_range]);
if ((status == htt_rx_status_ok) && peer) {
TXRX_STATS_ADD(pdev, priv.rx.normal.mpdus, num_mpdus);
/* valid frame - deposit it into the rx reordering buffer */
@@ -476,7 +602,7 @@ ol_rx_indication_handler(
#ifdef HTT_RX_RESTORE
if (htt_pdev->rx_ring.rx_reset) {
ol_rx_trigger_restore(htt_pdev, head_msdu, tail_msdu);
- return;
+ goto exit;
}
#endif
rx_mpdu_desc =
@@ -600,7 +726,7 @@ ol_rx_indication_handler(
#ifdef HTT_RX_RESTORE
if (htt_pdev->rx_ring.rx_reset) {
ol_rx_trigger_restore(htt_pdev, msdu, tail_msdu);
- return;
+ goto exit;
}
#endif
/* pull the MPDU desc off the desc queue */
@@ -671,6 +797,13 @@ ol_rx_indication_handler(
if (pdev->rx.flags.defrag_timeout_check) {
ol_rx_defrag_waitlist_flush(pdev);
}
+#ifdef HTT_RX_RESTORE
+exit:
+#endif
+ if (peer && fb)
+ smart_antenna_update_rx_stats(peer->mac_addr.raw, fb);
+ if (fb)
+ adf_os_mem_free(fb);
}
void
diff --git a/CORE/SERVICES/COMMON/ol_htt_rx_api.h b/CORE/SERVICES/COMMON/ol_htt_rx_api.h
index 8cf7a4548fb4..38aa4b7141ac 100644
--- a/CORE/SERVICES/COMMON/ol_htt_rx_api.h
+++ b/CORE/SERVICES/COMMON/ol_htt_rx_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015, 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 2018-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -259,7 +259,20 @@ int8_t
htt_rx_ind_noise_floor_chain(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
int8_t chain);
-void
+/**
+ * htt_rx_ind_sig() - Return SIG_A1 and SIG_A2
+ * @pdev: the HTT instance the rx data was received on
+ * @rx_ind_msg: the netbuf containing the rx indication message
+ * @sig_a1: SIG_A1
+ * @sig_a2: SIG_A2
+ * @type: preamble type
+ *
+ * return: 0 success, -1, SIG_A and preamble type is not avalible.
+ */
+int htt_rx_ind_sig(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
+ uint32_t *sig_a1, uint32_t *sig_a2, uint8_t *type);
+
+int
htt_rx_ind_legacy_rate(htt_pdev_handle pdev, adf_nbuf_t rx_ind_msg,
uint8_t *legacy_rate, uint8_t *legacy_rate_sel);
diff --git a/CORE/SERVICES/SA/smart_antenna_apis.h b/CORE/SERVICES/SA/smart_antenna_apis.h
index a1e536728c2c..44bdeadf35ac 100644
--- a/CORE/SERVICES/SA/smart_antenna_apis.h
+++ b/CORE/SERVICES/SA/smart_antenna_apis.h
@@ -58,6 +58,29 @@ enum radio_id {
};
/**
+ * enum legacy_rate
+ */
+enum legacy_rate {
+ CCK_1M_LONG_PREAMBLE = 0,
+ CCK_2M_LONG_PREAMBLE,
+ CCK_2M_SHORT_PREAMBLE,
+ CCK_5_5M_LONG_PREAMBLE,
+ CCK_5_5M_SHORT_PREAMBLE,
+ CCK_11M_LONG_PREAMBLE,
+ CCK_11M_SHORT_PREAMBLE,
+ OFDM_6M,
+ OFDM_9M,
+ OFDM_12M,
+ OFDM_18M,
+ OFDM_24M,
+ OFDM_36M,
+ OFDM_48M,
+ OFDM_54M,
+ INVALID_LEGACY_RATE = -1
+};
+
+
+/**
* struct sa_config - Smart Antenna config info
* @channel_num: SAP home channel number
*/
@@ -77,6 +100,14 @@ struct sa_rate_cap {
uint8_t ratecount[MAX_RATE_COUNTERS];
};
+#define SMART_ANT_BW_5MHZ BIT(0)
+#define SMART_ANT_BW_10MHZ BIT(1)
+#define SMART_ANT_BW_20MHZ BIT(2)
+#define SMART_ANT_BW_40MHZ BIT(3)
+#define SMART_ANT_BW_80MHZ BIT(4)
+#define SMART_ANT_NODE_HT BIT(8)
+#define SMART_ANT_NODE_VHT BIT(9)
+
/**
* struct sa_node_info - Detailed info about the connected peer
* @mac_addr: MAC address of the connected peer
@@ -89,13 +120,6 @@ struct sa_node_info {
uint8_t channel_num;
uint8_t nss;
-#define SMART_ANT_BW_5MHZ BIT(0)
-#define SMART_ANT_BW_10MHZ BIT(1)
-#define SMART_ANT_BW_20MHZ BIT(2)
-#define SMART_ANT_BW_40MHZ BIT(3)
-#define SMART_ANT_BW_80MHZ BIT(4)
-#define SMART_ANT_NODE_HT BIT(8)
-#define SMART_ANT_NODE_VHT BIT(9)
uint32_t node_caps;
struct sa_rate_cap rate_cap;
};
@@ -136,23 +160,58 @@ struct sa_tx_stats_feedback {
};
/**
- * struct sa_rx_stats_feedback - feedback for RX stats
+ * struct sa_rx_rate - RX rate
+ */
+struct sa_rx_rate {
+#define LEGACY_RATE 0
+#define HT_VHT_RATE 1
+ uint8_t type;
+ union {
+ enum legacy_rate legacy_rate;
+ struct {
+ uint8_t mcs_index;
+ uint8_t nss;
+ uint8_t bw;
+ } mcs;
+ } rate;
+};
+
+/**
+ * struct sa_rx_mpdu_stats - RX stats for MPDU
* @magic: magic number for deferent antenna settings
* @tid: TID
- * @rx_rate: msb is flag for legacy rate or mcs index
- * if msb=0, legacy rate is reported, units of 500 kb/s
- * if msb=1, MCS index is reported.
+ * @mcs: mcs index
+ * only valid when legacy_rate == INVALID_LEGACY_RATE
+ * @legacy_rate: legay rate
* @pkt_num: received packets nmber
* @rx_rssi: percchain rssi
- * @timestamp: timestap
+ * @rx_sn: perchain noise floor
+ * @timestamp_microsec: (output) the timestamp to microsecond resolution.
+ * -1 on error.
+ * @timestamp_submicrosec: the submicrosecond portion of the
+ * timestamp. -1 on error.
*/
-struct sa_rx_stats_feedback {
+struct sa_rx_mpdu_stats {
uint32_t magic;
uint8_t tid;
- uint16_t rx_rate;
+ uint8_t mcs;
+ struct sa_rx_rate rate;
uint16_t pkt_num;
uint8_t rx_rssi[SA_MAX_CHAIN_NUM];
- uint32_t timestamp;
+ uint8_t rx_nf[SA_MAX_CHAIN_NUM];
+ uint32_t timestamp_microsec;
+ uint32_t timestamp_submicrosec;
+};
+
+/**
+ * struct sa_rx_stats_feedback - RX stats Feedback
+ * @mpdu_count: mpdu count in this feedback
+ * @mpdu_stats: MPDU stats buffer
+ */
+struct sa_rx_stats_feedback
+{
+ uint32_t mpdu_count;
+ struct sa_rx_mpdu_stats mpdu_stats[0];
};
/**