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

Commit b73a4a41 authored by Tiger Yu's avatar Tiger Yu Committed by nshrivas
Browse files

qcacmn: Add memory barrier to avoid inconsistent reg write for valid flag

Add memory barrier to avoid inconsistent reg write for valid flag.

Change-Id: Ieb4ed80872961889f29de083a6b1dcdbe6a303d2
CRs-Fixed: 2699549
parent fd5eebb9
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -207,6 +207,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t;
 * @dequeue_val: register value at the time of delayed write dequeue
 * @dequeue_val: register value at the time of delayed write dequeue
 * @valid: whether this entry is valid or not
 * @valid: whether this entry is valid or not
 * @enqueue_time: enqueue time (qdf_log_timestamp)
 * @enqueue_time: enqueue time (qdf_log_timestamp)
 * @work_scheduled_time: work scheduled time (qdf_log_timestamp)
 * @dequeue_time: dequeue time (qdf_log_timestamp)
 * @dequeue_time: dequeue time (qdf_log_timestamp)
 */
 */
struct hal_reg_write_q_elem {
struct hal_reg_write_q_elem {
@@ -216,6 +217,7 @@ struct hal_reg_write_q_elem {
	uint32_t dequeue_val;
	uint32_t dequeue_val;
	uint8_t valid;
	uint8_t valid;
	qdf_time_t enqueue_time;
	qdf_time_t enqueue_time;
	qdf_time_t work_scheduled_time;
	qdf_time_t dequeue_time;
	qdf_time_t dequeue_time;
};
};


+19 −1
Original line number Original line Diff line number Diff line
@@ -450,7 +450,10 @@ static void hal_reg_write_work(void *arg)
	uint32_t *addr;
	uint32_t *addr;


	q_elem = &hal->reg_write_queue[(hal->read_idx)];
	q_elem = &hal->reg_write_queue[(hal->read_idx)];
	q_elem->work_scheduled_time = qdf_get_log_timestamp();


	/* Make sure q_elem consistent in the memory for multi-cores */
	qdf_rmb();
	if (!q_elem->valid)
	if (!q_elem->valid)
		return;
		return;


@@ -463,7 +466,11 @@ static void hal_reg_write_work(void *arg)
		return;
		return;
	}
	}


	while (q_elem->valid) {
	while (true) {
		qdf_rmb();
		if (!q_elem->valid)
			break;

		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;
@@ -558,6 +565,17 @@ static void hal_reg_write_enqueue(struct hal_soc *hal_soc,
	qdf_wmb();
	qdf_wmb();
	q_elem->valid = true;
	q_elem->valid = true;


	/*
	 * After all other fields in the q_elem has been updated
	 * in memory successfully, the valid flag needs to be updated
	 * in memory in time too.
	 * Else there is a chance that the dequeuing worker thread
	 * might read stale valid flag and the work will be bypassed
	 * for this round. And if there is no other work scheduled
	 * later, this hal register writing won't be updated any more.
	 */
	qdf_wmb();

	srng->reg_write_in_progress  = true;
	srng->reg_write_in_progress  = true;
	qdf_atomic_inc(&hal_soc->active_work_cnt);
	qdf_atomic_inc(&hal_soc->active_work_cnt);


+5 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,11 @@ typedef __qdf_wait_queue_head_t qdf_wait_queue_head_t;
 */
 */
#define qdf_wmb()                 __qdf_wmb()
#define qdf_wmb()                 __qdf_wmb()


/**
 * qdf_rmb - read memory barrier.
 */
#define qdf_rmb()                 __qdf_rmb()

/**
/**
 * qdf_mb - read + write memory barrier.
 * qdf_mb - read + write memory barrier.
 */
 */