Merge branch 'linus' into x86/x2apic
Conflicts: drivers/pci/dmar.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@ -224,6 +224,17 @@ void enable_irq(unsigned int irq)
|
||||
}
|
||||
EXPORT_SYMBOL(enable_irq);
|
||||
|
||||
int set_irq_wake_real(unsigned int irq, unsigned int on)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
int ret = -ENXIO;
|
||||
|
||||
if (desc->chip->set_wake)
|
||||
ret = desc->chip->set_wake(irq, on);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_irq_wake - control irq power management wakeup
|
||||
* @irq: interrupt to control
|
||||
@ -240,30 +251,34 @@ int set_irq_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
int ret = -ENXIO;
|
||||
int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
|
||||
int ret = 0;
|
||||
|
||||
/* wakeup-capable irqs can be shared between drivers that
|
||||
* don't need to have the same sleep mode behaviors.
|
||||
*/
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (on) {
|
||||
if (desc->wake_depth++ == 0)
|
||||
desc->status |= IRQ_WAKEUP;
|
||||
else
|
||||
set_wake = NULL;
|
||||
if (desc->wake_depth++ == 0) {
|
||||
ret = set_irq_wake_real(irq, on);
|
||||
if (ret)
|
||||
desc->wake_depth = 0;
|
||||
else
|
||||
desc->status |= IRQ_WAKEUP;
|
||||
}
|
||||
} else {
|
||||
if (desc->wake_depth == 0) {
|
||||
printk(KERN_WARNING "Unbalanced IRQ %d "
|
||||
"wake disable\n", irq);
|
||||
WARN_ON(1);
|
||||
} else if (--desc->wake_depth == 0)
|
||||
desc->status &= ~IRQ_WAKEUP;
|
||||
else
|
||||
set_wake = NULL;
|
||||
} else if (--desc->wake_depth == 0) {
|
||||
ret = set_irq_wake_real(irq, on);
|
||||
if (ret)
|
||||
desc->wake_depth = 1;
|
||||
else
|
||||
desc->status &= ~IRQ_WAKEUP;
|
||||
}
|
||||
}
|
||||
if (set_wake)
|
||||
ret = desc->chip->set_wake(irq, on);
|
||||
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
@ -300,6 +315,30 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
|
||||
desc->handle_irq = NULL;
|
||||
}
|
||||
|
||||
static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
|
||||
unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!chip || !chip->set_type) {
|
||||
/*
|
||||
* IRQF_TRIGGER_* but the PIC does not support multiple
|
||||
* flow-types?
|
||||
*/
|
||||
pr_warning("No set_type function for IRQ %d (%s)\n", irq,
|
||||
chip ? (chip->name ? : "unknown") : "unknown");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK);
|
||||
|
||||
if (ret)
|
||||
pr_err("setting flow type for irq %u failed (%pF)\n",
|
||||
irq, chip->set_type);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to register an irqaction - typically used to
|
||||
* allocate special interrupts that are part of the architecture.
|
||||
@ -311,6 +350,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
|
||||
const char *old_name = NULL;
|
||||
unsigned long flags;
|
||||
int shared = 0;
|
||||
int ret;
|
||||
|
||||
if (irq >= NR_IRQS)
|
||||
return -EINVAL;
|
||||
@ -368,36 +408,24 @@ int setup_irq(unsigned int irq, struct irqaction *new)
|
||||
shared = 1;
|
||||
}
|
||||
|
||||
*p = new;
|
||||
|
||||
/* Exclude IRQ from balancing */
|
||||
if (new->flags & IRQF_NOBALANCING)
|
||||
desc->status |= IRQ_NO_BALANCING;
|
||||
|
||||
if (!shared) {
|
||||
irq_chip_set_defaults(desc->chip);
|
||||
|
||||
/* Setup the type (level, edge polarity) if configured: */
|
||||
if (new->flags & IRQF_TRIGGER_MASK) {
|
||||
ret = __irq_set_trigger(desc->chip, irq, new->flags);
|
||||
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
} else
|
||||
compat_irq_chip_set_default_handler(desc);
|
||||
#if defined(CONFIG_IRQ_PER_CPU)
|
||||
if (new->flags & IRQF_PERCPU)
|
||||
desc->status |= IRQ_PER_CPU;
|
||||
#endif
|
||||
|
||||
/* Setup the type (level, edge polarity) if configured: */
|
||||
if (new->flags & IRQF_TRIGGER_MASK) {
|
||||
if (desc->chip->set_type)
|
||||
desc->chip->set_type(irq,
|
||||
new->flags & IRQF_TRIGGER_MASK);
|
||||
else
|
||||
/*
|
||||
* IRQF_TRIGGER_* but the PIC does not support
|
||||
* multiple flow-types?
|
||||
*/
|
||||
printk(KERN_WARNING "No IRQF_TRIGGER set_type "
|
||||
"function for IRQ %d (%s)\n", irq,
|
||||
desc->chip->name);
|
||||
} else
|
||||
compat_irq_chip_set_default_handler(desc);
|
||||
|
||||
desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
|
||||
IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
|
||||
|
||||
@ -415,6 +443,13 @@ int setup_irq(unsigned int irq, struct irqaction *new)
|
||||
/* Set default affinity mask once everything is setup */
|
||||
irq_select_affinity(irq);
|
||||
}
|
||||
|
||||
*p = new;
|
||||
|
||||
/* Exclude IRQ from balancing */
|
||||
if (new->flags & IRQF_NOBALANCING)
|
||||
desc->status |= IRQ_NO_BALANCING;
|
||||
|
||||
/* Reset broken irq detection when installing new handler */
|
||||
desc->irq_count = 0;
|
||||
desc->irqs_unhandled = 0;
|
||||
|
Reference in New Issue
Block a user