From ae120800baa609d9d95861f396b7f792493abbc2 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Wed, 6 Sep 2017 22:16:24 +0530 Subject: [PATCH] ath10k: synchronize WLAN ON/OFF cmd during system suspend During system suspend/resume or WLAN interface up/down by the network subsystem the ath10k SNOC WLAN driver configure WLAN enable/disable cmd with the WLAN firmware over QMI interface. The WLAN enable/disable cmd configuration with the WLAN firmware during system suspend is preventing the system suspend. Register PM event notifier for the ath10k SNOC platform driver and synchronize the WLAN HIF power down/up configuration, WLAN enable/disable cmd configuration with WLAN firmware according to the system power state. CRs-Fixed: 2110607 Change-Id: I5eeda967ae11c21ab5164c18b3e0a3bf668c916a Signed-off-by: Sarada Prasanna Garnayak --- drivers/net/wireless/ath/ath10k/snoc.c | 46 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/snoc.h | 2 ++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 13736750e463..f5aa88a76f17 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "core.h" #include "debug.h" #include "hif.h" @@ -955,9 +956,13 @@ static int ath10k_snoc_init_pipes(struct ath10k *ar) static void ath10k_snoc_hif_power_down(struct ath10k *ar) { + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); msleep(SNOC_HIF_POWER_DOWN_DELAY); - ath10k_snoc_qmi_wlan_disable(ar); + + if (!atomic_read(&ar_snoc->pm_ops_inprogress)) + ath10k_snoc_qmi_wlan_disable(ar); } int ath10k_snoc_get_ce_id(struct ath10k *ar, int irq) @@ -1141,10 +1146,18 @@ static int ath10k_snoc_claim(struct ath10k *ar) static int ath10k_snoc_hif_power_up(struct ath10k *ar) { int ret; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 driver state = %d\n", __func__, ar->state); + if (atomic_read(&ar_snoc->pm_ops_inprogress)) { + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "%s: WLAN OFF CMD Reset on PM Resume\n", __func__); + ath10k_snoc_qmi_wlan_disable(ar); + atomic_set(&ar_snoc->pm_ops_inprogress, 0); + } + if (ar->state == ATH10K_STATE_ON || test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) { ret = ath10k_snoc_bus_configure(ar); @@ -1208,6 +1221,33 @@ out: return ret; } +static +int ath10k_snoc_pm_notifier(struct notifier_block *nb, + unsigned long pm_event, void *data) +{ + struct ath10k_snoc *ar_snoc = + container_of(nb, struct ath10k_snoc, pm_notifier); + struct ath10k *ar = ar_snoc->ar; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "%s: PM Event: %lu\n", __func__, pm_event); + + switch (pm_event) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + case PM_RESTORE_PREPARE: + case PM_POST_RESTORE: + atomic_set(&ar_snoc->pm_ops_inprogress, 1); + break; + default: + break; + } + + return NOTIFY_DONE; +} + static const struct ath10k_hif_ops ath10k_snoc_hif_ops = { .tx_sg = ath10k_snoc_hif_tx_sg, .start = ath10k_snoc_hif_start, @@ -1306,6 +1346,9 @@ static int ath10k_snoc_probe(struct platform_device *pdev) ath10k_snoc_modem_ssr_register_notifier(ar); ath10k_snoc_pd_restart_enable(ar); + ar_snoc->pm_notifier.notifier_call = ath10k_snoc_pm_notifier; + register_pm_notifier(&ar_snoc->pm_notifier); + ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 probed\n", __func__); return 0; @@ -1338,6 +1381,7 @@ static int ath10k_snoc_remove(struct platform_device *pdev) ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 removed\n", __func__); + unregister_pm_notifier(&ar_snoc->pm_notifier); ath10k_core_unregister(ar); ath10k_snoc_pdr_unregister_notifier(ar); ath10k_snoc_modem_ssr_unregister_notifier(ar); diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 7a223b1d3ded..d6e05ba18cb8 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -148,12 +148,14 @@ struct ath10k_snoc { u32 *vaddr_rri_on_ddr; bool is_driver_probed; struct notifier_block modem_ssr_nb; + struct notifier_block pm_notifier; void *modem_notify_handler; struct ath10k_service_notifier_context *service_notifier; struct notifier_block service_notifier_nb; int total_domains; struct notifier_block get_service_nb; atomic_t fw_crashed; + atomic_t pm_ops_inprogress; struct ath10k_snoc_qmi_config qmi_cfg; };