Loading hal/wifi3.0/hal_internal.h +6 −0 Original line number Diff line number Diff line Loading @@ -227,12 +227,14 @@ struct hal_reg_write_q_elem { * @dequeues: writes dequeued from delayed work (not written yet) * @coalesces: writes not enqueued since srng is already queued up * @direct: writes not enqueued and written to register directly * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_srng_stats { uint32_t enqueues; uint32_t dequeues; uint32_t coalesces; uint32_t direct; uint32_t dequeue_delay; }; /** Loading Loading @@ -261,6 +263,7 @@ enum hal_reg_sched_delay { * @q_depth: current queue depth in delayed register write queue * @max_q_depth: maximum queue for delayed register write queue * @sched_delay: = kernel work sched delay + bus wakeup delay, histogram * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_soc_stats { qdf_atomic_t enqueues; Loading @@ -271,6 +274,7 @@ struct hal_reg_write_soc_stats { qdf_atomic_t q_depth; uint32_t max_q_depth; uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; uint32_t dequeue_delay; }; #endif Loading Loading @@ -390,6 +394,8 @@ struct hal_srng { #ifdef 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 */ qdf_time_t last_dequeue_time; /* srng specific delayed write stats */ struct hal_reg_write_srng_stats wstats; Loading hal/wifi3.0/hal_srng.c +61 −5 Original line number Diff line number Diff line Loading @@ -310,7 +310,7 @@ void hal_get_shadow_config(void *hal_soc, qdf_export_symbol(hal_get_shadow_config); static void hal_validate_shadow_register(struct hal_soc *hal, static bool hal_validate_shadow_register(struct hal_soc *hal, uint32_t *destination, uint32_t *shadow_address) { Loading @@ -332,13 +332,13 @@ static void hal_validate_shadow_register(struct hal_soc *hal, hal->shadow_config[index].addr); goto error; } return; return true; error: qdf_print("%s: baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x", __func__, hal->dev_base_addr, destination, shadow_address, shadow_0_offset, index); QDF_BUG(0); return; return false; } static void hal_target_based_configure(struct hal_soc *hal) Loading Loading @@ -478,6 +478,7 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, } q_elem->valid = 0; srng->last_dequeue_time = q_elem->dequeue_time; SRNG_UNLOCK(&srng->lock); return write_val; Loading Loading @@ -507,6 +508,57 @@ static inline void hal_reg_write_fill_sched_delay_hist(struct hal_soc *hal, hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; } #ifdef SHADOW_WRITE_DELAY #define SHADOW_WRITE_MIN_DELTA_US 5 #define SHADOW_WRITE_DELAY_US 50 /* * Never add those srngs which are performance relate. * The delay itself will hit performance heavily. */ #define IS_SRNG_MATCH(s) ((s)->ring_id == HAL_SRNG_CE_1_DST_STATUS || \ (s)->ring_id == HAL_SRNG_CE_1_DST) static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) { struct hal_srng *srng = elem->srng; struct hal_soc *hal = srng->hal_soc; qdf_time_t now; qdf_iomem_t real_addr; /* Check if it is target srng, and valid shadow reg */ if (qdf_likely(!IS_SRNG_MATCH(srng))) return false; if (srng->ring_dir == HAL_SRNG_SRC_RING) real_addr = SRNG_SRC_ADDR(srng, HP); else real_addr = SRNG_DST_ADDR(srng, TP); if (!hal_validate_shadow_register(hal, real_addr, elem->addr)) return false; /* Check the time delta from last write of same srng */ now = qdf_get_log_timestamp(); if (qdf_log_timestamp_to_usecs(now - srng->last_dequeue_time) > SHADOW_WRITE_MIN_DELTA_US) return false; /* Delay dequeue, and record */ qdf_udelay(SHADOW_WRITE_DELAY_US); srng->wstats.dequeue_delay++; hal->stats.wstats.dequeue_delay++; return true; } #else static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) { return false; } #endif /** * hal_reg_write_work() - Worker to process delayed writes * @arg: hal_soc pointer Loading Loading @@ -544,6 +596,10 @@ static void hal_reg_write_work(void *arg) if (!q_elem->valid) break; if (hal_reg_write_need_delay(q_elem)) hal_verbose_debug("Delay reg writer for srng 0x%x, addr 0x%pK", q_elem->srng->ring_id, q_elem->addr); q_elem->dequeue_time = qdf_get_log_timestamp(); ring_id = q_elem->srng->ring_id; addr = q_elem->addr; Loading Loading
hal/wifi3.0/hal_internal.h +6 −0 Original line number Diff line number Diff line Loading @@ -227,12 +227,14 @@ struct hal_reg_write_q_elem { * @dequeues: writes dequeued from delayed work (not written yet) * @coalesces: writes not enqueued since srng is already queued up * @direct: writes not enqueued and written to register directly * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_srng_stats { uint32_t enqueues; uint32_t dequeues; uint32_t coalesces; uint32_t direct; uint32_t dequeue_delay; }; /** Loading Loading @@ -261,6 +263,7 @@ enum hal_reg_sched_delay { * @q_depth: current queue depth in delayed register write queue * @max_q_depth: maximum queue for delayed register write queue * @sched_delay: = kernel work sched delay + bus wakeup delay, histogram * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_soc_stats { qdf_atomic_t enqueues; Loading @@ -271,6 +274,7 @@ struct hal_reg_write_soc_stats { qdf_atomic_t q_depth; uint32_t max_q_depth; uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; uint32_t dequeue_delay; }; #endif Loading Loading @@ -390,6 +394,8 @@ struct hal_srng { #ifdef 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 */ qdf_time_t last_dequeue_time; /* srng specific delayed write stats */ struct hal_reg_write_srng_stats wstats; Loading
hal/wifi3.0/hal_srng.c +61 −5 Original line number Diff line number Diff line Loading @@ -310,7 +310,7 @@ void hal_get_shadow_config(void *hal_soc, qdf_export_symbol(hal_get_shadow_config); static void hal_validate_shadow_register(struct hal_soc *hal, static bool hal_validate_shadow_register(struct hal_soc *hal, uint32_t *destination, uint32_t *shadow_address) { Loading @@ -332,13 +332,13 @@ static void hal_validate_shadow_register(struct hal_soc *hal, hal->shadow_config[index].addr); goto error; } return; return true; error: qdf_print("%s: baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x", __func__, hal->dev_base_addr, destination, shadow_address, shadow_0_offset, index); QDF_BUG(0); return; return false; } static void hal_target_based_configure(struct hal_soc *hal) Loading Loading @@ -478,6 +478,7 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, } q_elem->valid = 0; srng->last_dequeue_time = q_elem->dequeue_time; SRNG_UNLOCK(&srng->lock); return write_val; Loading Loading @@ -507,6 +508,57 @@ static inline void hal_reg_write_fill_sched_delay_hist(struct hal_soc *hal, hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; } #ifdef SHADOW_WRITE_DELAY #define SHADOW_WRITE_MIN_DELTA_US 5 #define SHADOW_WRITE_DELAY_US 50 /* * Never add those srngs which are performance relate. * The delay itself will hit performance heavily. */ #define IS_SRNG_MATCH(s) ((s)->ring_id == HAL_SRNG_CE_1_DST_STATUS || \ (s)->ring_id == HAL_SRNG_CE_1_DST) static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) { struct hal_srng *srng = elem->srng; struct hal_soc *hal = srng->hal_soc; qdf_time_t now; qdf_iomem_t real_addr; /* Check if it is target srng, and valid shadow reg */ if (qdf_likely(!IS_SRNG_MATCH(srng))) return false; if (srng->ring_dir == HAL_SRNG_SRC_RING) real_addr = SRNG_SRC_ADDR(srng, HP); else real_addr = SRNG_DST_ADDR(srng, TP); if (!hal_validate_shadow_register(hal, real_addr, elem->addr)) return false; /* Check the time delta from last write of same srng */ now = qdf_get_log_timestamp(); if (qdf_log_timestamp_to_usecs(now - srng->last_dequeue_time) > SHADOW_WRITE_MIN_DELTA_US) return false; /* Delay dequeue, and record */ qdf_udelay(SHADOW_WRITE_DELAY_US); srng->wstats.dequeue_delay++; hal->stats.wstats.dequeue_delay++; return true; } #else static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) { return false; } #endif /** * hal_reg_write_work() - Worker to process delayed writes * @arg: hal_soc pointer Loading Loading @@ -544,6 +596,10 @@ static void hal_reg_write_work(void *arg) if (!q_elem->valid) break; if (hal_reg_write_need_delay(q_elem)) hal_verbose_debug("Delay reg writer for srng 0x%x, addr 0x%pK", q_elem->srng->ring_id, q_elem->addr); q_elem->dequeue_time = qdf_get_log_timestamp(); ring_id = q_elem->srng->ring_id; addr = q_elem->addr; Loading