ソースを参照

qcacmn: Prevent runtime PM suspending during hif_force_wake_request

Currently if write non-shadow register and not in initial
phase, host will call hif_force_wake_request()-->
pld_force_wake_request_sync(), but this API can not guarantee
MHI/PCIe is in wake state if runtime PM suspending is ongoing
in parallel, later any register accessing through PCIe bus will hit
NOC error.

Add hif_pm_runtime_get_sync() in hif_force_wake_request() to prevent
runtime PM suspending.

Change-Id: Id60c6041a830d9ad27b0b4173a036c9c57fbf350
CRs-Fixed: 3120170
Jinwei Chen 3 年 前
コミット
a8fe61c936
2 ファイル変更21 行追加4 行削除
  1. 2 0
      hif/inc/hif.h
  2. 19 4
      hif/src/pcie/if_pci.c

+ 2 - 0
hif/inc/hif.h

@@ -1170,6 +1170,7 @@ hif_pm_wake_irq_type hif_pm_get_wake_irq_type(struct hif_opaque_softc *hif_ctx);
  * @RTPM_ID_CE_INTR_HANDLER: operation from ce interrupt handler
  * @RTPM_ID_WAKE_INTR_HANDLER: operation from wake interrupt handler
  * @RTPM_ID_SOC_IDLE_SHUTDOWN: operation in soc idle shutdown
+ * @RTPM_ID_HIF_FORCE_WAKE: operation in hif force wake
  */
 /* New value added to the enum must also be reflected in function
  *  rtpm_string_from_dbgid()
@@ -1192,6 +1193,7 @@ typedef enum {
 	RTPM_ID_CE_INTR_HANDLER,
 	RTPM_ID_WAKE_INTR_HANDLER,
 	RTPM_ID_SOC_IDLE_SHUTDOWN,
+	RTPM_ID_HIF_FORCE_WAKE,
 
 	RTPM_ID_MAX,
 } wlan_rtpm_dbgid;

+ 19 - 4
hif/src/pcie/if_pci.c

@@ -4012,8 +4012,13 @@ int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
 	struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn);
 
-	HIF_STATS_INC(pci_scn, mhi_force_wake_request_vote, 1);
+	/* Prevent runtime PM or trigger resume firstly */
+	if (hif_pm_runtime_get_sync(hif_handle, RTPM_ID_HIF_FORCE_WAKE)) {
+		hif_err("runtime pm get failed");
+		return -EINVAL;
+	}
 
+	HIF_STATS_INC(pci_scn, mhi_force_wake_request_vote, 1);
 	if (qdf_in_interrupt())
 		timeout = FORCE_WAKE_DELAY_TIMEOUT_MS * 1000;
 	else
@@ -4067,15 +4072,25 @@ int hif_force_wake_release(struct hif_opaque_softc *hif_handle)
 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
 	struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn);
 
+	/* Release umac force wake */
+	hif_write32_mb(scn, scn->mem + PCIE_REG_WAKE_UMAC_OFFSET, 0);
+
+	/* Release MHI force wake */
 	ret = pld_force_wake_release(scn->qdf_dev->dev);
 	if (ret) {
-		hif_err("force wake release failure");
+		hif_err("pld force wake release failure");
 		HIF_STATS_INC(pci_scn, mhi_force_wake_release_failure, 1);
 		return ret;
 	}
-
 	HIF_STATS_INC(pci_scn, mhi_force_wake_release_success, 1);
-	hif_write32_mb(scn, scn->mem + PCIE_REG_WAKE_UMAC_OFFSET, 0);
+
+	/* Release runtime PM force wake */
+	ret = hif_pm_runtime_put(hif_handle, RTPM_ID_HIF_FORCE_WAKE);
+	if (ret) {
+		hif_err("runtime pm put failure");
+		return ret;
+	}
+
 	HIF_STATS_INC(pci_scn, soc_force_wake_release_success, 1);
 	return 0;
 }