diff options
author | Andreas Noever <andreas.noever@gmail.com> | 2014-06-03 16:04:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-06-19 17:13:00 -0400 |
commit | 23dd5bb49d986f37977ed80dd2ca65040ead4392 (patch) | |
tree | 390db91ea55659f22ca93a15ac41bf584bd3a9b9 /drivers/thunderbolt/nhi.c | |
parent | c90553b3c4ac2389a71a5c012b6e5bb1160d48a7 (diff) |
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.c | 33 |
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 @@ | |||
7 | * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com> | 7 | * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/pm_runtime.h> | ||
10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
11 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
12 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
@@ -492,6 +493,22 @@ static irqreturn_t nhi_msi(int irq, void *data) | |||
492 | return IRQ_HANDLED; | 493 | return IRQ_HANDLED; |
493 | } | 494 | } |
494 | 495 | ||
496 | static int nhi_suspend_noirq(struct device *dev) | ||
497 | { | ||
498 | struct pci_dev *pdev = to_pci_dev(dev); | ||
499 | struct tb *tb = pci_get_drvdata(pdev); | ||
500 | thunderbolt_suspend(tb); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int nhi_resume_noirq(struct device *dev) | ||
505 | { | ||
506 | struct pci_dev *pdev = to_pci_dev(dev); | ||
507 | struct tb *tb = pci_get_drvdata(pdev); | ||
508 | thunderbolt_resume(tb); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
495 | static void nhi_shutdown(struct tb_nhi *nhi) | 512 | static void nhi_shutdown(struct tb_nhi *nhi) |
496 | { | 513 | { |
497 | int i; | 514 | int i; |
@@ -600,6 +617,21 @@ static void nhi_remove(struct pci_dev *pdev) | |||
600 | nhi_shutdown(nhi); | 617 | nhi_shutdown(nhi); |
601 | } | 618 | } |
602 | 619 | ||
620 | /* | ||
621 | * The tunneled pci bridges are siblings of us. Use resume_noirq to reenable | ||
622 | * the tunnels asap. A corresponding pci quirk blocks the downstream bridges | ||
623 | * resume_noirq until we are done. | ||
624 | */ | ||
625 | static const struct dev_pm_ops nhi_pm_ops = { | ||
626 | .suspend_noirq = nhi_suspend_noirq, | ||
627 | .resume_noirq = nhi_resume_noirq, | ||
628 | .freeze_noirq = nhi_suspend_noirq, /* | ||
629 | * we just disable hotplug, the | ||
630 | * pci-tunnels stay alive. | ||
631 | */ | ||
632 | .restore_noirq = nhi_resume_noirq, | ||
633 | }; | ||
634 | |||
603 | struct pci_device_id nhi_ids[] = { | 635 | struct pci_device_id nhi_ids[] = { |
604 | /* | 636 | /* |
605 | * We have to specify class, the TB bridges use the same device and | 637 | * We have to specify class, the TB bridges use the same device and |
@@ -626,6 +658,7 @@ static struct pci_driver nhi_driver = { | |||
626 | .id_table = nhi_ids, | 658 | .id_table = nhi_ids, |
627 | .probe = nhi_probe, | 659 | .probe = nhi_probe, |
628 | .remove = nhi_remove, | 660 | .remove = nhi_remove, |
661 | .driver.pm = &nhi_pm_ops, | ||
629 | }; | 662 | }; |
630 | 663 | ||
631 | static int __init nhi_init(void) | 664 | static int __init nhi_init(void) |