Message ID | 1805200.1exkRoNuC2@vostro.rjw.lan (mailing list archive) |
---|---|
State | RFC, archived |
Headers | show |
On Fri, Jul 25, 2014 at 02:47:25PM +0200, Rafael J. Wysocki wrote: > So it looks like we really need the "suspend" thing to either disable > the interrupt entirely (in which case all handlers for all actions > will not be invoked after it's been suspended) or leave it enabled > (causing all handlers to be invoked all the time). > > I'm not sure if we can do much beyond what's already in your tree > about that, then. > > Well, perhaps the patch failing the irq request in case of the > IRQF_NO_SUSPEND mismatch is a bit too drastic. Instead, we could > just print a warning in __setup_irq() in that case and then check > IRQF_NO_SUSPEND for all actions in __disable_irq(). > > What about this? I suppose, not failing the request_irq allows the machine to boot and mostly work, any funnies will be when the machine gets suspended. And disabling suspend might be overkill because it might just all work anyhow because the user didn't need that one particular wakeup source. What a terrible mess this. -- 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
Index: linux-pm/kernel/irq/manage.c =================================================================== --- linux-pm.orig/kernel/irq/manage.c +++ linux-pm/kernel/irq/manage.c @@ -385,8 +385,17 @@ setup_affinity(unsigned int irq, struct void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) { if (suspend) { - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND) - || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE)) + struct irqaction *action = desc->action; + unsigned int flags; + + if (!action || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE)) + return; + flags = IRQF_NO_SUSPEND; + do { + flags &= action->flags; + action = action->next; + } while (action); + if (flags) return; desc->istate |= IRQS_SUSPENDED; } @@ -1079,7 +1088,7 @@ __setup_irq(unsigned int irq, struct irq */ #define IRQF_MISMATCH \ - (IRQF_TRIGGER_MASK | IRQF_ONESHOT | IRQF_NO_SUSPEND) + (IRQF_TRIGGER_MASK | IRQF_ONESHOT) if (!((old->flags & new->flags) & IRQF_SHARED) || ((old->flags ^ new->flags) & IRQF_MISMATCH)) @@ -1090,6 +1099,13 @@ __setup_irq(unsigned int irq, struct irq (new->flags & IRQF_PERCPU)) goto mismatch; + if ((old->flags & IRQF_NO_SUSPEND) != + (new->flags & IRQF_NO_SUSPEND)) { + pr_err("irq %d: IRQF_NO_SUSPEND mismatch %08x (%s) vs. %08x (%s)\n", + irq, new->flags, new->name, old->flags, old->name); + pr_err("irq %d: IRQF_NO_SUSPEND will be ignored\n"); + } + /* add new interrupt at end of irq queue */ do { /*