summaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/domain.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2018-07-25 11:48:39 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-25 10:55:29 +0200
commit2d8ff0b586fb1c5bd81a3ab286dcc6bbc432044e (patch)
tree0bdc18fec7a9d72e29b0b754a24b9a1df876b34b /drivers/thunderbolt/domain.c
parentfa3af1cb1ec073265c9c87ec44faf006f2f12d96 (diff)
thunderbolt: Add support for runtime PM
When Thunderbolt host controller is set to RTD3 mode (Runtime D3) it is present all the time. Because of this it is important to runtime suspend the controller whenever possible. In case of ICM we have following rules which all needs to be true before the host controller can be put to D3: - The controller firmware reports to support RTD3 - All the connected devices announce support for RTD3 - There is no active XDomain connection Implement this using standard Linux runtime PM APIs so that when all the children devices are runtime suspended, the Thunderbolt host controller PCI device is runtime suspended as well. The ICM firmware then starts powering down power domains towards RTD3 but it can prevent this if it detects that there is an active Display Port stream (this is not visible to the software, though). The Thunderbolt host controller will be runtime resumed either when there is a remote wake event (device is connected or disconnected), or when there is access from userspace that requires hardware access. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/domain.c')
-rw-r--r--drivers/thunderbolt/domain.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
index e377128663e9..092381e2accf 100644
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <crypto/hash.h>
@@ -132,6 +133,8 @@ static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr,
if (!uuids)
return -ENOMEM;
+ pm_runtime_get_sync(&tb->dev);
+
if (mutex_lock_interruptible(&tb->lock)) {
ret = -ERESTARTSYS;
goto out;
@@ -153,7 +156,10 @@ static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr,
}
out:
+ pm_runtime_mark_last_busy(&tb->dev);
+ pm_runtime_put_autosuspend(&tb->dev);
kfree(uuids);
+
return ret;
}
@@ -208,9 +214,11 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
goto err_free_acl;
}
+ pm_runtime_get_sync(&tb->dev);
+
if (mutex_lock_interruptible(&tb->lock)) {
ret = -ERESTARTSYS;
- goto err_free_acl;
+ goto err_rpm_put;
}
ret = tb->cm_ops->set_boot_acl(tb, acl, tb->nboot_acl);
if (!ret) {
@@ -219,6 +227,9 @@ static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
}
mutex_unlock(&tb->lock);
+err_rpm_put:
+ pm_runtime_mark_last_busy(&tb->dev);
+ pm_runtime_put_autosuspend(&tb->dev);
err_free_acl:
kfree(acl);
err_free_str:
@@ -430,6 +441,13 @@ int tb_domain_add(struct tb *tb)
/* This starts event processing */
mutex_unlock(&tb->lock);
+ pm_runtime_no_callbacks(&tb->dev);
+ pm_runtime_set_active(&tb->dev);
+ pm_runtime_enable(&tb->dev);
+ pm_runtime_set_autosuspend_delay(&tb->dev, TB_AUTOSUSPEND_DELAY);
+ pm_runtime_mark_last_busy(&tb->dev);
+ pm_runtime_use_autosuspend(&tb->dev);
+
return 0;
err_domain_del:
@@ -518,6 +536,28 @@ void tb_domain_complete(struct tb *tb)
tb->cm_ops->complete(tb);
}
+int tb_domain_runtime_suspend(struct tb *tb)
+{
+ if (tb->cm_ops->runtime_suspend) {
+ int ret = tb->cm_ops->runtime_suspend(tb);
+ if (ret)
+ return ret;
+ }
+ tb_ctl_stop(tb->ctl);
+ return 0;
+}
+
+int tb_domain_runtime_resume(struct tb *tb)
+{
+ tb_ctl_start(tb->ctl);
+ if (tb->cm_ops->runtime_resume) {
+ int ret = tb->cm_ops->runtime_resume(tb);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
/**
* tb_domain_approve_switch() - Approve switch
* @tb: Domain the switch belongs to