qcacmn: Delay 50us when update same shadow reg
Add 50us delay if srng's shadow reg write again within 5us. Change-Id: I8d48496814e063ebd441db3520e3a5406c5db13e CRs-Fixed: 2965371
This commit is contained in:

committed by
Madan Koyyalamudi

parent
75c2cf25ab
commit
1104d6d5a7
@@ -352,12 +352,14 @@ struct hal_reg_write_q_elem {
|
|||||||
* @dequeues: writes dequeued from delayed work (not written yet)
|
* @dequeues: writes dequeued from delayed work (not written yet)
|
||||||
* @coalesces: writes not enqueued since srng is already queued up
|
* @coalesces: writes not enqueued since srng is already queued up
|
||||||
* @direct: writes not enqueued and written to register directly
|
* @direct: writes not enqueued and written to register directly
|
||||||
|
* @dequeue_delay: dequeue operation be delayed
|
||||||
*/
|
*/
|
||||||
struct hal_reg_write_srng_stats {
|
struct hal_reg_write_srng_stats {
|
||||||
uint32_t enqueues;
|
uint32_t enqueues;
|
||||||
uint32_t dequeues;
|
uint32_t dequeues;
|
||||||
uint32_t coalesces;
|
uint32_t coalesces;
|
||||||
uint32_t direct;
|
uint32_t direct;
|
||||||
|
uint32_t dequeue_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -386,6 +388,7 @@ enum hal_reg_sched_delay {
|
|||||||
* @q_depth: current queue depth in delayed register write queue
|
* @q_depth: current queue depth in delayed register write queue
|
||||||
* @max_q_depth: maximum queue for delayed register write queue
|
* @max_q_depth: maximum queue for delayed register write queue
|
||||||
* @sched_delay: = kernel work sched delay + bus wakeup delay, histogram
|
* @sched_delay: = kernel work sched delay + bus wakeup delay, histogram
|
||||||
|
* @dequeue_delay: dequeue operation be delayed
|
||||||
*/
|
*/
|
||||||
struct hal_reg_write_soc_stats {
|
struct hal_reg_write_soc_stats {
|
||||||
qdf_atomic_t enqueues;
|
qdf_atomic_t enqueues;
|
||||||
@@ -396,6 +399,7 @@ struct hal_reg_write_soc_stats {
|
|||||||
qdf_atomic_t q_depth;
|
qdf_atomic_t q_depth;
|
||||||
uint32_t max_q_depth;
|
uint32_t max_q_depth;
|
||||||
uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX];
|
uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX];
|
||||||
|
uint32_t dequeue_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
|
#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2
|
||||||
@@ -549,6 +553,9 @@ struct hal_srng {
|
|||||||
uint32_t last_reg_wr_val;
|
uint32_t last_reg_wr_val;
|
||||||
/* flag to indicate whether srng is already queued for delayed write */
|
/* flag to indicate whether srng is already queued for delayed write */
|
||||||
uint8_t reg_write_in_progress;
|
uint8_t reg_write_in_progress;
|
||||||
|
/* last dequeue elem time stamp */
|
||||||
|
qdf_time_t last_dequeue_time;
|
||||||
|
|
||||||
/* srng specific delayed write stats */
|
/* srng specific delayed write stats */
|
||||||
struct hal_reg_write_srng_stats wstats;
|
struct hal_reg_write_srng_stats wstats;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -328,7 +328,7 @@ void hal_get_shadow_config(void *hal_soc,
|
|||||||
qdf_export_symbol(hal_get_shadow_config);
|
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 *destination,
|
||||||
uint32_t *shadow_address)
|
uint32_t *shadow_address)
|
||||||
{
|
{
|
||||||
@@ -350,13 +350,13 @@ static void hal_validate_shadow_register(struct hal_soc *hal,
|
|||||||
hal->shadow_config[index].addr);
|
hal->shadow_config[index].addr);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
error:
|
error:
|
||||||
qdf_print("baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x",
|
qdf_print("baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x",
|
||||||
hal->dev_base_addr, destination, shadow_address,
|
hal->dev_base_addr, destination, shadow_address,
|
||||||
shadow_0_offset, index);
|
shadow_0_offset, index);
|
||||||
QDF_BUG(0);
|
QDF_BUG(0);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hal_target_based_configure(struct hal_soc *hal)
|
static void hal_target_based_configure(struct hal_soc *hal)
|
||||||
@@ -675,6 +675,7 @@ hal_process_reg_write_q_elem(struct hal_soc *hal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
q_elem->valid = 0;
|
q_elem->valid = 0;
|
||||||
|
srng->last_dequeue_time = q_elem->dequeue_time;
|
||||||
SRNG_UNLOCK(&srng->lock);
|
SRNG_UNLOCK(&srng->lock);
|
||||||
|
|
||||||
return write_val;
|
return write_val;
|
||||||
@@ -705,6 +706,57 @@ static inline void hal_reg_write_fill_sched_delay_hist(struct hal_soc *hal,
|
|||||||
hist[REG_WRITE_SCHED_DELAY_GT_5000us]++;
|
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
|
* hal_reg_write_work() - Worker to process delayed writes
|
||||||
* @arg: hal_soc pointer
|
* @arg: hal_soc pointer
|
||||||
@@ -743,6 +795,10 @@ static void hal_reg_write_work(void *arg)
|
|||||||
if (!q_elem->valid)
|
if (!q_elem->valid)
|
||||||
break;
|
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();
|
q_elem->dequeue_time = qdf_get_log_timestamp();
|
||||||
ring_id = q_elem->srng->ring_id;
|
ring_id = q_elem->srng->ring_id;
|
||||||
addr = q_elem->addr;
|
addr = q_elem->addr;
|
||||||
|
Reference in New Issue
Block a user