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_wakeup_irq
+Date:          April 2015
+Contact:       Alexandra Yates <alexandra.yates@linux.intel.org>
+Description:
+               The /sys/power/pm_wakeup_irq file reports to user space the IRQ
+               number of the first wakeup interrupt (that is, the first
+               interrupt from an IRQ line armed for system wakeup) seen by the
+               kernel during the most recent system suspend/resume cycle.
+
+               This output is useful for system wakeup diagnostics of spurious
+               wakeup interrupts.
 
  */
 bool events_check_enabled __read_mostly;
 
+/* First wakeup IRQ seen by the kernel in the last cycle. */
+unsigned int pm_wakeup_irq __read_mostly;
+
 /* If set and the system is suspending, terminate the suspend. */
 static bool pm_abort_suspend __read_mostly;
 
 void pm_wakeup_clear(void)
 {
        pm_abort_suspend = false;
+       pm_wakeup_irq = 0;
+}
+
+void pm_system_irq_wakeup(unsigned int irq_number)
+{
+       if (pm_wakeup_irq == 0) {
+               pm_wakeup_irq = irq_number;
+               pm_system_wakeup();
+       }
 }
 
 /**
 
 
 /* drivers/base/power/wakeup.c */
 extern bool events_check_enabled;
+extern unsigned int pm_wakeup_irq;
 
 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 irq_number);
 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);
 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 irq_number) {}
 
 static inline void lock_system_sleep(void) {}
 static inline void unlock_system_sleep(void) {}
 
                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;
 
 {
        pm_print_times_enabled = !!initcall_debug;
 }
+
+static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       char *buf)
+{
+       return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
+}
+
+static ssize_t pm_wakeup_irq_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t n)
+{
+       return -EINVAL;
+}
+power_attr(pm_wakeup_irq);
+
 #else /* !CONFIG_PM_SLEEP_DEBUG */
 static inline void pm_print_times_init(void) {}
 #endif /* CONFIG_PM_SLEEP_DEBUG */
 #endif
 #ifdef CONFIG_PM_SLEEP_DEBUG
        &pm_print_times_attr.attr,
+       &pm_wakeup_irq_attr.attr,
 #endif
 #endif
 #ifdef CONFIG_FREEZER