diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 91343f34ac..93760e4f9d 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -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); diff --git a/hif/src/ce/ce_service_srng.c b/hif/src/ce/ce_service_srng.c index e39434c597..19c5c4cc0e 100644 --- a/hif/src/ce/ce_service_srng.c +++ b/hif/src/ce/ce_service_srng.c @@ -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;