linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V7] Report interrupt that caused system wakeup
       [not found] <[PATCH V7] Report interrupt that caused system wakeup>
@ 2015-09-10  2:48 ` Alexandra Yates
  2015-09-10  7:36   ` Sergey Senozhatsky
  2015-09-10 14:14   ` Alan Stern
  0 siblings, 2 replies; 7+ messages in thread
From: Alexandra Yates @ 2015-09-10  2:48 UTC (permalink / raw)
  To: tglx, kristen.c.accardi, linux-pm, rjw; +Cc: Alexandra Yates

This feature reports which IRQ cause the system to wakeup from sleep last
time it was suspended.

It adds a new sysfs attribute under /sys/power/ named: pm_last_wakeup_irq
when read, will return the IRQ that caused the system to wakeup.
That will be useful for system wakeup diagnostics.

Signed-off-by: Alexandra Yates <alexandra.yates@linux.intel.com>
---
 Documentation/ABI/testing/sysfs-power | 11 +++++++++++
 drivers/base/power/wakeup.c           | 12 ++++++++++++
 include/linux/suspend.h               |  8 +++++++-
 kernel/irq/pm.c                       |  4 ++--
 kernel/power/main.c                   | 19 +++++++++++++++++++
 5 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index f455181..4f9cc3a 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -256,3 +256,14 @@ Description:
 		Writing a "1" enables this printing while writing a "0"
 		disables it.  The default value is "0".  Reading from this file
 		will display the current value.
+
+What:		/sys/power/pm_last_wakeup_irqs
+Date:		April 2015
+Contact:	Alexandra Yates <alexandra.yates@linux.intel.org>
+Description:
+		The /sys/power/pm_last_wakeup_irqs file allows user space
+		to identify and report the IRQs responsible for waking the
+		system up from sleep. The IRQD_WAKEUP_TRIGGERED flag is set and
+		reported when the given IRQ fires after it has been armed for
+		system wakeup. This output is useful for system wakeup
+		diagnostics.
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 51f15bc..f663fb1 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -870,6 +870,18 @@ void pm_wakeup_clear(void)
 	pm_abort_suspend = false;
 }
 
+void pm_system_irq_wakeup(unsigned int irq_number)
+{
+	if (wakeup_irq == 0)
+		wakeup_irq = irq_number;
+	pm_system_wakeup();
+}
+
+void pm_last_wakeup_irq_reset(void)
+{
+	wakeup_irq = 0;
+}
+
 /**
  * pm_get_wakeup_count - Read the number of registered wakeup events.
  * @count: Address to store the value at.
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 5efe743..eb5ad3b 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -371,6 +371,9 @@ static inline bool hibernation_available(void) { return false; }
 
 extern struct mutex pm_mutex;
 
+/* IRQ number which causes system wakeup  */
+extern unsigned int wakeup_irq;
+
 #ifdef CONFIG_PM_SLEEP
 void save_processor_state(void);
 void restore_processor_state(void);
@@ -378,7 +381,7 @@ void restore_processor_state(void);
 /* kernel/power/main.c */
 extern int register_pm_notifier(struct notifier_block *nb);
 extern int unregister_pm_notifier(struct notifier_block *nb);
-
+extern void pm_last_wakeup_irq_reset(void);
 #define pm_notifier(fn, pri) {				\
 	static struct notifier_block fn##_nb =			\
 		{ .notifier_call = fn, .priority = pri };	\
@@ -391,6 +394,7 @@ extern bool events_check_enabled;
 extern bool pm_wakeup_pending(void);
 extern void pm_system_wakeup(void);
 extern void pm_wakeup_clear(void);
+extern void pm_system_irq_wakeup(unsigned int);
 extern bool pm_get_wakeup_count(unsigned int *count, bool block);
 extern bool pm_save_wakeup_count(unsigned int count);
 extern void pm_wakep_autosleep_enabled(bool set);
@@ -440,6 +444,8 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
 static inline bool pm_wakeup_pending(void) { return false; }
 static inline void pm_system_wakeup(void) {}
 static inline void pm_wakeup_clear(void) {}
+static inline void pm_system_irq_wakeup(unsigned int) {}
+static inline void pm_last_wakeup_irq_reset(void){};
 
 static inline void lock_system_sleep(void) {}
 static inline void unlock_system_sleep(void) {}
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index d22786a..18178d7 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -21,7 +21,7 @@ bool irq_pm_check_wakeup(struct irq_desc *desc)
 		desc->istate |= IRQS_SUSPENDED | IRQS_PENDING;
 		desc->depth++;
 		irq_disable(desc);
-		pm_system_wakeup();
+		pm_system_irq_wakeup(irq_desc_get_irq(desc));
 		return true;
 	}
 	return false;
@@ -118,7 +118,7 @@ void suspend_device_irqs(void)
 {
 	struct irq_desc *desc;
 	int irq;
-
+	pm_last_wakeup_irq_reset();
 	for_each_irq_desc(irq, desc) {
 		unsigned long flags;
 		bool sync;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 63d395b..d2bd164 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -272,6 +272,24 @@ static inline void pm_print_times_init(void)
 {
 	pm_print_times_enabled = !!initcall_debug;
 }
+
+unsigned int wakeup_irq;
+EXPORT_SYMBOL_GPL(wakeup_irq);
+static ssize_t pm_last_wakeup_irq_show(struct kobject *kobj,
+					struct kobj_attribute *attr,
+					char *buf)
+{
+	return wakeup_irq ? sprintf(buf, "%u\n", wakeup_irq) : -EINVAL;
+}
+
+static ssize_t pm_last_wakeup_irq_store(struct kobject *kobj,
+					struct kobj_attribute *attr,
+					const char *buf, size_t n)
+{
+	return -EINVAL;
+}
+power_attr(pm_last_wakeup_irq);
+
 #else /* !CONFIG_PM_SLEEP_DEBUG */
 static inline void pm_print_times_init(void) {}
 #endif /* CONFIG_PM_SLEEP_DEBUG */
@@ -604,6 +622,7 @@ static struct attribute * g[] = {
 #endif
 #ifdef CONFIG_PM_SLEEP_DEBUG
 	&pm_print_times_attr.attr,
+	&pm_last_wakeup_irq_attr.attr,
 #endif
 #endif
 #ifdef CONFIG_FREEZER
-- 
1.9.1


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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10  2:48 ` [PATCH V7] Report interrupt that caused system wakeup Alexandra Yates
@ 2015-09-10  7:36   ` Sergey Senozhatsky
  2015-09-10 14:14   ` Alan Stern
  1 sibling, 0 replies; 7+ messages in thread
From: Sergey Senozhatsky @ 2015-09-10  7:36 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: tglx, Alexandra Yates, kristen.c.accardi, linux-pm

On (09/09/15 19:48), Alexandra Yates wrote:

[..]
> +static ssize_t pm_last_wakeup_irq_store(struct kobject *kobj,
> +					struct kobj_attribute *attr,
> +					const char *buf, size_t n)
> +{
> +	return -EINVAL;
> +}
> +power_attr(pm_last_wakeup_irq);

a side note,
do you guys want to define a power_attr_ro() macro and to drop 'return -EINVAL'
*_show() functions: pm_trace_dev_match_store() and pm_last_wakeup_irq_store()?

---

 kernel/power/main.c  | 9 +--------
 kernel/power/power.h | 9 +++++++++
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/kernel/power/main.c b/kernel/power/main.c
index 63d395b..0217a5c 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -548,14 +548,7 @@ static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
 	return show_trace_dev_match(buf, PAGE_SIZE);
 }
 
-static ssize_t
-pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
-			 const char *buf, size_t n)
-{
-	return -EINVAL;
-}
-
-power_attr(pm_trace_dev_match);
+power_attr_ro(pm_trace_dev_match);
 
 #endif /* CONFIG_PM_TRACE */
 
diff --git a/kernel/power/power.h b/kernel/power/power.h
index caadb56..efe1b3b 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -77,6 +77,15 @@ static struct kobj_attribute _name##_attr = {	\
 	.store	= _name##_store,		\
 }
 
+#define power_attr_ro(_name) \
+static struct kobj_attribute _name##_attr = {	\
+	.attr	= {				\
+		.name = __stringify(_name),	\
+		.mode = S_IRUGO,		\
+	},					\
+	.show	= _name##_show,			\
+}
+
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
 /* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */

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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10  2:48 ` [PATCH V7] Report interrupt that caused system wakeup Alexandra Yates
  2015-09-10  7:36   ` Sergey Senozhatsky
@ 2015-09-10 14:14   ` Alan Stern
  2015-09-10 18:42     ` Alexandra Yates
  1 sibling, 1 reply; 7+ messages in thread
From: Alan Stern @ 2015-09-10 14:14 UTC (permalink / raw)
  To: Alexandra Yates; +Cc: tglx, kristen.c.accardi, linux-pm, rjw

On Wed, 9 Sep 2015, Alexandra Yates wrote:

> This feature reports which IRQ cause the system to wakeup from sleep last
> time it was suspended.

I thought you said V7 of this patch was written based on the feedback I 
provided.  Obviously that is not true.

This feature does NOT report which IRQ caused the system to wake up
from sleep the last time it was suspended!  All it does is report one
of the IRQs which have occurred since the last time the system started
a sleep transition.

Alan Stern


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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10 14:14   ` Alan Stern
@ 2015-09-10 18:42     ` Alexandra Yates
  2015-09-10 19:15       ` Alan Stern
  0 siblings, 1 reply; 7+ messages in thread
From: Alexandra Yates @ 2015-09-10 18:42 UTC (permalink / raw)
  To: Alan Stern; +Cc: tglx, kristen.c.accardi, linux-pm, rjw

Hi Alan,

On 09/10/2015 07:14 AM, Alan Stern wrote:
> On Wed, 9 Sep 2015, Alexandra Yates wrote:
>
>> This feature reports which IRQ cause the system to wakeup from sleep last
>> time it was suspended.
> I thought you said V7 of this patch was written based on the feedback I
> provided.  Obviously that is not true.
Yes, that was the intention.
> This feature does NOT report which IRQ caused the system to wake up
> from sleep the last time it was suspended!  All it does is report one
> of the IRQs which have occurred since the last time the system started
> a sleep transition.
I'm not sure why you say this, please elaborate further.

The way I understand the code and proposed solution is that when
the system goes into freeze mode, at that point wakeup_irq is set to 0.

Once the system sees an interrupt at wakeup from freeze. wakeup_irq is 
set to
the irq_number that caused the wakeup.  This path of code is protected 
by spin lock,

which should protect the code path from other IRQs that came after the 
first IRQ.
This is only set once. When other IRQs come and the wakeup_irq is set 
then the code
doesn't store them.

> Alan Stern
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

-- 
Thank you,
<Alexandra>


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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10 18:42     ` Alexandra Yates
@ 2015-09-10 19:15       ` Alan Stern
  2015-09-10 22:21         ` Rafael J. Wysocki
  0 siblings, 1 reply; 7+ messages in thread
From: Alan Stern @ 2015-09-10 19:15 UTC (permalink / raw)
  To: Alexandra Yates; +Cc: tglx, kristen.c.accardi, linux-pm, rjw

On Thu, 10 Sep 2015, Alexandra Yates wrote:

> Hi Alan,
> 
> On 09/10/2015 07:14 AM, Alan Stern wrote:
> > On Wed, 9 Sep 2015, Alexandra Yates wrote:
> >
> >> This feature reports which IRQ cause the system to wakeup from sleep last
> >> time it was suspended.
> > I thought you said V7 of this patch was written based on the feedback I
> > provided.  Obviously that is not true.
> Yes, that was the intention.
> > This feature does NOT report which IRQ caused the system to wake up
> > from sleep the last time it was suspended!  All it does is report one
> > of the IRQs which have occurred since the last time the system started
> > a sleep transition.
> I'm not sure why you say this, please elaborate further.
> 
> The way I understand the code and proposed solution is that when
> the system goes into freeze mode, at that point wakeup_irq is set to 0.

I'm not sure what you mean by "freeze mode".  Do you mean that all the 
user processes have been frozen?

> Once the system sees an interrupt at wakeup from freeze. wakeup_irq is 
> set to
> the irq_number that caused the wakeup.  This path of code is protected 
> by spin lock,

The spin lock doesn't help if multiple IRQs have already been raised.  
How do you know which one caused the system to wake up?

> which should protect the code path from other IRQs that came after the 
> first IRQ.

Why so?  Waking up from sleep is a slow procedure; there is time for
several IRQs to be asserted before the system is ready to handle any of
them.  How do you know the first IRQ to be handled is the one that 
caused the wake up?

> This is only set once. When other IRQs come and the wakeup_irq is set 
> then the code
> doesn't store them.

What if the system entered freeze mode but then returned to normal 
operation without ever going to sleep, because an IRQ occurred first?  
Wouldn't you then store that IRQ?  But that IRQ did not cause the 
system to wake up, because the system never went to sleep.

Alan Stern


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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10 19:15       ` Alan Stern
@ 2015-09-10 22:21         ` Rafael J. Wysocki
  2015-09-11 14:07           ` Alan Stern
  0 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2015-09-10 22:21 UTC (permalink / raw)
  To: Alan Stern; +Cc: Alexandra Yates, tglx, kristen.c.accardi, linux-pm

On Thursday, September 10, 2015 03:15:24 PM Alan Stern wrote:
> On Thu, 10 Sep 2015, Alexandra Yates wrote:
> 
> > Hi Alan,
> > 
> > On 09/10/2015 07:14 AM, Alan Stern wrote:
> > > On Wed, 9 Sep 2015, Alexandra Yates wrote:
> > >
> > >> This feature reports which IRQ cause the system to wakeup from sleep last
> > >> time it was suspended.
> > > I thought you said V7 of this patch was written based on the feedback I
> > > provided.  Obviously that is not true.
> > Yes, that was the intention.
> > > This feature does NOT report which IRQ caused the system to wake up
> > > from sleep the last time it was suspended!  All it does is report one
> > > of the IRQs which have occurred since the last time the system started
> > > a sleep transition.

It doesn't do that.  It reports one of the IRQs that were armed for system
wakeup and have occurred since suspend_device_irqs() was last called (and
obviously before the subsequent resume_device_irqs() which clears the
"armed for system wakeup" flag).

> > I'm not sure why you say this, please elaborate further.
> > 
> > The way I understand the code and proposed solution is that when
> > the system goes into freeze mode, at that point wakeup_irq is set to 0.
> 
> I'm not sure what you mean by "freeze mode".  Do you mean that all the 
> user processes have been frozen?
> 
> > Once the system sees an interrupt at wakeup from freeze. wakeup_irq is 
> > set to
> > the irq_number that caused the wakeup.  This path of code is protected 
> > by spin lock,
> 
> The spin lock doesn't help if multiple IRQs have already been raised.  
> How do you know which one caused the system to wake up?

Actually, we don't, which is a good point.

However, the purpose of this mechanism is mostly debugging spurious wakeup
events and recording just the first wakeup interrupt we see should be
sufficient for that.

Spurious wakeup interrupts that always come it along with legitimate ones
are not really so much interesting from that angle. :-)

> > which should protect the code path from other IRQs that came after the 
> > first IRQ.
> 
> Why so?  Waking up from sleep is a slow procedure; there is time for
> several IRQs to be asserted before the system is ready to handle any of
> them.  How do you know the first IRQ to be handled is the one that 
> caused the wake up?

> > This is only set once. When other IRQs come and the wakeup_irq is set 
> > then the code
> > doesn't store them.
> 
> What if the system entered freeze mode but then returned to normal 
> operation without ever going to sleep, because an IRQ occurred first?  
> Wouldn't you then store that IRQ?

If the IRQ has been armed for system wakeup, that counts as a wakeup from
sleep.

> But that IRQ did not cause the system to wake up, because the system
> never went to sleep.

I guess we should just say in the changelog and the documentation that we
report that first wakeup interrupt we've seen in the last cycle (which may
not be the first one that really occured in some cases).

Thanks,
Rafael


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

* Re: [PATCH V7] Report interrupt that caused system wakeup
  2015-09-10 22:21         ` Rafael J. Wysocki
@ 2015-09-11 14:07           ` Alan Stern
  0 siblings, 0 replies; 7+ messages in thread
From: Alan Stern @ 2015-09-11 14:07 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Alexandra Yates, tglx, kristen.c.accardi, linux-pm

On Fri, 11 Sep 2015, Rafael J. Wysocki wrote:

> > The spin lock doesn't help if multiple IRQs have already been raised.  
> > How do you know which one caused the system to wake up?
> 
> Actually, we don't, which is a good point.
> 
> However, the purpose of this mechanism is mostly debugging spurious wakeup
> events and recording just the first wakeup interrupt we see should be
> sufficient for that.
> 
> Spurious wakeup interrupts that always come it along with legitimate ones
> are not really so much interesting from that angle. :-)
> 
> > > which should protect the code path from other IRQs that came after the 
> > > first IRQ.
> > 
> > Why so?  Waking up from sleep is a slow procedure; there is time for
> > several IRQs to be asserted before the system is ready to handle any of
> > them.  How do you know the first IRQ to be handled is the one that 
> > caused the wake up?
> 
> > > This is only set once. When other IRQs come and the wakeup_irq is set 
> > > then the code
> > > doesn't store them.
> > 
> > What if the system entered freeze mode but then returned to normal 
> > operation without ever going to sleep, because an IRQ occurred first?  
> > Wouldn't you then store that IRQ?
> 
> If the IRQ has been armed for system wakeup, that counts as a wakeup from
> sleep.
> 
> > But that IRQ did not cause the system to wake up, because the system
> > never went to sleep.
> 
> I guess we should just say in the changelog and the documentation that we
> report that first wakeup interrupt we've seen in the last cycle (which may
> not be the first one that really occured in some cases).

The patch itself is perfectly okay, as far as I can tell.  I just
didn't like the description, because it made claims that generally
aren't true.  The new description in the V8 submission is a lot better.

Alan Stern


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

end of thread, other threads:[~2015-09-11 14:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <[PATCH V7] Report interrupt that caused system wakeup>
2015-09-10  2:48 ` [PATCH V7] Report interrupt that caused system wakeup Alexandra Yates
2015-09-10  7:36   ` Sergey Senozhatsky
2015-09-10 14:14   ` Alan Stern
2015-09-10 18:42     ` Alexandra Yates
2015-09-10 19:15       ` Alan Stern
2015-09-10 22:21         ` Rafael J. Wysocki
2015-09-11 14:07           ` Alan Stern

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).