diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1b7f4df..8d37b32 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -468,10 +468,16 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
  * @irq_cpu_online:	configure an interrupt source for a secondary CPU
  * @irq_cpu_offline:	un-configure an interrupt source for a secondary CPU
+ * @irq_suspend_one:	called on an every irq to suspend it; called even if
+ *			this IRQ is configured for wakeup
+ * @irq_resume_one:	called on an every irq to resume it; called even if
+ *			this IRQ is configured for wakeup
  * @irq_suspend:	function called from core code on suspend once per
- *			chip, when one or more interrupts are installed
+ *			chip, when one or more interrupts are installed;
+ *			only works if using irq/generic-chip
  * @irq_resume:		function called from core code on resume once per chip,
- *			when one ore more interrupts are installed
+ *			when one ore more interrupts are installed;
+ *			only works if using irq/generic-chip
  * @irq_pm_shutdown:	function called from core code on shutdown once per chip
  * @irq_calc_mask:	Optional function to set irq_data.mask for special cases
  * @irq_print_chip:	optional to print special chip info in show_interrupts
@@ -515,6 +521,9 @@ struct irq_chip {
 	void		(*irq_cpu_online)(struct irq_data *data);
 	void		(*irq_cpu_offline)(struct irq_data *data);
 
+	void		(*irq_suspend_one)(struct irq_data *data);
+	void		(*irq_resume_one)(struct irq_data *data);
+
 	void		(*irq_suspend)(struct irq_data *data);
 	void		(*irq_resume)(struct irq_data *data);
 	void		(*irq_pm_shutdown)(struct irq_data *data);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 857f5f4..caf80c1 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -447,6 +447,22 @@ void unmask_threaded_irq(struct irq_desc *desc)
 	unmask_irq(desc);
 }
 
+void suspend_one_irq(struct irq_desc *desc)
+{
+	struct irq_chip *chip = desc->irq_data.chip;
+
+	if (chip->irq_suspend_one)
+		chip->irq_suspend_one(&desc->irq_data);
+}
+
+void resume_one_irq(struct irq_desc *desc)
+{
+	struct irq_chip *chip = desc->irq_data.chip;
+
+	if (chip->irq_resume_one)
+		chip->irq_resume_one(&desc->irq_data);
+}
+
 /*
  *	handle_nested_irq - Handle a nested irq from a irq thread
  *	@irq:	the interrupt number
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 7db284b..11c2dac 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -90,6 +90,8 @@ extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
 extern void mask_irq(struct irq_desc *desc);
 extern void unmask_irq(struct irq_desc *desc);
 extern void unmask_threaded_irq(struct irq_desc *desc);
+extern void suspend_one_irq(struct irq_desc *desc);
+extern void resume_one_irq(struct irq_desc *desc);
 
 #ifdef CONFIG_SPARSE_IRQ
 static inline void irq_mark_irq(unsigned int irq) { }
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index 8f557fa..b9e5338 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -69,19 +69,23 @@ void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
 
 static bool suspend_device_irq(struct irq_desc *desc)
 {
+	bool sync = false;
+
 	if (!desc->action || irq_desc_is_chained(desc) ||
 	    desc->no_suspend_depth)
-		return false;
+		goto exit;
 
 	if (irqd_is_wakeup_set(&desc->irq_data)) {
 		irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
+
 		/*
 		 * We return true here to force the caller to issue
 		 * synchronize_irq(). We need to make sure that the
 		 * IRQD_WAKEUP_ARMED is visible before we return from
 		 * suspend_device_irqs().
 		 */
-		return true;
+		sync = true;
+		goto exit;
 	}
 
 	desc->istate |= IRQS_SUSPENDED;
@@ -95,7 +99,10 @@ static bool suspend_device_irq(struct irq_desc *desc)
 	 */
 	if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
 		mask_irq(desc);
-	return true;
+
+exit:
+	suspend_one_irq(desc);
+	return sync;
 }
 
 /**
@@ -137,6 +144,8 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);
 
 static void resume_irq(struct irq_desc *desc)
 {
+	resume_one_irq(desc);
+
 	irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
 
 	if (desc->istate & IRQS_SUSPENDED)
