]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
thunderbolt: Only stop control channel when entering freeze
authorMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 31 Aug 2020 10:05:14 +0000 (13:05 +0300)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Wed, 16 Sep 2020 11:57:46 +0000 (14:57 +0300)
According to the kernel power management documentation freeze phase
should only quiesce the device, no need to configure wakes or put it to
low power state. For this reason we simply stop the control channel and
in case of Software Connection Manager also mark the hotplug disabled.
This should align the driver better with the PM framework expectations.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/thunderbolt/domain.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tb.h

index 00d66f06804aac440d8c2d0479a8aac139736ff3..a0182bf5a5f8bcacaf6c087714975eb79f457345 100644 (file)
@@ -546,6 +546,33 @@ int tb_domain_suspend(struct tb *tb)
        return tb->cm_ops->suspend ? tb->cm_ops->suspend(tb) : 0;
 }
 
+int tb_domain_freeze_noirq(struct tb *tb)
+{
+       int ret = 0;
+
+       mutex_lock(&tb->lock);
+       if (tb->cm_ops->freeze_noirq)
+               ret = tb->cm_ops->freeze_noirq(tb);
+       if (!ret)
+               tb_ctl_stop(tb->ctl);
+       mutex_unlock(&tb->lock);
+
+       return ret;
+}
+
+int tb_domain_thaw_noirq(struct tb *tb)
+{
+       int ret = 0;
+
+       mutex_lock(&tb->lock);
+       tb_ctl_start(tb->ctl);
+       if (tb->cm_ops->thaw_noirq)
+               ret = tb->cm_ops->thaw_noirq(tb);
+       mutex_unlock(&tb->lock);
+
+       return ret;
+}
+
 void tb_domain_complete(struct tb *tb)
 {
        if (tb->cm_ops->complete)
index bd24e8254336145346c8ba6c4c1d303a15c09e86..3f79baa54829dfd423ba417e5cb0c578213021da 100644 (file)
@@ -864,6 +864,22 @@ static int nhi_suspend_noirq(struct device *dev)
        return __nhi_suspend_noirq(dev, device_may_wakeup(dev));
 }
 
+static int nhi_freeze_noirq(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct tb *tb = pci_get_drvdata(pdev);
+
+       return tb_domain_freeze_noirq(tb);
+}
+
+static int nhi_thaw_noirq(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct tb *tb = pci_get_drvdata(pdev);
+
+       return tb_domain_thaw_noirq(tb);
+}
+
 static bool nhi_wake_supported(struct pci_dev *pdev)
 {
        u8 val;
@@ -1255,14 +1271,13 @@ static void nhi_remove(struct pci_dev *pdev)
 static const struct dev_pm_ops nhi_pm_ops = {
        .suspend_noirq = nhi_suspend_noirq,
        .resume_noirq = nhi_resume_noirq,
-       .freeze_noirq = nhi_suspend_noirq, /*
+       .freeze_noirq = nhi_freeze_noirq,  /*
                                            * we just disable hotplug, the
                                            * pci-tunnels stay alive.
                                            */
-       .thaw_noirq = nhi_resume_noirq,
+       .thaw_noirq = nhi_thaw_noirq,
        .restore_noirq = nhi_resume_noirq,
        .suspend = nhi_suspend,
-       .freeze = nhi_suspend,
        .poweroff_noirq = nhi_poweroff_noirq,
        .poweroff = nhi_suspend,
        .complete = nhi_complete,
index 170d1d846557259e3727f3f1bd2b4939c6455ef9..214fbc92c1b7d8333bddd3e2a1bc5d0e15b3bad6 100644 (file)
@@ -1424,6 +1424,22 @@ static int tb_free_unplugged_xdomains(struct tb_switch *sw)
        return ret;
 }
 
+static int tb_freeze_noirq(struct tb *tb)
+{
+       struct tb_cm *tcm = tb_priv(tb);
+
+       tcm->hotplug_active = false;
+       return 0;
+}
+
+static int tb_thaw_noirq(struct tb *tb)
+{
+       struct tb_cm *tcm = tb_priv(tb);
+
+       tcm->hotplug_active = true;
+       return 0;
+}
+
 static void tb_complete(struct tb *tb)
 {
        /*
@@ -1490,6 +1506,8 @@ static const struct tb_cm_ops tb_cm_ops = {
        .stop = tb_stop,
        .suspend_noirq = tb_suspend_noirq,
        .resume_noirq = tb_resume_noirq,
+       .freeze_noirq = tb_freeze_noirq,
+       .thaw_noirq = tb_thaw_noirq,
        .complete = tb_complete,
        .runtime_suspend = tb_runtime_suspend,
        .runtime_resume = tb_runtime_resume,
index 450f9cf160053df0b8f33dea1a65410f07a249c7..8b04a9deffc79652fdcf4793453df32e4b1c68f9 100644 (file)
@@ -351,6 +351,8 @@ struct tb_path {
  * @suspend_noirq: Connection manager specific suspend_noirq
  * @resume_noirq: Connection manager specific resume_noirq
  * @suspend: Connection manager specific suspend
+ * @freeze_noirq: Connection manager specific freeze_noirq
+ * @thaw_noirq: Connection manager specific thaw_noirq
  * @complete: Connection manager specific complete
  * @runtime_suspend: Connection manager specific runtime_suspend
  * @runtime_resume: Connection manager specific runtime_resume
@@ -373,6 +375,8 @@ struct tb_cm_ops {
        int (*suspend_noirq)(struct tb *tb);
        int (*resume_noirq)(struct tb *tb);
        int (*suspend)(struct tb *tb);
+       int (*freeze_noirq)(struct tb *tb);
+       int (*thaw_noirq)(struct tb *tb);
        void (*complete)(struct tb *tb);
        int (*runtime_suspend)(struct tb *tb);
        int (*runtime_resume)(struct tb *tb);
@@ -607,6 +611,8 @@ void tb_domain_remove(struct tb *tb);
 int tb_domain_suspend_noirq(struct tb *tb);
 int tb_domain_resume_noirq(struct tb *tb);
 int tb_domain_suspend(struct tb *tb);
+int tb_domain_freeze_noirq(struct tb *tb);
+int tb_domain_thaw_noirq(struct tb *tb);
 void tb_domain_complete(struct tb *tb);
 int tb_domain_runtime_suspend(struct tb *tb);
 int tb_domain_runtime_resume(struct tb *tb);