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
This commit is contained in:
Tiger Yu
2020-06-12 09:14:22 +08:00
committed by nshrivas
parent e3b05ae8ae
commit 0f08390fa4
3 changed files with 26 additions and 1 deletions

View File

@@ -237,6 +237,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t;
* @dequeue_val: register value at the time of delayed write dequeue
* @valid: whether this entry is valid or not
* @enqueue_time: enqueue time (qdf_log_timestamp)
* @work_scheduled_time: work scheduled time (qdf_log_timestamp)
* @dequeue_time: dequeue time (qdf_log_timestamp)
*/
struct hal_reg_write_q_elem {
@@ -246,6 +247,7 @@ struct hal_reg_write_q_elem {
uint32_t dequeue_val;
uint8_t valid;
qdf_time_t enqueue_time;
qdf_time_t work_scheduled_time;
qdf_time_t dequeue_time;
};

View File

@@ -461,7 +461,10 @@ static void hal_reg_write_work(void *arg)
uint32_t *addr;
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)
return;
@@ -474,7 +477,11 @@ static void hal_reg_write_work(void *arg)
return;
}
while (q_elem->valid) {
while (true) {
qdf_rmb();
if (!q_elem->valid)
break;
q_elem->dequeue_time = qdf_get_log_timestamp();
ring_id = q_elem->srng->ring_id;
addr = q_elem->addr;
@@ -569,6 +576,17 @@ static void hal_reg_write_enqueue(struct hal_soc *hal_soc,
qdf_wmb();
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;
qdf_atomic_inc(&hal_soc->active_work_cnt);

View File

@@ -51,6 +51,11 @@ typedef __qdf_wait_queue_head_t qdf_wait_queue_head_t;
*/
#define qdf_wmb() __qdf_wmb()
/**
* qdf_rmb - read memory barrier.
*/
#define qdf_rmb() __qdf_rmb()
/**
* qdf_mb - read + write memory barrier.
*/