Prechádzať zdrojové kódy

qcacmn: Monitor status ring handling

Changes to process PHY TLVs from monitor status ring and extract
information required for radiotap header.

Change-Id: I99d642e7506ea797b26dbfac89fd223d1a4c0a55
CRs-Fixed: 2048006
Karunakar Dasineni 8 rokov pred
rodič
commit
4055568bad

+ 1 - 1
dp/wifi3.0/dp_htt.c

@@ -815,7 +815,7 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng,
 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET_HEADER,
 		htt_tlv_filter->packet_header);
 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, ATTENTION,
-		htt_tlv_filter->ppdu_end_status_done);
+		htt_tlv_filter->attention);
 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START,
 		htt_tlv_filter->ppdu_start);
 	htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END,

+ 7 - 8
dp/wifi3.0/dp_main.c

@@ -2389,8 +2389,8 @@ static int dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle,
 	htt_tlv_filter.enable_mo = 1;
 
 	htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id,
-		pdev->rxdma_mon_dst_ring.hal_srng,
-		RXDMA_MONITOR_BUF,  RX_BUFFER_SIZE, &htt_tlv_filter);
+		pdev->rxdma_mon_buf_ring.hal_srng,
+		RXDMA_MONITOR_BUF, RX_BUFFER_SIZE, &htt_tlv_filter);
 
 	htt_tlv_filter.mpdu_start = 1;
 	htt_tlv_filter.msdu_start = 1;
@@ -2405,13 +2405,12 @@ static int dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle,
 	htt_tlv_filter.ppdu_end_user_stats_ext = 1;
 	htt_tlv_filter.ppdu_end_status_done = 1;
 	htt_tlv_filter.enable_fp = 1;
-	htt_tlv_filter.enable_md = 1;
+	htt_tlv_filter.enable_md = 0;
 	htt_tlv_filter.enable_mo = 1;
-	/*
-	 * htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id,
-	 * pdev->rxdma_mon_status_ring.hal_srng,
-	 * RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter);
-	 */
+
+	htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id,
+		pdev->rxdma_mon_status_ring.hal_srng, RXDMA_MONITOR_STATUS,
+		RX_BUFFER_SIZE, &htt_tlv_filter);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 52 - 70
dp/wifi3.0/dp_rx_mon_dest.c

@@ -99,8 +99,7 @@ done:
  * @tail: tail of decs list to be freed
  * Return: number of msdu in MPDU to be popped
  */
-static inline
-uint32_t
+static inline uint32_t
 dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 	void *rxdma_dst_ring_desc, qdf_nbuf_t *head_msdu,
 	qdf_nbuf_t *tail_msdu, uint32_t *npackets, uint32_t *ppdu_id,
@@ -161,6 +160,23 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 					"[%s][%d] msdu_nbuf=%p, data=%p\n",
 					__func__, __LINE__, msdu, data);
 
+				rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data);
+				msdu_ppdu_id =
+					HAL_RX_MON_HW_DESC_GET_PPDUID_GET(rx_desc_tlv);
+
+				QDF_TRACE(QDF_MODULE_ID_DP,
+					QDF_TRACE_LEVEL_DEBUG,
+					"[%s][%d] i=%d, ppdu_id=%x, msdu_ppdu_id=%x\n",
+					__func__, __LINE__, i, *ppdu_id, msdu_ppdu_id);
+				if (*ppdu_id != msdu_ppdu_id) {
+					*ppdu_id = msdu_ppdu_id;
+					return rx_bufs_used;
+				}
+
+				if (hal_rx_desc_is_first_msdu(rx_desc_tlv))
+					hal_rx_mon_hw_desc_get_mpdu_status(rx_desc_tlv,
+						&(dp_pdev->ppdu_info.rx_status));
+
 				rx_pkt_offset = HAL_RX_MON_HW_RX_DESC_SIZE();
 				/*
 				 * HW structures call this L3 header padding
@@ -176,7 +192,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 
 				qdf_nbuf_set_pktlen(msdu, rx_buf_size);
 
-				rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data);
 
 #if 0
 				/* Disble it.see packet on msdu done set to 0 */
@@ -200,17 +215,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 				}
 #endif
 
-				msdu_ppdu_id =
-				HAL_RX_MON_HW_DESC_GET_PPDUID_GET(rx_desc_tlv);
-
-#if 0
-				/* Temporary only handle destination ring */
-				if (*ppdu_id != msdu_ppdu_id) {
-					*ppdu_id = msdu_ppdu_id;
-					return rx_bufs_used;
-				}
-#endif
-
 				rx_bufs_used++;
 
 				QDF_TRACE(QDF_MODULE_ID_DP,
@@ -306,8 +310,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc,
 
 	rx_desc = qdf_nbuf_data(head_msdu);
 
-	HAL_RX_MON_HW_DESC_GET_PPDU_START_STATUS(rx_desc, rx_status);
-
 	decap_format = HAL_RX_DESC_GET_DECAP_FORMAT(rx_desc);
 
 	/* Easy case - The MSDU status indicates that this is a non-decapped
@@ -616,7 +618,6 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
 	struct cdp_mon_status *rs = &pdev->rx_mon_recv_status;
 	qdf_nbuf_t mon_skb, skb_next;
 	qdf_nbuf_t mon_mpdu = NULL;
-	struct mon_rx_status rx_mon_status;
 
 	if ((pdev->monitor_vdev == NULL) ||
 		(pdev->monitor_vdev->osif_rx_mon == NULL)) {
@@ -628,13 +629,10 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
 				tail_msdu, rs);
 
 	if (mon_mpdu) {
-		/* Push radiotap header */
-		dp_rx_extract_radiotap_info(rs, &rx_mon_status);
-
-		qdf_nbuf_update_radiotap(&rx_mon_status, mon_mpdu,
-				sizeof(struct rx_pkt_tlvs));
+		qdf_nbuf_update_radiotap(&(pdev->ppdu_info.rx_status),
+			mon_mpdu, sizeof(struct rx_pkt_tlvs));
 		pdev->monitor_vdev->osif_rx_mon(
-				pdev->monitor_vdev->osif_vdev, mon_mpdu, rs);
+				pdev->monitor_vdev->osif_vdev, mon_mpdu, NULL);
 	} else {
 		goto mon_deliver_fail;
 	}
@@ -676,8 +674,8 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota)
 	void *mon_dst_srng = pdev->rxdma_mon_dst_ring.hal_srng;
 	union dp_rx_desc_list_elem_t *head = NULL;
 	union dp_rx_desc_list_elem_t *tail = NULL;
-	struct dp_srng *dp_rxdma_srng;
-	struct rx_desc_pool *rx_desc_pool;
+	uint32_t ppdu_id;
+	uint32_t rx_bufs_used;
 
 #ifdef DP_INTR_POLL_BASED
 	if (!pdev)
@@ -687,12 +685,6 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota)
 	pdev_id = pdev->pdev_id;
 	mon_dst_srng = pdev->rxdma_mon_dst_ring.hal_srng;
 
-#if 0
-	/* Temporary only handle destination ring */
-	if (pdev->mon_ppdu_status != DP_PPDU_STATUS_DONE)
-		return;
-#endif
-
 	if (!mon_dst_srng) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 			"%s %d : HAL Monitor Destination Ring Init \
@@ -713,44 +705,40 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota)
 		return;
 	}
 
+	ppdu_id = pdev->ppdu_info.com_info.ppdu_id;
+	rx_bufs_used = 0;
 	while (qdf_likely((rxdma_dst_ring_desc =
-		hal_srng_dst_peek(hal_soc, mon_dst_srng)))) {
-			qdf_nbuf_t head_msdu, tail_msdu;
-			uint32_t rx_bufs_used = 0;
-			uint32_t npackets, ppdu_id;
-			head_msdu = (qdf_nbuf_t) NULL;
-			tail_msdu = (qdf_nbuf_t) NULL;
-
-			ppdu_id = pdev->mon_ppdu_id;
-			rx_bufs_used += dp_rx_mon_mpdu_pop(soc, mac_id,
-						rxdma_dst_ring_desc,
-						&head_msdu, &tail_msdu,
-						&npackets, &ppdu_id,
-						&head, &tail);
-#if 0
-			/* Temporary only handle destination ring */
-			if (ppdu_id != pdev->mon_ppdu_id) {
-				pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
-				break;
-			}
-#endif
-
-			dp_rx_mon_deliver(soc, mac_id, head_msdu, tail_msdu);
-
-			/* replenish function should be changed to include
-			 * ring pointer */
-			dp_rxdma_srng = &pdev->rxdma_mon_buf_ring;
-			rx_desc_pool = &soc->rx_desc_mon[pdev_id];
+		hal_srng_dst_peek(hal_soc, mon_dst_srng)) && quota--)) {
+		qdf_nbuf_t head_msdu, tail_msdu;
+		uint32_t npackets;
+		head_msdu = (qdf_nbuf_t) NULL;
+		tail_msdu = (qdf_nbuf_t) NULL;
+
+		rx_bufs_used += dp_rx_mon_mpdu_pop(soc, mac_id,
+					rxdma_dst_ring_desc,
+					&head_msdu, &tail_msdu,
+					&npackets, &ppdu_id,
+					&head, &tail);
+
+		if (ppdu_id != pdev->ppdu_info.com_info.ppdu_id) {
+			pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
+			qdf_mem_zero(&(pdev->ppdu_info.rx_status),
+				sizeof(pdev->ppdu_info.rx_status));
+			break;
+		}
 
-			dp_rx_buffers_replenish(soc, pdev_id, dp_rxdma_srng,
-				rx_desc_pool, rx_bufs_used, &head, &tail,
-				HAL_RX_BUF_RBM_SW3_BM);
+		dp_rx_mon_deliver(soc, mac_id, head_msdu, tail_msdu);
 
-			rxdma_dst_ring_desc = hal_srng_dst_get_next(hal_soc,
-				mon_dst_srng);
+		rxdma_dst_ring_desc = hal_srng_dst_get_next(hal_soc,
+			mon_dst_srng);
 	}
-
 	hal_srng_access_end(hal_soc, mon_dst_srng);
+
+	if (rx_bufs_used) {
+		dp_rx_buffers_replenish(soc, pdev_id,
+			&pdev->rxdma_mon_buf_ring, &soc->rx_desc_mon[pdev_id],
+			rx_bufs_used, &head, &tail, HAL_RX_BUF_RBM_SW3_BM);
+	}
 }
 
 static QDF_STATUS
@@ -940,12 +928,6 @@ static int dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id)
 				hal_srng_src_get_next(soc->hal_soc,
 					mon_desc_srng))) {
 
-				QDF_TRACE(QDF_MODULE_ID_TXRX,
-					QDF_TRACE_LEVEL_DEBUG,
-					"[%s][%d] desc=%p, i=%d, vaddr=%lx, paddr=%lx",
-					__func__, __LINE__, desc, i,
-					(unsigned long)vaddr, (unsigned long)paddr);
-
 				hal_set_link_desc_addr(desc, i, paddr);
 				num_entries--;
 				num_replenish_buf++;

+ 11 - 16
dp/wifi3.0/dp_rx_mon_status.c

@@ -36,7 +36,9 @@
 * Return: none
 */
 static inline void
-dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id) {
+dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id,
+	uint32_t quota)
+{
 	struct dp_pdev *pdev = soc->pdev_list[mac_id];
 	struct hal_rx_ppdu_info *ppdu_info;
 	qdf_nbuf_t status_nbuf;
@@ -73,12 +75,8 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id) {
 		qdf_nbuf_free(status_nbuf);
 
 		if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
-
 			pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE;
-			/* Temperary */
-			pdev->mon_ppdu_status =
-				DP_PPDU_STATUS_START;
-			break;
+			dp_rx_mon_dest_process(soc, mac_id, quota);
 		}
 	}
 	return;
@@ -237,8 +235,8 @@ dp_rx_mon_status_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) {
 	uint32_t work_done;
 
 	work_done = dp_rx_mon_status_srng_process(soc, mac_id, quota);
-
-	dp_rx_mon_status_process_tlv(soc, mac_id);
+	quota -= work_done;
+	dp_rx_mon_status_process_tlv(soc, mac_id, quota);
 
 	return work_done;
 }
@@ -255,14 +253,9 @@ dp_rx_mon_status_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) {
  */
 uint32_t
 dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) {
-	uint32_t work_done;
-
-	work_done = dp_rx_mon_status_process(soc, mac_id, quota);
-
-	dp_rx_mon_dest_process(soc, mac_id, quota);
-
-	return work_done;
+	return dp_rx_mon_status_process(soc, mac_id, quota);
 }
+
 /**
  * dp_rx_pdev_mon_detach() - detach dp rx for status ring
  * @pdev: core txrx pdev context
@@ -397,7 +390,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc,
 		hal_rxdma_buff_addr_info_set(rxdma_ring_entry, paddr,
 			(*desc_list)->rx_desc.cookie, owner);
 
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			"[%s][%d] rx_desc=%p, cookie=%d, nbuf=%p, \
 			status_buf=%p paddr=%p\n",
 			__func__, __LINE__, &(*desc_list)->rx_desc,
@@ -474,6 +467,8 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev) {
 	qdf_nbuf_queue_init(&pdev->rx_status_q);
 
 	pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
+	qdf_mem_zero(&(pdev->ppdu_info.rx_status),
+		sizeof(pdev->ppdu_info.rx_status));
 
 	return QDF_STATUS_SUCCESS;
 }

+ 0 - 1
dp/wifi3.0/dp_types.h

@@ -791,7 +791,6 @@ struct dp_pdev {
 	uint8_t operating_channel;
 
 	qdf_nbuf_queue_t rx_status_q;
-	uint32_t mon_ppdu_id;
 	uint32_t mon_ppdu_status;
 	struct cdp_mon_status rx_mon_recv_status;
 

+ 234 - 61
hal/wifi3.0/hal_api_mon.h

@@ -32,6 +32,7 @@
 	HAL_RX_LSB(block, field))
 
 #define HAL_RX_PHY_DATA_RADAR 0x01
+#define HAL_SU_MU_CODING_LDPC 0x01
 
 #define HAL_RX_FCS_LEN (4)
 #define KEY_EXTIV 0x20
@@ -74,6 +75,17 @@
 
 #define HAL_MAX_UL_MU_USERS			8
 
+#define HAL_RX_PKT_TYPE_11A	0
+#define HAL_RX_PKT_TYPE_11B	1
+#define HAL_RX_PKT_TYPE_11N	2
+#define HAL_RX_PKT_TYPE_11AC	3
+#define HAL_RX_PKT_TYPE_11AX	4
+
+#define HAL_RX_RECEPTION_TYPE_SU	0
+#define HAL_RX_RECEPTION_TYPE_MU_MIMO	1
+#define HAL_RX_RECEPTION_TYPE_OFDMA	2
+#define HAL_RX_RECEPTION_TYPE_MU_OFDMA	3
+
 enum {
 	HAL_HW_RX_DECAP_FORMAT_RAW = 0,
 	HAL_HW_RX_DECAP_FORMAT_NWIFI,
@@ -154,6 +166,16 @@ uint32_t HAL_RX_MON_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr)
 	return HAL_RX_GET(rx_attn, RX_ATTENTION_0, PHY_PPDU_ID);
 }
 
+/* TODO: Move all Rx descriptor functions to hal_rx.h to avoid duplication */
+static inline
+uint32_t hal_rx_desc_is_first_msdu(void *hw_desc_addr)
+{
+	struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr;
+	struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end;
+
+	return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU);
+}
+
 #define HAL_RX_BUFFER_ADDR_31_0_GET(buff_addr_info)		\
 	(_HAL_MS((*_OFFSET_TO_WORD_PTR(buff_addr_info,		\
 		BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_OFFSET)),	\
@@ -286,7 +308,7 @@ uint32 hal_get_rx_msdu_link_desc_size(void)
 
 enum {
 	HAL_PKT_TYPE_OFDM = 0,
-	HAL_CDP_PKT_TYPE_CCK,
+	HAL_PKT_TYPE_CCK,
 	HAL_PKT_TYPE_HT,
 	HAL_PKT_TYPE_VHT,
 	HAL_PKT_TYPE_HE,
@@ -313,73 +335,60 @@ enum {
 	HAL_RX_TYPE_MU_OFDMA_MIMO,
 };
 
+/**
+ * hal_rx_mon_hw_desc_get_mpdu_status: Retrieve MPDU status
+ *
+ * @ hw_desc_addr: Start address of Rx HW TLVs
+ * @ rs: Status for monitor mode
+ *
+ * Return: void
+ */
 static inline
-void HAL_RX_MON_HW_DESC_GET_PPDU_START_STATUS(void *hw_desc_addr,
-		struct cdp_mon_status *rs)
+void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr,
+		struct mon_rx_status *rs)
 {
 	struct rx_msdu_start *rx_msdu_start;
 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
-	uint32_t rx_pream_type;
-	uint32_t rx_sgi;
-	uint32_t rx_type;
-	uint32_t rx_bw;
-static  uint32_t pkt_type_hw_to_cdp[] = {
-			CDP_PKT_TYPE_OFDM,
-			CDP_PKT_TYPE_CCK,
-			CDP_PKT_TYPE_HT,
-			CDP_PKT_TYPE_VHT,
-			CDP_PKT_TYPE_HE,
-		};
-
-static  uint32_t sgi_hw_to_cdp[] = {
-			CDP_SGI_0_8_US,
-			CDP_SGI_0_4_US,
-			CDP_SGI_1_6_US,
-			CDP_SGI_3_2_US,
-		};
-
-static uint32_t rx_type_hw_to_cdp[] = {
-			CDP_RX_TYPE_SU,
-			CDP_RX_TYPE_MU_MIMO,
-			CDP_RX_TYPE_MU_OFDMA,
-			CDP_RX_TYPE_MU_OFDMA_MIMO,
-		};
-
-static uint32_t rx_bw_hw_to_cdp[] = {
-			CDP_FULL_RX_BW_20,
-			CDP_FULL_RX_BW_40,
-			CDP_FULL_RX_BW_80,
-			CDP_FULL_RX_BW_160,
-		};
-
-	rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start;
+	uint32_t reg_value;
 
-	rs->cdp_rs_tstamp.cdp_tsf = rx_msdu_start->ppdu_start_timestamp;
+	static uint32_t sgi_hw_to_cdp[] = {
+		CDP_SGI_0_8_US,
+		CDP_SGI_0_4_US,
+		CDP_SGI_1_6_US,
+		CDP_SGI_3_2_US,
+	};
 
-	rx_pream_type = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE);
-	rs->cdp_rs_pream_type = pkt_type_hw_to_cdp[rx_pream_type];
+	rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start;
 
-	rs->cdp_rs_user_rssi = HAL_RX_GET(rx_msdu_start,
+	rs->ant_signal_db = HAL_RX_GET(rx_msdu_start,
 					RX_MSDU_START_5, USER_RSSI);
-
-	rs->cdp_rs_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC);
-
-	rx_sgi = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI);
-	rs->cdp_rs_sgi  = sgi_hw_to_cdp[rx_sgi];
-
-	rs->cdf_rs_rate_mcs = HAL_RX_GET(rx_msdu_start,
+	rs->mcs = HAL_RX_GET(rx_msdu_start,
 					RX_MSDU_START_5, RATE_MCS);
+	rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC);
+
+	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI);
+	rs->sgi = sgi_hw_to_cdp[reg_value];
+	rs->nr_ant = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS);
+
+	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE);
+	switch (reg_value) {
+	case HAL_RX_PKT_TYPE_11AC:
+		rs->vht_flags = 1;
+		reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5,
+		RECEIVE_BANDWIDTH);
+		rs->vht_flag_values2 = 0x01 << reg_value;
+		rs->vht_flag_values3[0] = rs->mcs << 4;
+		break;
+	case HAL_RX_PKT_TYPE_11AX:
+		rs->he_flags = 1;
+		break;
+	default:
+		break;
+	}
 
-	rx_type = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE);
-
-	rs->cdp_rs_reception_type = rx_type_hw_to_cdp[rx_type];
-
-	rx_bw = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEIVE_BANDWIDTH);
-
-	rs->cdp_rs_bw = rx_bw_hw_to_cdp[rx_bw];
-
-	rs->cdp_rs_nss = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS);
-
+	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE);
+	rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0;
+	/* TODO: rs->beamformed should be set for SU beamforming also */
 }
 
 struct hal_rx_ppdu_user_info {
@@ -394,6 +403,7 @@ struct hal_rx_ppdu_common_info {
 struct hal_rx_ppdu_info {
 	struct hal_rx_ppdu_common_info com_info;
 	struct hal_rx_ppdu_user_info user_info[HAL_MAX_UL_MU_USERS];
+	struct mon_rx_status rx_status;
 };
 
 static inline uint32_t
@@ -404,9 +414,18 @@ hal_get_rx_status_buf_size(void) {
 
 static inline uint8_t*
 hal_rx_status_get_next_tlv(uint8_t *rx_tlv) {
-	uint32_t tlv_len;
+	uint32_t tlv_len, tlv_tag;
 
 	tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv);
+	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
+
+	/* The actual length of PPDU_END is the combined lenght of many PHY
+	 * TLVs that follow. Skip the TLV header and
+	 * rx_rxpcu_classification_overview that follows the header to get to
+	 * next TLV.
+	 */
+	if (tlv_tag == WIFIRX_PPDU_END_E)
+		tlv_len = sizeof(struct rx_rxpcu_classification_overview);
 
 	return (uint8_t *)(((unsigned long)(rx_tlv + tlv_len +
 			HAL_RX_TLV32_HDR_SIZE + 3)) & (~((unsigned long)3)));
@@ -415,7 +434,7 @@ hal_rx_status_get_next_tlv(uint8_t *rx_tlv) {
 static inline uint32_t
 hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 {
-	uint32_t tlv_tag, user_id, tlv_len;
+	uint32_t tlv_tag, user_id, tlv_len, value;
 
 	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
 	user_id = HAL_RX_GET_USER_TLV32_USERID(rx_tlv);
@@ -432,6 +451,10 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 		ppdu_info->com_info.ppdu_id =
 			HAL_RX_GET(rx_tlv, RX_PPDU_START_0,
 				PHY_PPDU_ID);
+		/* TODO: Ensure channel number is set in PHY meta data */
+		ppdu_info->rx_status.chan_freq =
+			HAL_RX_GET(rx_tlv, RX_PPDU_START_1,
+				SW_PHY_META_DATA);
 		ppdu_info->com_info.ppdu_timestamp =
 			HAL_RX_GET(rx_tlv, RX_PPDU_START_2,
 				PPDU_START_TIMESTAMP);
@@ -444,9 +467,16 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
 			"[%s][%d] ppdu_end_e len=%d\n",
 				__func__, __LINE__, tlv_len);
+		/* This is followed by sub-TLVs of PPDU_END */
 		break;
 
 	case WIFIRXPCU_PPDU_END_INFO_E:
+		ppdu_info->rx_status.tsft =
+			HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_1,
+				WB_TIMESTAMP_UPPER_32);
+		ppdu_info->rx_status.tsft = (ppdu_info->rx_status.tsft << 32) |
+			HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_0,
+				WB_TIMESTAMP_LOWER_32);
 		break;
 
 	case WIFIRX_PPDU_END_USER_STATS_E:
@@ -459,8 +489,147 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 		return HAL_TLV_STATUS_PPDU_DONE;
 
 	case WIFIDUMMY_E:
-		return HAL_TLV_STATUS_DUMMY;
+		return HAL_TLV_STATUS_PPDU_DONE;
 
+	case WIFIPHYRX_HT_SIG_E:
+	{
+		uint8_t *ht_sig_info = (uint8_t *)rx_tlv +
+				HAL_RX_OFFSET(PHYRX_HT_SIG_0,
+				HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS);
+		value = HAL_RX_GET(ht_sig_info, HT_SIG_INFO_1,
+				FEC_CODING);
+		ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ?
+			1 : 0;
+		break;
+	}
+	case WIFIPHYRX_VHT_SIG_A_E:
+	{
+		uint8_t *vht_sig_a_info = (uint8_t *)rx_tlv +
+				HAL_RX_OFFSET(PHYRX_VHT_SIG_A_0,
+				VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS);
+		value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_1,
+				SU_MU_CODING);
+		ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ?
+			1 : 0;
+		break;
+	}
+	case WIFIPHYRX_HE_SIG_A_SU_E:
+		ppdu_info->rx_status.he_sig_A1 =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_0,
+			HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_A1 |=
+			QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_SU;
+		/* TODO: Enabling all known bits. Check if this should be
+		 * enabled selectively
+		 */
+		ppdu_info->rx_status.he_sig_A1_known =
+			QDF_MON_STATUS_HE_SIG_A1_SU_KNOWN_ALL;
+		ppdu_info->rx_status.he_sig_A2 =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_1,
+			HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_A2_known =
+			QDF_MON_STATUS_HE_SIG_A2_SU_KNOWN_ALL;
+		break;
+	case WIFIPHYRX_HE_SIG_A_MU_DL_E:
+		ppdu_info->rx_status.he_sig_A1 =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_0,
+			HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_A1 |=
+			QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_MU;
+		ppdu_info->rx_status.he_sig_A1_known =
+			QDF_MON_STATUS_HE_SIG_A1_MU_KNOWN_ALL;
+
+		ppdu_info->rx_status.he_sig_A2 =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_1,
+			HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_A2_known =
+			QDF_MON_STATUS_HE_SIG_A2_MU_KNOWN_ALL;
+		break;
+	case WIFIPHYRX_HE_SIG_B1_MU_E:
+	{
+		uint8_t *he_sig_b1_mu_info = (uint8_t *)rx_tlv +
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_B1_MU_0,
+			HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS)));
+
+		ppdu_info->rx_status.he_sig_b_common_RU[0] =
+			HAL_RX_GET(he_sig_b1_mu_info, HE_SIG_B1_MU_INFO_0,
+				RU_ALLOCATION);
+
+		ppdu_info->rx_status.he_sig_b_common_known =
+			QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0;
+		/* TODO: Check on the availability of other fields in
+		 * sig_b_common
+		 */
+		break;
+	}
+	case WIFIPHYRX_HE_SIG_B2_MU_E:
+		ppdu_info->rx_status.he_sig_b_user =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_B2_MU_0,
+			HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_b_user_known =
+			QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL;
+		break;
+	case WIFIPHYRX_HE_SIG_B2_OFDMA_E:
+		ppdu_info->rx_status.he_sig_b_user =
+			*((uint32_t *)((uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_HE_SIG_B2_OFDMA_0,
+			HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS)));
+		ppdu_info->rx_status.he_sig_b_user_known =
+			QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL;
+		break;
+	case WIFIPHYRX_RSSI_LEGACY_E:
+	{
+		uint8_t *rssi_info_tlv = (uint8_t *)rx_tlv +
+			HAL_RX_OFFSET(PHYRX_RSSI_LEGACY_3,
+			RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_PRI20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_0, RSSI_EXT20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_0, RSSI_EXT40_LOW20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT40_LOW20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_0, RSSI_EXT40_HIGH20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT40_HIGH20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT80_LOW20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW_HIGH20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT80_LOW_HIGH20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH_LOW20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT80_HIGH_LOW20_CHAIN0: %d\n", value);
+
+		value = HAL_RX_GET(rssi_info_tlv,
+			RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH20_CHAIN0);
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+			"RSSI_EXT80_HIGH20_CHAIN0: %d\n", value);
+		break;
+	}
 	case 0:
 		return HAL_TLV_STATUS_PPDU_DONE;
 
@@ -468,6 +637,10 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
 		break;
 	}
 
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+		"%s TLV type: %d, TLV len:%d\n",
+		__func__, tlv_tag, tlv_len);
+
 	return HAL_TLV_STATUS_PPDU_NOT_DONE;
 }
 

+ 11 - 0
hal/wifi3.0/hal_internal.h

@@ -64,7 +64,18 @@
 #include "rx_ppdu_end_user_stats.h"
 #include "rx_ppdu_end_user_stats_ext.h"
 #include "rx_mpdu_desc_info.h"
+#include "rxpcu_ppdu_end_info.h"
+#include "phyrx_he_sig_a_su.h"
+#include "phyrx_he_sig_a_mu_dl.h"
+#include "phyrx_he_sig_b1_mu.h"
+#include "phyrx_he_sig_b2_mu.h"
+#include "phyrx_he_sig_b2_ofdma.h"
+#include "phyrx_vht_sig_a.h"
+#include "phyrx_ht_sig.h"
 #include "tx_msdu_extension.h"
+#include "receive_rssi_info.h"
+#include "phyrx_pkt_end.h"
+#include "phyrx_rssi_legacy.h"
 #include "wcss_version.h"
 #include "pld_common.h"
 #include "rx_msdu_link.h"

+ 12 - 0
qdf/inc/qdf_nbuf.h

@@ -178,6 +178,18 @@ struct mon_rx_status {
 	uint8_t  he_sig_b_common_RU[4];
 };
 
+/* Masks for HE SIG known fields in mon_rx_status structure */
+#define QDF_MON_STATUS_HE_SIG_A1_SU_KNOWN_ALL		0x000007ff
+#define QDF_MON_STATUS_HE_SIG_A1_MU_KNOWN_ALL		0x000003ff
+#define QDF_MON_STATUS_HE_SIG_A2_SU_KNOWN_ALL		0x00000ffd
+#define QDF_MON_STATUS_HE_SIG_A2_MU_KNOWN_ALL		0x00000ffd
+#define QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0	0x00000001
+#define QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL	0x00fe0000
+#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_SU		0x00000000
+#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_EXT_SU	0x40000000
+#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_MU		0x80000000
+#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_TRIG		0xc0000000
+
 /* DHCP Related Mask */
 #define QDF_DHCP_OPTION53			(0x35)
 #define QDF_DHCP_OPTION53_LENGTH		(1)

+ 1 - 1
qdf/linux/src/qdf_nbuf.c

@@ -2752,7 +2752,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
 		qdf_print("ERROR: not enough space to update radiotap\n");
 		return 0;
 	}
-	qdf_nbuf_pull_head(nbuf, headroom_sz  - rtap_len);
+	qdf_nbuf_push_head(nbuf, rtap_len);
 	qdf_mem_copy(qdf_nbuf_data(nbuf), rtap_buf, rtap_len);
 	return rtap_len;
 }