aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2011-04-18 07:25:44 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-20 01:11:40 -0400
commit6baa9b20a68a88c2fd751cbe8d7652009379351b (patch)
tree999283be451c020ff35110c336292e9d698d2464 /arch/sparc
parent06010fb588700e7fcb29e720c56884e3de5fd327 (diff)
sparc32: genirq support
The conversion of sparc32 to genirq is based on original work done by David S. Miller. Daniel Hellstrom has helped in the conversion and implemented the shutdowm functionality. Marcel van Nies <morcles@gmail.com> has tested this on Sparc Station 20 Test status: sun4c - not tested sun4m,pci - not tested sun4m,sbus - tested (Sparc Classic, Sparc Station 5, Sparc Station 20) sun4d - not tested leon - tested on various combinations of leon boards, including SMP variants generic Introduce use of GENERIC_HARDIRQS and GENERIC_IRQ_SHOW Allocate 64 IRQs - which is enough even for SS2000 Use a table of irq_bucket to maintain uses IRQs irq_bucket is also used to chain several irq's that must be called when the same intrrupt is asserted Use irq_link to link a interrupt source to the irq All plafforms must now supply their own build_device_irq method handler_irq rewriten to use generic irq support floppy Read FLOPPY_IRQ from platform device Use generic request_irq to register the floppy interrupt Rewrote sparc_floppy_irq to use the generic irq support pcic: Introduce irq_chip Store mask in chip_data for use in mask/unmask functions Add build_device_irq for pcic Use pcic_build_device_irq in pci_time_init allocate virtual irqs in pcic_fill_irq sun4c: Introduce irq_chip Store mask in chip_data for use in mask/unmask functions Add build_device_irq for sun4c Use sun4c_build_device_irq in sun4c_init_timers sun4m: Introduce irq_chip Introduce dedicated mask/unmask methods Introduce sun4m_handler_data that allow easy access to necessary data in the mask/unmask functions Add a helper method to enable profile_timer (used from smp) Added sun4m_build_device_irq Use sun4m_build_device_irq in sun4m_init_timers TODO: There is no replacement for smp_rotate that always scheduled next CPU as interrupt target upon an interrupt sun4d: Introduce irq_chip Introduce dedicated mask/unmask methods Introduce sun4d_handler_data that allow easy access to necessary data in mask/unmask fuctions Rewrote sun4d_handler_irq to use generic irq support TODO: The original implmentation of enable/disable had: if (irq < NR_IRQS) return; The new implmentation does not distingush between SBUS and cpu interrupts. I am no sure what is right here. I assume we need to do something for the cpu interrupts. I have not succeeded booting my sun4d box (with or without this patch) and my understanding of this platfrom is limited. So I would be a bit suprised if this works. leon: Introduce irq_chip Store mask in chip_data for use in mask/unmask functions Add build_device_irq for leon Use leon_build_device_irq in leon_init_timers Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: Daniel Hellstrom <daniel@gaisler.com> Tested-by: Daniel Hellstrom <daniel@gaisler.com> Tested-by: Marcel van Nies <morcles@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig6
-rw-r--r--arch/sparc/include/asm/floppy_32.h40
-rw-r--r--arch/sparc/include/asm/irq_32.h6
-rw-r--r--arch/sparc/include/asm/system_32.h5
-rw-r--r--arch/sparc/kernel/Makefile4
-rw-r--r--arch/sparc/kernel/irq.h45
-rw-r--r--arch/sparc/kernel/irq_32.c494
-rw-r--r--arch/sparc/kernel/kernel.h1
-rw-r--r--arch/sparc/kernel/leon_kernel.c70
-rw-r--r--arch/sparc/kernel/pcic.c83
-rw-r--r--arch/sparc/kernel/sun4c_irq.c150
-rw-r--r--arch/sparc/kernel/sun4d_irq.c472
-rw-r--r--arch/sparc/kernel/sun4m_irq.c179
-rw-r--r--arch/sparc/kernel/sun4m_smp.c16
14 files changed, 636 insertions, 935 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index e560d102215a..a56630d4f14b 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -25,6 +25,10 @@ config SPARC
25 select HAVE_DMA_ATTRS 25 select HAVE_DMA_ATTRS
26 select HAVE_DMA_API_DEBUG 26 select HAVE_DMA_API_DEBUG
27 select HAVE_ARCH_JUMP_LABEL 27 select HAVE_ARCH_JUMP_LABEL
28 select HAVE_GENERIC_HARDIRQS
29 select GENERIC_HARDIRQS_NO_DEPRECATED
30 select GENERIC_IRQ_SHOW
31
28 32
29config SPARC32 33config SPARC32
30 def_bool !64BIT 34 def_bool !64BIT
@@ -50,8 +54,6 @@ config SPARC64
50 select RTC_DRV_STARFIRE 54 select RTC_DRV_STARFIRE
51 select HAVE_PERF_EVENTS 55 select HAVE_PERF_EVENTS
52 select PERF_USE_VMALLOC 56 select PERF_USE_VMALLOC
53 select HAVE_GENERIC_HARDIRQS
54 select GENERIC_IRQ_SHOW
55 select IRQ_PREFLOW_FASTEOI 57 select IRQ_PREFLOW_FASTEOI
56 58
57config ARCH_DEFCONFIG 59config ARCH_DEFCONFIG
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h
index 86666f70322e..482c79e2a416 100644
--- a/arch/sparc/include/asm/floppy_32.h
+++ b/arch/sparc/include/asm/floppy_32.h
@@ -281,28 +281,27 @@ static inline void sun_fd_enable_dma(void)
281 pdma_areasize = pdma_size; 281 pdma_areasize = pdma_size;
282} 282}
283 283
284/* Our low-level entry point in arch/sparc/kernel/entry.S */ 284extern int sparc_floppy_request_irq(unsigned int irq,
285extern int sparc_floppy_request_irq(int irq, unsigned long flags, 285 irq_handler_t irq_handler);
286 irq_handler_t irq_handler);
287 286
288static int sun_fd_request_irq(void) 287static int sun_fd_request_irq(void)
289{ 288{
290 static int once = 0; 289 static int once = 0;
291 int error;
292 290
293 if(!once) { 291 if (!once) {
294 once = 1; 292 once = 1;
295 error = sparc_floppy_request_irq(FLOPPY_IRQ, 293 return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt);
296 IRQF_DISABLED, 294 } else {
297 floppy_interrupt); 295 return 0;
298 return ((error == 0) ? 0 : -1); 296 }
299 } else return 0;
300} 297}
301 298
302static struct linux_prom_registers fd_regs[2]; 299static struct linux_prom_registers fd_regs[2];
303 300
304static int sun_floppy_init(void) 301static int sun_floppy_init(void)
305{ 302{
303 struct platform_device *op;
304 struct device_node *dp;
306 char state[128]; 305 char state[128];
307 phandle tnode, fd_node; 306 phandle tnode, fd_node;
308 int num_regs; 307 int num_regs;
@@ -310,7 +309,6 @@ static int sun_floppy_init(void)
310 309
311 use_virtual_dma = 1; 310 use_virtual_dma = 1;
312 311
313 FLOPPY_IRQ = 11;
314 /* Forget it if we aren't on a machine that could possibly 312 /* Forget it if we aren't on a machine that could possibly
315 * ever have a floppy drive. 313 * ever have a floppy drive.
316 */ 314 */
@@ -349,6 +347,26 @@ static int sun_floppy_init(void)
349 sun_fdc = (struct sun_flpy_controller *) 347 sun_fdc = (struct sun_flpy_controller *)
350 of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); 348 of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
351 349
350 /* Look up irq in platform_device.
351 * We try "SUNW,fdtwo" and "fd"
352 */
353 for_each_node_by_name(dp, "SUNW,fdtwo") {
354 op = of_find_device_by_node(dp);
355 if (op)
356 break;
357 }
358 if (!op) {
359 for_each_node_by_name(dp, "fd") {
360 op = of_find_device_by_node(dp);
361 if (op)
362 break;
363 }
364 }
365 if (!op)
366 goto no_sun_fdc;
367
368 FLOPPY_IRQ = op->archdata.irqs[0];
369
352 /* Last minute sanity check... */ 370 /* Last minute sanity check... */
353 if(sun_fdc->status_82072 == 0xff) { 371 if(sun_fdc->status_82072 == 0xff) {
354 sun_fdc = NULL; 372 sun_fdc = NULL;
diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h
index eced3e3ebd30..2ae3acaeb1b3 100644
--- a/arch/sparc/include/asm/irq_32.h
+++ b/arch/sparc/include/asm/irq_32.h
@@ -6,7 +6,11 @@
6#ifndef _SPARC_IRQ_H 6#ifndef _SPARC_IRQ_H
7#define _SPARC_IRQ_H 7#define _SPARC_IRQ_H
8 8
9#define NR_IRQS 16 9/* Allocated number of logical irq numbers.
10 * sun4d boxes (ss2000e) should be OK with ~32.
11 * Be on the safe side and make room for 64
12 */
13#define NR_IRQS 64
10 14
11#include <linux/interrupt.h> 15#include <linux/interrupt.h>
12 16
diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h
index 890036b3689a..47a7e862474e 100644
--- a/arch/sparc/include/asm/system_32.h
+++ b/arch/sparc/include/asm/system_32.h
@@ -15,11 +15,6 @@
15 15
16#include <linux/irqflags.h> 16#include <linux/irqflags.h>
17 17
18static inline unsigned int probe_irq_mask(unsigned long val)
19{
20 return 0;
21}
22
23/* 18/*
24 * Sparc (general) CPU types 19 * Sparc (general) CPU types
25 */ 20 */
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 99aa4db6e9c2..9cff2709a96d 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -71,10 +71,6 @@ obj-$(CONFIG_SPARC64) += pcr.o
71obj-$(CONFIG_SPARC64) += nmi.o 71obj-$(CONFIG_SPARC64) += nmi.o
72obj-$(CONFIG_SPARC64_SMP) += cpumap.o 72obj-$(CONFIG_SPARC64_SMP) += cpumap.o
73 73
74# sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation
75obj-$(CONFIG_SPARC32) += devres.o
76devres-y := ../../../kernel/irq/devres.o
77
78obj-y += dma.o 74obj-y += dma.o
79 75
80obj-$(CONFIG_SPARC32_PCI) += pcic.o 76obj-$(CONFIG_SPARC32_PCI) += pcic.o
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 008453b798ec..a189c273f638 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -2,6 +2,23 @@
2 2
3#include <asm/btfixup.h> 3#include <asm/btfixup.h>
4 4
5struct irq_bucket {
6 struct irq_bucket *next;
7 unsigned int real_irq;
8 unsigned int irq;
9 unsigned int pil;
10};
11
12#define SUN4D_MAX_BOARD 10
13#define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5)
14
15/* Map between the irq identifier used in hw to the
16 * irq_bucket. The map is sufficient large to hold
17 * the sun4d hw identifiers.
18 */
19extern struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
20
21
5/* sun4m specific type definitions */ 22/* sun4m specific type definitions */
6 23
7/* This maps direct to CPU specific interrupt registers */ 24/* This maps direct to CPU specific interrupt registers */
@@ -35,6 +52,10 @@ struct sparc_irq_config {
35}; 52};
36extern struct sparc_irq_config sparc_irq_config; 53extern struct sparc_irq_config sparc_irq_config;
37 54
55unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
56void irq_link(unsigned int irq);
57void irq_unlink(unsigned int irq);
58void handler_irq(unsigned int pil, struct pt_regs *regs);
38 59
39/* Dave Redman (djhr@tadpole.co.uk) 60/* Dave Redman (djhr@tadpole.co.uk)
40 * changed these to function pointers.. it saves cycles and will allow 61 * changed these to function pointers.. it saves cycles and will allow
@@ -44,33 +65,9 @@ extern struct sparc_irq_config sparc_irq_config;
44 * Changed these to btfixup entities... It saves cycles :) 65 * Changed these to btfixup entities... It saves cycles :)
45 */ 66 */
46 67
47BTFIXUPDEF_CALL(void, disable_irq, unsigned int)
48BTFIXUPDEF_CALL(void, enable_irq, unsigned int)
49BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int)
50BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int)
51BTFIXUPDEF_CALL(void, clear_clock_irq, void) 68BTFIXUPDEF_CALL(void, clear_clock_irq, void)
52BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) 69BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int)
53 70
54static inline void __disable_irq(unsigned int irq)
55{
56 BTFIXUP_CALL(disable_irq)(irq);
57}
58
59static inline void __enable_irq(unsigned int irq)
60{
61 BTFIXUP_CALL(enable_irq)(irq);
62}
63
64static inline void disable_pil_irq(unsigned int irq)
65{
66 BTFIXUP_CALL(disable_pil_irq)(irq);
67}
68
69static inline void enable_pil_irq(unsigned int irq)
70{
71 BTFIXUP_CALL(enable_pil_irq)(irq);
72}
73
74static inline void clear_clock_irq(void) 71static inline void clear_clock_irq(void)
75{ 72{
76 BTFIXUP_CALL(clear_clock_irq)(); 73 BTFIXUP_CALL(clear_clock_irq)();
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index b2dbb4ba8608..197e1ba85484 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -15,6 +15,7 @@
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16 16
17#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
18#include <asm/cpudata.h>
18#include <asm/pcic.h> 19#include <asm/pcic.h>
19#include <asm/leon.h> 20#include <asm/leon.h>
20 21
@@ -101,284 +102,163 @@ EXPORT_SYMBOL(arch_local_irq_restore);
101 * directed CPU interrupts using the existing enable/disable irq code 102 * directed CPU interrupts using the existing enable/disable irq code
102 * with tweaks. 103 * with tweaks.
103 * 104 *
105 * Sun4d complicates things even further. IRQ numbers are arbitrary
106 * 32-bit values in that case. Since this is similar to sparc64,
107 * we adopt a virtual IRQ numbering scheme as is done there.
108 * Virutal interrupt numbers are allocated by build_irq(). So NR_IRQS
109 * just becomes a limit of how many interrupt sources we can handle in
110 * a single system. Even fully loaded SS2000 machines top off at
111 * about 32 interrupt sources or so, therefore a NR_IRQS value of 64
112 * is more than enough.
113 *
114 * We keep a map of per-PIL enable interrupts. These get wired
115 * up via the irq_chip->startup() method which gets invoked by
116 * the generic IRQ layer during request_irq().
104 */ 117 */
105 118
106 119
120/* Table of allocated irqs. Unused entries has irq == 0 */
121static struct irq_bucket irq_table[NR_IRQS];
122/* Protect access to irq_table */
123static DEFINE_SPINLOCK(irq_table_lock);
107 124
108/* 125/* Map between the irq identifier used in hw to the irq_bucket. */
109 * Dave Redman (djhr@tadpole.co.uk) 126struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
110 * 127/* Protect access to irq_map */
111 * There used to be extern calls and hard coded values here.. very sucky! 128static DEFINE_SPINLOCK(irq_map_lock);
112 * instead, because some of the devices attach very early, I do something
113 * equally sucky but at least we'll never try to free statically allocated
114 * space or call kmalloc before kmalloc_init :(.
115 *
116 * In fact it's the timer10 that attaches first.. then timer14
117 * then kmalloc_init is called.. then the tty interrupts attach.
118 * hmmm....
119 *
120 */
121#define MAX_STATIC_ALLOC 4
122struct irqaction static_irqaction[MAX_STATIC_ALLOC];
123int static_irq_count;
124
125static struct {
126 struct irqaction *action;
127 int flags;
128} sparc_irq[NR_IRQS];
129#define SPARC_IRQ_INPROGRESS 1
130
131/* Used to protect the IRQ action lists */
132DEFINE_SPINLOCK(irq_action_lock);
133 129
134int show_interrupts(struct seq_file *p, void *v) 130/* Allocate a new irq from the irq_table */
131unsigned int irq_alloc(unsigned int real_irq, unsigned int pil)
135{ 132{
136 int i = *(loff_t *)v;
137 struct irqaction *action;
138 unsigned long flags; 133 unsigned long flags;
139#ifdef CONFIG_SMP 134 unsigned int i;
140 int j; 135
141#endif 136 spin_lock_irqsave(&irq_table_lock, flags);
137 for (i = 1; i < NR_IRQS; i++) {
138 if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil)
139 goto found;
140 }
142 141
143 if (sparc_cpu_model == sun4d) 142 for (i = 1; i < NR_IRQS; i++) {
144 return show_sun4d_interrupts(p, v); 143 if (!irq_table[i].irq)
144 break;
145 }
145 146
146 spin_lock_irqsave(&irq_action_lock, flags);
147 if (i < NR_IRQS) { 147 if (i < NR_IRQS) {
148 action = sparc_irq[i].action; 148 irq_table[i].real_irq = real_irq;
149 if (!action) 149 irq_table[i].irq = i;
150 goto out_unlock; 150 irq_table[i].pil = pil;
151 seq_printf(p, "%3d: ", i); 151 } else {
152#ifndef CONFIG_SMP 152 printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
153 seq_printf(p, "%10u ", kstat_irqs(i)); 153 i = 0;
154#else
155 for_each_online_cpu(j) {
156 seq_printf(p, "%10u ",
157 kstat_cpu(j).irqs[i]);
158 }
159#endif
160 seq_printf(p, " %c %s",
161 (action->flags & IRQF_DISABLED) ? '+' : ' ',
162 action->name);
163 for (action = action->next; action; action = action->next) {
164 seq_printf(p, ",%s %s",
165 (action->flags & IRQF_DISABLED) ? " +" : "",
166 action->name);
167 }
168 seq_putc(p, '\n');
169 } 154 }
170out_unlock: 155found:
171 spin_unlock_irqrestore(&irq_action_lock, flags); 156 spin_unlock_irqrestore(&irq_table_lock, flags);
172 return 0; 157
158 return i;
173} 159}
174 160
175void free_irq(unsigned int irq, void *dev_id) 161/* Based on a single pil handler_irq may need to call several
162 * interrupt handlers. Use irq_map as entry to irq_table,
163 * and let each entry in irq_table point to the next entry.
164 */
165void irq_link(unsigned int irq)
176{ 166{
177 struct irqaction *action; 167 struct irq_bucket *p;
178 struct irqaction **actionp;
179 unsigned long flags; 168 unsigned long flags;
180 unsigned int cpu_irq; 169 unsigned int pil;
181 170
182 if (sparc_cpu_model == sun4d) { 171 BUG_ON(irq >= NR_IRQS);
183 sun4d_free_irq(irq, dev_id);
184 return;
185 }
186 cpu_irq = irq & (NR_IRQS - 1);
187 if (cpu_irq > 14) { /* 14 irq levels on the sparc */
188 printk(KERN_ERR "Trying to free bogus IRQ %d\n", irq);
189 return;
190 }
191 172
192 spin_lock_irqsave(&irq_action_lock, flags); 173 spin_lock_irqsave(&irq_map_lock, flags);
193 174
194 actionp = &sparc_irq[cpu_irq].action; 175 p = &irq_table[irq];
195 action = *actionp; 176 pil = p->pil;
177 BUG_ON(pil > SUN4D_MAX_IRQ);
178 p->next = irq_map[pil];
179 irq_map[pil] = p;
196 180
197 if (!action->handler) { 181 spin_unlock_irqrestore(&irq_map_lock, flags);
198 printk(KERN_ERR "Trying to free free IRQ%d\n", irq); 182}
199 goto out_unlock;
200 }
201 if (dev_id) {
202 for (; action; action = action->next) {
203 if (action->dev_id == dev_id)
204 break;
205 actionp = &action->next;
206 }
207 if (!action) {
208 printk(KERN_ERR "Trying to free free shared IRQ%d\n",
209 irq);
210 goto out_unlock;
211 }
212 } else if (action->flags & IRQF_SHARED) {
213 printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
214 irq);
215 goto out_unlock;
216 }
217 if (action->flags & SA_STATIC_ALLOC) {
218 /*
219 * This interrupt is marked as specially allocated
220 * so it is a bad idea to free it.
221 */
222 printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
223 irq, action->name);
224 goto out_unlock;
225 }
226
227 *actionp = action->next;
228
229 spin_unlock_irqrestore(&irq_action_lock, flags);
230 183
231 synchronize_irq(irq); 184void irq_unlink(unsigned int irq)
185{
186 struct irq_bucket *p, **pnext;
187 unsigned long flags;
232 188
233 spin_lock_irqsave(&irq_action_lock, flags); 189 BUG_ON(irq >= NR_IRQS);
234 190
235 kfree(action); 191 spin_lock_irqsave(&irq_map_lock, flags);
236 192
237 if (!sparc_irq[cpu_irq].action) 193 p = &irq_table[irq];
238 __disable_irq(irq); 194 BUG_ON(p->pil > SUN4D_MAX_IRQ);
195 pnext = &irq_map[p->pil];
196 while (*pnext != p)
197 pnext = &(*pnext)->next;
198 *pnext = p->next;
239 199
240out_unlock: 200 spin_unlock_irqrestore(&irq_map_lock, flags);
241 spin_unlock_irqrestore(&irq_action_lock, flags);
242} 201}
243EXPORT_SYMBOL(free_irq);
244 202
245/*
246 * This is called when we want to synchronize with
247 * interrupts. We may for example tell a device to
248 * stop sending interrupts: but to make sure there
249 * are no interrupts that are executing on another
250 * CPU we need to call this function.
251 */
252#ifdef CONFIG_SMP
253void synchronize_irq(unsigned int irq)
254{
255 unsigned int cpu_irq;
256 203
257 cpu_irq = irq & (NR_IRQS - 1); 204/* /proc/interrupts printing */
258 while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS) 205int arch_show_interrupts(struct seq_file *p, int prec)
259 cpu_relax();
260}
261EXPORT_SYMBOL(synchronize_irq);
262#endif /* SMP */
263
264void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs)
265{ 206{
266 int i; 207 int j;
267 struct irqaction *action;
268 unsigned int cpu_irq;
269 208
270 cpu_irq = irq & (NR_IRQS - 1); 209 seq_printf(p, "NMI: ");
271 action = sparc_irq[cpu_irq].action; 210 for_each_online_cpu(j)
272 211 seq_printf(p, "%10u ", cpu_data(j).counter);
273 printk(KERN_ERR "IO device interrupt, irq = %d\n", irq); 212 seq_printf(p, " Non-maskable interrupts\n");
274 printk(KERN_ERR "PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 213 return 0;
275 regs->npc, regs->u_regs[14]);
276 if (action) {
277 printk(KERN_ERR "Expecting: ");
278 for (i = 0; i < 16; i++)
279 if (action->handler)
280 printk(KERN_CONT "[%s:%d:0x%x] ", action->name,
281 i, (unsigned int)action->handler);
282 }
283 printk(KERN_ERR "AIEEE\n");
284 panic("bogus interrupt received");
285} 214}
286 215
287void handler_irq(int pil, struct pt_regs *regs) 216void handler_irq(unsigned int pil, struct pt_regs *regs)
288{ 217{
289 struct pt_regs *old_regs; 218 struct pt_regs *old_regs;
290 struct irqaction *action; 219 struct irq_bucket *p;
291 int cpu = smp_processor_id();
292 220
221 BUG_ON(pil > 15);
293 old_regs = set_irq_regs(regs); 222 old_regs = set_irq_regs(regs);
294 irq_enter(); 223 irq_enter();
295 disable_pil_irq(pil); 224
296#ifdef CONFIG_SMP 225 p = irq_map[pil];
297 /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ 226 while (p) {
298 if ((sparc_cpu_model==sun4m) && (pil < 10)) 227 struct irq_bucket *next = p->next;
299 smp4m_irq_rotate(cpu); 228
300#endif 229 generic_handle_irq(p->irq);
301 action = sparc_irq[pil].action; 230 p = next;
302 sparc_irq[pil].flags |= SPARC_IRQ_INPROGRESS; 231 }
303 kstat_cpu(cpu).irqs[pil]++;
304 do {
305 if (!action || !action->handler)
306 unexpected_irq(pil, NULL, regs);
307 action->handler(pil, action->dev_id);
308 action = action->next;
309 } while (action);
310 sparc_irq[pil].flags &= ~SPARC_IRQ_INPROGRESS;
311 enable_pil_irq(pil);
312 irq_exit(); 232 irq_exit();
313 set_irq_regs(old_regs); 233 set_irq_regs(old_regs);
314} 234}
315 235
316#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) 236#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
237static unsigned int floppy_irq;
317 238
318/* 239int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
319 * Fast IRQs on the Sparc can only have one routine attached to them,
320 * thus no sharing possible.
321 */
322static int request_fast_irq(unsigned int irq,
323 void (*handler)(void),
324 unsigned long irqflags, const char *devname)
325{ 240{
326 struct irqaction *action;
327 unsigned long flags;
328 unsigned int cpu_irq; 241 unsigned int cpu_irq;
329 int ret; 242 int err;
243
330#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON 244#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
331 struct tt_entry *trap_table; 245 struct tt_entry *trap_table;
332#endif 246#endif
333 cpu_irq = irq & (NR_IRQS - 1);
334 if (cpu_irq > 14) {
335 ret = -EINVAL;
336 goto out;
337 }
338 if (!handler) {
339 ret = -EINVAL;
340 goto out;
341 }
342 247
343 spin_lock_irqsave(&irq_action_lock, flags); 248 err = request_irq(irq, irq_handler, 0, "floppy", NULL);
249 if (err)
250 return -1;
344 251
345 action = sparc_irq[cpu_irq].action; 252 /* Save for later use in floppy interrupt handler */
346 if (action) { 253 floppy_irq = irq;
347 if (action->flags & IRQF_SHARED)
348 panic("Trying to register fast irq when already shared.\n");
349 if (irqflags & IRQF_SHARED)
350 panic("Trying to register fast irq as shared.\n");
351 254
352 /* Anyway, someone already owns it so cannot be made fast. */ 255 cpu_irq = (irq & (NR_IRQS - 1));
353 printk(KERN_ERR "request_fast_irq: Trying to register yet already owned.\n");
354 ret = -EBUSY;
355 goto out_unlock;
356 }
357
358 /*
359 * If this is flagged as statically allocated then we use our
360 * private struct which is never freed.
361 */
362 if (irqflags & SA_STATIC_ALLOC) {
363 if (static_irq_count < MAX_STATIC_ALLOC)
364 action = &static_irqaction[static_irq_count++];
365 else
366 printk(KERN_ERR "Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
367 irq, devname);
368 }
369
370 if (action == NULL)
371 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
372 if (!action) {
373 ret = -ENOMEM;
374 goto out_unlock;
375 }
376 256
377 /* Dork with trap table if we get this far. */ 257 /* Dork with trap table if we get this far. */
378#define INSTANTIATE(table) \ 258#define INSTANTIATE(table) \
379 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \ 259 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
380 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \ 260 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
381 SPARC_BRANCH((unsigned long) handler, \ 261 SPARC_BRANCH((unsigned long) floppy_hardint, \
382 (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\ 262 (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
383 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \ 263 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
384 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP; 264 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
@@ -399,22 +279,9 @@ static int request_fast_irq(unsigned int irq,
399 * writing we have no CPU-neutral interface to fine-grained flushes. 279 * writing we have no CPU-neutral interface to fine-grained flushes.
400 */ 280 */
401 flush_cache_all(); 281 flush_cache_all();
402 282 return 0;
403 action->flags = irqflags;
404 action->name = devname;
405 action->dev_id = NULL;
406 action->next = NULL;
407
408 sparc_irq[cpu_irq].action = action;
409
410 __enable_irq(irq);
411
412 ret = 0;
413out_unlock:
414 spin_unlock_irqrestore(&irq_action_lock, flags);
415out:
416 return ret;
417} 283}
284EXPORT_SYMBOL(sparc_floppy_request_irq);
418 285
419/* 286/*
420 * These variables are used to access state from the assembler 287 * These variables are used to access state from the assembler
@@ -440,154 +307,23 @@ EXPORT_SYMBOL(pdma_base);
440unsigned long pdma_areasize; 307unsigned long pdma_areasize;
441EXPORT_SYMBOL(pdma_areasize); 308EXPORT_SYMBOL(pdma_areasize);
442 309
443static irq_handler_t floppy_irq_handler; 310/* Use the generic irq support to call floppy_interrupt
444 311 * which was setup using request_irq() in sparc_floppy_request_irq().
312 * We only have one floppy interrupt so we do not need to check
313 * for additional handlers being wired up by irq_link()
314 */
445void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) 315void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
446{ 316{
447 struct pt_regs *old_regs; 317 struct pt_regs *old_regs;
448 int cpu = smp_processor_id();
449 318
450 old_regs = set_irq_regs(regs); 319 old_regs = set_irq_regs(regs);
451 disable_pil_irq(irq);
452 irq_enter(); 320 irq_enter();
453 kstat_cpu(cpu).irqs[irq]++; 321 generic_handle_irq(floppy_irq);
454 floppy_irq_handler(irq, dev_id);
455 irq_exit(); 322 irq_exit();
456 enable_pil_irq(irq);
457 set_irq_regs(old_regs); 323 set_irq_regs(old_regs);
458 /*
459 * XXX Eek, it's totally changed with preempt_count() and such
460 * if (softirq_pending(cpu))
461 * do_softirq();
462 */
463} 324}
464
465int sparc_floppy_request_irq(int irq, unsigned long flags,
466 irq_handler_t irq_handler)
467{
468 floppy_irq_handler = irq_handler;
469 return request_fast_irq(irq, floppy_hardint, flags, "floppy");
470}
471EXPORT_SYMBOL(sparc_floppy_request_irq);
472
473#endif 325#endif
474 326
475int request_irq(unsigned int irq,
476 irq_handler_t handler,
477 unsigned long irqflags, const char *devname, void *dev_id)
478{
479 struct irqaction *action, **actionp;
480 unsigned long flags;
481 unsigned int cpu_irq;
482 int ret;
483
484 if (sparc_cpu_model == sun4d)
485 return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
486
487 cpu_irq = irq & (NR_IRQS - 1);
488 if (cpu_irq > 14) {
489 ret = -EINVAL;
490 goto out;
491 }
492 if (!handler) {
493 ret = -EINVAL;
494 goto out;
495 }
496
497 spin_lock_irqsave(&irq_action_lock, flags);
498
499 actionp = &sparc_irq[cpu_irq].action;
500 action = *actionp;
501 if (action) {
502 if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) {
503 ret = -EBUSY;
504 goto out_unlock;
505 }
506 if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
507 printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
508 irq);
509 ret = -EBUSY;
510 goto out_unlock;
511 }
512 for ( ; action; action = *actionp)
513 actionp = &action->next;
514 }
515
516 /* If this is flagged as statically allocated then we use our
517 * private struct which is never freed.
518 */
519 if (irqflags & SA_STATIC_ALLOC) {
520 if (static_irq_count < MAX_STATIC_ALLOC)
521 action = &static_irqaction[static_irq_count++];
522 else
523 printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
524 irq, devname);
525 }
526 if (action == NULL)
527 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
528 if (!action) {
529 ret = -ENOMEM;
530 goto out_unlock;
531 }
532
533 action->handler = handler;
534 action->flags = irqflags;
535 action->name = devname;
536 action->next = NULL;
537 action->dev_id = dev_id;
538
539 *actionp = action;
540
541 __enable_irq(irq);
542
543 ret = 0;
544out_unlock:
545 spin_unlock_irqrestore(&irq_action_lock, flags);
546out:
547 return ret;
548}
549EXPORT_SYMBOL(request_irq);
550
551void disable_irq_nosync(unsigned int irq)
552{
553 __disable_irq(irq);
554}
555EXPORT_SYMBOL(disable_irq_nosync);
556
557void disable_irq(unsigned int irq)
558{
559 __disable_irq(irq);
560}
561EXPORT_SYMBOL(disable_irq);
562
563void enable_irq(unsigned int irq)
564{
565 __enable_irq(irq);
566}
567EXPORT_SYMBOL(enable_irq);
568
569/*
570 * We really don't need these at all on the Sparc. We only have
571 * stubs here because they are exported to modules.
572 */
573unsigned long probe_irq_on(void)
574{
575 return 0;
576}
577EXPORT_SYMBOL(probe_irq_on);
578
579int probe_irq_off(unsigned long mask)
580{
581 return 0;
582}
583EXPORT_SYMBOL(probe_irq_off);
584
585static unsigned int build_device_irq(struct platform_device *op,
586 unsigned int real_irq)
587{
588 return real_irq;
589}
590
591/* djhr 327/* djhr
592 * This could probably be made indirect too and assigned in the CPU 328 * This could probably be made indirect too and assigned in the CPU
593 * bits of the code. That would be much nicer I think and would also 329 * bits of the code. That would be much nicer I think and would also
@@ -598,8 +334,6 @@ static unsigned int build_device_irq(struct platform_device *op,
598 334
599void __init init_IRQ(void) 335void __init init_IRQ(void)
600{ 336{
601 sparc_irq_config.build_device_irq = build_device_irq;
602
603 switch (sparc_cpu_model) { 337 switch (sparc_cpu_model) {
604 case sun4c: 338 case sun4c:
605 case sun4: 339 case sun4:
@@ -629,9 +363,3 @@ void __init init_IRQ(void)
629 btfixup(); 363 btfixup();
630} 364}
631 365
632#ifdef CONFIG_PROC_FS
633void init_irq_proc(void)
634{
635 /* For now, nothing... */
636}
637#endif /* CONFIG_PROC_FS */
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 24ad449886be..487d67a4e7f6 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -37,6 +37,7 @@ extern void sun4c_init_IRQ(void);
37extern unsigned int lvl14_resolution; 37extern unsigned int lvl14_resolution;
38 38
39extern void sun4m_init_IRQ(void); 39extern void sun4m_init_IRQ(void);
40extern void sun4m_unmask_profile_irq(void);
40extern void sun4m_clear_profile_irq(int cpu); 41extern void sun4m_clear_profile_irq(int cpu);
41 42
42/* sun4d_irq.c */ 43/* sun4d_irq.c */
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 2969f777fa11..8591cf124ecf 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -83,20 +83,22 @@ static inline unsigned long get_irqmask(unsigned int irq)
83 return mask; 83 return mask;
84} 84}
85 85
86static void leon_enable_irq(unsigned int irq_nr) 86static void leon_unmask_irq(struct irq_data *data)
87{ 87{
88 unsigned long mask, flags; 88 unsigned long mask, flags;
89 mask = get_irqmask(irq_nr); 89
90 mask = (unsigned long)data->chip_data;
90 local_irq_save(flags); 91 local_irq_save(flags);
91 LEON3_BYPASS_STORE_PA(LEON_IMASK, 92 LEON3_BYPASS_STORE_PA(LEON_IMASK,
92 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); 93 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask)));
93 local_irq_restore(flags); 94 local_irq_restore(flags);
94} 95}
95 96
96static void leon_disable_irq(unsigned int irq_nr) 97static void leon_mask_irq(struct irq_data *data)
97{ 98{
98 unsigned long mask, flags; 99 unsigned long mask, flags;
99 mask = get_irqmask(irq_nr); 100
101 mask = (unsigned long)data->chip_data;
100 local_irq_save(flags); 102 local_irq_save(flags);
101 LEON3_BYPASS_STORE_PA(LEON_IMASK, 103 LEON3_BYPASS_STORE_PA(LEON_IMASK,
102 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); 104 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask)));
@@ -104,6 +106,50 @@ static void leon_disable_irq(unsigned int irq_nr)
104 106
105} 107}
106 108
109static unsigned int leon_startup_irq(struct irq_data *data)
110{
111 irq_link(data->irq);
112 leon_unmask_irq(data);
113 return 0;
114}
115
116static void leon_shutdown_irq(struct irq_data *data)
117{
118 leon_mask_irq(data);
119 irq_unlink(data->irq);
120}
121
122static struct irq_chip leon_irq = {
123 .name = "leon",
124 .irq_startup = leon_startup_irq,
125 .irq_shutdown = leon_shutdown_irq,
126 .irq_mask = leon_mask_irq,
127 .irq_unmask = leon_unmask_irq,
128};
129
130static unsigned int leon_build_device_irq(struct platform_device *op,
131 unsigned int real_irq)
132{
133 unsigned int irq;
134 unsigned long mask;
135
136 irq = 0;
137 mask = get_irqmask(real_irq);
138 if (mask == 0)
139 goto out;
140
141 irq = irq_alloc(real_irq, real_irq);
142 if (irq == 0)
143 goto out;
144
145 irq_set_chip_and_handler_name(irq, &leon_irq,
146 handle_simple_irq, "edge");
147 irq_set_chip_data(irq, (void *)mask);
148
149out:
150 return irq;
151}
152
107void __init leon_init_timers(irq_handler_t counter_fn) 153void __init leon_init_timers(irq_handler_t counter_fn)
108{ 154{
109 int irq; 155 int irq;
@@ -112,6 +158,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
112 int len; 158 int len;
113 int cpu, icsel; 159 int cpu, icsel;
114 int ampopts; 160 int ampopts;
161 int err;
115 162
116 leondebug_irq_disable = 0; 163 leondebug_irq_disable = 0;
117 leon_debug_irqout = 0; 164 leon_debug_irqout = 0;
@@ -219,11 +266,10 @@ void __init leon_init_timers(irq_handler_t counter_fn)
219 goto bad; 266 goto bad;
220 } 267 }
221 268
222 irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, 269 irq = leon_build_device_irq(NULL, leon3_gptimer_irq + leon3_gptimer_idx);
223 counter_fn, 270 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
224 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
225 271
226 if (irq) { 272 if (err) {
227 printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", 273 printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n",
228 LEON_INTERRUPT_TIMER1); 274 LEON_INTERRUPT_TIMER1);
229 prom_halt(); 275 prom_halt();
@@ -347,12 +393,8 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
347 393
348void __init leon_init_IRQ(void) 394void __init leon_init_IRQ(void)
349{ 395{
350 sparc_irq_config.init_timers = leon_init_timers; 396 sparc_irq_config.init_timers = leon_init_timers;
351 397 sparc_irq_config.build_device_irq = leon_build_device_irq;
352 BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM);
353 BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM);
354 BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM);
355 BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM);
356 398
357 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, 399 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq,
358 BTFIXUPCALL_NORM); 400 BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 2cdc131b50ac..948601a066ff 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -164,6 +164,9 @@ void __iomem *pcic_regs;
164volatile int pcic_speculative; 164volatile int pcic_speculative;
165volatile int pcic_trapped; 165volatile int pcic_trapped;
166 166
167/* forward */
168unsigned int pcic_build_device_irq(struct platform_device *op,
169 unsigned int real_irq);
167 170
168#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) 171#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
169 172
@@ -523,6 +526,7 @@ static void
523pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) 526pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
524{ 527{
525 struct pcic_ca2irq *p; 528 struct pcic_ca2irq *p;
529 unsigned int real_irq;
526 int i, ivec; 530 int i, ivec;
527 char namebuf[64]; 531 char namebuf[64];
528 532
@@ -551,26 +555,25 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
551 i = p->pin; 555 i = p->pin;
552 if (i >= 0 && i < 4) { 556 if (i >= 0 && i < 4) {
553 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); 557 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
554 dev->irq = ivec >> (i << 2) & 0xF; 558 real_irq = ivec >> (i << 2) & 0xF;
555 } else if (i >= 4 && i < 8) { 559 } else if (i >= 4 && i < 8) {
556 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); 560 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
557 dev->irq = ivec >> ((i-4) << 2) & 0xF; 561 real_irq = ivec >> ((i-4) << 2) & 0xF;
558 } else { /* Corrupted map */ 562 } else { /* Corrupted map */
559 printk("PCIC: BAD PIN %d\n", i); for (;;) {} 563 printk("PCIC: BAD PIN %d\n", i); for (;;) {}
560 } 564 }
561/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ 565/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */
562 566
563 /* 567 /* real_irq means PROM did not bother to program the upper
564 * dev->irq=0 means PROM did not bother to program the upper
565 * half of PCIC. This happens on JS-E with PROM 3.11, for instance. 568 * half of PCIC. This happens on JS-E with PROM 3.11, for instance.
566 */ 569 */
567 if (dev->irq == 0 || p->force) { 570 if (real_irq == 0 || p->force) {
568 if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ 571 if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
569 printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} 572 printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
570 } 573 }
571 printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", 574 printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",
572 p->irq, p->pin, dev->bus->number, dev->devfn); 575 p->irq, p->pin, dev->bus->number, dev->devfn);
573 dev->irq = p->irq; 576 real_irq = p->irq;
574 577
575 i = p->pin; 578 i = p->pin;
576 if (i >= 4) { 579 if (i >= 4) {
@@ -584,7 +587,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
584 ivec |= p->irq << (i << 2); 587 ivec |= p->irq << (i << 2);
585 writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); 588 writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO);
586 } 589 }
587 } 590 }
591 dev->irq = pcic_build_device_irq(NULL, real_irq);
588} 592}
589 593
590/* 594/*
@@ -729,6 +733,7 @@ void __init pci_time_init(void)
729 struct linux_pcic *pcic = &pcic0; 733 struct linux_pcic *pcic = &pcic0;
730 unsigned long v; 734 unsigned long v;
731 int timer_irq, irq; 735 int timer_irq, irq;
736 int err;
732 737
733 do_arch_gettimeoffset = pci_gettimeoffset; 738 do_arch_gettimeoffset = pci_gettimeoffset;
734 739
@@ -740,9 +745,10 @@ void __init pci_time_init(void)
740 timer_irq = PCI_COUNTER_IRQ_SYS(v); 745 timer_irq = PCI_COUNTER_IRQ_SYS(v);
741 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), 746 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
742 pcic->pcic_regs+PCI_COUNTER_IRQ); 747 pcic->pcic_regs+PCI_COUNTER_IRQ);
743 irq = request_irq(timer_irq, pcic_timer_handler, 748 irq = pcic_build_device_irq(NULL, timer_irq);
744 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 749 err = request_irq(irq, pcic_timer_handler,
745 if (irq) { 750 IRQF_TIMER, "timer", NULL);
751 if (err) {
746 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); 752 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
747 prom_halt(); 753 prom_halt();
748 } 754 }
@@ -803,50 +809,73 @@ static inline unsigned long get_irqmask(int irq_nr)
803 return 1 << irq_nr; 809 return 1 << irq_nr;
804} 810}
805 811
806static void pcic_disable_irq(unsigned int irq_nr) 812static void pcic_mask_irq(struct irq_data *data)
807{ 813{
808 unsigned long mask, flags; 814 unsigned long mask, flags;
809 815
810 mask = get_irqmask(irq_nr); 816 mask = (unsigned long)data->chip_data;
811 local_irq_save(flags); 817 local_irq_save(flags);
812 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); 818 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
813 local_irq_restore(flags); 819 local_irq_restore(flags);
814} 820}
815 821
816static void pcic_enable_irq(unsigned int irq_nr) 822static void pcic_unmask_irq(struct irq_data *data)
817{ 823{
818 unsigned long mask, flags; 824 unsigned long mask, flags;
819 825
820 mask = get_irqmask(irq_nr); 826 mask = (unsigned long)data->chip_data;
821 local_irq_save(flags); 827 local_irq_save(flags);
822 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); 828 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
823 local_irq_restore(flags); 829 local_irq_restore(flags);
824} 830}
825 831
826static void pcic_load_profile_irq(int cpu, unsigned int limit) 832static unsigned int pcic_startup_irq(struct irq_data *data)
827{ 833{
828 printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); 834 irq_link(data->irq);
835 pcic_unmask_irq(data);
836 return 0;
829} 837}
830 838
831/* We assume the caller has disabled local interrupts when these are called, 839static struct irq_chip pcic_irq = {
832 * or else very bizarre behavior will result. 840 .name = "pcic",
833 */ 841 .irq_startup = pcic_startup_irq,
834static void pcic_disable_pil_irq(unsigned int pil) 842 .irq_mask = pcic_mask_irq,
843 .irq_unmask = pcic_unmask_irq,
844};
845
846unsigned int pcic_build_device_irq(struct platform_device *op,
847 unsigned int real_irq)
835{ 848{
836 writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); 849 unsigned int irq;
850 unsigned long mask;
851
852 irq = 0;
853 mask = get_irqmask(real_irq);
854 if (mask == 0)
855 goto out;
856
857 irq = irq_alloc(real_irq, real_irq);
858 if (irq == 0)
859 goto out;
860
861 irq_set_chip_and_handler_name(irq, &pcic_irq,
862 handle_level_irq, "PCIC");
863 irq_set_chip_data(irq, (void *)mask);
864
865out:
866 return irq;
837} 867}
838 868
839static void pcic_enable_pil_irq(unsigned int pil) 869
870static void pcic_load_profile_irq(int cpu, unsigned int limit)
840{ 871{
841 writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); 872 printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);
842} 873}
843 874
844void __init sun4m_pci_init_IRQ(void) 875void __init sun4m_pci_init_IRQ(void)
845{ 876{
846 BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); 877 sparc_irq_config.build_device_irq = pcic_build_device_irq;
847 BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM); 878
848 BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM);
849 BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM);
850 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); 879 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
851 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); 880 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
852} 881}
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 90eea38ad66f..f6bf25a2ff80 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -65,62 +65,94 @@
65 */ 65 */
66unsigned char __iomem *interrupt_enable; 66unsigned char __iomem *interrupt_enable;
67 67
68static void sun4c_disable_irq(unsigned int irq_nr) 68static void sun4c_mask_irq(struct irq_data *data)
69{ 69{
70 unsigned long flags; 70 unsigned long mask = (unsigned long)data->chip_data;
71 unsigned char current_mask, new_mask; 71
72 72 if (mask) {
73 local_irq_save(flags); 73 unsigned long flags;
74 irq_nr &= (NR_IRQS - 1); 74
75 current_mask = sbus_readb(interrupt_enable); 75 local_irq_save(flags);
76 switch (irq_nr) { 76 mask = sbus_readb(interrupt_enable) & ~mask;
77 case 1: 77 sbus_writeb(mask, interrupt_enable);
78 new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
79 break;
80 case 8:
81 new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
82 break;
83 case 10:
84 new_mask = ((current_mask) & (~(SUN4C_INT_E10)));
85 break;
86 case 14:
87 new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
88 break;
89 default:
90 local_irq_restore(flags); 78 local_irq_restore(flags);
91 return;
92 } 79 }
93 sbus_writeb(new_mask, interrupt_enable);
94 local_irq_restore(flags);
95} 80}
96 81
97static void sun4c_enable_irq(unsigned int irq_nr) 82static void sun4c_unmask_irq(struct irq_data *data)
98{ 83{
99 unsigned long flags; 84 unsigned long mask = (unsigned long)data->chip_data;
100 unsigned char current_mask, new_mask; 85
101 86 if (mask) {
102 local_irq_save(flags); 87 unsigned long flags;
103 irq_nr &= (NR_IRQS - 1); 88
104 current_mask = sbus_readb(interrupt_enable); 89 local_irq_save(flags);
105 switch (irq_nr) { 90 mask = sbus_readb(interrupt_enable) | mask;
106 case 1: 91 sbus_writeb(mask, interrupt_enable);
107 new_mask = ((current_mask) | SUN4C_INT_E1);
108 break;
109 case 8:
110 new_mask = ((current_mask) | SUN4C_INT_E8);
111 break;
112 case 10:
113 new_mask = ((current_mask) | SUN4C_INT_E10);
114 break;
115 case 14:
116 new_mask = ((current_mask) | SUN4C_INT_E14);
117 break;
118 default:
119 local_irq_restore(flags); 92 local_irq_restore(flags);
120 return;
121 } 93 }
122 sbus_writeb(new_mask, interrupt_enable); 94}
123 local_irq_restore(flags); 95
96static unsigned int sun4c_startup_irq(struct irq_data *data)
97{
98 irq_link(data->irq);
99 sun4c_unmask_irq(data);
100
101 return 0;
102}
103
104static void sun4c_shutdown_irq(struct irq_data *data)
105{
106 sun4c_mask_irq(data);
107 irq_unlink(data->irq);
108}
109
110static struct irq_chip sun4c_irq = {
111 .name = "sun4c",
112 .irq_startup = sun4c_startup_irq,
113 .irq_shutdown = sun4c_shutdown_irq,
114 .irq_mask = sun4c_mask_irq,
115 .irq_unmask = sun4c_unmask_irq,
116};
117
118static unsigned int sun4c_build_device_irq(struct platform_device *op,
119 unsigned int real_irq)
120{
121 unsigned int irq;
122
123 if (real_irq >= 16) {
124 prom_printf("Bogus sun4c IRQ %u\n", real_irq);
125 prom_halt();
126 }
127
128 irq = irq_alloc(real_irq, real_irq);
129 if (irq) {
130 unsigned long mask = 0UL;
131
132 switch (real_irq) {
133 case 1:
134 mask = SUN4C_INT_E1;
135 break;
136 case 8:
137 mask = SUN4C_INT_E8;
138 break;
139 case 10:
140 mask = SUN4C_INT_E10;
141 break;
142 case 14:
143 mask = SUN4C_INT_E14;
144 break;
145 default:
146 /* All the rest are either always enabled,
147 * or are for signalling software interrupts.
148 */
149 break;
150 }
151 irq_set_chip_and_handler_name(irq, &sun4c_irq,
152 handle_level_irq, "level");
153 irq_set_chip_data(irq, (void *)mask);
154 }
155 return irq;
124} 156}
125 157
126struct sun4c_timer_info { 158struct sun4c_timer_info {
@@ -144,8 +176,9 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit)
144 176
145static void __init sun4c_init_timers(irq_handler_t counter_fn) 177static void __init sun4c_init_timers(irq_handler_t counter_fn)
146{ 178{
147 const struct linux_prom_irqs *irq; 179 const struct linux_prom_irqs *prom_irqs;
148 struct device_node *dp; 180 struct device_node *dp;
181 unsigned int irq;
149 const u32 *addr; 182 const u32 *addr;
150 int err; 183 int err;
151 184
@@ -163,9 +196,9 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
163 196
164 sun4c_timers = (void __iomem *) (unsigned long) addr[0]; 197 sun4c_timers = (void __iomem *) (unsigned long) addr[0];
165 198
166 irq = of_get_property(dp, "intr", NULL); 199 prom_irqs = of_get_property(dp, "intr", NULL);
167 of_node_put(dp); 200 of_node_put(dp);
168 if (!irq) { 201 if (!prom_irqs) {
169 prom_printf("sun4c_init_timers: No intr property\n"); 202 prom_printf("sun4c_init_timers: No intr property\n");
170 prom_halt(); 203 prom_halt();
171 } 204 }
@@ -178,15 +211,15 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
178 211
179 master_l10_counter = &sun4c_timers->l10_count; 212 master_l10_counter = &sun4c_timers->l10_count;
180 213
181 err = request_irq(irq[0].pri, counter_fn, 214 irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
182 (IRQF_DISABLED | SA_STATIC_ALLOC), 215 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
183 "timer", NULL);
184 if (err) { 216 if (err) {
185 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); 217 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
186 prom_halt(); 218 prom_halt();
187 } 219 }
188 220
189 sun4c_disable_irq(irq[1].pri); 221 /* disable timer interrupt */
222 sun4c_mask_irq(irq_get_irq_data(irq));
190} 223}
191 224
192#ifdef CONFIG_SMP 225#ifdef CONFIG_SMP
@@ -215,14 +248,11 @@ void __init sun4c_init_IRQ(void)
215 248
216 interrupt_enable = (void __iomem *) (unsigned long) addr[0]; 249 interrupt_enable = (void __iomem *) (unsigned long) addr[0];
217 250
218 BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
219 BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
220 BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
221 BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
222 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); 251 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
223 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); 252 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
224 253
225 sparc_irq_config.init_timers = sun4c_init_timers; 254 sparc_irq_config.init_timers = sun4c_init_timers;
255 sparc_irq_config.build_device_irq = sun4c_build_device_irq;
226 256
227#ifdef CONFIG_SMP 257#ifdef CONFIG_SMP
228 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); 258 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index ee35c45ffb89..14a043531dcb 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -22,22 +22,20 @@
22 * cpu local. CPU local interrupts cover the timer interrupts 22 * cpu local. CPU local interrupts cover the timer interrupts
23 * and whatnot, and we encode those as normal PILs between 23 * and whatnot, and we encode those as normal PILs between
24 * 0 and 15. 24 * 0 and 15.
25 * 25 * SBUS interrupts are encodes as a combination of board, level and slot.
26 * SBUS interrupts are encoded integers including the board number
27 * (plus one), the SBUS level, and the SBUS slot number. Sun4D
28 * IRQ dispatch is done by:
29 *
30 * 1) Reading the BW local interrupt table in order to get the bus
31 * interrupt mask.
32 *
33 * This table is indexed by SBUS interrupt level which can be
34 * derived from the PIL we got interrupted on.
35 *
36 * 2) For each bus showing interrupt pending from #1, read the
37 * SBI interrupt state register. This will indicate which slots
38 * have interrupts pending for that SBUS interrupt level.
39 */ 26 */
40 27
28struct sun4d_handler_data {
29 unsigned int cpuid; /* target cpu */
30 unsigned int real_irq; /* interrupt level */
31};
32
33
34static unsigned int sun4d_encode_irq(int board, int lvl, int slot)
35{
36 return (board + 1) << 5 | (lvl << 2) | slot;
37}
38
41struct sun4d_timer_regs { 39struct sun4d_timer_regs {
42 u32 l10_timer_limit; 40 u32 l10_timer_limit;
43 u32 l10_cur_countx; 41 u32 l10_cur_countx;
@@ -48,22 +46,13 @@ struct sun4d_timer_regs {
48 46
49static struct sun4d_timer_regs __iomem *sun4d_timers; 47static struct sun4d_timer_regs __iomem *sun4d_timers;
50 48
51#define TIMER_IRQ 10 49#define SUN4D_TIMER_IRQ 10
52
53#define MAX_STATIC_ALLOC 4
54 50
55/* Specify which cpu handle interrupts from which board. 51/* Specify which cpu handle interrupts from which board.
56 * Index is board - value is cpu. 52 * Index is board - value is cpu.
57 */ 53 */
58static unsigned char board_to_cpu[32]; 54static unsigned char board_to_cpu[32];
59 55
60static struct irqaction *irq_action[NR_IRQS];
61
62static struct sbus_action {
63 struct irqaction *action;
64 /* For SMP this needs to be extended */
65} *sbus_actions;
66
67static int pil_to_sbus[] = { 56static int pil_to_sbus[] = {
68 0, 57 0,
69 0, 58 0,
@@ -83,152 +72,81 @@ static int pil_to_sbus[] = {
83 0, 72 0,
84}; 73};
85 74
86static int sbus_to_pil[] = {
87 0,
88 2,
89 3,
90 5,
91 7,
92 9,
93 11,
94 13,
95};
96
97static int nsbi;
98
99/* Exported for sun4d_smp.c */ 75/* Exported for sun4d_smp.c */
100DEFINE_SPINLOCK(sun4d_imsk_lock); 76DEFINE_SPINLOCK(sun4d_imsk_lock);
101 77
102int show_sun4d_interrupts(struct seq_file *p, void *v) 78/* SBUS interrupts are encoded integers including the board number
79 * (plus one), the SBUS level, and the SBUS slot number. Sun4D
80 * IRQ dispatch is done by:
81 *
82 * 1) Reading the BW local interrupt table in order to get the bus
83 * interrupt mask.
84 *
85 * This table is indexed by SBUS interrupt level which can be
86 * derived from the PIL we got interrupted on.
87 *
88 * 2) For each bus showing interrupt pending from #1, read the
89 * SBI interrupt state register. This will indicate which slots
90 * have interrupts pending for that SBUS interrupt level.
91 *
92 * 3) Call the genreric IRQ support.
93 */
94static void sun4d_sbus_handler_irq(int sbusl)
103{ 95{
104 int i = *(loff_t *) v, j = 0, k = 0, sbusl; 96 unsigned int bus_mask;
105 struct irqaction *action; 97 unsigned int sbino, slot;
106 unsigned long flags; 98 unsigned int sbil;
107#ifdef CONFIG_SMP 99
108 int x; 100 bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
109#endif 101 bw_clear_intr_mask(sbusl, bus_mask);
110 102
111 spin_lock_irqsave(&irq_action_lock, flags); 103 sbil = (sbusl << 2);
112 if (i < NR_IRQS) { 104 /* Loop for each pending SBI */
113 sbusl = pil_to_sbus[i]; 105 for (sbino = 0; bus_mask; sbino++) {
114 if (!sbusl) { 106 unsigned int idx, mask;
115 action = *(i + irq_action); 107
116 if (!action) 108 bus_mask >>= 1;
117 goto out_unlock; 109 if (!(bus_mask & 1))
118 } else { 110 continue;
119 for (j = 0; j < nsbi; j++) { 111 /* XXX This seems to ACK the irq twice. acquire_sbi()
120 for (k = 0; k < 4; k++) 112 * XXX uses swap, therefore this writes 0xf << sbil,
121 action = sbus_actions[(j << 5) + (sbusl << 2) + k].action; 113 * XXX then later release_sbi() will write the individual
122 if (action) 114 * XXX bits which were set again.
123 goto found_it; 115 */
124 } 116 mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
125 goto out_unlock; 117 mask &= (0xf << sbil);
126 } 118
127found_it: seq_printf(p, "%3d: ", i); 119 /* Loop for each pending SBI slot */
128#ifndef CONFIG_SMP 120 idx = 0;
129 seq_printf(p, "%10u ", kstat_irqs(i)); 121 slot = (1 << sbil);
130#else 122 while (mask != 0) {
131 for_each_online_cpu(x) 123 unsigned int pil;
132 seq_printf(p, "%10u ", 124 struct irq_bucket *p;
133 kstat_cpu(cpu_logical_map(x)).irqs[i]); 125
134#endif 126 idx++;
135 seq_printf(p, "%c %s", 127 slot <<= 1;
136 (action->flags & IRQF_DISABLED) ? '+' : ' ', 128 if (!(mask & slot))
137 action->name); 129 continue;
138 action = action->next; 130
139 for (;;) { 131 mask &= ~slot;
140 for (; action; action = action->next) { 132 pil = sun4d_encode_irq(sbino, sbil, idx);
141 seq_printf(p, ",%s %s", 133
142 (action->flags & IRQF_DISABLED) ? " +" : "", 134 p = irq_map[pil];
143 action->name); 135 while (p) {
144 } 136 struct irq_bucket *next;
145 if (!sbusl) 137
146 break; 138 next = p->next;
147 k++; 139 generic_handle_irq(p->irq);
148 if (k < 4) { 140 p = next;
149 action = sbus_actions[(j << 5) + (sbusl << 2) + k].action;
150 } else {
151 j++;
152 if (j == nsbi)
153 break;
154 k = 0;
155 action = sbus_actions[(j << 5) + (sbusl << 2)].action;
156 } 141 }
142 release_sbi(SBI2DEVID(sbino), slot);
157 } 143 }
158 seq_putc(p, '\n');
159 }
160out_unlock:
161 spin_unlock_irqrestore(&irq_action_lock, flags);
162 return 0;
163}
164
165void sun4d_free_irq(unsigned int irq, void *dev_id)
166{
167 struct irqaction *action, **actionp;
168 struct irqaction *tmp = NULL;
169 unsigned long flags;
170
171 spin_lock_irqsave(&irq_action_lock, flags);
172 if (irq < 15)
173 actionp = irq + irq_action;
174 else
175 actionp = &(sbus_actions[irq - (1 << 5)].action);
176 action = *actionp;
177 if (!action) {
178 printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
179 goto out_unlock;
180 }
181 if (dev_id) {
182 for (; action; action = action->next) {
183 if (action->dev_id == dev_id)
184 break;
185 tmp = action;
186 }
187 if (!action) {
188 printk(KERN_ERR "Trying to free free shared IRQ%d\n",
189 irq);
190 goto out_unlock;
191 }
192 } else if (action->flags & IRQF_SHARED) {
193 printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
194 irq);
195 goto out_unlock;
196 }
197 if (action->flags & SA_STATIC_ALLOC) {
198 /*
199 * This interrupt is marked as specially allocated
200 * so it is a bad idea to free it.
201 */
202 printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
203 irq, action->name);
204 goto out_unlock;
205 } 144 }
206
207 if (tmp)
208 tmp->next = action->next;
209 else
210 *actionp = action->next;
211
212 spin_unlock_irqrestore(&irq_action_lock, flags);
213
214 synchronize_irq(irq);
215
216 spin_lock_irqsave(&irq_action_lock, flags);
217
218 kfree(action);
219
220 if (!(*actionp))
221 __disable_irq(irq);
222
223out_unlock:
224 spin_unlock_irqrestore(&irq_action_lock, flags);
225} 145}
226 146
227void sun4d_handler_irq(int pil, struct pt_regs *regs) 147void sun4d_handler_irq(int pil, struct pt_regs *regs)
228{ 148{
229 struct pt_regs *old_regs; 149 struct pt_regs *old_regs;
230 struct irqaction *action;
231 int cpu = smp_processor_id();
232 /* SBUS IRQ level (1 - 7) */ 150 /* SBUS IRQ level (1 - 7) */
233 int sbusl = pil_to_sbus[pil]; 151 int sbusl = pil_to_sbus[pil];
234 152
@@ -239,158 +157,85 @@ void sun4d_handler_irq(int pil, struct pt_regs *regs)
239 157
240 old_regs = set_irq_regs(regs); 158 old_regs = set_irq_regs(regs);
241 irq_enter(); 159 irq_enter();
242 kstat_cpu(cpu).irqs[pil]++; 160 if (sbusl == 0) {
243 if (!sbusl) { 161 /* cpu interrupt */
244 action = *(pil + irq_action); 162 struct irq_bucket *p;
245 if (!action) 163
246 unexpected_irq(pil, NULL, regs); 164 p = irq_map[pil];
247 do { 165 while (p) {
248 action->handler(pil, action->dev_id); 166 struct irq_bucket *next;
249 action = action->next; 167
250 } while (action); 168 next = p->next;
169 generic_handle_irq(p->irq);
170 p = next;
171 }
251 } else { 172 } else {
252 int bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff; 173 /* SBUS interrupt */
253 int sbino; 174 sun4d_sbus_handler_irq(sbusl);
254 struct sbus_action *actionp;
255 unsigned mask, slot;
256 int sbil = (sbusl << 2);
257
258 bw_clear_intr_mask(sbusl, bus_mask);
259
260 /* Loop for each pending SBI */
261 for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1)
262 if (bus_mask & 1) {
263 mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
264 mask &= (0xf << sbil);
265 actionp = sbus_actions + (sbino << 5) + (sbil);
266 /* Loop for each pending SBI slot */
267 for (slot = (1 << sbil); mask; slot <<= 1, actionp++)
268 if (mask & slot) {
269 mask &= ~slot;
270 action = actionp->action;
271
272 if (!action)
273 unexpected_irq(pil, NULL, regs);
274 do {
275 action->handler(pil, action->dev_id);
276 action = action->next;
277 } while (action);
278 release_sbi(SBI2DEVID(sbino), slot);
279 }
280 }
281 } 175 }
282 irq_exit(); 176 irq_exit();
283 set_irq_regs(old_regs); 177 set_irq_regs(old_regs);
284} 178}
285 179
286int sun4d_request_irq(unsigned int irq, 180
287 irq_handler_t handler, 181static void sun4d_mask_irq(struct irq_data *data)
288 unsigned long irqflags, const char *devname, void *dev_id)
289{ 182{
290 struct irqaction *action, *tmp = NULL, **actionp; 183 struct sun4d_handler_data *handler_data = data->handler_data;
184 unsigned int real_irq;
185#ifdef CONFIG_SMP
186 int cpuid = handler_data->cpuid;
291 unsigned long flags; 187 unsigned long flags;
292 int ret; 188#endif
293 189 real_irq = handler_data->real_irq;
294 if (irq > 14 && irq < (1 << 5)) { 190#ifdef CONFIG_SMP
295 ret = -EINVAL; 191 spin_lock_irqsave(&sun4d_imsk_lock, flags);
296 goto out; 192 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq));
297 } 193 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
298 194#else
299 if (!handler) { 195 cc_set_imsk(cc_get_imsk() | (1 << real_irq));
300 ret = -EINVAL; 196#endif
301 goto out;
302 }
303
304 spin_lock_irqsave(&irq_action_lock, flags);
305
306 if (irq >= (1 << 5))
307 actionp = &(sbus_actions[irq - (1 << 5)].action);
308 else
309 actionp = irq + irq_action;
310 action = *actionp;
311
312 if (action) {
313 if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) {
314 for (tmp = action; tmp->next; tmp = tmp->next)
315 /* find last entry - tmp used below */;
316 } else {
317 ret = -EBUSY;
318 goto out_unlock;
319 }
320 if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) {
321 printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
322 irq);
323 ret = -EBUSY;
324 goto out_unlock;
325 }
326 action = NULL; /* Or else! */
327 }
328
329 /* If this is flagged as statically allocated then we use our
330 * private struct which is never freed.
331 */
332 if (irqflags & SA_STATIC_ALLOC) {
333 if (static_irq_count < MAX_STATIC_ALLOC)
334 action = &static_irqaction[static_irq_count++];
335 else
336 printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
337 irq, devname);
338 }
339
340 if (action == NULL)
341 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
342
343 if (!action) {
344 ret = -ENOMEM;
345 goto out_unlock;
346 }
347
348 action->handler = handler;
349 action->flags = irqflags;
350 action->name = devname;
351 action->next = NULL;
352 action->dev_id = dev_id;
353
354 if (tmp)
355 tmp->next = action;
356 else
357 *actionp = action;
358
359 __enable_irq(irq);
360
361 ret = 0;
362out_unlock:
363 spin_unlock_irqrestore(&irq_action_lock, flags);
364out:
365 return ret;
366} 197}
367 198
368static void sun4d_disable_irq(unsigned int irq) 199static void sun4d_unmask_irq(struct irq_data *data)
369{ 200{
370 int tid = board_to_cpu[(irq >> 5) - 1]; 201 struct sun4d_handler_data *handler_data = data->handler_data;
202 unsigned int real_irq;
203#ifdef CONFIG_SMP
204 int cpuid = handler_data->cpuid;
371 unsigned long flags; 205 unsigned long flags;
206#endif
207 real_irq = handler_data->real_irq;
372 208
373 if (irq < NR_IRQS) 209#ifdef CONFIG_SMP
374 return;
375
376 spin_lock_irqsave(&sun4d_imsk_lock, flags); 210 spin_lock_irqsave(&sun4d_imsk_lock, flags);
377 cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); 211 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | ~(1 << real_irq));
378 spin_unlock_irqrestore(&sun4d_imsk_lock, flags); 212 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
213#else
214 cc_set_imsk(cc_get_imsk() | ~(1 << real_irq));
215#endif
379} 216}
380 217
381static void sun4d_enable_irq(unsigned int irq) 218static unsigned int sun4d_startup_irq(struct irq_data *data)
382{ 219{
383 int tid = board_to_cpu[(irq >> 5) - 1]; 220 irq_link(data->irq);
384 unsigned long flags; 221 sun4d_unmask_irq(data);
385 222 return 0;
386 if (irq < NR_IRQS) 223}
387 return;
388 224
389 spin_lock_irqsave(&sun4d_imsk_lock, flags); 225static void sun4d_shutdown_irq(struct irq_data *data)
390 cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); 226{
391 spin_unlock_irqrestore(&sun4d_imsk_lock, flags); 227 sun4d_mask_irq(data);
228 irq_unlink(data->irq);
392} 229}
393 230
231struct irq_chip sun4d_irq = {
232 .name = "sun4d",
233 .irq_startup = sun4d_startup_irq,
234 .irq_shutdown = sun4d_shutdown_irq,
235 .irq_unmask = sun4d_unmask_irq,
236 .irq_mask = sun4d_mask_irq,
237};
238
394#ifdef CONFIG_SMP 239#ifdef CONFIG_SMP
395static void sun4d_set_cpu_int(int cpu, int level) 240static void sun4d_set_cpu_int(int cpu, int level)
396{ 241{
@@ -447,15 +292,16 @@ static void __init sun4d_load_profile_irqs(void)
447unsigned int sun4d_build_device_irq(struct platform_device *op, 292unsigned int sun4d_build_device_irq(struct platform_device *op,
448 unsigned int real_irq) 293 unsigned int real_irq)
449{ 294{
450 static int pil_to_sbus[] = {
451 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
452 };
453 struct device_node *dp = op->dev.of_node; 295 struct device_node *dp = op->dev.of_node;
454 struct device_node *io_unit, *sbi = dp->parent; 296 struct device_node *io_unit, *sbi = dp->parent;
455 const struct linux_prom_registers *regs; 297 const struct linux_prom_registers *regs;
298 struct sun4d_handler_data *handler_data;
299 unsigned int pil;
300 unsigned int irq;
456 int board, slot; 301 int board, slot;
457 int sbusl; 302 int sbusl;
458 303
304 irq = 0;
459 while (sbi) { 305 while (sbi) {
460 if (!strcmp(sbi->name, "sbi")) 306 if (!strcmp(sbi->name, "sbi"))
461 break; 307 break;
@@ -488,7 +334,28 @@ unsigned int sun4d_build_device_irq(struct platform_device *op,
488 334
489 sbusl = pil_to_sbus[real_irq]; 335 sbusl = pil_to_sbus[real_irq];
490 if (sbusl) 336 if (sbusl)
491 return (((board + 1) << 5) + (sbusl << 2) + slot); 337 pil = sun4d_encode_irq(board, sbusl, slot);
338 else
339 pil = real_irq;
340
341 irq = irq_alloc(real_irq, pil);
342 if (irq == 0)
343 goto err_out;
344
345 handler_data = irq_get_handler_data(irq);
346 if (unlikely(handler_data))
347 goto err_out;
348
349 handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
350 if (unlikely(!handler_data)) {
351 prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
352 prom_halt();
353 }
354 handler_data->cpuid = board_to_cpu[board];
355 handler_data->real_irq = real_irq;
356 irq_set_chip_and_handler_name(irq, &sun4d_irq,
357 handle_level_irq, "level");
358 irq_set_handler_data(irq, handler_data);
492 359
493err_out: 360err_out:
494 return real_irq; 361 return real_irq;
@@ -522,6 +389,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
522{ 389{
523 struct device_node *dp; 390 struct device_node *dp;
524 struct resource res; 391 struct resource res;
392 unsigned int irq;
525 const u32 *reg; 393 const u32 *reg;
526 int err; 394 int err;
527 395
@@ -556,9 +424,8 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
556 424
557 master_l10_counter = &sun4d_timers->l10_cur_count; 425 master_l10_counter = &sun4d_timers->l10_cur_count;
558 426
559 err = request_irq(TIMER_IRQ, counter_fn, 427 irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ);
560 (IRQF_DISABLED | SA_STATIC_ALLOC), 428 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
561 "timer", NULL);
562 if (err) { 429 if (err) {
563 prom_printf("sun4d_init_timers: request_irq() failed with %d\n", 430 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
564 err); 431 err);
@@ -576,15 +443,6 @@ void __init sun4d_init_sbi_irq(void)
576#ifdef CONFIG_SMP 443#ifdef CONFIG_SMP
577 target_cpu = boot_cpu_id; 444 target_cpu = boot_cpu_id;
578#endif 445#endif
579
580 nsbi = 0;
581 for_each_node_by_name(dp, "sbi")
582 nsbi++;
583 sbus_actions = kzalloc(nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
584 if (!sbus_actions) {
585 prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
586 prom_halt();
587 }
588 for_each_node_by_name(dp, "sbi") { 446 for_each_node_by_name(dp, "sbi") {
589 int devid = of_getintprop_default(dp, "device-id", 0); 447 int devid = of_getintprop_default(dp, "device-id", 0);
590 int board = of_getintprop_default(dp, "board#", 0); 448 int board = of_getintprop_default(dp, "board#", 0);
@@ -607,12 +465,10 @@ void __init sun4d_init_IRQ(void)
607{ 465{
608 local_irq_disable(); 466 local_irq_disable();
609 467
610 BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM);
611 BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM);
612 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); 468 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
613 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); 469 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
614 470
615 sparc_irq_config.init_timers = sun4d_init_timers; 471 sparc_irq_config.init_timers = sun4d_init_timers;
616 sparc_irq_config.build_device_irq = sun4d_build_device_irq; 472 sparc_irq_config.build_device_irq = sun4d_build_device_irq;
617 473
618#ifdef CONFIG_SMP 474#ifdef CONFIG_SMP
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 69df6257a32e..422c16dad1f6 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -100,6 +100,11 @@
100struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; 100struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
101struct sun4m_irq_global __iomem *sun4m_irq_global; 101struct sun4m_irq_global __iomem *sun4m_irq_global;
102 102
103struct sun4m_handler_data {
104 bool percpu;
105 long mask;
106};
107
103/* Dave Redman (djhr@tadpole.co.uk) 108/* Dave Redman (djhr@tadpole.co.uk)
104 * The sun4m interrupt registers. 109 * The sun4m interrupt registers.
105 */ 110 */
@@ -142,9 +147,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
142#define OBP_INT_LEVEL_VME 0x40 147#define OBP_INT_LEVEL_VME 0x40
143 148
144#define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) 149#define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10)
145#define SUM4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14) 150#define SUN4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14)
146 151
147static unsigned long irq_mask[0x50] = { 152static unsigned long sun4m_imask[0x50] = {
148 /* 0x00 - SMP */ 153 /* 0x00 - SMP */
149 0, SUN4M_SOFT_INT(1), 154 0, SUN4M_SOFT_INT(1),
150 SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), 155 SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3),
@@ -169,7 +174,7 @@ static unsigned long irq_mask[0x50] = {
169 SUN4M_INT_VIDEO, SUN4M_INT_MODULE, 174 SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
170 SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, 175 SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
171 (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), 176 (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
172 SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, 177 SUN4M_INT_AUDIO, SUN4M_INT_E14, SUN4M_INT_MODULE_ERR,
173 /* 0x30 - sbus */ 178 /* 0x30 - sbus */
174 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), 179 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
175 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), 180 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
@@ -182,105 +187,110 @@ static unsigned long irq_mask[0x50] = {
182 0, SUN4M_INT_VME(6), 0, 0 187 0, SUN4M_INT_VME(6), 0, 0
183}; 188};
184 189
185static unsigned long sun4m_get_irqmask(unsigned int irq) 190static void sun4m_mask_irq(struct irq_data *data)
186{ 191{
187 unsigned long mask; 192 struct sun4m_handler_data *handler_data = data->handler_data;
188 193 int cpu = smp_processor_id();
189 if (irq < 0x50)
190 mask = irq_mask[irq];
191 else
192 mask = 0;
193 194
194 if (!mask) 195 if (handler_data->mask) {
195 printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", 196 unsigned long flags;
196 irq);
197 197
198 return mask; 198 local_irq_save(flags);
199 if (handler_data->percpu) {
200 sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->set);
201 } else {
202 sbus_writel(handler_data->mask, &sun4m_irq_global->mask_set);
203 }
204 local_irq_restore(flags);
205 }
199} 206}
200 207
201static void sun4m_disable_irq(unsigned int irq_nr) 208static void sun4m_unmask_irq(struct irq_data *data)
202{ 209{
203 unsigned long mask, flags; 210 struct sun4m_handler_data *handler_data = data->handler_data;
204 int cpu = smp_processor_id(); 211 int cpu = smp_processor_id();
205 212
206 mask = sun4m_get_irqmask(irq_nr); 213 if (handler_data->mask) {
207 local_irq_save(flags); 214 unsigned long flags;
208 if (irq_nr > 15)
209 sbus_writel(mask, &sun4m_irq_global->mask_set);
210 else
211 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
212 local_irq_restore(flags);
213}
214
215static void sun4m_enable_irq(unsigned int irq_nr)
216{
217 unsigned long mask, flags;
218 int cpu = smp_processor_id();
219 215
220 /* Dreadful floppy hack. When we use 0x2b instead of
221 * 0x0b the system blows (it starts to whistle!).
222 * So we continue to use 0x0b. Fixme ASAP. --P3
223 */
224 if (irq_nr != 0x0b) {
225 mask = sun4m_get_irqmask(irq_nr);
226 local_irq_save(flags);
227 if (irq_nr > 15)
228 sbus_writel(mask, &sun4m_irq_global->mask_clear);
229 else
230 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
231 local_irq_restore(flags);
232 } else {
233 local_irq_save(flags); 216 local_irq_save(flags);
234 sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); 217 if (handler_data->percpu) {
218 sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear);
219 } else {
220 sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear);
221 }
235 local_irq_restore(flags); 222 local_irq_restore(flags);
236 } 223 }
237} 224}
238 225
239static unsigned long cpu_pil_to_imask[16] = { 226static unsigned int sun4m_startup_irq(struct irq_data *data)
240/*0*/ 0x00000000, 227{
241/*1*/ 0x00000000, 228 irq_link(data->irq);
242/*2*/ SUN4M_INT_SBUS(0) | SUN4M_INT_VME(0), 229 sun4m_unmask_irq(data);
243/*3*/ SUN4M_INT_SBUS(1) | SUN4M_INT_VME(1), 230 return 0;
244/*4*/ SUN4M_INT_SCSI, 231}
245/*5*/ SUN4M_INT_SBUS(2) | SUN4M_INT_VME(2),
246/*6*/ SUN4M_INT_ETHERNET,
247/*7*/ SUN4M_INT_SBUS(3) | SUN4M_INT_VME(3),
248/*8*/ SUN4M_INT_VIDEO,
249/*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR,
250/*10*/ SUN4M_INT_REALTIME,
251/*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY,
252/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
253/*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
254/*14*/ SUN4M_INT_E14,
255/*15*/ SUN4M_INT_ERROR,
256};
257 232
258/* We assume the caller has disabled local interrupts when these are called, 233static void sun4m_shutdown_irq(struct irq_data *data)
259 * or else very bizarre behavior will result.
260 */
261static void sun4m_disable_pil_irq(unsigned int pil)
262{ 234{
263 sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); 235 sun4m_mask_irq(data);
236 irq_unlink(data->irq);
264} 237}
265 238
266static void sun4m_enable_pil_irq(unsigned int pil) 239static struct irq_chip sun4m_irq = {
240 .name = "sun4m",
241 .irq_startup = sun4m_startup_irq,
242 .irq_shutdown = sun4m_shutdown_irq,
243 .irq_mask = sun4m_mask_irq,
244 .irq_unmask = sun4m_unmask_irq,
245};
246
247
248static unsigned int sun4m_build_device_irq(struct platform_device *op,
249 unsigned int real_irq)
267{ 250{
268 sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); 251 struct sun4m_handler_data *handler_data;
252 unsigned int irq;
253 unsigned int pil;
254
255 if (real_irq >= OBP_INT_LEVEL_VME) {
256 prom_printf("Bogus sun4m IRQ %u\n", real_irq);
257 prom_halt();
258 }
259 pil = (real_irq & 0xf);
260 irq = irq_alloc(real_irq, pil);
261
262 if (irq == 0)
263 goto out;
264
265 handler_data = irq_get_handler_data(irq);
266 if (unlikely(handler_data))
267 goto out;
268
269 handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC);
270 if (unlikely(!handler_data)) {
271 prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n");
272 prom_halt();
273 }
274
275 handler_data->mask = sun4m_imask[real_irq];
276 handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD;
277 irq_set_chip_and_handler_name(irq, &sun4m_irq,
278 handle_level_irq, "level");
279 irq_set_handler_data(irq, handler_data);
280
281out:
282 return irq;
269} 283}
270 284
271#ifdef CONFIG_SMP 285#ifdef CONFIG_SMP
272static void sun4m_send_ipi(int cpu, int level) 286static void sun4m_send_ipi(int cpu, int level)
273{ 287{
274 unsigned long mask = sun4m_get_irqmask(level); 288 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
275
276 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
277} 289}
278 290
279static void sun4m_clear_ipi(int cpu, int level) 291static void sun4m_clear_ipi(int cpu, int level)
280{ 292{
281 unsigned long mask = sun4m_get_irqmask(level); 293 sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
282
283 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
284} 294}
285 295
286static void sun4m_set_udt(int cpu) 296static void sun4m_set_udt(int cpu)
@@ -343,7 +353,15 @@ void sun4m_nmi(struct pt_regs *regs)
343 prom_halt(); 353 prom_halt();
344} 354}
345 355
346/* Exported for sun4m_smp.c */ 356void sun4m_unmask_profile_irq(void)
357{
358 unsigned long flags;
359
360 local_irq_save(flags);
361 sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear);
362 local_irq_restore(flags);
363}
364
347void sun4m_clear_profile_irq(int cpu) 365void sun4m_clear_profile_irq(int cpu)
348{ 366{
349 sbus_readl(&timers_percpu[cpu]->l14_limit); 367 sbus_readl(&timers_percpu[cpu]->l14_limit);
@@ -358,6 +376,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
358{ 376{
359 struct device_node *dp = of_find_node_by_name(NULL, "counter"); 377 struct device_node *dp = of_find_node_by_name(NULL, "counter");
360 int i, err, len, num_cpu_timers; 378 int i, err, len, num_cpu_timers;
379 unsigned int irq;
361 const u32 *addr; 380 const u32 *addr;
362 381
363 if (!dp) { 382 if (!dp) {
@@ -384,8 +403,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
384 403
385 master_l10_counter = &timers_global->l10_count; 404 master_l10_counter = &timers_global->l10_count;
386 405
387 err = request_irq(SUN4M_TIMER_IRQ, counter_fn, 406 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
388 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 407
408 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
389 if (err) { 409 if (err) {
390 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", 410 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
391 err); 411 err);
@@ -452,14 +472,11 @@ void __init sun4m_init_IRQ(void)
452 if (num_cpu_iregs == 4) 472 if (num_cpu_iregs == 4)
453 sbus_writel(0, &sun4m_irq_global->interrupt_target); 473 sbus_writel(0, &sun4m_irq_global->interrupt_target);
454 474
455 BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
456 BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
457 BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
458 BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
459 BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); 475 BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
460 BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); 476 BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
461 477
462 sparc_irq_config.init_timers = sun4m_init_timers; 478 sparc_irq_config.init_timers = sun4m_init_timers;
479 sparc_irq_config.build_device_irq = sun4m_build_device_irq;
463 480
464#ifdef CONFIG_SMP 481#ifdef CONFIG_SMP
465 BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); 482 BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 5cc7dc51de3d..58b8d849674c 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -150,20 +150,6 @@ void __init smp4m_smp_done(void)
150 /* Ok, they are spinning and ready to go. */ 150 /* Ok, they are spinning and ready to go. */
151} 151}
152 152
153/* At each hardware IRQ, we get this called to forward IRQ reception
154 * to the next processor. The caller must disable the IRQ level being
155 * serviced globally so that there are no double interrupts received.
156 *
157 * XXX See sparc64 irq.c.
158 */
159void smp4m_irq_rotate(int cpu)
160{
161 int next = cpu_data(cpu).next;
162
163 if (next != cpu)
164 set_irq_udt(next);
165}
166
167static struct smp_funcall { 153static struct smp_funcall {
168 smpfunc_t func; 154 smpfunc_t func;
169 unsigned long arg1; 155 unsigned long arg1;
@@ -277,7 +263,7 @@ static void __cpuinit smp_setup_percpu_timer(void)
277 load_profile_irq(cpu, lvl14_resolution); 263 load_profile_irq(cpu, lvl14_resolution);
278 264
279 if (cpu == boot_cpu_id) 265 if (cpu == boot_cpu_id)
280 enable_pil_irq(14); 266 sun4m_unmask_profile_irq();
281} 267}
282 268
283static void __init smp4m_blackbox_id(unsigned *addr) 269static void __init smp4m_blackbox_id(unsigned *addr)