diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index c4f20cae85..cc27f0c072 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -2634,6 +2634,7 @@ struct cdp_per_cpu_packets { * @tx.desc_in_use: Descriptors in use at soc * @tx.dropped_fw_removed: HW_release_reason == FW removed * @tx.invalid_release_source: tx completion release_src != HW or FW + * @tx.invalid_tx_comp_desc: TX Desc from completion ring Desc is not valid * @tx.wifi_internal_error: tx completion wifi_internal_error * @tx.non_wifi_internal_err: tx completion non_wifi_internal_error * @tx.tx_comp_loop_pkt_limit_hit: TX Comp loop packet limit hit @@ -2717,6 +2718,7 @@ struct cdp_soc_stats { uint32_t desc_in_use; uint32_t dropped_fw_removed; uint32_t invalid_release_source; + uint32_t invalid_tx_comp_desc; uint32_t wifi_internal_error[CDP_MAX_WIFI_INT_ERROR_REASONS]; uint32_t non_wifi_internal_err; uint32_t tx_comp_loop_pkt_limit_hit; diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index 7d9263eb1b..b6811b4c79 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/dp/wifi3.0/be/dp_be_tx.c @@ -79,29 +79,60 @@ struct dp_mlo_mpass_buf { extern uint8_t sec_type_map[MAX_CDP_SEC_TYPE]; -#ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH -static inline uint16_t dp_tx_comp_get_peer_id(struct dp_soc *soc, - void *tx_comp_hal_desc) -{ - uint16_t peer_id = hal_tx_comp_get_peer_id(tx_comp_hal_desc); - struct dp_tx_comp_peer_id *tx_peer_id = - (struct dp_tx_comp_peer_id *)&peer_id; +#ifdef DP_TX_COMP_RING_DESC_SANITY_CHECK +/* + * Value to mark ring desc is invalidated by buffer_virt_addr_63_32 field + * of WBM2SW ring Desc. + */ +#define DP_TX_COMP_DESC_BUFF_VA_32BITS_HI_INVALIDATE 0x12121212 - return (tx_peer_id->peer_id | - (tx_peer_id->ml_peer_valid << soc->peer_id_shift)); +/** + * dp_tx_comp_desc_check_and_invalidate() - sanity check for ring desc and + * invalidate it after each reaping + * @tx_comp_hal_desc: ring desc virtual address + * @r_tx_desc: pointer to current dp TX Desc pointer + * @tx_desc_va: the original 64 bits Desc VA got from ring Desc + * @hw_cc_done: HW cookie conversion done or not + * + * If HW CC is done, check the buffer_virt_addr_63_32 value to know if + * ring Desc is stale or not. if HW CC is not done, then compare PA between + * ring Desc and current TX desc. + * + * Return: None. + */ +static inline +void dp_tx_comp_desc_check_and_invalidate(void *tx_comp_hal_desc, + struct dp_tx_desc_s **r_tx_desc, + uint64_t tx_desc_va, + bool hw_cc_done) +{ + qdf_dma_addr_t desc_dma_addr; + + if (qdf_likely(hw_cc_done)) { + /* Check upper 32 bits */ + if (DP_TX_COMP_DESC_BUFF_VA_32BITS_HI_INVALIDATE == + (tx_desc_va >> 32)) + *r_tx_desc = NULL; + + /* Invalidate the ring desc for 32 ~ 63 bits of VA */ + hal_tx_comp_set_desc_va_63_32( + tx_comp_hal_desc, + DP_TX_COMP_DESC_BUFF_VA_32BITS_HI_INVALIDATE); + } else { + /* Compare PA between ring desc and current TX desc stored */ + desc_dma_addr = hal_tx_comp_get_paddr(tx_comp_hal_desc); + + if (desc_dma_addr != (*r_tx_desc)->dma_addr) + *r_tx_desc = NULL; + } } #else -/* Combine ml_peer_valid and peer_id field */ -#define DP_BE_TX_COMP_PEER_ID_MASK 0x00003fff -#define DP_BE_TX_COMP_PEER_ID_SHIFT 0 - -static inline uint16_t dp_tx_comp_get_peer_id(struct dp_soc *soc, - void *tx_comp_hal_desc) +static inline +void dp_tx_comp_desc_check_and_invalidate(void *tx_comp_hal_desc, + struct dp_tx_desc_s **r_tx_desc, + uint64_t tx_desc_va, + bool hw_cc_done) { - uint16_t peer_id = hal_tx_comp_get_peer_id(tx_comp_hal_desc); - - return ((peer_id & DP_BE_TX_COMP_PEER_ID_MASK) >> - DP_BE_TX_COMP_PEER_ID_SHIFT); } #endif @@ -112,12 +143,15 @@ void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc, struct dp_tx_desc_s **r_tx_desc) { uint32_t tx_desc_id; + uint64_t tx_desc_va = 0; + bool hw_cc_done = + hal_tx_comp_get_cookie_convert_done(tx_comp_hal_desc); - if (qdf_likely( - hal_tx_comp_get_cookie_convert_done(tx_comp_hal_desc))) { + if (qdf_likely(hw_cc_done)) { /* HW cookie conversion done */ - *r_tx_desc = (struct dp_tx_desc_s *) - hal_tx_comp_get_desc_va(tx_comp_hal_desc); + tx_desc_va = hal_tx_comp_get_desc_va(tx_comp_hal_desc); + *r_tx_desc = (struct dp_tx_desc_s *)(uintptr_t)tx_desc_va; + } else { /* SW do cookie conversion to VA */ tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc); @@ -125,21 +159,33 @@ void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc, (struct dp_tx_desc_s *)dp_cc_desc_find(soc, tx_desc_id); } + dp_tx_comp_desc_check_and_invalidate(tx_comp_hal_desc, + r_tx_desc, tx_desc_va, + hw_cc_done); + if (*r_tx_desc) - (*r_tx_desc)->peer_id = dp_tx_comp_get_peer_id(soc, - tx_comp_hal_desc); + (*r_tx_desc)->peer_id = + dp_tx_comp_get_peer_id_be(soc, + tx_comp_hal_desc); } #else void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc, void *tx_comp_hal_desc, struct dp_tx_desc_s **r_tx_desc) { - *r_tx_desc = (struct dp_tx_desc_s *) - hal_tx_comp_get_desc_va(tx_comp_hal_desc); + uint64_t tx_desc_va; + tx_desc_va = hal_tx_comp_get_desc_va(tx_comp_hal_desc); + *r_tx_desc = (struct dp_tx_desc_s *)(uintptr_t)tx_desc_va; + + dp_tx_comp_desc_check_and_invalidate(tx_comp_hal_desc, + r_tx_desc, + tx_desc_va, + true); if (*r_tx_desc) - (*r_tx_desc)->peer_id = dp_tx_comp_get_peer_id(soc, - tx_comp_hal_desc); + (*r_tx_desc)->peer_id = + dp_tx_comp_get_peer_id_be(soc, + tx_comp_hal_desc); } #endif /* DP_HW_COOKIE_CONVERT_EXCEPTION */ #else @@ -155,9 +201,14 @@ void dp_tx_comp_get_params_from_hal_desc_be(struct dp_soc *soc, *r_tx_desc = (struct dp_tx_desc_s *)dp_cc_desc_find(soc, tx_desc_id); + dp_tx_comp_desc_check_and_invalidate(tx_comp_hal_desc, + r_tx_desc, 0, + false); + if (*r_tx_desc) - (*r_tx_desc)->peer_id = dp_tx_comp_get_peer_id(soc, - tx_comp_hal_desc); + (*r_tx_desc)->peer_id = + dp_tx_comp_get_peer_id_be(soc, + tx_comp_hal_desc); } #endif /* DP_FEATURE_HW_COOKIE_CONVERSION */ diff --git a/dp/wifi3.0/be/dp_be_tx.h b/dp/wifi3.0/be/dp_be_tx.h index 902c34b99a..6492dab71e 100644 --- a/dp/wifi3.0/be/dp_be_tx.h +++ b/dp/wifi3.0/be/dp_be_tx.h @@ -49,6 +49,33 @@ struct __attribute__((__packed__)) dp_tx_comp_peer_id { #define DP_TX_FAST_DESC_SIZE 24 #define DP_TX_L3_L4_CSUM_ENABLE 0x1f +#ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH +/** + * dp_tx_comp_get_peer_id_be() - Get peer ID from TX Comp Desc + * @soc: Handle to DP Soc structure + * @tx_comp_hal_desc: TX comp ring descriptor + * + * Return: Peer ID + */ +static inline uint16_t dp_tx_comp_get_peer_id_be(struct dp_soc *soc, + void *tx_comp_hal_desc) +{ + uint16_t peer_id = hal_tx_comp_get_peer_id(tx_comp_hal_desc); + struct dp_tx_comp_peer_id *tx_peer_id = + (struct dp_tx_comp_peer_id *)&peer_id; + + return (tx_peer_id->peer_id | + (tx_peer_id->ml_peer_valid << soc->peer_id_shift)); +} +#else +static inline uint16_t dp_tx_comp_get_peer_id_be(struct dp_soc *soc, + void *tx_comp_hal_desc) +{ + return hal_tx_comp_get_peer_id(tx_comp_hal_desc); + +} +#endif + /** * dp_tx_hw_enqueue_be() - Enqueue to TCL HW for transmit for BE target * @soc: DP Soc Handle diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index d3020948c8..aeba7f15cf 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -7165,6 +7165,8 @@ void dp_txrx_path_stats(struct dp_soc *soc) DP_PRINT_STATS("Invalid release source: %u", soc->stats.tx.invalid_release_source); + DP_PRINT_STATS("Invalid TX desc from completion ring: %u", + soc->stats.tx.invalid_tx_comp_desc); DP_PRINT_STATS("Dropped in host:"); DP_PRINT_STATS("Total packets dropped: %u,", pdev->stats.tx_i.dropped.dropped_pkt.num); @@ -7714,6 +7716,8 @@ dp_print_soc_tx_stats(struct dp_soc *soc) soc->stats.tx.tcl_ring_full[3]); DP_PRINT_STATS("Tx invalid completion release = %u", soc->stats.tx.invalid_release_source); + DP_PRINT_STATS("TX invalid Desc from completion ring = %u", + soc->stats.tx.invalid_tx_comp_desc); DP_PRINT_STATS("Tx comp wbm internal error = %d : [%d %d %d %d]", soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_ALL], soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_BUFFER], @@ -8860,6 +8864,8 @@ QDF_STATUS dp_txrx_get_soc_stats(struct cdp_soc_t *soc_hdl, soc_stats->tx.dropped_fw_removed = soc->stats.tx.dropped_fw_removed; soc_stats->tx.invalid_release_source = soc->stats.tx.invalid_release_source; + soc_stats->tx.invalid_tx_comp_desc = + soc->stats.tx.invalid_tx_comp_desc; for (inx = 0; inx < CDP_MAX_WIFI_INT_ERROR_REASONS; inx++) soc_stats->tx.wifi_internal_error[inx] = soc->stats.tx.wbm_internal_error[inx]; diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 152ca5cc4c..d6cd1be410 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -5825,8 +5825,10 @@ more_data: soc->arch_ops.tx_comp_get_params_from_hal_desc(soc, tx_comp_hal_desc, &tx_desc); - if (!tx_desc) { + if (qdf_unlikely(!tx_desc)) { dp_err("unable to retrieve tx_desc!"); + hal_dump_comp_desc(tx_comp_hal_desc); + DP_STATS_INC(soc, tx.invalid_tx_comp_desc, 1); QDF_BUG(0); continue; } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 017d27cf9a..c9383bf8c5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1097,6 +1097,8 @@ struct dp_soc_stats { uint32_t dropped_fw_removed; /* tx completion release_src != TQM or FW */ uint32_t invalid_release_source; + /* TX descriptor from completion ring Desc is not valid */ + uint32_t invalid_tx_comp_desc; /* tx completion wbm_internal_error */ uint32_t wbm_internal_error[MAX_WBM_INT_ERROR_REASONS]; /* tx completion non_wbm_internal_error */ @@ -1885,9 +1887,9 @@ struct dp_arch_ops { struct cdp_tx_exception_metadata *metadata, struct dp_tx_msdu_info_s *msdu_info); - void (*tx_comp_get_params_from_hal_desc)(struct dp_soc *soc, - void *tx_comp_hal_desc, - struct dp_tx_desc_s **desc); + void (*tx_comp_get_params_from_hal_desc)(struct dp_soc *soc, + void *tx_comp_hal_desc, + struct dp_tx_desc_s **desc); void (*dp_tx_process_htt_completion)(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, uint8_t *status, diff --git a/hal/wifi3.0/be/hal_be_tx.h b/hal/wifi3.0/be/hal_be_tx.h index b8ba5e5447..5621b173cc 100644 --- a/hal/wifi3.0/be/hal_be_tx.h +++ b/hal/wifi3.0/be/hal_be_tx.h @@ -570,6 +570,20 @@ static inline uint8_t hal_tx_comp_get_cookie_convert_done(void *hal_desc) } #endif +/** + * hal_tx_comp_set_desc_va_63_32() - Set bit 32~63 value for 64 bit VA + * @hal_desc: completion ring descriptor pointer + * @val: value to be set + * + * Return: None + */ +static inline void hal_tx_comp_set_desc_va_63_32(void *hal_desc, uint32_t val) +{ + HAL_SET_FLD(hal_desc, + WBM2SW_COMPLETION_RING_TX, + BUFFER_VIRT_ADDR_63_32) = val; +} + /** * hal_tx_comp_get_desc_va() - Get Desc virtual address within completion Desc * @hal_desc: completion ring descriptor pointer @@ -578,7 +592,7 @@ static inline uint8_t hal_tx_comp_get_cookie_convert_done(void *hal_desc) * * Return: TX desc virtual address */ -static inline uintptr_t hal_tx_comp_get_desc_va(void *hal_desc) +static inline uint64_t hal_tx_comp_get_desc_va(void *hal_desc) { uint64_t va_from_desc; @@ -590,7 +604,7 @@ static inline uintptr_t hal_tx_comp_get_desc_va(void *hal_desc) WBM2SW_COMPLETION_RING_TX, BUFFER_VIRT_ADDR_63_32)) << 32); - return (uintptr_t)va_from_desc; + return va_from_desc; } /*---------------------------------------------------------------------------