Explorar o código

qcacmn: Add history for register write failure

Maintain a history of the register writes which
have failed. The failure of register write is
determined by reading back the register after
writing a value to that register. If the read
value does not match the value which was written
then it is termed as a failed register write.

Change-Id: Ic3423c2cbd74bf498c0d3dd8ee7ce4231054541a
CRs-Fixed: 2624475
Rakesh Pillai %!s(int64=5) %!d(string=hai) anos
pai
achega
8e01014b7d
Modificáronse 3 ficheiros con 97 adicións e 7 borrados
  1. 25 7
      hal/wifi3.0/hal_api.h
  2. 38 0
      hal/wifi3.0/hal_internal.h
  3. 34 0
      hal/wifi3.0/hal_srng.c

+ 25 - 7
hal/wifi3.0/hal_api.h

@@ -104,6 +104,30 @@ hal_set_verbose_debug(bool flag)
 #define HAL_STATS_INC(_handle, _field, _delta)
 #endif
 
+#ifdef ENABLE_HAL_REG_WR_HISTORY
+#define HAL_REG_WRITE_FAIL_HIST_ADD(hal_soc, offset, wr_val, rd_val) \
+	hal_reg_wr_fail_history_add(hal_soc, offset, wr_val, rd_val)
+
+void hal_reg_wr_fail_history_add(struct hal_soc *hal_soc,
+				 uint32_t offset,
+				 uint32_t wr_val,
+				 uint32_t rd_val);
+
+static inline int hal_history_get_next_index(qdf_atomic_t *table_index,
+					     int array_size)
+{
+	int record_index = qdf_atomic_inc_return(table_index);
+
+	return record_index & (array_size - 1);
+}
+#else
+#define HAL_REG_WRITE_FAIL_HIST_ADD(hal_soc, offset, wr_val, rd_val) \
+	hal_err("write failed at reg offset 0x%x, write 0x%x read 0x%x\n", \
+		offset,	\
+		wr_val,	\
+		rd_val)
+#endif
+
 /**
  * hal_reg_write_result_check() - check register writing result
  * @hal_soc: HAL soc handle
@@ -121,14 +145,8 @@ static inline void hal_reg_write_result_check(struct hal_soc *hal_soc,
 
 	value = qdf_ioread32(hal_soc->dev_base_addr + offset);
 	if (exp_val != value) {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
-			  "register offset 0x%x write failed!\n", offset);
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
-			  "the expectation 0x%x, actual value 0x%x\n",
-			  exp_val,
-			  value);
+		HAL_REG_WRITE_FAIL_HIST_ADD(hal_soc, offset, exp_val, value);
 		HAL_STATS_INC(hal_soc, reg_write_fail, 1);
-		QDF_BUG(0);
 	}
 }
 

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

@@ -20,6 +20,7 @@
 #define _HAL_INTERNAL_H_
 
 #include "qdf_types.h"
+#include "qdf_atomic.h"
 #include "qdf_lock.h"
 #include "qdf_mem.h"
 #include "qdf_nbuf.h"
@@ -484,6 +485,40 @@ struct hal_soc_stats {
 	uint32_t reg_write_fail;
 };
 
+#ifdef ENABLE_HAL_REG_WR_HISTORY
+/* The history size should always be a power of 2 */
+#define HAL_REG_WRITE_HIST_SIZE 8
+
+/**
+ * struct hal_reg_write_fail_entry - Record of
+ *		register write which failed.
+ * @timestamp: timestamp of reg write failure
+ * @reg_offset: offset of register where the write failed
+ * @write_val: the value which was to be written
+ * @read_val: the value read back from the register after write
+ */
+struct hal_reg_write_fail_entry {
+	uint64_t timestamp;
+	uint32_t reg_offset;
+	uint32_t write_val;
+	uint32_t read_val;
+};
+
+/**
+ * struct hal_reg_write_fail_history - Hal layer history
+ *		of all the register write failures.
+ * @index: index to add the new record
+ * @record: array of all the records in history
+ *
+ * This structure holds the history of register write
+ * failures at HAL layer.
+ */
+struct hal_reg_write_fail_history {
+	qdf_atomic_t index;
+	struct hal_reg_write_fail_entry record[HAL_REG_WRITE_HIST_SIZE];
+};
+#endif
+
 /**
  * HAL context to be used to access SRNG APIs (currently used by data path
  * and transport (CE) modules)
@@ -535,6 +570,9 @@ struct hal_soc {
 	bool init_phase;
 	/* Hal level stats */
 	struct hal_soc_stats stats;
+#ifdef ENABLE_HAL_REG_WR_HISTORY
+	struct hal_reg_write_fail_history *reg_wr_fail_hist;
+#endif
 };
 
 void hal_qca6750_attach(struct hal_soc *hal_soc);

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

@@ -47,6 +47,39 @@ void hal_qca6750_attach(struct hal_soc *hal);
 bool is_hal_verbose_debug_enabled;
 #endif
 
+#ifdef ENABLE_HAL_REG_WR_HISTORY
+struct hal_reg_write_fail_history hal_reg_wr_hist;
+
+void hal_reg_wr_fail_history_add(struct hal_soc *hal_soc,
+				 uint32_t offset,
+				 uint32_t wr_val, uint32_t rd_val)
+{
+	struct hal_reg_write_fail_entry *record;
+	int idx;
+
+	idx = hal_history_get_next_index(&hal_soc->reg_wr_fail_hist->index,
+					 HAL_REG_WRITE_HIST_SIZE);
+
+	record = &hal_soc->reg_wr_fail_hist->record[idx];
+
+	record->timestamp = qdf_get_log_timestamp();
+	record->reg_offset = offset;
+	record->write_val = wr_val;
+	record->read_val = rd_val;
+}
+
+static void hal_reg_write_fail_history_init(struct hal_soc *hal)
+{
+	hal->reg_wr_fail_hist = &hal_reg_wr_hist;
+
+	qdf_atomic_set(&hal->reg_wr_fail_hist->index, -1);
+}
+#else
+static void hal_reg_write_fail_history_init(struct hal_soc *hal)
+{
+}
+#endif
+
 /**
  * hal_get_srng_ring_id() - get the ring id of a descriped ring
  * @hal: hal_soc data structure
@@ -370,6 +403,7 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev)
 	hal->target_type = hal_get_target_type(hal_soc_to_hal_soc_handle(hal));
 
 	hal_target_based_configure(hal);
+	hal_reg_write_fail_history_init(hal);
 	/**
 	 * Indicate Initialization of srngs to avoid force wake
 	 * as umac power collapse is not enabled yet