浏览代码

qcacmn: Fix race with F.W in updating CE control register

In current case when RRI on DDR feature is enabled then host
programs CE control register, but there is chance of F.W also
programming the CE control register around same time this leads
to race and chance of either host/F.W value getting over written.

So to avoid this while programming the CE control register for
RRI on DDR enablement, update it with F.W programming value also
i.e DMA length. So if incase register value over written due to
race proper value will be updated to register either by host/F.W.

Change-Id: I2560c74726b21128d1cd50805d987fda1b2a1230
CRs-Fixed: 3561689
Karthik Kantamneni 2 年之前
父节点
当前提交
b965b762b1
共有 2 个文件被更改,包括 42 次插入0 次删除
  1. 36 0
      hif/src/ce/ce_main.c
  2. 6 0
      hif/src/ce/ce_reg.h

+ 36 - 0
hif/src/ce/ce_main.c

@@ -4405,6 +4405,7 @@ static inline QDF_STATUS hif_alloc_rri_on_ddr(struct hif_softc *scn)
  *
  * Return: None
  */
+#ifdef QCA_WIFI_WCN6450
 static inline void hif_config_rri_on_ddr(struct hif_softc *scn)
 {
 	unsigned int i;
@@ -4424,6 +4425,41 @@ static inline void hif_config_rri_on_ddr(struct hif_softc *scn)
 	for (i = 0; i < CE_COUNT; i++)
 		CE_IDX_UPD_EN_SET(scn, CE_BASE_ADDRESS(i));
 }
+#else
+static inline void hif_config_rri_on_ddr(struct hif_softc *scn)
+{
+	unsigned int i;
+	uint32_t high_paddr, low_paddr;
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct CE_pipe_config *ce_config;
+
+	if (hif_alloc_rri_on_ddr(scn) != QDF_STATUS_SUCCESS)
+		return;
+
+	low_paddr  = RRI_ON_DDR_PADDR_LOW(scn->paddr_rri_on_ddr);
+	high_paddr = RRI_ON_DDR_PADDR_HIGH(scn->paddr_rri_on_ddr);
+
+	hif_debug("using srri and drri from DDR");
+
+	WRITE_CE_DDR_ADDRESS_FOR_RRI_LOW(scn, low_paddr);
+	WRITE_CE_DDR_ADDRESS_FOR_RRI_HIGH(scn, high_paddr);
+
+	for (i = 0; i < CE_COUNT; i++) {
+		ce_config = &hif_state->target_ce_config[i];
+		/*
+		 * For DST channel program both IDX_UPD_EN and
+		 * DMAX length(behalf of F.W) at once to avoid
+		 * race with F.W register update.
+		 */
+		if (ce_config->pipedir == PIPEDIR_IN && ce_config->nbytes_max)
+			CE_IDX_UPD_EN_DMAX_LEN_SET(scn, CE_BASE_ADDRESS(i),
+						   ce_config->nbytes_max);
+		else
+			CE_IDX_UPD_EN_SET(scn, CE_BASE_ADDRESS(i));
+	}
+}
+#endif
+
 #else
 /**
  * hif_config_rri_on_ddr(): Configure the RRI on DDR mechanism

+ 6 - 0
hif/src/ce/ce_reg.h

@@ -370,6 +370,12 @@ unsigned int hif_get_dst_ring_read_index(struct hif_softc *scn,
 #define CE_SRC_RING_SZ_SET(scn, CE_ctrl_addr, n) \
 	A_TARGET_WRITE(scn, (CE_ctrl_addr) + SR_SIZE_ADDRESS, (n))
 
+#define CE_IDX_UPD_EN_DMAX_LEN_SET(scn, CE_ctrl_addr, n) \
+	A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS, \
+	   ((A_TARGET_READ(scn, (CE_ctrl_addr) + \
+	   CE_CTRL1_ADDRESS) & ~CE_CTRL1_DMAX_LENGTH_MASK) | \
+	   CE_CTRL1_DMAX_LENGTH_SET(n) | CE_CTRL1_IDX_UPD_EN))
+
 #define CE_SRC_RING_DMAX_SET(scn, CE_ctrl_addr, n) \
 	A_TARGET_WRITE(scn, (CE_ctrl_addr) + CE_CTRL1_ADDRESS, \
 	   (A_TARGET_READ(scn, (CE_ctrl_addr) + \