|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
|
|
|
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
|
|
|
*
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
@@ -18,13 +18,20 @@
|
|
|
#include <linux/pci.h>
|
|
|
#include <linux/moduleparam.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
-
|
|
|
+#include <linux/suspend.h>
|
|
|
#include "wil6210.h"
|
|
|
|
|
|
static bool use_msi = true;
|
|
|
module_param(use_msi, bool, S_IRUGO);
|
|
|
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+static int wil6210_pm_notify(struct notifier_block *notify_block,
|
|
|
+ unsigned long mode, void *unused);
|
|
|
+#endif /* CONFIG_PM_SLEEP */
|
|
|
+#endif /* CONFIG_PM */
|
|
|
+
|
|
|
static
|
|
|
void wil_set_capabilities(struct wil6210_priv *wil)
|
|
|
{
|
|
@@ -238,6 +245,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
goto bus_disable;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+ wil->pm_notify.notifier_call = wil6210_pm_notify;
|
|
|
+ rc = register_pm_notifier(&wil->pm_notify);
|
|
|
+ if (rc)
|
|
|
+ /* Do not fail the driver initialization, as suspend can
|
|
|
+ * be prevented in a later phase if needed
|
|
|
+ */
|
|
|
+ wil_err(wil, "register_pm_notifier failed: %d\n", rc);
|
|
|
+#endif /* CONFIG_PM_SLEEP */
|
|
|
+#endif /* CONFIG_PM */
|
|
|
+
|
|
|
wil6210_debugfs_init(wil);
|
|
|
|
|
|
|
|
@@ -267,6 +286,12 @@ static void wil_pcie_remove(struct pci_dev *pdev)
|
|
|
|
|
|
wil_dbg_misc(wil, "%s()\n", __func__);
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+ unregister_pm_notifier(&wil->pm_notify);
|
|
|
+#endif /* CONFIG_PM_SLEEP */
|
|
|
+#endif /* CONFIG_PM */
|
|
|
+
|
|
|
wil6210_debugfs_remove(wil);
|
|
|
wil_if_remove(wil);
|
|
|
wil_if_pcie_disable(wil);
|
|
@@ -335,6 +360,45 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static int wil6210_pm_notify(struct notifier_block *notify_block,
|
|
|
+ unsigned long mode, void *unused)
|
|
|
+{
|
|
|
+ struct wil6210_priv *wil = container_of(
|
|
|
+ notify_block, struct wil6210_priv, pm_notify);
|
|
|
+ int rc = 0;
|
|
|
+ enum wil_platform_event evt;
|
|
|
+
|
|
|
+ wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode);
|
|
|
+
|
|
|
+ switch (mode) {
|
|
|
+ case PM_HIBERNATION_PREPARE:
|
|
|
+ case PM_SUSPEND_PREPARE:
|
|
|
+ case PM_RESTORE_PREPARE:
|
|
|
+ rc = wil_can_suspend(wil, false);
|
|
|
+ if (rc)
|
|
|
+ break;
|
|
|
+ evt = WIL_PLATFORM_EVT_PRE_SUSPEND;
|
|
|
+ if (wil->platform_ops.notify)
|
|
|
+ rc = wil->platform_ops.notify(wil->platform_handle,
|
|
|
+ evt);
|
|
|
+ break;
|
|
|
+ case PM_POST_SUSPEND:
|
|
|
+ case PM_POST_HIBERNATION:
|
|
|
+ case PM_POST_RESTORE:
|
|
|
+ evt = WIL_PLATFORM_EVT_POST_SUSPEND;
|
|
|
+ if (wil->platform_ops.notify)
|
|
|
+ rc = wil->platform_ops.notify(wil->platform_handle,
|
|
|
+ evt);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ wil_dbg_pm(wil, "unhandled notify mode %ld\n", mode);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ wil_dbg_pm(wil, "notification mode %ld: rc (%d)\n", mode, rc);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
static int wil6210_pm_suspend(struct device *dev)
|
|
|
{
|
|
|
return wil6210_suspend(dev, false);
|