m68k/mac: Optimize interrupts using chain handlers

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
This commit is contained in:
Geert Uytterhoeven
2011-08-10 12:48:29 +02:00
parent ddc7fd25d0
commit 9145db564e
4 changed files with 300 additions and 65 deletions

View File

@@ -33,8 +33,6 @@
int psc_present;
volatile __u8 *psc;
irqreturn_t psc_irq(int, void *);
/*
* Debugging dump, used in various places to see what's going on.
*/
@@ -114,27 +112,41 @@ void __init psc_init(void)
}
}
/*
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
*/
void __init psc_register_interrupts(void)
{
if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
pr_err("Couldn't register psc%d interrupt\n", 3);
if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
pr_err("Couldn't register psc%d interrupt\n", 4);
if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
pr_err("Couldn't register psc%d interrupt\n", 5);
if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
pr_err("Couldn't register psc%d interrupt\n", 6);
}
/*
* PSC interrupt handler. It's a lot like the VIA interrupt handler.
*/
irqreturn_t psc_irq(int irq, void *dev_id)
#ifdef CONFIG_GENERIC_HARDIRQS
static void psc_irq(unsigned int irq, struct irq_desc *desc)
{
unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
int pIFR = pIFRbase + offset;
int pIER = pIERbase + offset;
int irq_num;
unsigned char irq_bit, events;
#ifdef DEBUG_IRQS
printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
#endif
events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
if (!events)
return;
irq_num = irq << 3;
irq_bit = 1;
do {
if (events & irq_bit) {
psc_write_byte(pIFR, irq_bit);
generic_handle_irq(irq_num);
}
irq_num++;
irq_bit <<= 1;
} while (events >= irq_bit);
}
#else
static irqreturn_t psc_irq(int irq, void *dev_id)
{
int pIFR = pIFRbase + ((int) dev_id);
int pIER = pIERbase + ((int) dev_id);
@@ -162,6 +174,34 @@ irqreturn_t psc_irq(int irq, void *dev_id)
} while (events >= irq_bit);
return IRQ_HANDLED;
}
#endif
/*
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
*/
void __init psc_register_interrupts(void)
{
#ifdef CONFIG_GENERIC_HARDIRQS
irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
#else /* !CONFIG_GENERIC_HARDIRQS */
if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
pr_err("Couldn't register psc%d interrupt\n", 3);
if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
pr_err("Couldn't register psc%d interrupt\n", 4);
if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
pr_err("Couldn't register psc%d interrupt\n", 5);
if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
pr_err("Couldn't register psc%d interrupt\n", 6);
#endif /* !CONFIG_GENERIC_HARDIRQS */
}
void psc_irq_enable(int irq) {
int irq_src = IRQ_SRC(irq);