summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/nhi.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2017-06-06 15:25:15 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-06-09 11:42:43 +0200
commitbdccf295d7cdf6f28ceec1dcc31a79d0a1697d21 (patch)
tree41926128da459fc10bfaba4b3ce6feec0cab1a0e /drivers/thunderbolt/nhi.c
parent3e13676862f90dbf5b00d57d5599e57788289897 (diff)
downloadlinux-bdccf295d7cdf6f28ceec1dcc31a79d0a1697d21.tar.gz
linux-bdccf295d7cdf6f28ceec1dcc31a79d0a1697d21.tar.bz2
linux-bdccf295d7cdf6f28ceec1dcc31a79d0a1697d21.zip
thunderbolt: Do not touch the hardware if the NHI is gone on resume
On PCs the NHI host controller is only present when there is a device connected. When the last device is disconnected the host controller will dissappear shortly (within 10s). Now if that happens when we are suspended we should not try to touch the hardware anymore, so add a flag for this and check it before we re-enable rings. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com> Reviewed-by: Michael Jamet <michael.jamet@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 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.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index c358c074f925..14311535661d 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -403,6 +403,8 @@ void ring_start(struct tb_ring *ring)
{
mutex_lock(&ring->nhi->lock);
mutex_lock(&ring->lock);
+ if (ring->nhi->going_away)
+ goto err;
if (ring->running) {
dev_WARN(&ring->nhi->pdev->dev, "ring already started\n");
goto err;
@@ -449,6 +451,8 @@ void ring_stop(struct tb_ring *ring)
mutex_lock(&ring->lock);
dev_info(&ring->nhi->pdev->dev, "stopping %s %d\n",
RING_TYPE(ring), ring->hop);
+ if (ring->nhi->going_away)
+ goto err;
if (!ring->running) {
dev_WARN(&ring->nhi->pdev->dev, "%s %d already stopped\n",
RING_TYPE(ring), ring->hop);
@@ -653,6 +657,14 @@ static int nhi_resume_noirq(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct tb *tb = pci_get_drvdata(pdev);
+ /*
+ * Check that the device is still there. It may be that the user
+ * unplugged last device which causes the host controller to go
+ * away on PCs.
+ */
+ if (!pci_device_is_present(pdev))
+ tb->nhi->going_away = true;
+
return tb_domain_resume_noirq(tb);
}