diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9159f19755..a963bbf1f3 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -7039,6 +7039,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX REL DUP DESC: %d", soc->stats.rx.err.hal_wbm_rel_dup); + DP_PRINT_STATS("RXDMA ERR DUP DESC: %d", + soc->stats.rx.err.hal_rxdma_err_dup); + for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) { index += qdf_snprint(&rxdma_error[index], DP_RXDMA_ERR_LENGTH - index, diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index fcb9e6c101..845e4e2484 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -1553,6 +1553,26 @@ done: return rx_bufs_used; /* Assume no scale factor for now */ } +/** + * dup_desc_dbg() - dump and assert if duplicate rx desc found + * + * @soc: core DP main context + * @rxdma_dst_ring_desc: void pointer to monitor link descriptor buf addr info + * @rx_desc: void pointer to rx descriptor + * + * Return: void + */ +static void dup_desc_dbg(struct dp_soc *soc, + void *rxdma_dst_ring_desc, + void *rx_desc) +{ + DP_STATS_INC(soc, rx.err.hal_rxdma_err_dup, 1); + dp_rx_dump_info_and_assert(soc, + soc->rx_rel_ring.hal_srng, + rxdma_dst_ring_desc, + rx_desc); +} + /** * dp_rx_err_mpdu_pop() - extract the MSDU's from link descs * @@ -1585,6 +1605,7 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, uint8_t rxdma_error_code = 0; uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST; struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); + void *ring_desc; msdu = 0; @@ -1629,6 +1650,25 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, msdu_list.sw_cookie[i]); qdf_assert_always(rx_desc); msdu = rx_desc->nbuf; + /* + * this is a unlikely scenario + * where the host is reaping + * a descriptor which + * it already reaped just a while ago + * but is yet to replenish + * it back to HW. + * In this case host will dump + * the last 128 descriptors + * including the software descriptor + * rx_desc and assert. + */ + ring_desc = rxdma_dst_ring_desc; + if (qdf_unlikely(!rx_desc->in_use)) { + dup_desc_dbg(soc, + ring_desc, + rx_desc); + continue; + } qdf_nbuf_unmap_single(soc->osdev, msdu, QDF_DMA_FROM_DEVICE); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 3e01513a76..a31434ed46 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -711,6 +711,8 @@ struct dp_soc_stats { uint32_t hal_reo_dest_dup; /* HAL WBM RELEASE Duplicate count */ uint32_t hal_wbm_rel_dup; + /* HAL RXDMA error Duplicate count */ + uint32_t hal_rxdma_err_dup; } err; /* packet count per core - per ring */ diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 005922d38f..6f5cc08463 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1438,7 +1438,7 @@ static inline void hal_srng_dump_ring(struct hal_soc *hal, void *hal_ring) desc = &srng->ring_base_vaddr[tp - srng->entry_size]; QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_FATAL, + QDF_TRACE_LEVEL_DEBUG, desc, (srng->entry_size << 2)); tp -= srng->entry_size;