diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2018-07-25 11:48:39 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-07-25 10:55:29 +0200 |
commit | 2d8ff0b586fb1c5bd81a3ab286dcc6bbc432044e (patch) | |
tree | 0bdc18fec7a9d72e29b0b754a24b9a1df876b34b /drivers/thunderbolt/domain.c | |
parent | fa3af1cb1ec073265c9c87ec44faf006f2f12d96 (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.c | 42 |
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 |