mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	genirq: record trigger type
Genirq hasn't previously recorded the trigger type used by any given IRQ,
although some irq_chip support has done so.  That data can be useful when
troubleshooting.  This patch records it in the relevant irq_desc.status
bits, and improves consistency between the two driver-visible calls
affected:
 - Make set_irq_type() usage match request_irq() usage:
    * IRQ_TYPE_NONE should be a NOP; succeed, so irq_chip methods
      won't have to handle that case any more (many do it wrong).
    * IRQ_TYPE_PROBE is ignored; any buggy out-of-tree callers
      might need to switch over to the real IRQ probing code.
    * emit the same diagnostics (from shared utility code)
 - Their kerneldoc now reflects usage:
    * request_irq() flags include IRQF_TRIGGER_* to specify
      active edge(s)/level ... docs previously omitted that
    * set_irq_type() is declared in <linux/irq.h> so callers
      should use the (bit-equivalent) IRQ_TYPE_* symbols there
Also: adds a warning about shared IRQs that don't end up using the
requested trigger mode; and fix an unrelated "sparse" warning.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
			
			
This commit is contained in:
		
							parent
							
								
									d6d5aeb661
								
							
						
					
					
						commit
						0c5d1eb77a
					
				
					 3 changed files with 29 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -111,9 +111,9 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
 | 
			
		|||
EXPORT_SYMBOL(set_irq_chip);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	set_irq_type - set the irq type for an irq
 | 
			
		||||
 *	set_irq_type - set the irq trigger type for an irq
 | 
			
		||||
 *	@irq:	irq number
 | 
			
		||||
 *	@type:	interrupt type - see include/linux/interrupt.h
 | 
			
		||||
 *	@type:	IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
 | 
			
		||||
 */
 | 
			
		||||
int set_irq_type(unsigned int irq, unsigned int type)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -127,11 +127,12 @@ int set_irq_type(unsigned int irq, unsigned int type)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	desc = irq_desc + irq;
 | 
			
		||||
	if (desc->chip->set_type) {
 | 
			
		||||
		spin_lock_irqsave(&desc->lock, flags);
 | 
			
		||||
		ret = desc->chip->set_type(irq, type);
 | 
			
		||||
		spin_unlock_irqrestore(&desc->lock, flags);
 | 
			
		||||
	}
 | 
			
		||||
	if (type == IRQ_TYPE_NONE)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&desc->lock, flags);
 | 
			
		||||
	ret = __irq_set_trigger(desc, irq, flags);
 | 
			
		||||
	spin_unlock_irqrestore(&desc->lock, flags);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(set_irq_type);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,9 @@ extern void irq_chip_set_defaults(struct irq_chip *chip);
 | 
			
		|||
/* Set default handler: */
 | 
			
		||||
extern void compat_irq_chip_set_default_handler(struct irq_desc *desc);
 | 
			
		||||
 | 
			
		||||
extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 | 
			
		||||
		unsigned long flags);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PROC_FS
 | 
			
		||||
extern void register_irq_proc(unsigned int irq);
 | 
			
		||||
extern void register_handler_proc(unsigned int irq, struct irqaction *action);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,7 +216,7 @@ void enable_irq(unsigned int irq)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(enable_irq);
 | 
			
		||||
 | 
			
		||||
int set_irq_wake_real(unsigned int irq, unsigned int on)
 | 
			
		||||
static int set_irq_wake_real(unsigned int irq, unsigned int on)
 | 
			
		||||
{
 | 
			
		||||
	struct irq_desc *desc = irq_desc + irq;
 | 
			
		||||
	int ret = -ENXIO;
 | 
			
		||||
| 
						 | 
				
			
			@ -305,10 +305,11 @@ 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,
 | 
			
		||||
int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 | 
			
		||||
		unsigned long flags)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct irq_chip *chip = desc->chip;
 | 
			
		||||
 | 
			
		||||
	if (!chip || !chip->set_type) {
 | 
			
		||||
		/*
 | 
			
		||||
| 
						 | 
				
			
			@ -326,6 +327,11 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
 | 
			
		|||
		pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
 | 
			
		||||
				(int)(flags & IRQF_TRIGGER_MASK),
 | 
			
		||||
				irq, chip->set_type);
 | 
			
		||||
	else {
 | 
			
		||||
		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 | 
			
		||||
		desc->status &= ~IRQ_TYPE_SENSE_MASK;
 | 
			
		||||
		desc->status |= flags & IRQ_TYPE_SENSE_MASK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -404,7 +410,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 | 
			
		|||
 | 
			
		||||
		/* Setup the type (level, edge polarity) if configured: */
 | 
			
		||||
		if (new->flags & IRQF_TRIGGER_MASK) {
 | 
			
		||||
			ret = __irq_set_trigger(desc->chip, irq, new->flags);
 | 
			
		||||
			ret = __irq_set_trigger(desc, irq, new->flags);
 | 
			
		||||
 | 
			
		||||
			if (ret) {
 | 
			
		||||
				spin_unlock_irqrestore(&desc->lock, flags);
 | 
			
		||||
| 
						 | 
				
			
			@ -430,6 +436,14 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 | 
			
		|||
 | 
			
		||||
		/* Set default affinity mask once everything is setup */
 | 
			
		||||
		irq_select_affinity(irq);
 | 
			
		||||
 | 
			
		||||
	} else if ((new->flags & IRQF_TRIGGER_MASK)
 | 
			
		||||
			&& (new->flags & IRQF_TRIGGER_MASK)
 | 
			
		||||
				!= (desc->status & IRQ_TYPE_SENSE_MASK)) {
 | 
			
		||||
		/* hope the handler works with the actual trigger mode... */
 | 
			
		||||
		pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
 | 
			
		||||
				irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
 | 
			
		||||
				(int)(new->flags & IRQF_TRIGGER_MASK));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*p = new;
 | 
			
		||||
| 
						 | 
				
			
			@ -586,6 +600,7 @@ EXPORT_SYMBOL(free_irq);
 | 
			
		|||
 *	IRQF_SHARED		Interrupt is shared
 | 
			
		||||
 *	IRQF_DISABLED	Disable local interrupts while processing
 | 
			
		||||
 *	IRQF_SAMPLE_RANDOM	The interrupt can be used for entropy
 | 
			
		||||
 *	IRQF_TRIGGER_*		Specify active edge(s) or level
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
int request_irq(unsigned int irq, irq_handler_t handler,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue