[PATCH 363/379][SRU][OEM-5.6] UBUNTU: SAUCE: ath11k: put target to suspend when system enters suspend state

You-Sheng Yang vicamo.yang at canonical.com
Wed Dec 23 08:51:36 UTC 2020


From: Carl Huang <cjhuang at codeaurora.org>

BugLink: https://bugs.launchpad.net/bugs/1879633

This change is to put target to suspend state when OS enters
suspend state and resume the target when OS resumes.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <cjhuang at codeaurora.org>
Signed-off-by: Kalle Valo <kvalo at codeaurora.org>
(cherry picked from commit 68023bee4d61ea2b02af49bba00adabba51d8b6b
https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git)
Signed-off-by: You-Sheng Yang <vicamo.yang at canonical.com>
---
 drivers/net/wireless/ath/ath11k/core.c | 38 ++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/core.h |  2 ++
 drivers/net/wireless/ath/ath11k/hw.h   |  1 +
 drivers/net/wireless/ath/ath11k/pci.c  | 41 ++++++++++++++++++++++++--
 4 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index ebd6886a8c18..6e126e2ffffe 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -65,6 +65,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_monitor = true,
 		.supports_shadow_regs = false,
 		.idle_ps = false,
+		.support_suspend = false,
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -102,6 +103,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_monitor = true,
 		.supports_shadow_regs = false,
 		.idle_ps = false,
+		.support_suspend = false,
 	},
 	{
 		.name = "qca6390 hw2.0",
@@ -138,6 +140,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_monitor = false,
 		.supports_shadow_regs = true,
 		.idle_ps = true,
+		.support_suspend = true,
 	},
 };
 
@@ -937,5 +940,40 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
 }
 EXPORT_SYMBOL(ath11k_core_alloc);
 
+int ath11k_core_suspend(struct ath11k_base *ab)
+{
+	struct ath11k *ar = ab->pdevs[0].ar;
+	int ret = 0;
+
+	if (ab->hw_params.support_suspend) {
+		reinit_completion(&ar->target_suspend);
+		ath11k_wmi_pdev_suspend(ar, 1, 0);
+		ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ);
+		if (ret == 0) {
+			ath11k_warn(ab,
+				    "timed out while waiting for suspend completion\n");
+			return -ETIMEDOUT;
+		} else if (!ar->target_suspend_ack) {
+			ath11k_warn(ab, "suspend failed\n");
+			return -EAGAIN;
+		}
+
+		return ath11k_hif_suspend(ab);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ath11k_core_suspend);
+
+int ath11k_core_resume(struct ath11k_base *ab)
+{
+	if (ab->hw_params.support_suspend) {
+		ath11k_hif_resume(ab);
+		ath11k_wmi_pdev_resume(ab->pdevs[0].ar, 0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ath11k_core_resume);
+
 MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a51bb6f918a0..a0ff7579b310 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -888,6 +888,8 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
 void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
 
 void ath11k_core_halt(struct ath11k *ar);
+int ath11k_core_resume(struct ath11k_base *ab);
+int ath11k_core_suspend(struct ath11k_base *ab);
 
 const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
 						    const char *filename);
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 1dda4257e6d7..0df9c901aa3a 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -161,6 +161,7 @@ struct ath11k_hw_params {
 	bool supports_monitor;
 	bool supports_shadow_regs;
 	bool idle_ps;
+	bool support_suspend;
 };
 
 struct ath11k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 0a59a7ccd7dc..4f058ceaa0f1 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -243,13 +243,17 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
 
 static void ath11k_pci_force_wake(struct ath11k_base *ab)
 {
+	int val;
+
+	ath11k_pci_write32(ab, PCIE_SCRATCH_0_SOC_PCIE_REG, 0);
 	ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
-	mdelay(5);
+	mdelay(10);
+	val = ath11k_pci_read32(ab, PCIE_SCRATCH_0_SOC_PCIE_REG);
+	ath11k_dbg(ab, ATH11K_DBG_PCI, "forcw_wake scratch 0: 0x%x\n", val);
 }
 
 static void ath11k_pci_sw_reset(struct ath11k_base *ab)
 {
-	ath11k_pci_soc_global_reset(ab);
 	ath11k_mhi_clear_vector(ab);
 	ath11k_pci_soc_global_reset(ab);
 	ath11k_mhi_set_mhictrl_reset(ab);
@@ -885,9 +889,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
 {
 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
 
+	ath11k_pci_force_wake(ab_pci->ab);
 	ath11k_mhi_stop(ab_pci);
 	clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
-	ath11k_pci_force_wake(ab_pci->ab);
 	ath11k_pci_sw_reset(ab_pci->ab);
 }
 
@@ -1180,12 +1184,43 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
 	ath11k_pci_power_down(ab);
 }
 
+static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
+{
+	struct ath11k_base *ab = dev_get_drvdata(dev);
+	int ret;
+
+	ret = ath11k_core_suspend(ab);
+	if (ret)
+		ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
+
+	return ret;
+}
+
+static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
+{
+	struct ath11k_base *ab = dev_get_drvdata(dev);
+	int ret;
+
+	ret = ath11k_core_resume(ab);
+	if (ret)
+		ath11k_warn(ab, "failed to resume hif: %d\n", ret);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
+			 ath11k_pci_pm_suspend,
+			 ath11k_pci_pm_resume);
+
 static struct pci_driver ath11k_pci_driver = {
 	.name = "ath11k_pci",
 	.id_table = ath11k_pci_id_table,
 	.probe = ath11k_pci_probe,
 	.remove = ath11k_pci_remove,
 	.shutdown = ath11k_pci_shutdown,
+#ifdef CONFIG_PM
+	.driver.pm = &ath11k_pci_pm_ops,
+#endif
 };
 
 static int ath11k_pci_init(void)
-- 
2.29.2




More information about the kernel-team mailing list