linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PM / runtime: Add support for wake-up reason for wakeirqs
@ 2019-10-09 18:28 Tony Lindgren
  2019-10-09 18:51 ` Alan Stern
  0 siblings, 1 reply; 3+ messages in thread
From: Tony Lindgren @ 2019-10-09 18:28 UTC (permalink / raw)
  To: Rafael J . Wysocki, Alan Stern
  Cc: Dmitry Torokhov, Grygorii Strashko, Ulf Hansson, linux-pm,
	linux-kernel

With generic wakeirqs we can wake a device, but do not know if the
device woke to a wakeirq. Let's add pm_runtime_wakeup_is_wakeirq() so
a device can check the wake-up reason.

This can used for cases where a device wakes up on its own to a
wake-up interrupt, and the device PM runtime resume function can
then skip some or all of the device wake-up sequence based on
pm_runtime_wakeup_is_wakeirq().

Let's only add RPM_WAKEUP_NONE and RPM_WAKEUP_WAKEIRQ for now, other
events can be added later on if really needed.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/base/power/wakeirq.c | 14 ++++++++++++--
 include/linux/pm.h           | 14 ++++++++++++++
 include/linux/pm_runtime.h   |  6 ++++++
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -127,13 +127,18 @@ EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
 static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
 {
 	struct wake_irq *wirq = _wirq;
+	struct device *dev = wirq->dev;
+	unsigned long flags;
 	int res;
 
+	spin_lock_irqsave(&dev->power.lock, flags);
+	dev->power.wakeup_reason = RPM_WAKEUP_WAKEIRQ;
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
 	/* Maybe abort suspend? */
 	if (irqd_is_wakeup_set(irq_get_irq_data(irq))) {
 		pm_wakeup_event(wirq->dev, 0);
-
-		return IRQ_HANDLED;
+		goto out_handled;
 	}
 
 	/* We don't want RPM_ASYNC or RPM_NOWAIT here */
@@ -142,6 +147,11 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
 		dev_warn(wirq->dev,
 			 "wake IRQ with no resume: %i\n", res);
 
+out_handled:
+	spin_lock_irqsave(&dev->power.lock, flags);
+	dev->power.wakeup_reason = RPM_WAKEUP_NONE;
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
 	return IRQ_HANDLED;
 }
 
diff --git a/include/linux/pm.h b/include/linux/pm.h
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -523,6 +523,19 @@ enum rpm_request {
 	RPM_REQ_RESUME,
 };
 
+/*
+ * Device run-time wake-up reason types.
+ *
+ * RPM_WAKEUP_NONE	No wake-up reason
+ *
+ * RPM_WAKEUP_WAKEIRQ	Wake-up to a dedicated wakeirq
+ */
+
+enum rpm_wakeup_reason {
+	RPM_WAKEUP_NONE = 0,
+	RPM_WAKEUP_WAKEIRQ,
+};
+
 struct wakeup_source;
 struct wake_irq;
 struct pm_domain_data;
@@ -615,6 +628,7 @@ struct dev_pm_info {
 	unsigned int		use_autosuspend:1;
 	unsigned int		timer_autosuspends:1;
 	unsigned int		memalloc_noio:1;
+	unsigned int		wakeup_reason:1;
 	unsigned int		links_count;
 	enum rpm_request	request;
 	enum rpm_status		runtime_status;
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -117,6 +117,11 @@ static inline bool pm_runtime_is_irq_safe(struct device *dev)
 	return dev->power.irq_safe;
 }
 
+static inline bool pm_runtime_wakeup_is_wakeirq(struct device *dev)
+{
+	return dev->power.wakeup_reason == RPM_WAKEUP_WAKEIRQ;
+}
+
 extern u64 pm_runtime_suspended_time(struct device *dev);
 
 #else /* !CONFIG_PM */
@@ -183,6 +188,7 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {}
 static inline void pm_runtime_put_suppliers(struct device *dev) {}
 static inline void pm_runtime_new_link(struct device *dev) {}
 static inline void pm_runtime_drop_link(struct device *dev) {}
+static inline bool pm_runtime_wakeup_is_wakeirq(struct device *dev) { return false; }
 
 #endif /* !CONFIG_PM */
 
-- 
2.23.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] PM / runtime: Add support for wake-up reason for wakeirqs
  2019-10-09 18:28 [PATCH] PM / runtime: Add support for wake-up reason for wakeirqs Tony Lindgren
@ 2019-10-09 18:51 ` Alan Stern
  2019-10-09 19:55   ` Tony Lindgren
  0 siblings, 1 reply; 3+ messages in thread
From: Alan Stern @ 2019-10-09 18:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Rafael J . Wysocki, Dmitry Torokhov, Grygorii Strashko,
	Ulf Hansson, linux-pm, linux-kernel

On Wed, 9 Oct 2019, Tony Lindgren wrote:

> With generic wakeirqs we can wake a device, but do not know if the
> device woke to a wakeirq. Let's add pm_runtime_wakeup_is_wakeirq() so
> a device can check the wake-up reason.

People have tried many times over the years to do something like this.  
It's never right.

The problem is simple: It's impossible to know for certain why the
system woke up from suspend.  In fact, there may be many wakeup sources
all active at the same time, and any of them could be the one
responsible for actually waking the system.

All you can do is check to see whether a particular wakeup source is
active at the present moment.  You can't tell whether it was active in
the past (while the system was suspended) or whether it caused the
system to resume.

Alan Stern


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] PM / runtime: Add support for wake-up reason for wakeirqs
  2019-10-09 18:51 ` Alan Stern
@ 2019-10-09 19:55   ` Tony Lindgren
  0 siblings, 0 replies; 3+ messages in thread
From: Tony Lindgren @ 2019-10-09 19:55 UTC (permalink / raw)
  To: Alan Stern
  Cc: Rafael J . Wysocki, Dmitry Torokhov, Grygorii Strashko,
	Ulf Hansson, linux-pm, linux-kernel

* Alan Stern <stern@rowland.harvard.edu> [191009 18:51]:
> On Wed, 9 Oct 2019, Tony Lindgren wrote:
> 
> > With generic wakeirqs we can wake a device, but do not know if the
> > device woke to a wakeirq. Let's add pm_runtime_wakeup_is_wakeirq() so
> > a device can check the wake-up reason.
> 
> People have tried many times over the years to do something like this.  
> It's never right.
> 
> The problem is simple: It's impossible to know for certain why the
> system woke up from suspend.  In fact, there may be many wakeup sources
> all active at the same time, and any of them could be the one
> responsible for actually waking the system.

Hmm yeah good point. Even with dedicated wakeirq it could race
against a timer for the wake-up event.

> All you can do is check to see whether a particular wakeup source is
> active at the present moment.  You can't tell whether it was active in
> the past (while the system was suspended) or whether it caused the
> system to resume.

We can actually do more than that now though :)

With handle_threaded_wake_irq() we could optionally call a handler
before we call pm_runtime_resume() and let the consumer device
driver figure out what the state is.

Regards,

Tony

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-10-09 19:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-10-09 18:28 [PATCH] PM / runtime: Add support for wake-up reason for wakeirqs Tony Lindgren
2019-10-09 18:51 ` Alan Stern
2019-10-09 19:55   ` Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).