Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1543982
| From | Lukas Wunner <lukas@wunner.de> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH v3 7/7] thunderbolt: Runtime suspend NHI when idle |
| Date | 2016-12-17 15:50 +0100 |
| Message-ID | <sPotb-2qh-7@gated-at.bofh.it> (permalink) |
| References | <sPojw-2mJ-25@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
Runtime suspend the NHI when no Thunderbolt devices have been plugged in
for 10 sec (user-configurable via autosuspend_delay_ms in sysfs).
The NHI is not able to detect plug events while suspended, it relies on
the GPE handler to resume it on hotplug.
After the NHI resumes, it takes about 700 ms until a hotplug event
appears on the RX ring. In case autosuspend_delay_ms has been reduced
to 0 by the user, we need to wait in tb_resume() to avoid going back to
sleep before we had a chance to detect a hotplugged device. A runtime
pm ref is held for the duration of tb_handle_hotplug() to keep the NHI
awake while the hotplug event is processed.
Apart from that we acquire a runtime pm ref for each newly allocated
switch (except for the root switch) and drop one when a switch is freed,
thereby ensuring the NHI stays active as long as devices are plugged in.
This behaviour is identical to the macOS driver.
Cc: Andreas Noever <andreas.noever@gmail.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
drivers/thunderbolt/nhi.c | 2 ++
drivers/thunderbolt/power.c | 9 +++++++++
drivers/thunderbolt/switch.c | 9 +++++++++
drivers/thunderbolt/tb.c | 13 +++++++++++++
4 files changed, 33 insertions(+)
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 88fb2fb..319ed81 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -632,6 +632,8 @@ static const struct dev_pm_ops nhi_pm_ops = {
* pci-tunnels stay alive.
*/
.restore_noirq = nhi_resume_noirq,
+ .runtime_suspend = nhi_suspend_noirq,
+ .runtime_resume = nhi_resume_noirq,
};
static struct pci_device_id nhi_ids[] = {
diff --git a/drivers/thunderbolt/power.c b/drivers/thunderbolt/power.c
index 4d7c6a0..1b5f066 100644
--- a/drivers/thunderbolt/power.c
+++ b/drivers/thunderbolt/power.c
@@ -320,6 +320,12 @@ void thunderbolt_power_init(struct tb *tb)
tb->power = power;
+ pm_runtime_allow(nhi_dev);
+ pm_runtime_set_autosuspend_delay(nhi_dev, 10000);
+ pm_runtime_use_autosuspend(nhi_dev);
+ pm_runtime_mark_last_busy(nhi_dev);
+ pm_runtime_put_autosuspend(nhi_dev);
+
return;
err:
@@ -336,6 +342,9 @@ void thunderbolt_power_fini(struct tb *tb)
if (!power)
return;
+ pm_runtime_get(nhi_dev);
+ pm_runtime_forbid(nhi_dev);
+
tb->power = NULL;
dev_pm_domain_set(upstream_dev, NULL);
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index c6f30b1..422fe6e 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -5,6 +5,7 @@
*/
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "tb.h"
@@ -326,6 +327,11 @@ void tb_switch_free(struct tb_switch *sw)
if (!sw->is_unplugged)
tb_plug_events_active(sw, false);
+ if (sw != sw->tb->root_switch) {
+ pm_runtime_mark_last_busy(&sw->tb->nhi->pdev->dev);
+ pm_runtime_put_autosuspend(&sw->tb->nhi->pdev->dev);
+ }
+
kfree(sw->ports);
kfree(sw->drom);
kfree(sw);
@@ -420,6 +426,9 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
if (tb_plug_events_active(sw, true))
goto err;
+ if (tb->root_switch)
+ pm_runtime_get(&tb->nhi->pdev->dev);
+
return sw;
err:
kfree(sw->ports);
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 24b6d30..a3fedf9 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "tb.h"
#include "tb_regs.h"
@@ -217,8 +218,11 @@ static void tb_handle_hotplug(struct work_struct *work)
{
struct tb_hotplug_event *ev = container_of(work, typeof(*ev), work);
struct tb *tb = ev->tb;
+ struct device *dev = &tb->nhi->pdev->dev;
struct tb_switch *sw;
struct tb_port *port;
+
+ pm_runtime_get(dev);
mutex_lock(&tb->lock);
if (!tb->hotplug_active)
goto out; /* during init, suspend or shutdown */
@@ -274,6 +278,8 @@ static void tb_handle_hotplug(struct work_struct *work)
out:
mutex_unlock(&tb->lock);
kfree(ev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
/**
@@ -433,4 +439,11 @@ void thunderbolt_resume(struct tb *tb)
tb->hotplug_active = true;
mutex_unlock(&tb->lock);
tb_info(tb, "resume finished\n");
+
+ /*
+ * If runtime resuming due to a hotplug event (rather than resuming
+ * from system sleep), wait for it to arrive. May take about 700 ms.
+ */
+ if (tb->nhi->pdev->dev.power.runtime_status == RPM_RESUMING)
+ msleep(1000);
}
--
2.10.2
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH v3 0/7] Runtime PM for Thunderbolt on Macs Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:40 +0100
[PATCH v3 5/7] PM: Make requirements of dev_pm_domain_set() more precise Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
[PATCH v3 4/7] Revert "PM / Runtime: Remove the exported function pm_children_suspended()" Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
[PATCH v3 6/7] thunderbolt: Power down controller when idle Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
Re: [PATCH v3 6/7] thunderbolt: Power down controller when idle Andy Shevchenko <andy.shevchenko@gmail.com> - 2016-12-19 00:10 +0100
Re: [PATCH v3 6/7] thunderbolt: Power down controller when idle Lukas Wunner <lukas@wunner.de> - 2016-12-20 12:30 +0100
Re: [PATCH v3 6/7] thunderbolt: Power down controller when idle Andy Shevchenko <andy.shevchenko@gmail.com> - 2016-12-20 14:50 +0100
Re: [PATCH v3 6/7] thunderbolt: Power down controller when idle Lukas Wunner <lukas@wunner.de> - 2016-12-21 12:00 +0100
[PATCH v3 2/7] PCI: Allow runtime PM on Thunderbolt ports Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
[PATCH v3 7/7] thunderbolt: Runtime suspend NHI when idle Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
[PATCH v3 1/7] PCI: Recognize Thunderbolt devices Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
[PATCH v3 3/7] PCI: Don't block runtime PM for Thunderbolt host hotplug ports Lukas Wunner <lukas@wunner.de> - 2016-12-17 15:50 +0100
csiph-web