summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/nhi.c
diff options
context:
space:
mode:
authorAndreas Noever <andreas.noever@gmail.com>2014-06-03 22:04:12 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-06-19 23:13:00 +0200
commit23dd5bb49d986f37977ed80dd2ca65040ead4392 (patch)
tree390db91ea55659f22ca93a15ac41bf584bd3a9b9 /drivers/thunderbolt/nhi.c
parentthunderbolt: Read switch uid from EEPROM (diff)
downloadlinux-23dd5bb49d986f37977ed80dd2ca65040ead4392.tar.xz
linux-23dd5bb49d986f37977ed80dd2ca65040ead4392.zip
thunderbolt: Add suspend/hibernate support
We use _noirq since we have to restore the pci tunnels before the pci core wakes the tunneled devices. Signed-off-by: Andreas Noever <andreas.noever@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/nhi.c')
-rw-r--r--drivers/thunderbolt/nhi.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index d2b9ce857818..346b41e7d5d1 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -7,6 +7,7 @@
* Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
*/
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -492,6 +493,22 @@ static irqreturn_t nhi_msi(int irq, void *data)
return IRQ_HANDLED;
}
+static int nhi_suspend_noirq(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct tb *tb = pci_get_drvdata(pdev);
+ thunderbolt_suspend(tb);
+ return 0;
+}
+
+static int nhi_resume_noirq(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct tb *tb = pci_get_drvdata(pdev);
+ thunderbolt_resume(tb);
+ return 0;
+}
+
static void nhi_shutdown(struct tb_nhi *nhi)
{
int i;
@@ -600,6 +617,21 @@ static void nhi_remove(struct pci_dev *pdev)
nhi_shutdown(nhi);
}
+/*
+ * The tunneled pci bridges are siblings of us. Use resume_noirq to reenable
+ * the tunnels asap. A corresponding pci quirk blocks the downstream bridges
+ * resume_noirq until we are done.
+ */
+static const struct dev_pm_ops nhi_pm_ops = {
+ .suspend_noirq = nhi_suspend_noirq,
+ .resume_noirq = nhi_resume_noirq,
+ .freeze_noirq = nhi_suspend_noirq, /*
+ * we just disable hotplug, the
+ * pci-tunnels stay alive.
+ */
+ .restore_noirq = nhi_resume_noirq,
+};
+
struct pci_device_id nhi_ids[] = {
/*
* We have to specify class, the TB bridges use the same device and
@@ -626,6 +658,7 @@ static struct pci_driver nhi_driver = {
.id_table = nhi_ids,
.probe = nhi_probe,
.remove = nhi_remove,
+ .driver.pm = &nhi_pm_ops,
};
static int __init nhi_init(void)