From 8e01014b7da7ee39a2264b36fb8116b6f6528dea Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Tue, 18 Feb 2020 19:49:57 +0530 Subject: [PATCH] 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 --- hal/wifi3.0/hal_api.h | 32 +++++++++++++++++++++++++------- hal/wifi3.0/hal_internal.h | 38 ++++++++++++++++++++++++++++++++++++++ hal/wifi3.0/hal_srng.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 75d7caa9b6..5005f15c3f 100644 --- a/hal/wifi3.0/hal_api.h +++ b/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); } } diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 8230d86b6a..d6f4e5fd4a 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/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); diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index c8b62909e5..f21fc435a0 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/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