Procházet zdrojové kódy

qcacmn: Add srng pointer register writing history support

Add srng pointer register writing history, it is helpful
for debugging srng HP/TP update issue from host side.
(1) if host faced UMAC source ring, record the HP value and timestamp
when host write the register.
(2) if host faced UMAC destination ring, record the TP value and
timestamp when host write the register.

Change-Id: Ib98e48e1d32defb0d8b30b854b5b0c23691cca59
CRs-Fixed: 3427908
Jinwei Chen před 2 roky
rodič
revize
95dcc45ec2
3 změnil soubory, kde provedl 85 přidání a 0 odebrání
  1. 2 0
      hal/wifi3.0/hal_api.h
  2. 78 0
      hal/wifi3.0/hal_internal.h
  3. 5 0
      hal/wifi3.0/hal_srng.c

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

@@ -467,6 +467,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc,
 						uint32_t value)
 {
 	qdf_iowrite32(addr, value);
+	hal_srng_reg_his_add(srng, value);
 }
 #elif defined(FEATURE_HAL_DELAYED_REG_WRITE)
 static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc,
@@ -483,6 +484,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc,
 						uint32_t value)
 {
 	hal_write_address_32_mb(hal_soc, addr, value, false);
+	hal_srng_reg_his_add(srng, value);
 }
 #endif
 

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

@@ -692,6 +692,32 @@ hal_get_tsf_enum(uint32_t tsf_id, uint32_t mac_id,
 	}
 }
 
+#ifdef HAL_SRNG_REG_HIS_DEBUG
+
+#define HAL_SRNG_REG_MAX_ENTRIES 64
+
+/**
+ * struct hal_srng_reg_his_entry - history entry for single srng pointer
+ *                                 register update
+ * @write_time: register write timestamp
+ * @write_value: register write value
+ */
+struct hal_srng_reg_his_entry {
+	qdf_time_t write_time;
+	uint32_t write_value;
+};
+
+/**
+ * struct hal_srng_reg_his_ctx - context for srng pointer writing history
+ * @current_idx: the index which has recorded srng pointer writing
+ * @reg_his_arr: array to record the history
+ */
+struct hal_srng_reg_his_ctx {
+	qdf_atomic_t current_idx;
+	struct hal_srng_reg_his_entry reg_his_arr[HAL_SRNG_REG_MAX_ENTRIES];
+};
+#endif
+
 /* Common SRNG ring structure for source and destination rings */
 struct hal_srng {
 	/* Unique SRNG ring ID */
@@ -847,8 +873,60 @@ struct hal_srng {
 	uint16_t pointer_timer_threshold;
 	/* Number threshold of ring entries to issue pointer update */
 	uint8_t pointer_num_threshold;
+#ifdef HAL_SRNG_REG_HIS_DEBUG
+	/* pointer register writing history for this srng */
+	struct hal_srng_reg_his_ctx reg_his_ctx;
+#endif
 };
 
+#ifdef HAL_SRNG_REG_HIS_DEBUG
+/**
+ * hal_srng_reg_his_init() - SRNG register history context initialize
+ *
+ * @srng: SRNG handle pointer
+ *
+ * Return: None
+ */
+static inline
+void hal_srng_reg_his_init(struct hal_srng *srng)
+{
+	qdf_atomic_set(&srng->reg_his_ctx.current_idx, -1);
+}
+
+/**
+ * hal_srng_reg_his_add() - add pointer writing history to SRNG
+ *
+ * @srng: SRNG handle pointer
+ * @reg_val: pointer value to write
+ *
+ * Return: None
+ */
+static inline
+void hal_srng_reg_his_add(struct hal_srng *srng, uint32_t reg_val)
+{
+	uint32_t write_idx;
+	struct hal_srng_reg_his_entry *reg_his_entry;
+
+	write_idx = qdf_atomic_inc_return(&srng->reg_his_ctx.current_idx);
+	write_idx = write_idx & (HAL_SRNG_REG_MAX_ENTRIES - 1);
+
+	reg_his_entry = &srng->reg_his_ctx.reg_his_arr[write_idx];
+
+	reg_his_entry->write_time = qdf_get_log_timestamp();
+	reg_his_entry->write_value = reg_val;
+}
+#else
+static inline
+void hal_srng_reg_his_init(struct hal_srng *srng)
+{
+}
+
+static inline
+void hal_srng_reg_his_add(struct hal_srng *srng, uint32_t reg_val)
+{
+}
+#endif
+
 /* HW SRNG configuration table */
 struct hal_hw_srng_config {
 	int start_ring_id;

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

@@ -686,6 +686,7 @@ hal_process_reg_write_q_elem(struct hal_soc *hal,
 					srng->u.dst_ring.tp, false);
 		write_val = srng->u.dst_ring.tp;
 	}
+	hal_srng_reg_his_add(srng, write_val);
 
 	q_elem->valid = 0;
 	srng->last_dequeue_time = q_elem->dequeue_time;
@@ -1056,6 +1057,7 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc,
 		     PLD_MHI_STATE_L0 ==
 		     pld_get_mhi_state(hal_soc->qdf_dev->dev))) {
 			hal_write_address_32_mb(hal_soc, addr, value, false);
+			hal_srng_reg_his_add(srng, value);
 			qdf_atomic_inc(&hal_soc->stats.wstats.direct);
 			srng->wstats.direct++;
 		} else {
@@ -1070,6 +1072,7 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc,
 		    PLD_MHI_STATE_L0 ==
 		    pld_get_mhi_state(hal_soc->qdf_dev->dev)) {
 			hal_write_address_32_mb(hal_soc, addr, value, false);
+			hal_srng_reg_his_add(srng, value);
 			qdf_atomic_inc(&hal_soc->stats.wstats.direct);
 			srng->wstats.direct++;
 		} else {
@@ -1090,6 +1093,7 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc,
 		qdf_atomic_inc(&hal_soc->stats.wstats.direct);
 		srng->wstats.direct++;
 		hal_write_address_32_mb(hal_soc, addr, value, false);
+		hal_srng_reg_his_add(srng, value);
 	} else {
 		hal_reg_write_enqueue(hal_soc, srng, addr, value);
 	}
@@ -1556,6 +1560,7 @@ void *hal_srng_setup_idx(void *hal_soc, int ring_type, int ring_num, int mac_id,
 		return NULL;
 	}
 
+	hal_srng_reg_his_init(srng);
 	dev_base_addr = hal->dev_base_addr;
 	srng->ring_id = ring_id;
 	srng->ring_type = ring_type;