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
This commit is contained in:
@@ -104,6 +104,30 @@ hal_set_verbose_debug(bool flag)
|
|||||||
#define HAL_STATS_INC(_handle, _field, _delta)
|
#define HAL_STATS_INC(_handle, _field, _delta)
|
||||||
#endif
|
#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_reg_write_result_check() - check register writing result
|
||||||
* @hal_soc: HAL soc handle
|
* @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);
|
value = qdf_ioread32(hal_soc->dev_base_addr + offset);
|
||||||
if (exp_val != value) {
|
if (exp_val != value) {
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
|
HAL_REG_WRITE_FAIL_HIST_ADD(hal_soc, offset, exp_val, value);
|
||||||
"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_STATS_INC(hal_soc, reg_write_fail, 1);
|
HAL_STATS_INC(hal_soc, reg_write_fail, 1);
|
||||||
QDF_BUG(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#define _HAL_INTERNAL_H_
|
#define _HAL_INTERNAL_H_
|
||||||
|
|
||||||
#include "qdf_types.h"
|
#include "qdf_types.h"
|
||||||
|
#include "qdf_atomic.h"
|
||||||
#include "qdf_lock.h"
|
#include "qdf_lock.h"
|
||||||
#include "qdf_mem.h"
|
#include "qdf_mem.h"
|
||||||
#include "qdf_nbuf.h"
|
#include "qdf_nbuf.h"
|
||||||
@@ -484,6 +485,40 @@ struct hal_soc_stats {
|
|||||||
uint32_t reg_write_fail;
|
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
|
* HAL context to be used to access SRNG APIs (currently used by data path
|
||||||
* and transport (CE) modules)
|
* and transport (CE) modules)
|
||||||
@@ -535,6 +570,9 @@ struct hal_soc {
|
|||||||
bool init_phase;
|
bool init_phase;
|
||||||
/* Hal level stats */
|
/* Hal level stats */
|
||||||
struct hal_soc_stats 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);
|
void hal_qca6750_attach(struct hal_soc *hal_soc);
|
||||||
|
@@ -47,6 +47,39 @@ void hal_qca6750_attach(struct hal_soc *hal);
|
|||||||
bool is_hal_verbose_debug_enabled;
|
bool is_hal_verbose_debug_enabled;
|
||||||
#endif
|
#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_get_srng_ring_id() - get the ring id of a descriped ring
|
||||||
* @hal: hal_soc data structure
|
* @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_type = hal_get_target_type(hal_soc_to_hal_soc_handle(hal));
|
||||||
|
|
||||||
hal_target_based_configure(hal);
|
hal_target_based_configure(hal);
|
||||||
|
hal_reg_write_fail_history_init(hal);
|
||||||
/**
|
/**
|
||||||
* Indicate Initialization of srngs to avoid force wake
|
* Indicate Initialization of srngs to avoid force wake
|
||||||
* as umac power collapse is not enabled yet
|
* as umac power collapse is not enabled yet
|
||||||
|
Reference in New Issue
Block a user