diff options
Diffstat (limited to 'kernel/irq/manage.c')
| -rw-r--r-- | kernel/irq/manage.c | 15 | 
1 files changed, 14 insertions, 1 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a8e8f05962..4c69326aa77 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -944,6 +944,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  	}  	/* +	 * Drivers are often written to work w/o knowledge about the +	 * underlying irq chip implementation, so a request for a +	 * threaded irq without a primary hard irq context handler +	 * requires the ONESHOT flag to be set. Some irq chips like +	 * MSI based interrupts are per se one shot safe. Check the +	 * chip flags, so we can avoid the unmask dance at the end of +	 * the threaded handler for those. +	 */ +	if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) +		new->flags &= ~IRQF_ONESHOT; + +	/*  	 * The following block of code has to be executed atomically  	 */  	raw_spin_lock_irqsave(&desc->lock, flags); @@ -1017,7 +1029,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  		 */  		new->thread_mask = 1 << ffz(thread_mask); -	} else if (new->handler == irq_default_primary_handler) { +	} else if (new->handler == irq_default_primary_handler && +		   !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {  		/*  		 * The interrupt was requested with handler = NULL, so  		 * we use the default primary handler for it. But it  |