diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-12 20:33:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-12 20:33:21 -0400 |
commit | 480c93df5b99699390f93a7024c9f60d09da0e96 (patch) | |
tree | b93b6c8c71c5f2e716dd05b126e01ef4e20ff0af /arch/sparc | |
parent | aecfcde920da8d32949f6cbbc1fc051b4ef9e7be (diff) | |
parent | d820ac4c2fa881079e6b689d2098adce337558ae (diff) |
Merge branch 'core/locking' into tracing/ftrace
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/irq_64.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 3d2c6baae96b..233bd87a9637 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
@@ -324,17 +324,25 @@ static void sun4u_set_affinity(unsigned int virt_irq, | |||
324 | sun4u_irq_enable(virt_irq); | 324 | sun4u_irq_enable(virt_irq); |
325 | } | 325 | } |
326 | 326 | ||
327 | /* Don't do anything. The desc->status check for IRQ_DISABLED in | ||
328 | * handler_irq() will skip the handler call and that will leave the | ||
329 | * interrupt in the sent state. The next ->enable() call will hit the | ||
330 | * ICLR register to reset the state machine. | ||
331 | * | ||
332 | * This scheme is necessary, instead of clearing the Valid bit in the | ||
333 | * IMAP register, to handle the case of IMAP registers being shared by | ||
334 | * multiple INOs (and thus ICLR registers). Since we use a different | ||
335 | * virtual IRQ for each shared IMAP instance, the generic code thinks | ||
336 | * there is only one user so it prematurely calls ->disable() on | ||
337 | * free_irq(). | ||
338 | * | ||
339 | * We have to provide an explicit ->disable() method instead of using | ||
340 | * NULL to get the default. The reason is that if the generic code | ||
341 | * sees that, it also hooks up a default ->shutdown method which | ||
342 | * invokes ->mask() which we do not want. See irq_chip_set_defaults(). | ||
343 | */ | ||
327 | static void sun4u_irq_disable(unsigned int virt_irq) | 344 | static void sun4u_irq_disable(unsigned int virt_irq) |
328 | { | 345 | { |
329 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | ||
330 | |||
331 | if (likely(data)) { | ||
332 | unsigned long imap = data->imap; | ||
333 | unsigned long tmp = upa_readq(imap); | ||
334 | |||
335 | tmp &= ~IMAP_VALID; | ||
336 | upa_writeq(tmp, imap); | ||
337 | } | ||
338 | } | 346 | } |
339 | 347 | ||
340 | static void sun4u_irq_eoi(unsigned int virt_irq) | 348 | static void sun4u_irq_eoi(unsigned int virt_irq) |
@@ -747,7 +755,8 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
747 | 755 | ||
748 | desc = irq_desc + virt_irq; | 756 | desc = irq_desc + virt_irq; |
749 | 757 | ||
750 | desc->handle_irq(virt_irq, desc); | 758 | if (!(desc->status & IRQ_DISABLED)) |
759 | desc->handle_irq(virt_irq, desc); | ||
751 | 760 | ||
752 | bucket_pa = next_pa; | 761 | bucket_pa = next_pa; |
753 | } | 762 | } |