qcacmn: Add WAR to skip status ring entry

STATUS_BUFFER_DONE tlv written in first word for a status
buffer indicates that DMA is done for that status ring entry.

In existing implementation, for a status ring entry if
STATUS_BUFFER_DONE tlv is not written by HW, we poll on to status ring
entry until DMA is done by HW.

During lmac reset it may happnen that HW will not write STATUS_BUFFER_DONE
tlv in status buffer, in that case we end up polling infinitely leading
to backpressure on monitor status ring.

As per MAC team's suggestion, when HP + 1 entry is peeked and if DMA
is not done and if HP + 2 entry's DMA done is set,
replenish HP + 1 entry and start processing in next interrupt.
If HP + 2 entry's DMA done is not set,
poll onto HP + 1 entry DMA done to be set.

CRs-Fixed: 2740988
Change-Id: Ieef667f0bb4a47e74fc320c93243c637409f47f0
This commit is contained in:
Amir
2020-07-29 15:36:24 +05:30
committed by snandini
parent f6f16ac551
commit 376724d4f9
5 changed files with 158 additions and 11 deletions

View File

@@ -1549,6 +1549,41 @@ void *hal_srng_src_peek_n_get_next(hal_soc_handle_t hal_soc_hdl,
return NULL;
}
/**
* hal_srng_src_peek_n_get_next_next - Get next to next, i.e HP + 2 entry
* from a ring without moving head pointer.
*
* @hal_soc: Opaque HAL SOC handle
* @hal_ring_hdl: Source ring pointer
*
* Return: Opaque pointer for next to next ring entry; NULL on failire
*/
static inline
void *hal_srng_src_peek_n_get_next_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;
/* 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)
*/
if ((((srng->u.src_ring.hp + (srng->entry_size)) %
srng->ring_size) != srng->u.src_ring.cached_tp) &&
(((srng->u.src_ring.hp + (srng->entry_size * 2)) %
srng->ring_size) != srng->u.src_ring.cached_tp)) {
desc = &(srng->ring_base_vaddr[(srng->u.src_ring.hp +
(srng->entry_size * 2)) %
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