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
这个提交包含在:
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
在新工单中引用
屏蔽一个用户