diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 9627403f7a..38070b10b1 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -1681,7 +1681,7 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id, * BUFFER_ADDR_INFO STRUCT */ while (qdf_likely((rxdma_mon_status_ring_entry = - hal_srng_src_peek(hal_soc, mon_status_srng)) + hal_srng_src_peek_n_get_next(hal_soc, mon_status_srng)) && quota--)) { uint32_t rx_buf_cookie; qdf_nbuf_t status_nbuf; @@ -1722,9 +1722,22 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id, dp_info_rl("tlv tag status error hp:%u, tp:%u", hp, tp); pdev->rx_mon_stats.tlv_tag_status_err++; - /* WAR for missing status: Skip status entry */ - hal_srng_src_get_next(hal_soc, mon_status_srng); - continue; + + /* RxDMA status done bit might not be set even + * though tp is moved by HW. + * So Hold on to current entry on + * monitor status ring + */ + + /* If done status is missing, hold onto status + * ring until status is done for this status + * ring buffer. + * Keep HP in mon_status_ring unchanged, + * and break from here. + * Check status for same buffer for next time + * dp_rx_mon_status_srng_process + */ + break; } qdf_nbuf_set_pktlen(status_nbuf, RX_DATA_BUFFER_SIZE); @@ -1965,7 +1978,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, num_req_buffers = num_entries_avail; } - while (count < num_req_buffers) { + while (count <= num_req_buffers) { rx_netbuf = dp_rx_nbuf_prepare(dp_soc, dp_pdev); /* @@ -1984,8 +1997,9 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0); next = (*desc_list)->next; - rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc, - rxdma_srng); + rxdma_ring_entry = hal_srng_src_get_cur_hp_n_move_next( + dp_soc->hal_soc, + rxdma_srng); if (qdf_unlikely(!rxdma_ring_entry)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 36e7a7c728..85a11dfbcd 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1389,7 +1389,8 @@ void *hal_srng_src_get_next(void *hal_soc, } /** - * hal_srng_src_peek - Get next entry from a ring without moving head pointer. + * hal_srng_src_peek_n_get_next - Get next entry from a ring without + * moving head pointer. * hal_srng_src_get_next should be called subsequently to move the head pointer * * @hal_soc: Opaque HAL SOC handle @@ -1398,8 +1399,8 @@ void *hal_srng_src_get_next(void *hal_soc, * Return: Opaque pointer for next ring entry; NULL on failire */ static inline -void *hal_srng_src_peek(hal_soc_handle_t hal_soc_hdl, - hal_ring_handle_t hal_ring_hdl) +void *hal_srng_src_peek_n_get_next(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; @@ -1412,13 +1413,44 @@ void *hal_srng_src_peek(hal_soc_handle_t hal_soc_hdl, */ if (((srng->u.src_ring.hp + srng->entry_size) % srng->ring_size) != srng->u.src_ring.cached_tp) { - desc = &(srng->ring_base_vaddr[srng->u.src_ring.hp]); + desc = &(srng->ring_base_vaddr[(srng->u.src_ring.hp + + srng->entry_size) % + srng->ring_size]); return (void *)desc; } return NULL; } +/** + * hal_srng_src_get_cur_hp_n_move_next () - API returns current hp + * and move hp to next in src ring + * + * Usage: This API should only be used at init time replenish. + * + * @hal_soc_hdl: HAL soc handle + * @hal_ring_hdl: Source ring pointer + * + */ +static inline void * +hal_srng_src_get_cur_hp_n_move_next(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + uint32_t *cur_desc = NULL; + uint32_t next_hp; + + cur_desc = &srng->ring_base_vaddr[(srng->u.src_ring.hp)]; + + next_hp = (srng->u.src_ring.hp + srng->entry_size) % + srng->ring_size; + + if (next_hp != srng->u.src_ring.cached_tp) + srng->u.src_ring.hp = next_hp; + + return (void *)cur_desc; +} + /** * hal_srng_src_num_avail - Returns number of available entries in src ring *