@@ -1611,6 +1611,7 @@ static struct irq_chip xen_pirq_chip __read_mostly = {
.irq_set_affinity = set_affinity_irq,
.irq_retrigger = retrigger_dynirq,
+ .flags = IRQCHIP_SHUTDOWN_ON_SUSPEND,
};
static struct irq_chip xen_percpu_chip __read_mostly = {
@@ -542,6 +542,7 @@ struct irq_chip {
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
* IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
* IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips
+ * IRQCHIP_SHUTDOWN_ON_SUSPEND: Shutdown non wake irqs in the suspend path
*/
enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
@@ -553,6 +554,7 @@ enum {
IRQCHIP_EOI_THREADED = (1 << 6),
IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7),
IRQCHIP_SUPPORTS_NMI = (1 << 8),
+ IRQCHIP_SHUTDOWN_ON_SUSPEND = (1 << 9),
};
#include <linux/irqdesc.h>
@@ -233,7 +233,7 @@ __irq_startup_managed(struct irq_desc *desc, struct cpumask *aff, bool force)
}
#endif
-static int __irq_startup(struct irq_desc *desc)
+int __irq_startup(struct irq_desc *desc)
{
struct irq_data *d = irq_desc_get_irq_data(desc);
int ret = 0;
@@ -80,6 +80,7 @@ extern void __enable_irq(struct irq_desc *desc);
extern int irq_activate(struct irq_desc *desc);
extern int irq_activate_and_startup(struct irq_desc *desc, bool resend);
extern int irq_startup(struct irq_desc *desc, bool resend, bool force);
+extern int __irq_startup(struct irq_desc *desc);
extern void irq_shutdown(struct irq_desc *desc);
extern void irq_shutdown_and_deactivate(struct irq_desc *desc);
@@ -85,16 +85,25 @@ static bool suspend_device_irq(struct irq_desc *desc)
}
desc->istate |= IRQS_SUSPENDED;
- __disable_irq(desc);
-
/*
- * Hardware which has no wakeup source configuration facility
- * requires that the non wakeup interrupts are masked at the
- * chip level. The chip implementation indicates that with
- * IRQCHIP_MASK_ON_SUSPEND.
+ * Some irq chips (e.g. XEN PIRQ) require a full shutdown on suspend
+ * as some of the legacy drivers(e.g. floppy) do nothing during the
+ * suspend path
*/
- if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
- mask_irq(desc);
+ if (irq_desc_get_chip(desc)->flags & IRQCHIP_SHUTDOWN_ON_SUSPEND) {
+ irq_shutdown(desc);
+ } else {
+ __disable_irq(desc);
+
+ /*
+ * Hardware which has no wakeup source configuration facility
+ * requires that the non wakeup interrupts are masked at the
+ * chip level. The chip implementation indicates that with
+ * IRQCHIP_MASK_ON_SUSPEND.
+ */
+ if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
+ mask_irq(desc);
+ }
return true;
}
@@ -152,7 +161,11 @@ static void resume_irq(struct irq_desc *desc)
irq_state_set_masked(desc);
resume:
desc->istate &= ~IRQS_SUSPENDED;
- __enable_irq(desc);
+
+ if (irq_desc_get_chip(desc)->flags & IRQCHIP_SHUTDOWN_ON_SUSPEND)
+ __irq_startup(desc);
+ else
+ __enable_irq(desc);
}
static void resume_irqs(bool want_early)