From 4fdb9be46170bdf8761388837e09acd4c8551b25 Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Fri, 11 Sep 2020 15:00:48 +0800 Subject: [PATCH] qcacmn: Retry reo_dst_ctrl register writing if fails If reo_dst_ctrl register writing failed, this is a fatal error for IPA pipe going to down case as RX frames will still be routed to IPA rings then hit NOC error. retry register writing to see any chance to write successfully, if fail always, trigger SSR or panic. Change-Id: I3c03faa28e6cc93f396944579a360d5405c8138e CRs-Fixed: 2774789 --- hal/wifi3.0/hal_api.h | 45 ++++++++++++++++++++++++++++++++++++ hal/wifi3.0/hal_hw_headers.h | 3 +++ hal/wifi3.0/hal_srng.c | 12 ++++++---- qdf/inc/qdf_types.h | 2 ++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 489f49c13032..06a707e96509 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -533,6 +533,51 @@ uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) } #endif +/* Max times allowed for register writing retry */ +#define HAL_REG_WRITE_RETRY_MAX 5 +/* Delay milliseconds for each time retry */ +#define HAL_REG_WRITE_RETRY_DELAY 1 + +/** + * hal_write32_mb_confirm_retry() - write register with confirming and + do retry/recovery if writing failed + * @hal_soc: hal soc handle + * @offset: offset address from the BAR + * @value: value to write + * @recovery: is recovery needed or not. + * + * Write the register value with confirming and read it back, if + * read back value is not as expected, do retry for writing, if + * retry hit max times allowed but still fail, check if recovery + * needed. + * + * Return: None + */ +static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc, + uint32_t offset, + uint32_t value, + bool recovery) +{ + uint8_t retry_cnt = 0; + uint32_t read_value; + + while (retry_cnt <= HAL_REG_WRITE_RETRY_MAX) { + hal_write32_mb_confirm(hal_soc, offset, value); + read_value = hal_read32_mb(hal_soc, offset); + if (qdf_likely(read_value == value)) + break; + + /* write failed, do retry */ + hal_warn("Retry reg offset 0x%x, value 0x%x, read value 0x%x", + offset, value, read_value); + qdf_mdelay(HAL_REG_WRITE_RETRY_DELAY); + retry_cnt++; + } + + if (retry_cnt > HAL_REG_WRITE_RETRY_MAX && recovery) + qdf_trigger_self_recovery(NULL, QDF_HAL_REG_WRITE_FAILURE); +} + #ifdef FEATURE_HAL_DELAYED_REG_WRITE /** * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats diff --git a/hal/wifi3.0/hal_hw_headers.h b/hal/wifi3.0/hal_hw_headers.h index 43cb81841905..49aff583a367 100644 --- a/hal/wifi3.0/hal_hw_headers.h +++ b/hal/wifi3.0/hal_hw_headers.h @@ -116,6 +116,9 @@ #define HAL_REG_WRITE_CONFIRM(_soc, _reg, _value) \ hal_write32_mb_confirm(_soc, (_reg), (_value)) +#define HAL_REG_WRITE_CONFIRM_RETRY(_soc, _reg, _value, _recovery) \ + hal_write32_mb_confirm_retry(_soc, (_reg), (_value), (_recovery)) + #define HAL_REG_READ(_soc, _offset) \ hal_read32_mb(_soc, (_offset)) diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index f6427486c09b..f242b0579a39 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -970,28 +970,32 @@ void hal_reo_read_write_ctrl_ix(hal_soc_handle_t hal_soc_hdl, bool read, reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix0); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix0, true); } if (ix1) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_1_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE(hal, reg_offset, *ix1); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix1, true); } if (ix2) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix2); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix2, true); } if (ix3) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix3); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix3, true); } } } diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index a1b2518a1405..cfad243b11cc 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -1341,6 +1341,7 @@ enum qdf_suspend_type { * @QDF_VDEV_DELETE_RESPONSE_TIMED_OUT: Delete response timeout from FW * @QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT: Peer delete all resp timeout * @QDF_WMI_BUF_SEQUENCE_MISMATCH: WMI Tx completion buffer sequence mismatch + * @QDF_HAL_REG_WRITE_FAILURE: HAL register writing failures */ enum qdf_hang_reason { QDF_REASON_UNSPECIFIED, @@ -1364,6 +1365,7 @@ enum qdf_hang_reason { QDF_VDEV_DELETE_RESPONSE_TIMED_OUT, QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT, QDF_WMI_BUF_SEQUENCE_MISMATCH, + QDF_HAL_REG_WRITE_FAILURE, }; /**