Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bc1c35c authored by Rakesh Pillai's avatar Rakesh Pillai Committed by Madan Koyyalamudi
Browse files

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
parent f43d5ac1
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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;
};

/**
@@ -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;
@@ -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

@@ -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;
+61 −5
Original line number Diff line number Diff line
@@ -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)
{
@@ -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)
@@ -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;
@@ -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
@@ -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;