diff options
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 70 |
1 files changed, 26 insertions, 44 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index ad134bbc151c..f2668f2bed9c 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -70,7 +70,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY | |||
70 | */ | 70 | */ |
71 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) | 71 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) |
72 | 72 | ||
73 | static struct irqaction *irq_action[NR_IRQS+1]; | 73 | static struct irqaction *irq_action[NR_IRQS]; |
74 | 74 | ||
75 | /* This only synchronizes entities which modify IRQ handler | 75 | /* This only synchronizes entities which modify IRQ handler |
76 | * state and some selected user-level spots that want to | 76 | * state and some selected user-level spots that want to |
@@ -116,12 +116,9 @@ int show_interrupts(struct seq_file *p, void *v) | |||
116 | kstat_cpu(j).irqs[i]); | 116 | kstat_cpu(j).irqs[i]); |
117 | } | 117 | } |
118 | #endif | 118 | #endif |
119 | seq_printf(p, " %s:%lx", action->name, | 119 | seq_printf(p, " %s", action->name); |
120 | get_ino_in_irqaction(action)); | 120 | for (action = action->next; action; action = action->next) |
121 | for (action = action->next; action; action = action->next) { | 121 | seq_printf(p, ", %s", action->name); |
122 | seq_printf(p, ", %s:%lx", action->name, | ||
123 | get_ino_in_irqaction(action)); | ||
124 | } | ||
125 | seq_putc(p, '\n'); | 122 | seq_putc(p, '\n'); |
126 | } | 123 | } |
127 | out_unlock: | 124 | out_unlock: |
@@ -245,48 +242,47 @@ void disable_irq(unsigned int irq) | |||
245 | } | 242 | } |
246 | } | 243 | } |
247 | 244 | ||
248 | static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup, | 245 | static void build_irq_error(const char *msg, unsigned int ino, int inofixup, |
249 | unsigned long iclr, unsigned long imap, | 246 | unsigned long iclr, unsigned long imap, |
250 | struct ino_bucket *bucket) | 247 | struct ino_bucket *bucket) |
251 | { | 248 | { |
252 | prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> " | 249 | prom_printf("IRQ: INO %04x (%016lx:%016lx) --> " |
253 | "(%d:%d:%016lx:%016lx), halting...\n", | 250 | "(%d:%016lx:%016lx), halting...\n", |
254 | ino, bucket->pil, bucket->iclr, bucket->imap, | 251 | ino, bucket->iclr, bucket->imap, |
255 | pil, inofixup, iclr, imap); | 252 | inofixup, iclr, imap); |
256 | prom_halt(); | 253 | prom_halt(); |
257 | } | 254 | } |
258 | 255 | ||
259 | unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap) | 256 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) |
260 | { | 257 | { |
261 | struct ino_bucket *bucket; | 258 | struct ino_bucket *bucket; |
262 | int ino; | 259 | int ino; |
263 | 260 | ||
264 | BUG_ON(pil == 0); | ||
265 | BUG_ON(tlb_type == hypervisor); | 261 | BUG_ON(tlb_type == hypervisor); |
266 | 262 | ||
267 | /* RULE: Both must be specified in all other cases. */ | 263 | /* RULE: Both must be specified in all other cases. */ |
268 | if (iclr == 0UL || imap == 0UL) { | 264 | if (iclr == 0UL || imap == 0UL) { |
269 | prom_printf("Invalid build_irq %d %d %016lx %016lx\n", | 265 | prom_printf("Invalid build_irq %d %016lx %016lx\n", |
270 | pil, inofixup, iclr, imap); | 266 | inofixup, iclr, imap); |
271 | prom_halt(); | 267 | prom_halt(); |
272 | } | 268 | } |
273 | 269 | ||
274 | ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; | 270 | ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; |
275 | if (ino > NUM_IVECS) { | 271 | if (ino > NUM_IVECS) { |
276 | prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n", | 272 | prom_printf("Invalid INO %04x (%d:%016lx:%016lx)\n", |
277 | ino, pil, inofixup, iclr, imap); | 273 | ino, inofixup, iclr, imap); |
278 | prom_halt(); | 274 | prom_halt(); |
279 | } | 275 | } |
280 | 276 | ||
281 | bucket = &ivector_table[ino]; | 277 | bucket = &ivector_table[ino]; |
282 | if (bucket->flags & IBF_ACTIVE) | 278 | if (bucket->flags & IBF_ACTIVE) |
283 | build_irq_error("IRQ: Trying to build active INO bucket.\n", | 279 | build_irq_error("IRQ: Trying to build active INO bucket.\n", |
284 | ino, pil, inofixup, iclr, imap, bucket); | 280 | ino, inofixup, iclr, imap, bucket); |
285 | 281 | ||
286 | if (bucket->irq_info) { | 282 | if (bucket->irq_info) { |
287 | if (bucket->imap != imap || bucket->iclr != iclr) | 283 | if (bucket->imap != imap || bucket->iclr != iclr) |
288 | build_irq_error("IRQ: Trying to reinit INO bucket.\n", | 284 | build_irq_error("IRQ: Trying to reinit INO bucket.\n", |
289 | ino, pil, inofixup, iclr, imap, bucket); | 285 | ino, inofixup, iclr, imap, bucket); |
290 | 286 | ||
291 | goto out; | 287 | goto out; |
292 | } | 288 | } |
@@ -302,14 +298,13 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long | |||
302 | */ | 298 | */ |
303 | bucket->imap = imap; | 299 | bucket->imap = imap; |
304 | bucket->iclr = iclr; | 300 | bucket->iclr = iclr; |
305 | bucket->pil = pil; | ||
306 | bucket->flags = 0; | 301 | bucket->flags = 0; |
307 | 302 | ||
308 | out: | 303 | out: |
309 | return __irq(bucket); | 304 | return __irq(bucket); |
310 | } | 305 | } |
311 | 306 | ||
312 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags) | 307 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags) |
313 | { | 308 | { |
314 | struct ino_bucket *bucket; | 309 | struct ino_bucket *bucket; |
315 | unsigned long sysino; | 310 | unsigned long sysino; |
@@ -328,7 +323,6 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsign | |||
328 | bucket->imap = ~0UL - sysino; | 323 | bucket->imap = ~0UL - sysino; |
329 | bucket->iclr = ~0UL - sysino; | 324 | bucket->iclr = ~0UL - sysino; |
330 | 325 | ||
331 | bucket->pil = pil; | ||
332 | bucket->flags = flags; | 326 | bucket->flags = flags; |
333 | 327 | ||
334 | bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); | 328 | bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); |
@@ -356,16 +350,12 @@ static void atomic_bucket_insert(struct ino_bucket *bucket) | |||
356 | 350 | ||
357 | static int check_irq_sharing(int pil, unsigned long irqflags) | 351 | static int check_irq_sharing(int pil, unsigned long irqflags) |
358 | { | 352 | { |
359 | struct irqaction *action, *tmp; | 353 | struct irqaction *action; |
360 | 354 | ||
361 | action = *(irq_action + pil); | 355 | action = *(irq_action + pil); |
362 | if (action) { | 356 | if (action) { |
363 | if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { | 357 | if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) |
364 | for (tmp = action; tmp->next; tmp = tmp->next) | ||
365 | ; | ||
366 | } else { | ||
367 | return -EBUSY; | 358 | return -EBUSY; |
368 | } | ||
369 | } | 359 | } |
370 | return 0; | 360 | return 0; |
371 | } | 361 | } |
@@ -425,12 +415,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ | |||
425 | * installing a new handler, but is this really a problem, | 415 | * installing a new handler, but is this really a problem, |
426 | * only the sysadmin is able to do this. | 416 | * only the sysadmin is able to do this. |
427 | */ | 417 | */ |
428 | rand_initialize_irq(irq); | 418 | rand_initialize_irq(PIL_DEVICE_IRQ); |
429 | } | 419 | } |
430 | 420 | ||
431 | spin_lock_irqsave(&irq_action_lock, flags); | 421 | spin_lock_irqsave(&irq_action_lock, flags); |
432 | 422 | ||
433 | if (check_irq_sharing(bucket->pil, irqflags)) { | 423 | if (check_irq_sharing(PIL_DEVICE_IRQ, irqflags)) { |
434 | spin_unlock_irqrestore(&irq_action_lock, flags); | 424 | spin_unlock_irqrestore(&irq_action_lock, flags); |
435 | return -EBUSY; | 425 | return -EBUSY; |
436 | } | 426 | } |
@@ -454,7 +444,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ | |||
454 | put_ino_in_irqaction(action, irq); | 444 | put_ino_in_irqaction(action, irq); |
455 | put_smpaff_in_irqaction(action, CPU_MASK_NONE); | 445 | put_smpaff_in_irqaction(action, CPU_MASK_NONE); |
456 | 446 | ||
457 | append_irq_action(bucket->pil, action); | 447 | append_irq_action(PIL_DEVICE_IRQ, action); |
458 | 448 | ||
459 | enable_irq(irq); | 449 | enable_irq(irq); |
460 | 450 | ||
@@ -478,16 +468,15 @@ EXPORT_SYMBOL(request_irq); | |||
478 | 468 | ||
479 | static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) | 469 | static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) |
480 | { | 470 | { |
481 | struct ino_bucket *bucket = __bucket(irq); | ||
482 | struct irqaction *action, **pp; | 471 | struct irqaction *action, **pp; |
483 | 472 | ||
484 | pp = irq_action + bucket->pil; | 473 | pp = irq_action + PIL_DEVICE_IRQ; |
485 | action = *pp; | 474 | action = *pp; |
486 | if (unlikely(!action)) | 475 | if (unlikely(!action)) |
487 | return NULL; | 476 | return NULL; |
488 | 477 | ||
489 | if (unlikely(!action->handler)) { | 478 | if (unlikely(!action->handler)) { |
490 | printk("Freeing free IRQ %d\n", bucket->pil); | 479 | printk("Freeing free IRQ %d\n", PIL_DEVICE_IRQ); |
491 | return NULL; | 480 | return NULL; |
492 | } | 481 | } |
493 | 482 | ||
@@ -648,7 +637,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs) | |||
648 | 637 | ||
649 | /* Test and add entropy */ | 638 | /* Test and add entropy */ |
650 | if (random & SA_SAMPLE_RANDOM) | 639 | if (random & SA_SAMPLE_RANDOM) |
651 | add_interrupt_randomness(bp->pil); | 640 | add_interrupt_randomness(PIL_DEVICE_IRQ); |
652 | out: | 641 | out: |
653 | bp->flags &= ~IBF_INPROGRESS; | 642 | bp->flags &= ~IBF_INPROGRESS; |
654 | } | 643 | } |
@@ -691,7 +680,7 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
691 | while (bp) { | 680 | while (bp) { |
692 | struct ino_bucket *nbp = __bucket(bp->irq_chain); | 681 | struct ino_bucket *nbp = __bucket(bp->irq_chain); |
693 | 682 | ||
694 | kstat_this_cpu.irqs[bp->pil]++; | 683 | kstat_this_cpu.irqs[bp->virt_irq]++; |
695 | 684 | ||
696 | bp->irq_chain = 0; | 685 | bp->irq_chain = 0; |
697 | process_bucket(bp, regs); | 686 | process_bucket(bp, regs); |
@@ -817,16 +806,9 @@ static void distribute_irqs(void) | |||
817 | spin_lock_irqsave(&irq_action_lock, flags); | 806 | spin_lock_irqsave(&irq_action_lock, flags); |
818 | cpu = 0; | 807 | cpu = 0; |
819 | 808 | ||
820 | /* | ||
821 | * Skip the timer at [0], and very rare error/power intrs at [15]. | ||
822 | * Also level [12], it causes problems on Ex000 systems. | ||
823 | */ | ||
824 | for (level = 1; level < NR_IRQS; level++) { | 809 | for (level = 1; level < NR_IRQS; level++) { |
825 | struct irqaction *p = irq_action[level]; | 810 | struct irqaction *p = irq_action[level]; |
826 | 811 | ||
827 | if (level == 12) | ||
828 | continue; | ||
829 | |||
830 | while(p) { | 812 | while(p) { |
831 | cpu = retarget_one_irq(p, cpu); | 813 | cpu = retarget_one_irq(p, cpu); |
832 | p = p->next; | 814 | p = p->next; |