Browse Source

qcacmn: Make HTT PPDU TLV processing backward compatible

For HTT PPDU Stats TLVs, if target has provided less data than expected,
pad the data with zeros until it matches the expected length and
process the TLV, instead of     asserting.

This enables testing of different FW and Host versions during regression
analysis.

CRs-Fixed: 2451611
Change-Id: I79aaad8a6fde6d49510c3a212b21425ac784ad5c
Tallapragada Kalyan 5 years ago
parent
commit
f7b0f745c4
4 changed files with 118 additions and 35 deletions
  1. 87 35
      dp/wifi3.0/dp_htt.c
  2. 1 0
      dp/wifi3.0/dp_htt.h
  3. 28 0
      dp/wifi3.0/dp_main.c
  4. 2 0
      dp/wifi3.0/dp_types.h

+ 87 - 35
dp/wifi3.0/dp_htt.c

@@ -36,7 +36,6 @@
 #define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE
 
 #define HTT_HTC_PKT_POOL_INIT_SIZE 64
-#define HTT_T2H_MAX_MSG_SIZE 2048
 
 #define HTT_MSG_BUF_SIZE(msg_bytes) \
 	((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
@@ -2489,6 +2488,38 @@ dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(struct dp_pdev *pdev,
 	return QDF_STATUS_E_ALREADY;
 }
 
+/**
+ * dp_validate_fix_ppdu_tlv(): Function to validate the length of PPDU
+ *
+ * If the TLV length sent as part of PPDU TLV is less that expected size i.e
+ * size of corresponding data structure, pad the remaining bytes with zeros
+ * and continue processing the TLVs
+ *
+ * @pdev: DP pdev handle
+ * @tag_buf: TLV buffer
+ * @tlv_expected_size: Expected size of Tag
+ * @tlv_len: TLV length received from FW
+ *
+ * Return: Pointer to updated TLV
+ */
+static inline uint32_t *dp_validate_fix_ppdu_tlv(struct dp_pdev *pdev,
+						 uint32_t *tag_buf,
+						 uint16_t tlv_expected_size,
+						 uint16_t tlv_len)
+{
+	uint32_t *tlv_desc = tag_buf;
+
+	qdf_assert_always(tlv_len != 0);
+
+	if (tlv_len < tlv_expected_size) {
+		qdf_mem_zero(pdev->ppdu_tlv_buf, tlv_expected_size);
+		qdf_mem_copy(pdev->ppdu_tlv_buf, tag_buf, tlv_len);
+		tlv_desc = pdev->ppdu_tlv_buf;
+	}
+
+	return tlv_desc;
+}
+
 /**
  * dp_process_ppdu_tag(): Function to process the PPDU TLVs
  * @pdev: DP pdev handle
@@ -2502,71 +2533,92 @@ static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf,
 		uint32_t tlv_len, struct ppdu_info *ppdu_info)
 {
 	uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf);
+	uint16_t tlv_expected_size;
+	uint32_t *tlv_desc;
 
 	switch (tlv_type) {
 	case HTT_PPDU_STATS_COMMON_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_common_tlv));
-		dp_process_ppdu_stats_common_tlv(pdev, tag_buf, ppdu_info);
+		tlv_expected_size = sizeof(htt_ppdu_stats_common_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
+		dp_process_ppdu_stats_common_tlv(pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMMON_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_user_common_tlv));
-		dp_process_ppdu_stats_user_common_tlv(
-				pdev, tag_buf, ppdu_info);
+		tlv_expected_size = sizeof(htt_ppdu_stats_user_common_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
+		dp_process_ppdu_stats_user_common_tlv(pdev, tlv_desc,
+						      ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_RATE_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_user_rate_tlv));
-		dp_process_ppdu_stats_user_rate_tlv(pdev, tag_buf, ppdu_info);
+		tlv_expected_size = sizeof(htt_ppdu_stats_user_rate_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
+		dp_process_ppdu_stats_user_rate_tlv(pdev, tlv_desc,
+						    ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_enq_mpdu_bitmap_64_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_enq_mpdu_bitmap_64_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_256_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_enq_mpdu_bitmap_256_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_enq_mpdu_bitmap_256_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV:
-		qdf_assert_always(tlv_len >=
-				sizeof(htt_ppdu_stats_user_cmpltn_common_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_user_cmpltn_common_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_cmpltn_common_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV:
-		qdf_assert_always(tlv_len >=
-			sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV:
-		qdf_assert_always(tlv_len >=
-			sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV:
-		qdf_assert_always(tlv_len >=
-			sizeof(htt_ppdu_stats_user_compltn_ack_ba_status_tlv));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_user_compltn_ack_ba_status_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMMON_ARRAY_TLV:
-		qdf_assert_always(tlv_len >=
-			sizeof(htt_ppdu_stats_usr_common_array_tlv_v));
+		tlv_expected_size =
+			sizeof(htt_ppdu_stats_usr_common_array_tlv_v);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_common_array_tlv(
-				pdev, tag_buf, ppdu_info);
+				pdev, tlv_desc, ppdu_info);
 		break;
 	case HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV:
-		qdf_assert_always(tlv_len >=
-			sizeof(htt_ppdu_stats_flush_tlv));
+		tlv_expected_size = sizeof(htt_ppdu_stats_flush_tlv);
+		tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf,
+						    tlv_expected_size, tlv_len);
 		dp_process_ppdu_stats_user_compltn_flush_tlv(
-				pdev, tag_buf);
+				pdev, tlv_desc);
 		break;
 	default:
 		break;

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

@@ -60,6 +60,7 @@
 #define DP_SCAN_PEER_ID 0xFFFF
 
 #define DP_HTT_HTC_PKT_MISCLIST_SIZE          256
+#define HTT_T2H_MAX_MSG_SIZE 2048
 
 #define HTT_T2H_EXT_STATS_TLV_START_OFFSET    3
 

+ 28 - 0
dp/wifi3.0/dp_main.c

@@ -3240,6 +3240,26 @@ void  dp_iterate_update_peer_list(void *pdev_hdl)
 {
 }
 #endif
+
+/*
+ * dp_htt_ppdu_stats_attach() - attach resources for HTT PPDU stats processing
+ * @pdev: Datapath PDEV handle
+ *
+ * Return: QDF_STATUS_SUCCESS: Success
+ *         QDF_STATUS_E_NOMEM: Error
+ */
+static QDF_STATUS dp_htt_ppdu_stats_attach(struct dp_pdev *pdev)
+{
+	pdev->ppdu_tlv_buf = qdf_mem_malloc(HTT_T2H_MAX_MSG_SIZE);
+
+	if (!pdev->ppdu_tlv_buf) {
+		QDF_TRACE_ERROR(QDF_MODULE_ID_DP, "ppdu_tlv_buf alloc fail");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /*
 * dp_pdev_attach_wifi3() - attach txrx pdev
 * @ctrl_pdev: Opaque PDEV object
@@ -3479,6 +3499,10 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 	qdf_event_create(&pdev->fw_peer_stats_event);
 
 	pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
+
+	if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS)
+		goto fail1;
+
 	dp_tx_ppdu_stats_attach(pdev);
 
 	return (struct cdp_pdev *)pdev;
@@ -3558,6 +3582,10 @@ static void dp_htt_ppdu_stats_detach(struct dp_pdev *pdev)
 		qdf_nbuf_free(ppdu_info->nbuf);
 		qdf_mem_free(ppdu_info);
 	}
+
+	if (pdev->ppdu_tlv_buf)
+		qdf_mem_free(pdev->ppdu_tlv_buf);
+
 }
 
 #if !defined(DISABLE_MON_CONFIG)

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

@@ -1597,6 +1597,8 @@ struct dp_pdev {
 	struct dp_pdev_tx_capture tx_capture;
 	/* stats counter for tx ppdu processed */
 	uint64_t tx_ppdu_proc;
+
+	uint32_t *ppdu_tlv_buf; /* Buffer to hold HTT ppdu stats TLVs*/
 };
 
 struct dp_peer;