summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-09-15 18:12:38 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-09-15 18:12:38 -0700
commit809e35f581c3441857eb150c1f7d67e217bd735c (patch)
treed282aca9735e408c040d828604c4be9cb0d41c3d
parent393bfcf23206ec8302876474526b6e595cbaacce (diff)
parentae120800baa609d9d95861f396b7f792493abbc2 (diff)
Merge "ath10k: synchronize WLAN ON/OFF cmd during system suspend"
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c46
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.h2
2 files changed, 47 insertions, 1 deletions
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 <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
+#include <linux/suspend.h>
#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;
};