forked from mirrors/linux
		
	[PATCH] genirq: core
Core genirq support: add the irq-chip and irq-flow abstractions. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
							parent
							
								
									a34db9b28a
								
							
						
					
					
						commit
						6a6de9ef58
					
				
					 7 changed files with 182 additions and 22 deletions
				
			
		|  | @ -43,20 +43,36 @@ | ||||||
| #define IRQ_NOPROBE	512	/* IRQ is not valid for probing */ | #define IRQ_NOPROBE	512	/* IRQ is not valid for probing */ | ||||||
| #define IRQ_NOREQUEST	1024	/* IRQ cannot be requested */ | #define IRQ_NOREQUEST	1024	/* IRQ cannot be requested */ | ||||||
| #define IRQ_NOAUTOEN	2048	/* IRQ will not be enabled on request irq */ | #define IRQ_NOAUTOEN	2048	/* IRQ will not be enabled on request irq */ | ||||||
|  | #define IRQ_DELAYED_DISABLE \ | ||||||
|  | 			4096	/* IRQ disable (masking) happens delayed. */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * IRQ types, see also include/linux/interrupt.h | ||||||
|  |  */ | ||||||
|  | #define IRQ_TYPE_NONE		0x0000		/* Default, unspecified type */ | ||||||
|  | #define IRQ_TYPE_EDGE_RISING	0x0001		/* Edge rising type */ | ||||||
|  | #define IRQ_TYPE_EDGE_FALLING	0x0002		/* Edge falling type */ | ||||||
|  | #define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) | ||||||
|  | #define IRQ_TYPE_LEVEL_HIGH	0x0004		/* Level high type */ | ||||||
|  | #define IRQ_TYPE_LEVEL_LOW	0x0008		/* Level low type */ | ||||||
|  | #define IRQ_TYPE_SIMPLE		0x0010		/* Simple type */ | ||||||
|  | #define IRQ_TYPE_PERCPU		0x0020		/* Per CPU type */ | ||||||
|  | #define IRQ_TYPE_PROBE		0x0040		/* Probing in progress */ | ||||||
|  | 
 | ||||||
|  | struct proc_dir_entry; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * struct hw_interrupt_type - hardware interrupt type descriptor |  * struct irq_chip - hardware interrupt chip descriptor | ||||||
|  * |  * | ||||||
|  * @name:		name for /proc/interrupts |  * @name:		name for /proc/interrupts | ||||||
|  * @startup:		start up the interrupt (defaults to ->enable if NULL) |  * @startup:		start up the interrupt (defaults to ->enable if NULL) | ||||||
|  * @shutdown:		shut down the interrupt (defaults to ->disable if NULL) |  * @shutdown:		shut down the interrupt (defaults to ->disable if NULL) | ||||||
|  * @enable:		enable the interrupt (defaults to chip->unmask if NULL) |  * @enable:		enable the interrupt (defaults to chip->unmask if NULL) | ||||||
|  * @disable:		disable the interrupt (defaults to chip->mask if NULL) |  * @disable:		disable the interrupt (defaults to chip->mask if NULL) | ||||||
|  * @handle_irq:		irq flow handler called from the arch IRQ glue code |  | ||||||
|  * @ack:		start of a new interrupt |  * @ack:		start of a new interrupt | ||||||
|  * @mask:		mask an interrupt source |  * @mask:		mask an interrupt source | ||||||
|  * @mask_ack:		ack and mask an interrupt source |  * @mask_ack:		ack and mask an interrupt source | ||||||
|  * @unmask:		unmask an interrupt source |  * @unmask:		unmask an interrupt source | ||||||
|  * @hold:		same interrupt while the handler is running |  | ||||||
|  * @end:		end of interrupt |  * @end:		end of interrupt | ||||||
|  * @set_affinity:	set the CPU affinity on SMP machines |  * @set_affinity:	set the CPU affinity on SMP machines | ||||||
|  * @retrigger:		resend an IRQ to the CPU |  * @retrigger:		resend an IRQ to the CPU | ||||||
|  | @ -64,33 +80,45 @@ | ||||||
|  * @set_wake:		enable/disable power-management wake-on of an IRQ |  * @set_wake:		enable/disable power-management wake-on of an IRQ | ||||||
|  * |  * | ||||||
|  * @release:		release function solely used by UML |  * @release:		release function solely used by UML | ||||||
|  |  * @typename:		obsoleted by name, kept as migration helper | ||||||
|  */ |  */ | ||||||
| struct hw_interrupt_type { | struct irq_chip { | ||||||
| 	const char	*typename; | 	const char	*name; | ||||||
| 	unsigned int	(*startup)(unsigned int irq); | 	unsigned int	(*startup)(unsigned int irq); | ||||||
| 	void		(*shutdown)(unsigned int irq); | 	void		(*shutdown)(unsigned int irq); | ||||||
| 	void		(*enable)(unsigned int irq); | 	void		(*enable)(unsigned int irq); | ||||||
| 	void		(*disable)(unsigned int irq); | 	void		(*disable)(unsigned int irq); | ||||||
|  | 
 | ||||||
| 	void		(*ack)(unsigned int irq); | 	void		(*ack)(unsigned int irq); | ||||||
|  | 	void		(*mask)(unsigned int irq); | ||||||
|  | 	void		(*mask_ack)(unsigned int irq); | ||||||
|  | 	void		(*unmask)(unsigned int irq); | ||||||
|  | 
 | ||||||
| 	void		(*end)(unsigned int irq); | 	void		(*end)(unsigned int irq); | ||||||
| 	void		(*set_affinity)(unsigned int irq, cpumask_t dest); | 	void		(*set_affinity)(unsigned int irq, cpumask_t dest); | ||||||
| 	int		(*retrigger)(unsigned int irq); | 	int		(*retrigger)(unsigned int irq); | ||||||
|  | 	int		(*set_type)(unsigned int irq, unsigned int flow_type); | ||||||
|  | 	int		(*set_wake)(unsigned int irq, unsigned int on); | ||||||
| 
 | 
 | ||||||
| 	/* Currently used only by UML, might disappear one day.*/ | 	/* Currently used only by UML, might disappear one day.*/ | ||||||
| #ifdef CONFIG_IRQ_RELEASE_METHOD | #ifdef CONFIG_IRQ_RELEASE_METHOD | ||||||
| 	void		(*release)(unsigned int irq, void *dev_id); | 	void		(*release)(unsigned int irq, void *dev_id); | ||||||
| #endif | #endif | ||||||
|  | 	/*
 | ||||||
|  | 	 * For compatibility, ->typename is copied into ->name. | ||||||
|  | 	 * Will disappear. | ||||||
|  | 	 */ | ||||||
|  | 	const char	*typename; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct hw_interrupt_type  hw_irq_controller; |  | ||||||
| 
 |  | ||||||
| struct proc_dir_entry; |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * struct irq_desc - interrupt descriptor |  * struct irq_desc - interrupt descriptor | ||||||
|  * |  * | ||||||
|  * @handler:		interrupt type dependent handler functions |  * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()] | ||||||
|  * @handler_data:	data for the type handlers |  * @chip:		low level interrupt hardware access | ||||||
|  |  * @handler_data:	per-IRQ data for the irq_chip methods | ||||||
|  |  * @chip_data:		platform-specific per-chip private data for the chip | ||||||
|  |  *			methods, to allow shared chip implementations | ||||||
|  * @action:		the irq action chain |  * @action:		the irq action chain | ||||||
|  * @status:		status information |  * @status:		status information | ||||||
|  * @depth:		disable-depth, for nested irq_disable() calls |  * @depth:		disable-depth, for nested irq_disable() calls | ||||||
|  | @ -98,6 +126,7 @@ struct proc_dir_entry; | ||||||
|  * @irqs_unhandled:	stats field for spurious unhandled interrupts |  * @irqs_unhandled:	stats field for spurious unhandled interrupts | ||||||
|  * @lock:		locking for SMP |  * @lock:		locking for SMP | ||||||
|  * @affinity:		IRQ affinity on SMP |  * @affinity:		IRQ affinity on SMP | ||||||
|  |  * @cpu:		cpu index useful for balancing | ||||||
|  * @pending_mask:	pending rebalanced interrupts |  * @pending_mask:	pending rebalanced interrupts | ||||||
|  * @move_irq:		need to re-target IRQ destination |  * @move_irq:		need to re-target IRQ destination | ||||||
|  * @dir:		/proc/irq/ procfs entry |  * @dir:		/proc/irq/ procfs entry | ||||||
|  | @ -106,16 +135,22 @@ struct proc_dir_entry; | ||||||
|  * Pad this out to 32 bytes for cache and indexing reasons. |  * Pad this out to 32 bytes for cache and indexing reasons. | ||||||
|  */ |  */ | ||||||
| struct irq_desc { | struct irq_desc { | ||||||
| 	hw_irq_controller	*chip; | 	void fastcall		(*handle_irq)(unsigned int irq, | ||||||
|  | 					      struct irq_desc *desc, | ||||||
|  | 					      struct pt_regs *regs); | ||||||
|  | 	struct irq_chip		*chip; | ||||||
|  | 	void			*handler_data; | ||||||
| 	void			*chip_data; | 	void			*chip_data; | ||||||
| 	struct irqaction	*action;	/* IRQ action list */ | 	struct irqaction	*action;	/* IRQ action list */ | ||||||
| 	unsigned int		status;		/* IRQ status */ | 	unsigned int		status;		/* IRQ status */ | ||||||
|  | 
 | ||||||
| 	unsigned int		depth;		/* nested irq disables */ | 	unsigned int		depth;		/* nested irq disables */ | ||||||
| 	unsigned int		irq_count;	/* For detecting broken IRQs */ | 	unsigned int		irq_count;	/* For detecting broken IRQs */ | ||||||
| 	unsigned int		irqs_unhandled; | 	unsigned int		irqs_unhandled; | ||||||
| 	spinlock_t		lock; | 	spinlock_t		lock; | ||||||
| #ifdef CONFIG_SMP | #ifdef CONFIG_SMP | ||||||
| 	cpumask_t		affinity; | 	cpumask_t		affinity; | ||||||
|  | 	unsigned int		cpu; | ||||||
| #endif | #endif | ||||||
| #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) | #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) | ||||||
| 	cpumask_t		pending_mask; | 	cpumask_t		pending_mask; | ||||||
|  | @ -131,6 +166,9 @@ extern struct irq_desc irq_desc[NR_IRQS]; | ||||||
| /*
 | /*
 | ||||||
|  * Migration helpers for obsolete names, they will go away: |  * Migration helpers for obsolete names, they will go away: | ||||||
|  */ |  */ | ||||||
|  | #define hw_interrupt_type	irq_chip | ||||||
|  | typedef struct irq_chip		hw_irq_controller; | ||||||
|  | #define no_irq_type		no_irq_chip | ||||||
| typedef struct irq_desc		irq_desc_t; | typedef struct irq_desc		irq_desc_t; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -138,6 +176,17 @@ typedef struct irq_desc		irq_desc_t; | ||||||
|  */ |  */ | ||||||
| #include <asm/hw_irq.h> | #include <asm/hw_irq.h> | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Architectures call this to let the generic IRQ layer | ||||||
|  |  * handle an interrupt: | ||||||
|  |  */ | ||||||
|  | static inline void generic_handle_irq(unsigned int irq, struct pt_regs *regs) | ||||||
|  | { | ||||||
|  | 	struct irq_desc *desc = irq_desc + irq; | ||||||
|  | 
 | ||||||
|  | 	desc->handle_irq(irq, desc, regs); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| extern int setup_irq(unsigned int irq, struct irqaction *new); | extern int setup_irq(unsigned int irq, struct irqaction *new); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_GENERIC_HARDIRQS | #ifdef CONFIG_GENERIC_HARDIRQS | ||||||
|  | @ -236,27 +285,100 @@ static inline int select_smp_affinity(unsigned int irq) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern int no_irq_affinity; | extern int no_irq_affinity; | ||||||
| extern int noirqdebug_setup(char *str); |  | ||||||
| 
 | 
 | ||||||
| extern irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, | /* Handle irq action chains: */ | ||||||
| 				    struct irqaction *action); | extern int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, | ||||||
|  | 			    struct irqaction *action); | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Explicit fastcall, because i386 4KSTACKS calls it from assembly: |  * Built-in IRQ handlers for various IRQ types, | ||||||
|  |  * callable via desc->chip->handle_irq() | ||||||
|  |  */ | ||||||
|  | extern void fastcall | ||||||
|  | handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); | ||||||
|  | extern void fastcall | ||||||
|  | handle_fastack_irq(unsigned int irq, struct irq_desc *desc, | ||||||
|  | 			 struct pt_regs *regs); | ||||||
|  | extern void fastcall | ||||||
|  | handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); | ||||||
|  | extern void fastcall | ||||||
|  | handle_simple_irq(unsigned int irq, struct irq_desc *desc, | ||||||
|  | 		  struct pt_regs *regs); | ||||||
|  | extern void fastcall | ||||||
|  | handle_percpu_irq(unsigned int irq, struct irq_desc *desc, | ||||||
|  | 		  struct pt_regs *regs); | ||||||
|  | extern void fastcall | ||||||
|  | handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Get a descriptive string for the highlevel handler, for | ||||||
|  |  * /proc/interrupts output: | ||||||
|  |  */ | ||||||
|  | extern const char * | ||||||
|  | handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *, | ||||||
|  | 					struct pt_regs *)); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Monolithic do_IRQ implementation. | ||||||
|  |  * (is an explicit fastcall, because i386 4KSTACKS calls it from assembly) | ||||||
|  */ |  */ | ||||||
| extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); | extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); | ||||||
| 
 | 
 | ||||||
|  | /* Handling of unhandled and spurious interrupts: */ | ||||||
| extern void note_interrupt(unsigned int irq, struct irq_desc *desc, | extern void note_interrupt(unsigned int irq, struct irq_desc *desc, | ||||||
| 			   int action_ret, struct pt_regs *regs); | 			   int action_ret, struct pt_regs *regs); | ||||||
| extern int can_request_irq(unsigned int irq, unsigned long irqflags); |  | ||||||
| 
 | 
 | ||||||
| /* Resending of interrupts :*/ | /* Resending of interrupts :*/ | ||||||
| void check_irq_resend(struct irq_desc *desc, unsigned int irq); | void check_irq_resend(struct irq_desc *desc, unsigned int irq); | ||||||
| 
 | 
 | ||||||
|  | /* Initialize /proc/irq/ */ | ||||||
| extern void init_irq_proc(void); | extern void init_irq_proc(void); | ||||||
| 
 | 
 | ||||||
| #endif /* CONFIG_GENERIC_HARDIRQS */ | /* Enable/disable irq debugging output: */ | ||||||
|  | extern int noirqdebug_setup(char *str); | ||||||
| 
 | 
 | ||||||
| extern hw_irq_controller no_irq_type;  /* needed in every arch ? */ | /* Checks whether the interrupt can be requested by request_irq(): */ | ||||||
|  | extern int can_request_irq(unsigned int irq, unsigned long irqflags); | ||||||
|  | 
 | ||||||
|  | /* Dummy irq-chip implementation: */ | ||||||
|  | extern struct irq_chip no_irq_chip; | ||||||
|  | 
 | ||||||
|  | extern void | ||||||
|  | set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, | ||||||
|  | 			 void fastcall (*handle)(unsigned int, | ||||||
|  | 						 struct irq_desc *, | ||||||
|  | 						 struct pt_regs *)); | ||||||
|  | extern void | ||||||
|  | __set_irq_handler(unsigned int irq, | ||||||
|  | 		  void fastcall (*handle)(unsigned int, struct irq_desc *, | ||||||
|  | 					  struct pt_regs *), | ||||||
|  | 		  int is_chained); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Set a highlevel flow handler for a given IRQ: | ||||||
|  |  */ | ||||||
|  | static inline void | ||||||
|  | set_irq_handler(unsigned int irq, | ||||||
|  | 		void fastcall (*handle)(unsigned int, struct irq_desc *, | ||||||
|  | 					struct pt_regs *)) | ||||||
|  | { | ||||||
|  | 	__set_irq_handler(irq, handle, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Set a highlevel chained flow handler for a given IRQ. | ||||||
|  |  * (a chained handler is automatically enabled and set to | ||||||
|  |  *  IRQ_NOREQUEST and IRQ_NOPROBE) | ||||||
|  |  */ | ||||||
|  | static inline void | ||||||
|  | set_irq_chained_handler(unsigned int irq, | ||||||
|  | 			void fastcall (*handle)(unsigned int, struct irq_desc *, | ||||||
|  | 						struct pt_regs *)) | ||||||
|  | { | ||||||
|  | 	__set_irq_handler(irq, handle, 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||||||
| 
 | 
 | ||||||
| #endif /* !CONFIG_S390 */ | #endif /* !CONFIG_S390 */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,8 +40,15 @@ unsigned long probe_irq_on(void) | ||||||
| 		desc = irq_desc + i; | 		desc = irq_desc + i; | ||||||
| 
 | 
 | ||||||
| 		spin_lock_irq(&desc->lock); | 		spin_lock_irq(&desc->lock); | ||||||
| 		if (!desc->action && !(desc->status & IRQ_NOPROBE)) | 		if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * Some chips need to know about probing in | ||||||
|  | 			 * progress: | ||||||
|  | 			 */ | ||||||
|  | 			if (desc->chip->set_type) | ||||||
|  | 				desc->chip->set_type(i, IRQ_TYPE_PROBE); | ||||||
| 			desc->chip->startup(i); | 			desc->chip->startup(i); | ||||||
|  | 		} | ||||||
| 		spin_unlock_irq(&desc->lock); | 		spin_unlock_irq(&desc->lock); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,16 @@ | ||||||
| 
 | 
 | ||||||
| #include "internals.h" | #include "internals.h" | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * handle_bad_irq - handle spurious and unhandled irqs | ||||||
|  |  */ | ||||||
|  | void fastcall | ||||||
|  | handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) | ||||||
|  | { | ||||||
|  | 	kstat_this_cpu.irqs[irq]++; | ||||||
|  | 	ack_bad_irq(irq); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Linux has a controller-independent interrupt architecture. |  * Linux has a controller-independent interrupt architecture. | ||||||
|  * Every controller has a 'controller-template', that is used |  * Every controller has a 'controller-template', that is used | ||||||
|  |  | ||||||
|  | @ -4,6 +4,12 @@ | ||||||
| 
 | 
 | ||||||
| extern int noirqdebug; | extern int noirqdebug; | ||||||
| 
 | 
 | ||||||
|  | /* Set default functions for irq_chip structures: */ | ||||||
|  | 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); | ||||||
|  | 
 | ||||||
| #ifdef CONFIG_PROC_FS | #ifdef CONFIG_PROC_FS | ||||||
| extern void register_irq_proc(unsigned int irq); | extern void register_irq_proc(unsigned int irq); | ||||||
| extern void register_handler_proc(unsigned int irq, struct irqaction *action); | extern void register_handler_proc(unsigned int irq, struct irqaction *action); | ||||||
|  |  | ||||||
|  | @ -153,6 +153,17 @@ int can_request_irq(unsigned int irq, unsigned long irqflags) | ||||||
| 	return !action; | 	return !action; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void compat_irq_chip_set_default_handler(struct irq_desc *desc) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * If the architecture still has not overriden | ||||||
|  | 	 * the flow handler then zap the default. This | ||||||
|  | 	 * should catch incorrect flow-type setting. | ||||||
|  | 	 */ | ||||||
|  | 	if (desc->handle_irq == &handle_bad_irq) | ||||||
|  | 		desc->handle_irq = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Internal function to register an irqaction - typically used to |  * Internal function to register an irqaction - typically used to | ||||||
|  * allocate special interrupts that are part of the architecture. |  * allocate special interrupts that are part of the architecture. | ||||||
|  | @ -217,6 +228,9 @@ int setup_irq(unsigned int irq, struct irqaction *new) | ||||||
| 		desc->status |= IRQ_PER_CPU; | 		desc->status |= IRQ_PER_CPU; | ||||||
| #endif | #endif | ||||||
| 	if (!shared) { | 	if (!shared) { | ||||||
|  | 		irq_chip_set_defaults(desc->chip); | ||||||
|  | 		compat_irq_chip_set_default_handler(desc); | ||||||
|  | 
 | ||||||
| 		desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | | 		desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | | ||||||
| 				  IRQ_INPROGRESS); | 				  IRQ_INPROGRESS); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,9 +37,9 @@ static void resend_irqs(unsigned long arg) | ||||||
| 		irq = find_first_bit(irqs_resend, NR_IRQS); | 		irq = find_first_bit(irqs_resend, NR_IRQS); | ||||||
| 		clear_bit(irq, irqs_resend); | 		clear_bit(irq, irqs_resend); | ||||||
| 		desc = irq_desc + irq; | 		desc = irq_desc + irq; | ||||||
| 		spin_lock_irqsave(&desc->lock, flags); | 		local_irq_disable(); | ||||||
| 		desc->handle_irq(irq, desc, NULL); | 		desc->handle_irq(irq, desc, NULL); | ||||||
| 		spin_unlock_irqrestore(&desc->lock, flags); | 		local_irq_enable(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -168,6 +168,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, | ||||||
| 		 */ | 		 */ | ||||||
| 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq); | 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq); | ||||||
| 		desc->status |= IRQ_DISABLED; | 		desc->status |= IRQ_DISABLED; | ||||||
|  | 		desc->depth = 1; | ||||||
| 		desc->chip->disable(irq); | 		desc->chip->disable(irq); | ||||||
| 	} | 	} | ||||||
| 	desc->irqs_unhandled = 0; | 	desc->irqs_unhandled = 0; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Thomas Gleixner
						Thomas Gleixner