mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	genirq: fix irq_desc->depth handling with DEBUG_SHIRQ
When DEBUG_SHIRQ is selected, a spurious IRQ is issued before the setup_irq() initializes the desc->depth. An IRQ handler may call disable_irq_nosync(), but then setup_irq() will overwrite desc->depth, and upon enable_irq() we'll catch this WARN: ------------[ cut here ]------------ Badness at kernel/irq/manage.c:180 NIP: c0061ab8 LR: c0061f10 CTR: 00000000 REGS: cf83be50 TRAP: 0700 Not tainted (2.6.27-rc3-23450-g74919b0) MSR: 00021032 <ME,IR,DR> CR: 22042022 XER: 20000000 TASK = cf829100[5] 'events/0' THREAD: cf83a000 GPR00: c0061f10 cf83bf00 cf829100 c038e674 00000016 00000000 cf83bef8 00000038 GPR08: c0298910 00000000 c0310d28 cf83a000 00000c9c 1001a1a8 0fffe000 00800000 GPR16: ffffffff 00000000 007fff00 00000000 007ffeb0 c03320a0 c031095c c0310924 GPR24: cf8292ec cf807190 cf83a000 00009032 c038e6a4 c038e674 cf99b1cc c038e674 NIP [c0061ab8] __enable_irq+0x20/0x80 LR [c0061f10] enable_irq+0x50/0x70 Call Trace: [cf83bf00] [c038e674] irq_desc+0x630/0x9000 (unreliable) [cf83bf10] [c0061f10] enable_irq+0x50/0x70 [cf83bf30] [c01abe94] phy_change+0x68/0x108 [cf83bf50] [c0046394] run_workqueue+0xc4/0x16c [cf83bf90] [c0046834] worker_thread+0x74/0xd4 [cf83bfd0] [c004ab7c] kthread+0x48/0x84 [cf83bff0] [c00135e0] kernel_thread+0x44/0x60 Instruction dump: 4e800020 3d20c031 38a94214 4bffffcc 9421fff0 7c0802a6 93e1000c 7c7f1b78 90010014 8123001c 2f890000 409e001c <0fe00000> 80010014 83e1000c 38210010 That trace corresponds to this line: WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); The patch fixes the problem by moving the SHIRQ code below the setup_irq(). Unfortunately we can't easily move the SHIRQ code inside the setup_irq(), since it grabs a spinlock, so to prvent a 'real' IRQ from interfere us we should disable that IRQ. p.s. The driver in question is drivers/net/phy/phy.c. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Cc: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
		
							parent
							
								
									8d00a6c8f6
								
							
						
					
					
						commit
						377bf1e4ac
					
				
					 1 changed files with 10 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -596,26 +596,29 @@ int request_irq(unsigned int irq, irq_handler_t handler,
 | 
			
		|||
	action->next = NULL;
 | 
			
		||||
	action->dev_id = dev_id;
 | 
			
		||||
 | 
			
		||||
	retval = setup_irq(irq, action);
 | 
			
		||||
	if (retval)
 | 
			
		||||
		kfree(action);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DEBUG_SHIRQ
 | 
			
		||||
	if (irqflags & IRQF_SHARED) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * It's a shared IRQ -- the driver ought to be prepared for it
 | 
			
		||||
		 * to happen immediately, so let's make sure....
 | 
			
		||||
		 * We do this before actually registering it, to make sure that
 | 
			
		||||
		 * a 'real' IRQ doesn't run in parallel with our fake
 | 
			
		||||
		 * We disable the irq to make sure that a 'real' IRQ doesn't
 | 
			
		||||
		 * run in parallel with our fake.
 | 
			
		||||
		 */
 | 
			
		||||
		unsigned long flags;
 | 
			
		||||
 | 
			
		||||
		disable_irq(irq);
 | 
			
		||||
		local_irq_save(flags);
 | 
			
		||||
 | 
			
		||||
		handler(irq, dev_id);
 | 
			
		||||
 | 
			
		||||
		local_irq_restore(flags);
 | 
			
		||||
		enable_irq(irq);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	retval = setup_irq(irq, action);
 | 
			
		||||
	if (retval)
 | 
			
		||||
		kfree(action);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(request_irq);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue