diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 0871e660b9..dd6e389a69 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -447,8 +447,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, { qdf_iowrite32(addr, value); } -#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, struct hal_srng *srng, void __iomem *addr, @@ -770,8 +769,7 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc, } #endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index ce7aeb2cb1..0317892c5d 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -25,8 +25,7 @@ #include "qdf_mem.h" #include "qdf_nbuf.h" #include "pld_common.h" -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) #include "qdf_defer.h" #include "qdf_timer.h" #endif @@ -398,8 +397,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t; */ #define HAL_SRNG_FLUSH_EVENT BIT(0) -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * struct hal_reg_write_q_elem - delayed register write queue element @@ -480,21 +478,6 @@ struct hal_reg_write_soc_stats { uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; uint32_t dequeue_delay; }; - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -struct hal_reg_write_tcl_stats { - uint32_t wq_delayed; - uint32_t wq_direct; - uint32_t timer_enq; - uint32_t timer_direct; - uint32_t enq_timer_set; - uint32_t direct_timer_set; - uint32_t timer_reset; - qdf_time_t enq_time; - qdf_time_t deq_time; - uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; -}; -#endif #endif struct hal_offload_info { @@ -646,10 +629,7 @@ struct hal_srng { /* 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 */ - uint32_t last_reg_wr_val; +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /* flag to indicate whether srng is already queued for delayed write */ uint8_t reg_write_in_progress; /* last dequeue elem time stamp */ @@ -1035,8 +1015,7 @@ struct hal_hw_txrx_ops { */ struct hal_soc_stats { uint32_t reg_write_fail; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) struct hal_reg_write_soc_stats wstats; #endif #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE @@ -1152,20 +1131,6 @@ struct hal_soc { /* read index used by worker thread to dequeue/write registers */ uint32_t read_idx; #endif /*FEATURE_HAL_DELAYED_REG_WRITE */ -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 - /* delayed work for TCL reg write to be queued into workqueue */ - qdf_work_t tcl_reg_write_work; - /* workqueue for TCL delayed register writes */ - qdf_workqueue_t *tcl_reg_write_wq; - /* flag denotes whether TCL delayed write work is active */ - qdf_atomic_t tcl_work_active; - /* flag indiactes TCL write happening from direct context */ - bool tcl_direct; - /* timer to handle the pending TCL reg writes */ - qdf_timer_t tcl_reg_write_timer; - /* stats related to TCL reg write */ - struct hal_reg_write_tcl_stats tcl_stats; -#endif /* FEATURE_HAL_DELAYED_REG_WRITE_V2 */ qdf_atomic_t active_work_cnt; #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE struct shadow_reg_config @@ -1176,8 +1141,7 @@ struct hal_soc { bool dmac_cmn_src_rxbuf_ring; }; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_delayed_reg_write() - delayed regiter write * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 68bf5cfacd..e9a21c221f 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -505,8 +505,7 @@ uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl) qdf_export_symbol(hal_get_target_type); -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_is_reg_write_tput_level_high() - throughput level for delayed reg writes * @hal: hal_soc pointer @@ -560,41 +559,6 @@ void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl) hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf))); } -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_dump_tcl_stats() - dump the TCL reg write stats - * @hal: hal_soc pointer - * - * Return: None - */ -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - uint32_t *hist = hal->tcl_stats.sched_delay; - char buf[HAL_REG_WRITE_SRNG_STATS_LEN]; - - hal_debug("TCL: %s sched-delay hist %u %u %u %u", - hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf)), - hist[REG_WRITE_SCHED_DELAY_SUB_100us], - hist[REG_WRITE_SCHED_DELAY_SUB_1000us], - hist[REG_WRITE_SCHED_DELAY_SUB_5000us], - hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - hal_debug("wq_dly %u wq_dir %u tim_enq %u tim_dir %u enq_tim_cnt %u dir_tim_cnt %u rst_tim_cnt %u", - hal->tcl_stats.wq_delayed, - hal->tcl_stats.wq_direct, - hal->tcl_stats.timer_enq, - hal->tcl_stats.timer_direct, - hal->tcl_stats.enq_timer_set, - hal->tcl_stats.direct_timer_set, - hal->tcl_stats.timer_reset); -} - -#else -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ -} -#endif - void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) { uint32_t *hist; @@ -612,8 +576,6 @@ void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) hist[REG_WRITE_SCHED_DELAY_SUB_1000us], hist[REG_WRITE_SCHED_DELAY_SUB_5000us], hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - - hal_dump_tcl_stats(hal); } int hal_get_reg_write_pending_work(void *hal_soc) @@ -636,46 +598,6 @@ int hal_get_reg_write_pending_work(void *hal_soc) #define HAL_REG_WRITE_QUEUE_LEN 32 #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_process_reg_write_q_elem() - process a regiter write queue element - * @hal: hal_soc pointer - * @q_elem: pointer to hal regiter write queue element - * - * Return: The value which was written to the address - */ -static uint32_t -hal_process_reg_write_q_elem(struct hal_soc *hal, - struct hal_reg_write_q_elem *q_elem) -{ - struct hal_srng *srng = q_elem->srng; - uint32_t write_val; - - SRNG_LOCK(&srng->lock); - srng->reg_write_in_progress = false; - srng->wstats.dequeues++; - - if (srng->ring_dir == HAL_SRNG_SRC_RING) { - write_val = srng->u.src_ring.hp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.src_ring.hp_addr, - write_val, false); - } else { - write_val = srng->u.dst_ring.tp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.dst_ring.tp_addr, - write_val, false); - } - - return write_val; -} -#else /** * hal_process_reg_write_q_elem() - process a regiter write queue element * @hal: hal_soc pointer @@ -715,7 +637,6 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, return write_val; } -#endif /** * hal_reg_write_fill_sched_delay_hist() - fill reg write delay histogram in hal @@ -1022,384 +943,6 @@ static inline void hal_delayed_reg_write_deinit(struct hal_soc *hal) } #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef MEMORY_DEBUG -/** - * hal_reg_write_get_timestamp() - Function to get the timestamp - * - * Return: return present simestamp - */ -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return qdf_get_log_timestamp(); -} - -/** - * hal_del_reg_write_ts_usecs() - Convert the timestamp to micro secs - * @ts: timestamp value to be converted - * - * Return: return the timestamp in micro secs - */ -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return qdf_log_timestamp_to_usecs(ts); -} - -/** - * hal_tcl_write_fill_sched_delay_hist() - fill TCL reg write delay histogram - * @hal: hal_soc pointer - * @delay: delay in us - * - * Return: None - */ -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ - uint32_t *hist; - uint32_t delay_us; - - hal->tcl_stats.deq_time = hal_del_reg_write_get_ts(); - delay_us = hal_del_reg_write_ts_usecs(hal->tcl_stats.deq_time - - hal->tcl_stats.enq_time); - - hist = hal->tcl_stats.sched_delay; - if (delay_us < 100) - hist[REG_WRITE_SCHED_DELAY_SUB_100us]++; - else if (delay_us < 1000) - hist[REG_WRITE_SCHED_DELAY_SUB_1000us]++; - else if (delay_us < 5000) - hist[REG_WRITE_SCHED_DELAY_SUB_5000us]++; - else - hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; -} - -#else -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return 0; -} - -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return 0; -} - -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ -} -#endif - -/** - * hal_tcl_reg_write_work() - Worker to process delayed SW2TCL1 writes - * @arg: hal_soc pointer - * - * Return: None - */ -static void hal_tcl_reg_write_work(void *arg) -{ - struct hal_soc *hal = arg; - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - - SRNG_LOCK(&srng->lock); - srng->wstats.dequeues++; - hal_tcl_write_fill_sched_delay_hist(hal); - - /* - * During the tranition of low to high tput scenario, reg write moves - * from delayed to direct write context, there is a little chance that - * worker thread gets scheduled later than direct context write which - * already wrote the latest HP value. This check can catch that case - * and avoid the repetitive writing of the same HP value. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - if (hal->tcl_direct) { - /* - * TCL reg writes have been moved to direct context and - * the assumption is that PCIe bus stays in Active state - * during high tput, hence its fine to write the HP - * while the SRNG_LOCK is being held. - */ - hal->tcl_stats.wq_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } else { - /* - * TCL reg write to happen in delayed context, - * write operation might take time due to possibility of - * PCIe bus stays in low power state during low tput, - * Hence release the SRNG_LOCK before writing. - */ - hal->tcl_stats.wq_delayed++; - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } - - /* - * Decrement active_work_cnt to make sure that hif_try_complete_tasks - * will wait. This will avoid race condition between delayed register - * worker and bus suspend (system suspend or runtime suspend). - * - * The following decrement should be done at the end! - */ - qdf_atomic_dec(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, false); -} - -static void __hal_flush_tcl_reg_write_work(struct hal_soc *hal) -{ - qdf_cancel_work(&hal->tcl_reg_write_work); -} - -/** - * hal_tcl_reg_write_enqueue() - enqueue TCL register writes into kworker - * @hal_soc: hal_soc pointer - * @srng: srng pointer - * @addr: iomem address of regiter - * @value: value to be written to iomem address - * - * This function executes from within the SRNG LOCK - * - * Return: None - */ -static void hal_tcl_reg_write_enqueue(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_soc->tcl_stats.enq_time = hal_del_reg_write_get_ts(); - - if (qdf_queue_work(hal_soc->qdf_dev, hal_soc->tcl_reg_write_wq, - &hal_soc->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal_soc->active_work_cnt); - qdf_atomic_set(&hal_soc->tcl_work_active, true); - srng->wstats.enqueues++; - } else { - hal_soc->tcl_stats.enq_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } -} - -/** - * hal_tcl_reg_write_timer() - timer handler to take care of pending TCL writes - * @arg: srng handle - * - * This function handles the pending TCL reg writes missed due to the previous - * scheduled worker running. - * - * Return: None - */ -static void hal_tcl_reg_write_timer(void *arg) -{ - hal_ring_handle_t srng_hdl = arg; - struct hal_srng *srng; - struct hal_soc *hal; - - srng = (struct hal_srng *)srng_hdl; - hal = srng->hal_soc; - - if (hif_pm_runtime_get(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE, - true)) { - hal_srng_set_event(srng_hdl, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(srng_hdl); - goto fail; - } - - SRNG_LOCK(&srng->lock); - if (hal->tcl_direct) { - /* - * Due to the previous scheduled worker still running, - * direct reg write cannot be performed, so posted the - * pending writes to timer context. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal->tcl_stats.timer_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - /* - * Due to the previous scheduled worker still running, - * queue_work from delayed context would fail, - * so retry from timer context. - */ - if (qdf_queue_work(hal->qdf_dev, hal->tcl_reg_write_wq, - &hal->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, true); - srng->wstats.enqueues++; - hal->tcl_stats.timer_enq++; - } else { - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - hal->tcl_stats.timer_reset++; - qdf_timer_mod(&hal->tcl_reg_write_timer, 1); - } - } - } - SRNG_UNLOCK(&srng->lock); - hif_pm_runtime_put(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE); - -fail: - return; -} - -/** - * hal_delayed_tcl_reg_write_init() - Initialization for delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * Initialize main data structures to process TCL register writes in a delayed - * workqueue. - * - * Return: QDF_STATUS_SUCCESS on success else a QDF error. - */ -static QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - QDF_STATUS status; - - hal->tcl_reg_write_wq = - qdf_alloc_high_prior_ordered_workqueue("hal_tcl_reg_write_wq"); - if (!hal->tcl_reg_write_wq) { - hal_err("hal_tcl_reg_write_wq alloc failed"); - return QDF_STATUS_E_NOMEM; - } - - status = qdf_create_work(0, &hal->tcl_reg_write_work, - hal_tcl_reg_write_work, hal); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_work create failed"); - goto fail; - } - - status = qdf_timer_init(hal->qdf_dev, &hal->tcl_reg_write_timer, - hal_tcl_reg_write_timer, (void *)srng, - QDF_TIMER_TYPE_WAKE_APPS); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_timer init failed"); - goto fail; - } - - qdf_atomic_init(&hal->tcl_work_active); - - return QDF_STATUS_SUCCESS; - -fail: - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); - return status; -} - -/** - * hal_delayed_tcl_reg_write_deinit() - De-Initialize delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * De-initialize main data structures to process TCL register writes in a - * delayed workqueue. - * - * Return: None - */ -static void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ - qdf_timer_stop(&hal->tcl_reg_write_timer); - qdf_timer_free(&hal->tcl_reg_write_timer); - - __hal_flush_tcl_reg_write_work(hal); - qdf_flush_workqueue(0, hal->tcl_reg_write_wq); - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); -} - -#else -static inline QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - return QDF_STATUS_SUCCESS; -} - -static inline void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ -} -#endif - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef FEATURE_HAL_DELAYED_REG_WRITE -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_reg_write_enqueue(hal_soc, srng, addr, value); -} -#else -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); -} -#endif - -void hal_delayed_reg_write(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - switch (srng->ring_type) { - case TCL_DATA: - if (hal_is_reg_write_tput_level_high(hal_soc)) { - hal_soc->tcl_direct = true; - if (srng->reg_write_in_progress || - !qdf_atomic_read(&hal_soc->tcl_work_active)) { - /* - * Now the delayed work have either completed - * the writing or not even scheduled and would - * be blocked by SRNG_LOCK, hence it is fine to - * do direct write here. - */ - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, - srng->last_reg_wr_val, - false); - } else { - hal_soc->tcl_stats.direct_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } - } else { - hal_soc->tcl_direct = false; - if (srng->reg_write_in_progress) { - srng->wstats.coalesces++; - } else { - hal_tcl_reg_write_enqueue(hal_soc, srng, - addr, value); - } - } - break; - case CE_SRC: - case CE_DST: - case CE_DST_STATUS: - hal_reg_write_enqueue_v2(hal_soc, srng, addr, value); - break; - default: - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); - break; - } -} - -#else #ifdef FEATURE_HAL_DELAYED_REG_WRITE #ifdef QCA_WIFI_QCA6750 void hal_delayed_reg_write(struct hal_soc *hal_soc, @@ -1460,7 +1003,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, } #endif #endif -#endif /** * hal_attach - Initialize HAL layer @@ -1538,7 +1080,6 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev) qdf_atomic_init(&hal->active_work_cnt); hal_delayed_reg_write_init(hal); - hal_delayed_tcl_reg_write_init(hal); return (void *)hal; fail3: @@ -1595,7 +1136,6 @@ extern void hal_detach(void *hal_soc) struct hal_soc *hal = (struct hal_soc *)hal_soc; hal_delayed_reg_write_deinit(hal); - hal_delayed_tcl_reg_write_deinit(hal); qdf_mem_free(hal->ops); qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev,