diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-08-10 06:48:29 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-11-08 16:35:50 -0500 |
commit | 9145db564eae98134de8eb8d64b47d7177eccfdd (patch) | |
tree | 7d0e25514abba33b6082f5a13963442cf390a058 /arch/m68k/mac/psc.c | |
parent | ddc7fd25d09678f8252c0321ef4b66e8451abe7d (diff) |
m68k/mac: Optimize interrupts using chain handlers
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/mac/psc.c')
-rw-r--r-- | arch/m68k/mac/psc.c | 74 |
1 files changed, 57 insertions, 17 deletions
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index 0a34b7afc376..52840b8c03b8 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c | |||
@@ -33,8 +33,6 @@ | |||
33 | int psc_present; | 33 | int psc_present; |
34 | volatile __u8 *psc; | 34 | volatile __u8 *psc; |
35 | 35 | ||
36 | irqreturn_t psc_irq(int, void *); | ||
37 | |||
38 | /* | 36 | /* |
39 | * Debugging dump, used in various places to see what's going on. | 37 | * Debugging dump, used in various places to see what's going on. |
40 | */ | 38 | */ |
@@ -115,26 +113,40 @@ void __init psc_init(void) | |||
115 | } | 113 | } |
116 | 114 | ||
117 | /* | 115 | /* |
118 | * Register the PSC interrupt dispatchers for autovector interrupts 3-6. | 116 | * PSC interrupt handler. It's a lot like the VIA interrupt handler. |
119 | */ | 117 | */ |
120 | 118 | ||
121 | void __init psc_register_interrupts(void) | 119 | #ifdef CONFIG_GENERIC_HARDIRQS |
120 | static void psc_irq(unsigned int irq, struct irq_desc *desc) | ||
122 | { | 121 | { |
123 | if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) | 122 | unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc); |
124 | pr_err("Couldn't register psc%d interrupt\n", 3); | 123 | int pIFR = pIFRbase + offset; |
125 | if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) | 124 | int pIER = pIERbase + offset; |
126 | pr_err("Couldn't register psc%d interrupt\n", 4); | 125 | int irq_num; |
127 | if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) | 126 | unsigned char irq_bit, events; |
128 | pr_err("Couldn't register psc%d interrupt\n", 5); | ||
129 | if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) | ||
130 | pr_err("Couldn't register psc%d interrupt\n", 6); | ||
131 | } | ||
132 | 127 | ||
133 | /* | 128 | #ifdef DEBUG_IRQS |
134 | * PSC interrupt handler. It's a lot like the VIA interrupt handler. | 129 | printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n", |
135 | */ | 130 | irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); |
131 | #endif | ||
136 | 132 | ||
137 | irqreturn_t psc_irq(int irq, void *dev_id) | 133 | events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; |
134 | if (!events) | ||
135 | return; | ||
136 | |||
137 | irq_num = irq << 3; | ||
138 | irq_bit = 1; | ||
139 | do { | ||
140 | if (events & irq_bit) { | ||
141 | psc_write_byte(pIFR, irq_bit); | ||
142 | generic_handle_irq(irq_num); | ||
143 | } | ||
144 | irq_num++; | ||
145 | irq_bit <<= 1; | ||
146 | } while (events >= irq_bit); | ||
147 | } | ||
148 | #else | ||
149 | static irqreturn_t psc_irq(int irq, void *dev_id) | ||
138 | { | 150 | { |
139 | int pIFR = pIFRbase + ((int) dev_id); | 151 | int pIFR = pIFRbase + ((int) dev_id); |
140 | int pIER = pIERbase + ((int) dev_id); | 152 | int pIER = pIERbase + ((int) dev_id); |
@@ -162,6 +174,34 @@ irqreturn_t psc_irq(int irq, void *dev_id) | |||
162 | } while (events >= irq_bit); | 174 | } while (events >= irq_bit); |
163 | return IRQ_HANDLED; | 175 | return IRQ_HANDLED; |
164 | } | 176 | } |
177 | #endif | ||
178 | |||
179 | /* | ||
180 | * Register the PSC interrupt dispatchers for autovector interrupts 3-6. | ||
181 | */ | ||
182 | |||
183 | void __init psc_register_interrupts(void) | ||
184 | { | ||
185 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
186 | irq_set_chained_handler(IRQ_AUTO_3, psc_irq); | ||
187 | irq_set_handler_data(IRQ_AUTO_3, (void *)0x30); | ||
188 | irq_set_chained_handler(IRQ_AUTO_4, psc_irq); | ||
189 | irq_set_handler_data(IRQ_AUTO_4, (void *)0x40); | ||
190 | irq_set_chained_handler(IRQ_AUTO_5, psc_irq); | ||
191 | irq_set_handler_data(IRQ_AUTO_5, (void *)0x50); | ||
192 | irq_set_chained_handler(IRQ_AUTO_6, psc_irq); | ||
193 | irq_set_handler_data(IRQ_AUTO_6, (void *)0x60); | ||
194 | #else /* !CONFIG_GENERIC_HARDIRQS */ | ||
195 | if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30)) | ||
196 | pr_err("Couldn't register psc%d interrupt\n", 3); | ||
197 | if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40)) | ||
198 | pr_err("Couldn't register psc%d interrupt\n", 4); | ||
199 | if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50)) | ||
200 | pr_err("Couldn't register psc%d interrupt\n", 5); | ||
201 | if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60)) | ||
202 | pr_err("Couldn't register psc%d interrupt\n", 6); | ||
203 | #endif /* !CONFIG_GENERIC_HARDIRQS */ | ||
204 | } | ||
165 | 205 | ||
166 | void psc_irq_enable(int irq) { | 206 | void psc_irq_enable(int irq) { |
167 | int irq_src = IRQ_SRC(irq); | 207 | int irq_src = IRQ_SRC(irq); |