qcacmn: Fix ce ring timeout interrupt hw work arround
Interrupt was constantly firing because the low_threshold was improperly configured. The low threshold needs to be 1 less than the number of buffers posted when the CE is fully posted. The srng backed CE's are setup with nentries - 2 buffers as the fully posted amount, therefore the threshold needs to be nentries - 3. Also fixes a bug where a reused variable is not cleared. This bug could result in the threshold being set to a garbages value. Change-Id: Iac840bfd6677683bf2feb42d8bdbd050f42e895d CRs-Fixed: 2090603
This commit is contained in:

committed by
snandini

parent
1fecd15636
commit
9b55b5fbb9
@@ -882,6 +882,7 @@ static inline void hal_srng_src_hw_init(struct hal_soc *hal,
|
||||
}
|
||||
SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
|
||||
|
||||
reg_val = 0;
|
||||
if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
|
||||
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1,
|
||||
LOW_THRESHOLD), srng->u.src_ring.low_threshold);
|
||||
|
@@ -625,6 +625,35 @@ static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,
|
||||
&ring_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* ce_srng_initialize_dest_timer_interrupt_war() - war initialization
|
||||
* @dest_ring: ring being initialized
|
||||
* @ring_params: pointer to initialized parameters
|
||||
*
|
||||
* For Napier & Hawkeye v1, the status ring timer interrupts do not work
|
||||
* As a work arround host configures the destination rings to be a proxy for
|
||||
* work needing to be done.
|
||||
*
|
||||
* The interrupts are setup such that if the destination ring is less than fully
|
||||
* posted, there is likely undone work for the status ring that the host should
|
||||
* process.
|
||||
*
|
||||
* There is a timing bug in srng based copy engines such that a fully posted
|
||||
* srng based copy engine has 2 empty entries instead of just one. The copy
|
||||
* engine data sturctures work with 1 empty entry, but the software frequently
|
||||
* fails to post the last entry due to the race condition.
|
||||
*/
|
||||
static void ce_srng_initialize_dest_timer_interrupt_war(
|
||||
struct CE_ring_state *dest_ring,
|
||||
struct hal_srng_params *ring_params) {
|
||||
int num_buffers_when_fully_posted = dest_ring->nentries - 2;
|
||||
|
||||
ring_params->low_threshold = num_buffers_when_fully_posted - 1;
|
||||
ring_params->intr_timer_thres_us = 1024;
|
||||
ring_params->intr_batch_cntr_thres_entries = 0;
|
||||
ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
|
||||
}
|
||||
|
||||
static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
|
||||
struct CE_ring_state *dest_ring,
|
||||
struct CE_attr *attr)
|
||||
@@ -642,11 +671,8 @@ static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
|
||||
if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
|
||||
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
|
||||
if (status_ring_timer_thresh_work_arround) {
|
||||
/* hw bug work arround*/
|
||||
ring_params.low_threshold = dest_ring->nentries - 1;
|
||||
ring_params.intr_timer_thres_us = 1024;
|
||||
ring_params.intr_batch_cntr_thres_entries = 0;
|
||||
ring_params.flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
|
||||
ce_srng_initialize_dest_timer_interrupt_war(
|
||||
dest_ring, &ring_params);
|
||||
} else {
|
||||
/* normal behavior for future chips */
|
||||
ring_params.low_threshold = dest_ring->nentries >> 3;
|
||||
|
Reference in New Issue
Block a user