Bläddra i källkod

qcacmn: Add support for Mesh RX stats

Added suport to extract per packet rx stats from tlv headers and to send
them to upper layers in predfined format.

Change-Id: If8aea2038939162a11ab869b585a0b203a396d71
CRs-Fixed: 2003389
Venkateswara Swamy Bandaru 8 år sedan
förälder
incheckning
c14b1b6f66
2 ändrade filer med 231 tillägg och 0 borttagningar
  1. 68 0
      dp/wifi3.0/dp_rx.c
  2. 163 0
      dp/wifi3.0/hal_rx.h

+ 68 - 0
dp/wifi3.0/dp_rx.c

@@ -23,6 +23,9 @@
 #include "hal_api.h"
 #include "hal_api.h"
 #include "qdf_nbuf.h"
 #include "qdf_nbuf.h"
 #include <ieee80211.h>
 #include <ieee80211.h>
+#ifdef MESH_MODE_SUPPORT
+#include "if_meta_hdr.h"
+#endif
 
 
 /*
 /*
  * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
  * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
@@ -225,6 +228,68 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 	return false;
 	return false;
 }
 }
 
 
+#ifdef MESH_MODE_SUPPORT
+
+/**
+ * dp_rx_fill_mesh_stats() - Fills the mesh per packet receive stats
+ *
+ * @vdev: DP Virtual device handle
+ * @nbuf: Buffer pointer
+ *
+ * This function allocated memory for mesh receive stats and fill the
+ * required stats. Stores the memory address in skb cb.
+ *
+ * Return: void
+ */
+static
+void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
+{
+	struct mesh_recv_hdr_s *rx_info = NULL;
+	uint32_t pkt_type;
+	uint32_t nss;
+	uint32_t rate_mcs;
+	uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf);
+
+	/* fill recv mesh stats */
+	rx_info = qdf_mem_malloc(sizeof(struct mesh_recv_hdr_s));
+
+	/* upper layers are resposible to free this memory */
+
+	if (rx_info == NULL) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"Memory allocation failed for mesh rx stats");
+		return;
+	}
+
+	if (qdf_nbuf_is_chfrag_start(nbuf))
+		rx_info->rs_flags |= MESH_RX_FIRST_MSDU;
+
+	if (qdf_nbuf_is_chfrag_end(nbuf))
+		rx_info->rs_flags |= MESH_RX_LAST_MSDU;
+
+	if (hal_rx_attn_msdu_get_is_decrypted(rx_tlv_hdr)) {
+		rx_info->rs_flags |= MESH_RX_DECRYPTED;
+		rx_info->rs_keyix = hal_rx_msdu_get_keyid(rx_tlv_hdr);
+		rx_info->rs_flags |= MESH_KEY_NOTFILLED;
+	}
+
+	rx_info->rs_rssi = hal_rx_msdu_start_get_rssi(rx_tlv_hdr);
+	rx_info->rs_channel = hal_rx_msdu_start_get_freq(rx_tlv_hdr);
+	pkt_type = hal_rx_msdu_start_get_pkt_type(rx_tlv_hdr);
+	rate_mcs = hal_rx_msdu_start_rate_mcs_get(rx_tlv_hdr);
+	nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr);
+	rx_info->rs_ratephy1 = rate_mcs | (nss << 0x4) | (pkt_type << 6);
+
+	qdf_nbuf_set_fctx_type(nbuf, (void *)rx_info, CB_FTYPE_MESH_RX_INFO);
+}
+#else
+static
+void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
+{
+}
+
+#endif
+
 
 
 /**
 /**
  * dp_rx_process() - Brain of the Rx processing functionality
  * dp_rx_process() - Brain of the Rx processing functionality
@@ -469,6 +534,9 @@ done:
 			/* Set length in nbuf */
 			/* Set length in nbuf */
 			qdf_nbuf_set_pktlen(nbuf, pkt_len);
 			qdf_nbuf_set_pktlen(nbuf, pkt_len);
 
 
+			if (qdf_unlikely(vdev->mesh_vdev))
+				dp_rx_fill_mesh_stats(vdev, nbuf);
+
 			/*
 			/*
 			 * Advance the packet start pointer by total size of
 			 * Advance the packet start pointer by total size of
 			 * pre-header TLV's
 			 * pre-header TLV's

+ 163 - 0
dp/wifi3.0/hal_rx.h

@@ -826,6 +826,169 @@ hal_rx_msdu_start_rate_mcs_get(uint8_t *buf)
 	return rate_mcs;
 	return rate_mcs;
 }
 }
 
 
+#define HAL_RX_ATTN_DECRYPT_STATUS_GET(_rx_attn)		\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_attn,		\
+		RX_ATTENTION_2_DECRYPT_STATUS_CODE_OFFSET)),	\
+		RX_ATTENTION_2_DECRYPT_STATUS_CODE_MASK,	\
+		RX_ATTENTION_2_DECRYPT_STATUS_CODE_LSB))
+
+/*
+ * hal_rx_attn_msdu_get_is_decrypted(): API to get the decrypt status of the
+ *  packet from rx_attention
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(decryt status)
+ */
+
+static inline uint32_t
+hal_rx_attn_msdu_get_is_decrypted(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_attention *rx_attn = &pkt_tlvs->attn_tlv.rx_attn;
+	uint32_t is_decrypt = 0;
+	uint32_t decrypt_status;
+
+	decrypt_status = HAL_RX_ATTN_DECRYPT_STATUS_GET(rx_attn);
+
+	if (!decrypt_status)
+		is_decrypt = 1;
+
+	return is_decrypt;
+}
+
+/*
+ * Get key index from RX_MSDU_END
+ */
+#define HAL_RX_MSDU_END_KEYID_OCTET_GET(_rx_msdu_end)	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end,	\
+		RX_MSDU_END_2_KEY_ID_OCTET_OFFSET)),	\
+		RX_MSDU_END_2_KEY_ID_OCTET_MASK,	\
+		RX_MSDU_END_2_KEY_ID_OCTET_LSB))
+/*
+ * hal_rx_msdu_get_keyid(): API to get the key id if the decrypted packet
+ * from rx_msdu_end
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(key id)
+ */
+
+static inline uint32_t
+hal_rx_msdu_get_keyid(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end;
+	uint32_t keyid_octet;
+
+	keyid_octet = HAL_RX_MSDU_END_KEYID_OCTET_GET(msdu_end);
+
+	return (keyid_octet >> 6) & 0x3;
+}
+
+#define HAL_RX_MSDU_START_RSSI_GET(_rx_msdu_start) 	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_start,  \
+		RX_MSDU_START_5_USER_RSSI_OFFSET)),	\
+		RX_MSDU_START_5_USER_RSSI_MASK,		\
+		RX_MSDU_START_5_USER_RSSI_LSB))
+/*
+ * hal_rx_msdu_start_get_rssi(): API to get the rssi of received pkt
+ * from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(rssi)
+ */
+
+static inline uint32_t
+hal_rx_msdu_start_get_rssi(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start = &pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t rssi;
+
+	rssi = HAL_RX_MSDU_START_RSSI_GET(msdu_start);
+
+	return rssi;
+
+}
+
+#define HAL_RX_MSDU_START_FREQ_GET(_rx_msdu_start) 		\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_start,  	\
+		RX_MSDU_START_7_SW_PHY_META_DATA_OFFSET)),      \
+		RX_MSDU_START_7_SW_PHY_META_DATA_MASK,  	\
+		RX_MSDU_START_7_SW_PHY_META_DATA_LSB))
+
+/*
+ * hal_rx_msdu_start_get_freq(): API to get the frequency of operating channel
+ * from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(frequency)
+ */
+
+static inline uint32_t
+hal_rx_msdu_start_get_freq(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start =
+		&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t freq;
+
+	freq = HAL_RX_MSDU_START_FREQ_GET(msdu_start);
+
+	return freq;
+}
+
+
+#define HAL_RX_MSDU_START_PKT_TYPE_GET(_rx_msdu_start) 	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_start,  \
+		RX_MSDU_START_5_PKT_TYPE_OFFSET)),      \
+		RX_MSDU_START_5_PKT_TYPE_MASK,  	\
+		RX_MSDU_START_5_PKT_TYPE_LSB))
+
+/*
+ * hal_rx_msdu_start_get_pkt_type(): API to get the pkt type
+ * from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(pkt type)
+ */
+
+static inline uint32_t
+hal_rx_msdu_start_get_pkt_type(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start = &pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t pkt_type;
+
+	pkt_type = HAL_RX_MSDU_START_PKT_TYPE_GET(msdu_start);
+
+	return pkt_type;
+}
+
+#define HAL_RX_MSDU_START_NSS_GET(_rx_msdu_start)      	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\
+	RX_MSDU_START_5_NSS_OFFSET)),          		\
+	RX_MSDU_START_5_NSS_MASK,              		\
+	RX_MSDU_START_5_NSS_LSB))
+
+/*
+ * hal_rx_msdu_start_nss_get(): API to get the NSS
+ * Interval from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(nss)
+ */
+
+static inline uint32_t
+hal_rx_msdu_start_nss_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start =
+				&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t nss;
+
+	nss = HAL_RX_MSDU_START_NSS_GET(msdu_start);
+	return nss;
+}
 
 
 /*******************************************************************************
 /*******************************************************************************
  * RX ERROR APIS
  * RX ERROR APIS