diff mbox series

[SRU,OEM-OSP1-B/E,1/6] PCI: irq: Introduce rearm_wake_irq()

Message ID 20200113094034.510111-2-vicamo.yang@canonical.com
State New
Headers show
Series [SRU,OEM-OSP1-B/E,1/6] PCI: irq: Introduce rearm_wake_irq() | expand

Commit Message

You-Sheng Yang Jan. 13, 2020, 9:40 a.m. UTC
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

BugLink: https://bugs.launchpad.net/bugs/1859407

Introduce a new function, rearm_wake_irq(), allowing a wakeup IRQ
to be armed for systen wakeup detection again without running any
action handlers associated with it after it has been armed for
wakeup detection and triggered.

That is useful for IRQs, like ACPI SCI, that may deliver wakeup
as well as non-wakeup interrupts when armed for systen wakeup
detection.  In those cases, it may be possible to determine whether
or not the delivered interrupt is a systen wakeup one without
running the entire action handler (or handlers, if the IRQ is
shared) for the IRQ, and if the interrupt turns out to be a
non-wakeup one, the IRQ can be rearmed with the help of the
new function.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
(cherry picked from commit 3a79bc63d90750f737ab9d7219bd3091d2fd6d84)
Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
---
 include/linux/interrupt.h |  1 +
 kernel/irq/pm.c           | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+)
diff mbox series

Patch

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 4a728dba02e22..3e7497432dab5 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -220,6 +220,7 @@  extern void irq_wake_thread(unsigned int irq, void *dev_id);
 /* The following three functions are for the core kernel use only. */
 extern void suspend_device_irqs(void);
 extern void resume_device_irqs(void);
+extern void rearm_wake_irq(unsigned int irq);
 
 /**
  * struct irq_affinity_notify - context for notification of IRQ affinity changes
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index d6961d3c6f9e2..8f557fa1f4fe4 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -176,6 +176,26 @@  static void resume_irqs(bool want_early)
 	}
 }
 
+/**
+ * rearm_wake_irq - rearm a wakeup interrupt line after signaling wakeup
+ * @irq: Interrupt to rearm
+ */
+void rearm_wake_irq(unsigned int irq)
+{
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
+
+	if (!desc || !(desc->istate & IRQS_SUSPENDED) ||
+	    !irqd_is_wakeup_set(&desc->irq_data))
+		return;
+
+	desc->istate &= ~IRQS_SUSPENDED;
+	irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
+	__enable_irq(desc);
+
+	irq_put_desc_busunlock(desc, flags);
+}
+
 /**
  * irq_pm_syscore_ops - enable interrupt lines early
  *