diff --git a/dp/wifi3.0/li/dp_li_tx.c b/dp/wifi3.0/li/dp_li_tx.c index 272d5bba3f..1d14d956cc 100644 --- a/dp/wifi3.0/li/dp_li_tx.c +++ b/dp/wifi3.0/li/dp_li_tx.c @@ -89,6 +89,36 @@ static inline uint8_t dp_tx_get_rbm_id_li(struct dp_soc *soc, } #endif +#if defined(CLEAR_SW2TCL_CONSUMED_DESC) +/** + * dp_tx_clear_consumed_hw_descs - Reset all the consumed Tx ring descs to 0 + * + * @soc: DP soc handle + * @hal_ring_hdl: Source ring pointer + * + * Return: void + */ +static inline +void dp_tx_clear_consumed_hw_descs(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl) +{ + void *desc = hal_srng_src_get_next_consumed(soc->hal_soc, hal_ring_hdl); + + while (desc) { + hal_tx_desc_clear(desc); + desc = hal_srng_src_get_next_consumed(soc->hal_soc, + hal_ring_hdl); + } +} + +#else +static inline +void dp_tx_clear_consumed_hw_descs(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl) +{ +} +#endif /* CLEAR_SW2TCL_CONSUMED_DESC */ + QDF_STATUS dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata, @@ -189,6 +219,8 @@ dp_tx_hw_enqueue_li(struct dp_soc *soc, struct dp_vdev *vdev, return status; } + dp_tx_clear_consumed_hw_descs(soc, hal_ring_hdl); + /* Sync cached descriptor with HW */ hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl); diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 87e17859ef..902487a468 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1911,6 +1911,48 @@ void hal_get_sw_hptp(void *hal_soc, hal_ring_handle_t hal_ring_hdl, } } +#if defined(CLEAR_SW2TCL_CONSUMED_DESC) +/** + * hal_srng_src_get_next_consumed - Get the next desc if consumed by HW + * + * @hal_soc: Opaque HAL SOC handle + * @hal_ring_hdl: Source ring pointer + * + * Return: pointer to descriptor if consumed by HW, else NULL + */ +static inline +void *hal_srng_src_get_next_consumed(void *hal_soc, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + uint32_t *desc = NULL; + /* TODO: Using % is expensive, but we have to do this since + * size of some SRNG rings is not power of 2 (due to descriptor + * sizes). Need to create separate API for rings used + * per-packet, with sizes power of 2 (TCL2SW, REO2SW, + * SW2RXDMA and CE rings) + */ + uint32_t next_entry = (srng->last_desc_cleared + srng->entry_size) % + srng->ring_size; + + if (next_entry != (srng->u.src_ring.cached_tp + srng->entry_size) % + srng->ring_size) { + desc = &srng->ring_base_vaddr[next_entry]; + srng->last_desc_cleared = next_entry; + } + + return desc; +} + +#else +static inline +void *hal_srng_src_get_next_consumed(void *hal_soc, + hal_ring_handle_t hal_ring_hdl) +{ + return NULL; +} +#endif /* CLEAR_SW2TCL_CONSUMED_DESC */ + /** * hal_srng_src_get_next - Get next entry from a source ring and move cached tail pointer * diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index f78ff02c58..29411a11f3 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -601,6 +601,10 @@ struct hal_srng { unsigned long srng_event; /* last flushed time stamp */ uint64_t last_flush_ts; +#if defined(CLEAR_SW2TCL_CONSUMED_DESC) + /* last ring desc entry cleared */ + uint32_t last_desc_cleared; +#endif #if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) /* Previous hp/tp (based on ring dir) value written to the reg */ diff --git a/hal/wifi3.0/li/hal_li_tx.h b/hal/wifi3.0/li/hal_li_tx.h index 0b6a86500a..6cf7e6dc8a 100644 --- a/hal/wifi3.0/li/hal_li_tx.h +++ b/hal/wifi3.0/li/hal_li_tx.h @@ -229,6 +229,18 @@ void hal_tx_desc_set_dscp_tid_table_id(hal_soc_handle_t hal_soc_hdl, hal_soc->ops->hal_tx_desc_set_dscp_tid_table_id(desc, id); } +/** + * hal_tx_desc_clear - Clear the HW descriptor entry + * @hw_desc: Hardware descriptor to be cleared + * + * Return: void + */ +static inline void hal_tx_desc_clear(void *hw_desc) +{ + qdf_mem_set(hw_desc + sizeof(struct tlv_32_hdr), + HAL_TX_DESC_LEN_BYTES, 0); +} + /** * hal_tx_desc_sync - Commit the descriptor to Hardware * @hal_tx_des_cached: Cached descriptor that software maintains