qcacmn: Fix the ppdu id and buffer reading issue

Read the ppdu id from MPDU start TLV instead of
ATTENTION TLV. The MPDU could extend to multiple
SKB buffer. The ATTENTION TLV will be in the TLV
of last SKB buffer. MPDU start will be in the
first SKB buffer in MPDU. Read ppdu id from MPDU
start TLV guarentee the correct reading
The msdu count in MPDU from REO entrance ring is for
msdu count for decap frame or MPDU count for not decap
frame. msdu length in msdu desc info is for msdu
length for decap frame or MPDU length for not decap
frame. The MPDU could extend to multiple SKB.
The continous bit in msdu desc info indicate if
the MPDU/MSDU extend to next SKB. code is modified
accordingly.

Change-Id: If9aeb278f84a57d64651e1f877b5185f6db63cd2
diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c
index b691bc9..ebfc4f4 100644
--- a/dp/wifi3.0/dp_rx_err.c
+++ b/dp/wifi3.0/dp_rx_err.c
@@ -963,7 +963,6 @@
 	uint32_t rx_bufs_used = 0;
 	uint32_t msdu_cnt;
 	uint32_t i;
-	bool mpdu_err;
 	uint8_t push_reason;
 	uint8_t rxdma_error_code = 0;
 
@@ -972,7 +971,7 @@
 	last = NULL;
 
 	hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info,
-		&p_last_buf_addr_info, &msdu_cnt, &mpdu_err);
+		&p_last_buf_addr_info, &msdu_cnt);
 
 	push_reason =
 		hal_rx_reo_ent_rxdma_push_reason_get(rxdma_dst_ring_desc);
diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c
index 7d337df..da478a2 100644
--- a/dp/wifi3.0/dp_rx_mon_dest.c
+++ b/dp/wifi3.0/dp_rx_mon_dest.c
@@ -85,6 +85,27 @@
 }
 
 /**
+ * dp_mon_adjust_frag_len() - MPDU and MSDU may spread across
+ *				multiple nbufs. This function
+ *                              is to return data length in
+ *				fragmented buffer
+ *
+ * @total_len: pointer to remaining data length.
+ * @frag_len: poiter to data length in this fragment.
+*/
+static inline void dp_mon_adjust_frag_len(uint32_t *total_len,
+uint32_t *frag_len)
+{
+	if (*total_len >= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN)) {
+		*frag_len = RX_BUFFER_SIZE - RX_PKT_TLVS_LEN;
+		*total_len -= *frag_len;
+	} else {
+		*frag_len = *total_len;
+		*total_len = 0;
+	}
+}
+
+/**
  * dp_rx_mon_mpdu_pop() - Return a MPDU link descriptor to HW
  *			      (WBM), following error handling
  *
@@ -121,14 +142,23 @@
 	uint32_t msdu_ppdu_id, msdu_cnt;
 	uint8_t *data;
 	uint32_t i;
-	bool mpdu_fcs_err;
+	bool mpdu_err = false;
+	uint32_t total_frag_len, frag_len;
+	bool is_frag, is_first_msdu;
 
 	msdu = 0;
 
 	last = NULL;
 
 	hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info,
-		&p_last_buf_addr_info, &msdu_cnt, &mpdu_fcs_err);
+		&p_last_buf_addr_info, &msdu_cnt);
+
+	if(HAL_RX_WBM_RXDMA_PSH_RSN_ERROR ==
+		hal_rx_reo_ent_rxdma_push_reason_get(rxdma_dst_ring_desc))
+		mpdu_err = true;
+
+	is_frag = false;
+	is_first_msdu = true;
 
 	do {
 		rx_msdu_link_desc =
@@ -136,13 +166,8 @@
 
 		qdf_assert(rx_msdu_link_desc);
 
-		num_msdus = (msdu_cnt > HAL_RX_NUM_MSDU_DESC) ?
-			HAL_RX_NUM_MSDU_DESC:msdu_cnt;
-
 		hal_rx_msdu_list_get(rx_msdu_link_desc, &msdu_list, &num_msdus);
 
-		msdu_cnt -= num_msdus;
-
 		for (i = 0; i < num_msdus; i++) {
 			uint32_t l2_hdr_offset;
 			struct dp_rx_desc *rx_desc =
@@ -163,8 +188,12 @@
 					__func__, __LINE__, msdu, data);
 
 				rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data);
-				msdu_ppdu_id =
+
+				if(is_first_msdu) {
+					msdu_ppdu_id =
 					HAL_RX_MON_HW_DESC_GET_PPDUID_GET(rx_desc_tlv);
+					is_first_msdu = false;
+				}
 
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					QDF_TRACE_LEVEL_DEBUG,
@@ -179,7 +208,7 @@
 					__func__, __LINE__, *ppdu_id,
 					msdu_ppdu_id);
 
-				if (*ppdu_id != msdu_ppdu_id) {
+				if ((*ppdu_id != msdu_ppdu_id) && !mpdu_err) {
 					*ppdu_id = msdu_ppdu_id;
 					return rx_bufs_used;
 				}
@@ -188,6 +217,28 @@
 					hal_rx_mon_hw_desc_get_mpdu_status(rx_desc_tlv,
 						&(dp_pdev->ppdu_info.rx_status));
 
+
+				if(msdu_list.msdu_info[i].msdu_flags &
+					HAL_MSDU_F_MSDU_CONTINUATION) {
+					if(!is_frag) {
+						total_frag_len =
+						msdu_list.msdu_info[i].msdu_len;
+						is_frag = true;
+					}
+					dp_mon_adjust_frag_len(
+						&total_frag_len, &frag_len);
+				} else {
+					if(is_frag) {
+						dp_mon_adjust_frag_len(
+							&total_frag_len, &frag_len);
+					} else {
+						frag_len =
+						msdu_list.msdu_info[i].msdu_len;
+					}
+					is_frag = false;
+					msdu_cnt--;
+				}
+
 				rx_pkt_offset = HAL_RX_MON_HW_RX_DESC_SIZE();
 				/*
 				 * HW structures call this L3 header padding
@@ -199,7 +250,7 @@
 				hal_rx_msdu_end_l3_hdr_padding_get(data);
 
 				rx_buf_size = rx_pkt_offset + l2_hdr_offset
-					+ msdu_list.msdu_info[i].msdu_len;
+					+ frag_len;
 
 				qdf_nbuf_set_pktlen(msdu, rx_buf_size);
 
diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h
index 5e6d31a..51bc4bc 100644
--- a/dp/wifi3.0/hal_rx.h
+++ b/dp/wifi3.0/hal_rx.h
@@ -1683,21 +1683,17 @@
 	struct rx_msdu_link *msdu_link = (struct rx_msdu_link *)msdu_link_desc;
 	int i;
 
-	if (*num_msdus > HAL_RX_NUM_MSDU_DESC)
-		*num_msdus = HAL_RX_NUM_MSDU_DESC;
-
 	msdu_details = HAL_RX_LINK_DESC_MSDU0_PTR(msdu_link);
 
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 		"[%s][%d] msdu_link=%p msdu_details=%p\n",
 		__func__, __LINE__, msdu_link, msdu_details);
 
-	for (i = 0; i < *num_msdus; i++) {
+	for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) {
 		/* num_msdus received in mpdu descriptor may be incorrect
 		 * sometimes due to HW issue. Check msdu buffer address also */
 		if (HAL_RX_BUFFER_ADDR_31_0_GET(
 			&msdu_details[i].buffer_addr_info_details) == 0) {
-			*num_msdus = i;
 			break;
 		}
 		msdu_desc_info = HAL_RX_MSDU_DESC_INFO_GET(&msdu_details[i]);
@@ -1713,6 +1709,7 @@
 			"[%s][%d] i=%d sw_cookie=%d\n",
 			__func__, __LINE__, i, msdu_list->sw_cookie[i]);
 	}
+	*num_msdus = i;
 }
 
 /**
diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h
index 8c47ab5..50ec3dc 100644
--- a/hal/wifi3.0/hal_api_mon.h
+++ b/hal/wifi3.0/hal_api_mon.h
@@ -158,12 +158,13 @@
 static inline
 uint32_t HAL_RX_MON_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr)
 {
-	struct rx_attention *rx_attn;
+	struct rx_mpdu_info *rx_mpdu_info;
 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
 
-	rx_attn = &rx_desc->attn_tlv.rx_attn;
+	rx_mpdu_info =
+		&rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details;
 
-	return HAL_RX_GET(rx_attn, RX_ATTENTION_0, PHY_PPDU_ID);
+	return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID);
 }
 
 /* TODO: Move all Rx descriptor functions to hal_rx.h to avoid duplication */
@@ -205,15 +206,13 @@
  * the current descriptor
  * @ buf_info: structure to return the buffer information
  * @ msdu_cnt: pointer to msdu count in MPDU
- * @ mpdu_fcs_err: pointer to valuable of mpdu fcs error
  * Return: void
  */
 static inline
 void hal_rx_reo_ent_buf_paddr_get(void *rx_desc,
 	struct hal_buf_info *buf_info,
 	void **pp_buf_addr_info,
-	uint32_t *msdu_cnt,
-	bool *mpdu_fcs_err
+	uint32_t *msdu_cnt
 )
 {
 	struct reo_entrance_ring *reo_ent_ring =
@@ -221,24 +220,10 @@
 	struct buffer_addr_info *buf_addr_info;
 	struct rx_mpdu_desc_info *rx_mpdu_desc_info_details;
 	uint32_t loop_cnt;
-	uint32_t rxdma_push_reason;
-	uint32_t rxdma_error_code;
 
 	rx_mpdu_desc_info_details =
 	&reo_ent_ring->reo_level_mpdu_frame_info.rx_mpdu_desc_info_details;
 
-	rxdma_push_reason = HAL_RX_GET(reo_ent_ring, REO_ENTRANCE_RING_6,
-			RXDMA_PUSH_REASON);
-
-	*mpdu_fcs_err = false;
-
-	if (rxdma_push_reason == HAL_RX_WBM_RXDMA_PSH_RSN_ERROR) {
-		rxdma_error_code = HAL_RX_GET(reo_ent_ring,
-			REO_ENTRANCE_RING_6, RXDMA_ERROR_CODE);
-		if (rxdma_error_code == HAL_RXDMA_ERR_FCS)
-			*mpdu_fcs_err = true;
-	}
-
 	*msdu_cnt = HAL_RX_GET(rx_mpdu_desc_info_details,
 				RX_MPDU_DESC_INFO_0, MSDU_COUNT);