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:
@@ -237,6 +237,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 {
|
||||||
@@ -246,6 +247,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -461,7 +461,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;
|
||||||
|
|
||||||
@@ -474,7 +477,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;
|
||||||
@@ -569,6 +576,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);
|
||||||
|
|
||||||
|
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user