Explorar o código

qcacmn: Fix delay req queue not update to date issue

Delay write of SRNG regs may happen on different CPUs.
Sometimes wmb may not sufficient to protect the update
in sequence. Change is aimed to buy more time for the
update of different CPUs.

Change-Id: I4149decf5a29ea213aa38abd2bef062f25d7858d
CRs-Fixed: 3591457
Yu Tian hai 1 ano
pai
achega
667450308d
Modificáronse 2 ficheiros con 17 adicións e 0 borrados
  1. 2 0
      hal/wifi3.0/hal_internal.h
  2. 15 0
      hal/wifi3.0/hal_srng.c

+ 2 - 0
hal/wifi3.0/hal_internal.h

@@ -498,6 +498,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t;
  * @work_scheduled_time: work scheduled time (qdf_log_timestamp)
  * @dequeue_time: dequeue time (qdf_log_timestamp)
  * @cpu_id: record cpuid when schedule work
+ * @ring_id: saved srng id
  */
 struct hal_reg_write_q_elem {
 	struct hal_srng *srng;
@@ -509,6 +510,7 @@ struct hal_reg_write_q_elem {
 	qdf_time_t work_scheduled_time;
 	qdf_time_t dequeue_time;
 	int cpu_id;
+	qdf_atomic_t ring_id;
 };
 
 /**

+ 15 - 0
hal/wifi3.0/hal_srng.c

@@ -835,6 +835,20 @@ static void hal_reg_write_work(void *arg)
 		if (!q_elem->valid)
 			break;
 
+		qdf_rmb();
+		/* buy some more time to make sure all fields
+		 * in q_elem is updated per different CPUs, in
+		 * case wmb/rmb is not taken effect
+		 */
+		if (qdf_unlikely(!q_elem->srng ||
+				 (qdf_atomic_read(&q_elem->ring_id) !=
+				 q_elem->srng->ring_id))) {
+			hal_err_rl("q_elem fields not up to date %d %d",
+				   q_elem->srng->ring_id,
+				   qdf_atomic_read(&q_elem->ring_id));
+			qdf_assert_always(0);
+		}
+
 		q_elem->dequeue_time = qdf_get_log_timestamp();
 		ring_id = q_elem->srng->ring_id;
 		addr = q_elem->addr;
@@ -934,6 +948,7 @@ static void hal_reg_write_enqueue(struct hal_soc *hal_soc,
 
 	q_elem->srng = srng;
 	q_elem->addr = addr;
+	qdf_atomic_set(&q_elem->ring_id, srng->ring_id);
 	q_elem->enqueue_val = value;
 	q_elem->enqueue_time = qdf_get_log_timestamp();