Browse Source

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
Jinwei Chen 4 years ago
parent
commit
4fdb9be461
4 changed files with 58 additions and 4 deletions
  1. 45 0
      hal/wifi3.0/hal_api.h
  2. 3 0
      hal/wifi3.0/hal_hw_headers.h
  3. 8 4
      hal/wifi3.0/hal_srng.c
  4. 2 0
      qdf/inc/qdf_types.h

+ 45 - 0
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

+ 3 - 0
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))
 

+ 8 - 4
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);
 		}
 	}
 }

+ 2 - 0
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,
 };
 
 /**