From f7b0f745c4ce47860bd1e448f2c9c3e951b0442e Mon Sep 17 00:00:00 2001 From: Tallapragada Kalyan Date: Tue, 14 May 2019 16:59:42 +0530 Subject: [PATCH] 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 --- dp/wifi3.0/dp_htt.c | 122 ++++++++++++++++++++++++++++++------------ dp/wifi3.0/dp_htt.h | 1 + dp/wifi3.0/dp_main.c | 28 ++++++++++ dp/wifi3.0/dp_types.h | 2 + 4 files changed, 118 insertions(+), 35 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index be9fd113f078..400d2ce9c4f3 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/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; diff --git a/dp/wifi3.0/dp_htt.h b/dp/wifi3.0/dp_htt.h index 84e10abe9d30..c085d93be375 100644 --- a/dp/wifi3.0/dp_htt.h +++ b/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 diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index fa538f5c9d27..ec33fbfbafa2 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 4cd275c73349..c6543e1e7d7a 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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;