aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/xics.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 07:36:01 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 07:36:01 -0400
commit0ebfff1491ef85d41ddf9c633834838be144f69f (patch)
tree5b469a6d61a9fcfbf94e7b6d411e544dbdec8dec /arch/powerpc/platforms/pseries/xics.c
parentf63e115fb50db39706b955b81e3375ef6bab2268 (diff)
[POWERPC] Add new interrupt mapping core and change platforms to use it
This adds the new irq remapper core and removes the old one. Because there are some fundamental conflicts with the old code, like the value of NO_IRQ which I'm now setting to 0 (as per discussions with Linus), etc..., this commit also changes the relevant platform and driver code over to use the new remapper (so as not to cause difficulties later in bisecting). This patch removes the old pre-parsing of the open firmware interrupt tree along with all the bogus assumptions it made to try to renumber interrupts according to the platform. This is all to be handled by the new code now. For the pSeries XICS interrupt controller, a single remapper host is created for the whole machine regardless of how many interrupt presentation and source controllers are found, and it's set to match any device node that isn't a 8259. That works fine on pSeries and avoids having to deal with some of the complexities of split source controllers vs. presentation controllers in the pSeries device trees. The powerpc i8259 PIC driver now always requests the legacy interrupt range. It also has the feature of being able to match any device node (including NULL) if passed no device node as an input. That will help porting over platforms with broken device-trees like Pegasos who don't have a proper interrupt tree. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries/xics.c')
-rw-r--r--arch/powerpc/platforms/pseries/xics.c485
1 files changed, 297 insertions, 188 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index c7f04420066..716972aa977 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -8,6 +8,9 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11
12#undef DEBUG
13
11#include <linux/types.h> 14#include <linux/types.h>
12#include <linux/threads.h> 15#include <linux/threads.h>
13#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -19,6 +22,7 @@
19#include <linux/gfp.h> 22#include <linux/gfp.h>
20#include <linux/radix-tree.h> 23#include <linux/radix-tree.h>
21#include <linux/cpu.h> 24#include <linux/cpu.h>
25
22#include <asm/firmware.h> 26#include <asm/firmware.h>
23#include <asm/prom.h> 27#include <asm/prom.h>
24#include <asm/io.h> 28#include <asm/io.h>
@@ -31,9 +35,6 @@
31 35
32#include "xics.h" 36#include "xics.h"
33 37
34/* This is used to map real irq numbers to virtual */
35static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
36
37#define XICS_IPI 2 38#define XICS_IPI 2
38#define XICS_IRQ_SPURIOUS 0 39#define XICS_IRQ_SPURIOUS 0
39 40
@@ -64,12 +65,12 @@ struct xics_ipl {
64 65
65static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS]; 66static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
66 67
67static int xics_irq_8259_cascade = 0;
68static int xics_irq_8259_cascade_real = 0;
69static unsigned int default_server = 0xFF; 68static unsigned int default_server = 0xFF;
70static unsigned int default_distrib_server = 0; 69static unsigned int default_distrib_server = 0;
71static unsigned int interrupt_server_size = 8; 70static unsigned int interrupt_server_size = 8;
72 71
72static struct irq_host *xics_host;
73
73/* 74/*
74 * XICS only has a single IPI, so encode the messages per CPU 75 * XICS only has a single IPI, so encode the messages per CPU
75 */ 76 */
@@ -85,7 +86,7 @@ static int ibm_int_off;
85/* Direct HW low level accessors */ 86/* Direct HW low level accessors */
86 87
87 88
88static inline int direct_xirr_info_get(int n_cpu) 89static inline unsigned int direct_xirr_info_get(int n_cpu)
89{ 90{
90 return in_be32(&xics_per_cpu[n_cpu]->xirr.word); 91 return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
91} 92}
@@ -130,7 +131,7 @@ static inline long plpar_xirr(unsigned long *xirr_ret)
130 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); 131 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
131} 132}
132 133
133static inline int lpar_xirr_info_get(int n_cpu) 134static inline unsigned int lpar_xirr_info_get(int n_cpu)
134{ 135{
135 unsigned long lpar_rc; 136 unsigned long lpar_rc;
136 unsigned long return_value; 137 unsigned long return_value;
@@ -138,7 +139,7 @@ static inline int lpar_xirr_info_get(int n_cpu)
138 lpar_rc = plpar_xirr(&return_value); 139 lpar_rc = plpar_xirr(&return_value);
139 if (lpar_rc != H_SUCCESS) 140 if (lpar_rc != H_SUCCESS)
140 panic(" bad return code xirr - rc = %lx \n", lpar_rc); 141 panic(" bad return code xirr - rc = %lx \n", lpar_rc);
141 return (int)return_value; 142 return (unsigned int)return_value;
142} 143}
143 144
144static inline void lpar_xirr_info_set(int n_cpu, int value) 145static inline void lpar_xirr_info_set(int n_cpu, int value)
@@ -175,11 +176,11 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
175 176
176 177
177#ifdef CONFIG_SMP 178#ifdef CONFIG_SMP
178static int get_irq_server(unsigned int irq) 179static int get_irq_server(unsigned int virq)
179{ 180{
180 unsigned int server; 181 unsigned int server;
181 /* For the moment only implement delivery to all cpus or one cpu */ 182 /* For the moment only implement delivery to all cpus or one cpu */
182 cpumask_t cpumask = irq_desc[irq].affinity; 183 cpumask_t cpumask = irq_desc[virq].affinity;
183 cpumask_t tmp = CPU_MASK_NONE; 184 cpumask_t tmp = CPU_MASK_NONE;
184 185
185 if (!distribute_irqs) 186 if (!distribute_irqs)
@@ -200,7 +201,7 @@ static int get_irq_server(unsigned int irq)
200 201
201} 202}
202#else 203#else
203static int get_irq_server(unsigned int irq) 204static int get_irq_server(unsigned int virq)
204{ 205{
205 return default_server; 206 return default_server;
206} 207}
@@ -213,9 +214,11 @@ static void xics_unmask_irq(unsigned int virq)
213 int call_status; 214 int call_status;
214 unsigned int server; 215 unsigned int server;
215 216
216 irq = virt_irq_to_real(irq_offset_down(virq)); 217 pr_debug("xics: unmask virq %d\n", virq);
217 WARN_ON(irq == NO_IRQ); 218
218 if (irq == XICS_IPI || irq == NO_IRQ) 219 irq = (unsigned int)irq_map[virq].hwirq;
220 pr_debug(" -> map to hwirq 0x%x\n", irq);
221 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
219 return; 222 return;
220 223
221 server = get_irq_server(virq); 224 server = get_irq_server(virq);
@@ -267,75 +270,57 @@ static void xics_mask_irq(unsigned int virq)
267{ 270{
268 unsigned int irq; 271 unsigned int irq;
269 272
270 irq = virt_irq_to_real(irq_offset_down(virq)); 273 pr_debug("xics: mask virq %d\n", virq);
271 WARN_ON(irq == NO_IRQ); 274
272 if (irq != NO_IRQ) 275 irq = (unsigned int)irq_map[virq].hwirq;
273 xics_mask_real_irq(irq); 276 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
277 return;
278 xics_mask_real_irq(irq);
274} 279}
275 280
276static void xics_set_irq_revmap(unsigned int virq) 281static unsigned int xics_startup(unsigned int virq)
277{ 282{
278 unsigned int irq; 283 unsigned int irq;
279 284
280 irq = irq_offset_down(virq); 285 /* force a reverse mapping of the interrupt so it gets in the cache */
281 if (radix_tree_insert(&irq_map, virt_irq_to_real(irq), 286 irq = (unsigned int)irq_map[virq].hwirq;
282 &virt_irq_to_real_map[irq]) == -ENOMEM) 287 irq_radix_revmap(xics_host, irq);
283 printk(KERN_CRIT "Out of memory creating real -> virtual"
284 " IRQ mapping for irq %u (real 0x%x)\n",
285 virq, virt_irq_to_real(irq));
286}
287 288
288static unsigned int xics_startup(unsigned int virq) 289 /* unmask it */
289{
290 xics_set_irq_revmap(virq);
291 xics_unmask_irq(virq); 290 xics_unmask_irq(virq);
292 return 0; 291 return 0;
293} 292}
294 293
295static unsigned int real_irq_to_virt(unsigned int real_irq) 294static void xics_eoi_direct(unsigned int virq)
296{
297 unsigned int *ptr;
298
299 ptr = radix_tree_lookup(&irq_map, real_irq);
300 if (ptr == NULL)
301 return NO_IRQ;
302 return ptr - virt_irq_to_real_map;
303}
304
305static void xics_eoi_direct(unsigned int irq)
306{ 295{
307 int cpu = smp_processor_id(); 296 int cpu = smp_processor_id();
297 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
308 298
309 iosync(); 299 iosync();
310 direct_xirr_info_set(cpu, ((0xff << 24) | 300 direct_xirr_info_set(cpu, (0xff << 24) | irq);
311 (virt_irq_to_real(irq_offset_down(irq)))));
312} 301}
313 302
314 303
315static void xics_eoi_lpar(unsigned int irq) 304static void xics_eoi_lpar(unsigned int virq)
316{ 305{
317 int cpu = smp_processor_id(); 306 int cpu = smp_processor_id();
307 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
318 308
319 iosync(); 309 iosync();
320 lpar_xirr_info_set(cpu, ((0xff << 24) | 310 lpar_xirr_info_set(cpu, (0xff << 24) | irq);
321 (virt_irq_to_real(irq_offset_down(irq)))));
322
323} 311}
324 312
325static inline int xics_remap_irq(int vec) 313static inline unsigned int xics_remap_irq(unsigned int vec)
326{ 314{
327 int irq; 315 unsigned int irq;
328 316
329 vec &= 0x00ffffff; 317 vec &= 0x00ffffff;
330 318
331 if (vec == XICS_IRQ_SPURIOUS) 319 if (vec == XICS_IRQ_SPURIOUS)
332 return NO_IRQ; 320 return NO_IRQ;
333 321 irq = irq_radix_revmap(xics_host, vec);
334 irq = real_irq_to_virt(vec);
335 if (irq == NO_IRQ)
336 irq = real_irq_to_virt_slowpath(vec);
337 if (likely(irq != NO_IRQ)) 322 if (likely(irq != NO_IRQ))
338 return irq_offset_up(irq); 323 return irq;
339 324
340 printk(KERN_ERR "Interrupt %u (real) is invalid," 325 printk(KERN_ERR "Interrupt %u (real) is invalid,"
341 " disabling it.\n", vec); 326 " disabling it.\n", vec);
@@ -343,14 +328,14 @@ static inline int xics_remap_irq(int vec)
343 return NO_IRQ; 328 return NO_IRQ;
344} 329}
345 330
346static int xics_get_irq_direct(struct pt_regs *regs) 331static unsigned int xics_get_irq_direct(struct pt_regs *regs)
347{ 332{
348 unsigned int cpu = smp_processor_id(); 333 unsigned int cpu = smp_processor_id();
349 334
350 return xics_remap_irq(direct_xirr_info_get(cpu)); 335 return xics_remap_irq(direct_xirr_info_get(cpu));
351} 336}
352 337
353static int xics_get_irq_lpar(struct pt_regs *regs) 338static unsigned int xics_get_irq_lpar(struct pt_regs *regs)
354{ 339{
355 unsigned int cpu = smp_processor_id(); 340 unsigned int cpu = smp_processor_id();
356 341
@@ -437,8 +422,8 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
437 unsigned long newmask; 422 unsigned long newmask;
438 cpumask_t tmp = CPU_MASK_NONE; 423 cpumask_t tmp = CPU_MASK_NONE;
439 424
440 irq = virt_irq_to_real(irq_offset_down(virq)); 425 irq = (unsigned int)irq_map[virq].hwirq;
441 if (irq == XICS_IPI || irq == NO_IRQ) 426 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
442 return; 427 return;
443 428
444 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); 429 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
@@ -469,6 +454,24 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
469 } 454 }
470} 455}
471 456
457void xics_setup_cpu(void)
458{
459 int cpu = smp_processor_id();
460
461 xics_set_cpu_priority(cpu, 0xff);
462
463 /*
464 * Put the calling processor into the GIQ. This is really only
465 * necessary from a secondary thread as the OF start-cpu interface
466 * performs this function for us on primary threads.
467 *
468 * XXX: undo of teardown on kexec needs this too, as may hotplug
469 */
470 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
471 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
472}
473
474
472static struct irq_chip xics_pic_direct = { 475static struct irq_chip xics_pic_direct = {
473 .typename = " XICS ", 476 .typename = " XICS ",
474 .startup = xics_startup, 477 .startup = xics_startup,
@@ -489,90 +492,245 @@ static struct irq_chip xics_pic_lpar = {
489}; 492};
490 493
491 494
492void xics_setup_cpu(void) 495static int xics_host_match(struct irq_host *h, struct device_node *node)
493{ 496{
494 int cpu = smp_processor_id(); 497 /* IBM machines have interrupt parents of various funky types for things
498 * like vdevices, events, etc... The trick we use here is to match
499 * everything here except the legacy 8259 which is compatible "chrp,iic"
500 */
501 return !device_is_compatible(node, "chrp,iic");
502}
495 503
496 xics_set_cpu_priority(cpu, 0xff); 504static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
505 irq_hw_number_t hw, unsigned int flags)
506{
507 unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
497 508
498 /* 509 pr_debug("xics: map_direct virq %d, hwirq 0x%lx, flags: 0x%x\n",
499 * Put the calling processor into the GIQ. This is really only 510 virq, hw, flags);
500 * necessary from a secondary thread as the OF start-cpu interface 511
501 * performs this function for us on primary threads. 512 if (sense && sense != IRQ_TYPE_LEVEL_LOW)
502 * 513 printk(KERN_WARNING "xics: using unsupported sense 0x%x"
503 * XXX: undo of teardown on kexec needs this too, as may hotplug 514 " for irq %d (h: 0x%lx)\n", flags, virq, hw);
515
516 get_irq_desc(virq)->status |= IRQ_LEVEL;
517 set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
518 return 0;
519}
520
521static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
522 irq_hw_number_t hw, unsigned int flags)
523{
524 unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
525
526 pr_debug("xics: map_lpar virq %d, hwirq 0x%lx, flags: 0x%x\n",
527 virq, hw, flags);
528
529 if (sense && sense != IRQ_TYPE_LEVEL_LOW)
530 printk(KERN_WARNING "xics: using unsupported sense 0x%x"
531 " for irq %d (h: 0x%lx)\n", flags, virq, hw);
532
533 get_irq_desc(virq)->status |= IRQ_LEVEL;
534 set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
535 return 0;
536}
537
538static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
539 u32 *intspec, unsigned int intsize,
540 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
541
542{
543 /* Current xics implementation translates everything
544 * to level. It is not technically right for MSIs but this
545 * is irrelevant at this point. We might get smarter in the future
504 */ 546 */
505 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 547 *out_hwirq = intspec[0];
506 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); 548 *out_flags = IRQ_TYPE_LEVEL_LOW;
549
550 return 0;
551}
552
553static struct irq_host_ops xics_host_direct_ops = {
554 .match = xics_host_match,
555 .map = xics_host_map_direct,
556 .xlate = xics_host_xlate,
557};
558
559static struct irq_host_ops xics_host_lpar_ops = {
560 .match = xics_host_match,
561 .map = xics_host_map_lpar,
562 .xlate = xics_host_xlate,
563};
564
565static void __init xics_init_host(void)
566{
567 struct irq_host_ops *ops;
568
569 if (firmware_has_feature(FW_FEATURE_LPAR))
570 ops = &xics_host_lpar_ops;
571 else
572 ops = &xics_host_direct_ops;
573 xics_host = irq_alloc_host(IRQ_HOST_MAP_TREE, 0, ops,
574 XICS_IRQ_SPURIOUS);
575 BUG_ON(xics_host == NULL);
576 irq_set_default_host(xics_host);
507} 577}
508 578
509void xics_init_IRQ(void) 579static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
580 unsigned long size)
510{ 581{
582#ifdef CONFIG_SMP
511 int i; 583 int i;
512 unsigned long intr_size = 0;
513 struct device_node *np;
514 uint *ireg, ilen, indx = 0;
515 unsigned long intr_base = 0;
516 struct xics_interrupt_node {
517 unsigned long addr;
518 unsigned long size;
519 } intnodes[NR_CPUS];
520 struct irq_chip *chip;
521 584
522 ppc64_boot_msg(0x20, "XICS Init"); 585 /* This may look gross but it's good enough for now, we don't quite
586 * have a hard -> linux processor id matching.
587 */
588 for_each_possible_cpu(i) {
589 if (!cpu_present(i))
590 continue;
591 if (hw_id == get_hard_smp_processor_id(i)) {
592 xics_per_cpu[i] = ioremap(addr, size);
593 return;
594 }
595 }
596#else
597 if (hw_id != 0)
598 return;
599 xics_per_cpu[0] = ioremap(addr, size);
600#endif /* CONFIG_SMP */
601}
523 602
524 ibm_get_xive = rtas_token("ibm,get-xive"); 603static void __init xics_init_one_node(struct device_node *np,
525 ibm_set_xive = rtas_token("ibm,set-xive"); 604 unsigned int *indx)
526 ibm_int_on = rtas_token("ibm,int-on"); 605{
527 ibm_int_off = rtas_token("ibm,int-off"); 606 unsigned int ilen;
607 u32 *ireg;
528 608
529 np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); 609 /* This code does the theorically broken assumption that the interrupt
530 if (!np) 610 * server numbers are the same as the hard CPU numbers.
531 panic("xics_init_IRQ: can't find interrupt presentation"); 611 * This happens to be the case so far but we are playing with fire...
612 * should be fixed one of these days. -BenH.
613 */
614 ireg = (u32 *)get_property(np, "ibm,interrupt-server-ranges", NULL);
532 615
533nextnode: 616 /* Do that ever happen ? we'll know soon enough... but even good'old
534 ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); 617 * f80 does have that property ..
618 */
619 WARN_ON(ireg == NULL);
535 if (ireg) { 620 if (ireg) {
536 /* 621 /*
537 * set node starting index for this node 622 * set node starting index for this node
538 */ 623 */
539 indx = *ireg; 624 *indx = *ireg;
540 } 625 }
541 626 ireg = (u32 *)get_property(np, "reg", &ilen);
542 ireg = (uint *)get_property(np, "reg", &ilen);
543 if (!ireg) 627 if (!ireg)
544 panic("xics_init_IRQ: can't find interrupt reg property"); 628 panic("xics_init_IRQ: can't find interrupt reg property");
545 629
546 while (ilen) { 630 while (ilen >= (4 * sizeof(u32))) {
547 intnodes[indx].addr = (unsigned long)*ireg++ << 32; 631 unsigned long addr, size;
548 ilen -= sizeof(uint); 632
549 intnodes[indx].addr |= *ireg++; 633 /* XXX Use proper OF parsing code here !!! */
550 ilen -= sizeof(uint); 634 addr = (unsigned long)*ireg++ << 32;
551 intnodes[indx].size = (unsigned long)*ireg++ << 32; 635 ilen -= sizeof(u32);
552 ilen -= sizeof(uint); 636 addr |= *ireg++;
553 intnodes[indx].size |= *ireg++; 637 ilen -= sizeof(u32);
554 ilen -= sizeof(uint); 638 size = (unsigned long)*ireg++ << 32;
555 indx++; 639 ilen -= sizeof(u32);
556 if (indx >= NR_CPUS) break; 640 size |= *ireg++;
641 ilen -= sizeof(u32);
642 xics_map_one_cpu(*indx, addr, size);
643 (*indx)++;
644 }
645}
646
647
648static void __init xics_setup_8259_cascade(void)
649{
650 struct device_node *np, *old, *found = NULL;
651 int cascade, naddr;
652 u32 *addrp;
653 unsigned long intack = 0;
654
655 for_each_node_by_type(np, "interrupt-controller")
656 if (device_is_compatible(np, "chrp,iic")) {
657 found = np;
658 break;
659 }
660 if (found == NULL) {
661 printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
662 return;
557 } 663 }
664 cascade = irq_of_parse_and_map(found, 0);
665 if (cascade == NO_IRQ) {
666 printk(KERN_ERR "xics: failed to map cascade interrupt");
667 return;
668 }
669 pr_debug("xics: cascade mapped to irq %d\n", cascade);
670
671 for (old = of_node_get(found); old != NULL ; old = np) {
672 np = of_get_parent(old);
673 of_node_put(old);
674 if (np == NULL)
675 break;
676 if (strcmp(np->name, "pci") != 0)
677 continue;
678 addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL);
679 if (addrp == NULL)
680 continue;
681 naddr = prom_n_addr_cells(np);
682 intack = addrp[naddr-1];
683 if (naddr > 1)
684 intack |= ((unsigned long)addrp[naddr-2]) << 32;
685 }
686 if (intack)
687 printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack);
688 i8259_init(found, intack);
689 of_node_put(found);
690 set_irq_chained_handler(cascade, pseries_8259_cascade);
691}
558 692
559 np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation"); 693void __init xics_init_IRQ(void)
560 if ((indx < NR_CPUS) && np) goto nextnode; 694{
695 int i;
696 struct device_node *np;
697 u32 *ireg, ilen, indx = 0;
698 int found = 0;
699
700 ppc64_boot_msg(0x20, "XICS Init");
701
702 ibm_get_xive = rtas_token("ibm,get-xive");
703 ibm_set_xive = rtas_token("ibm,set-xive");
704 ibm_int_on = rtas_token("ibm,int-on");
705 ibm_int_off = rtas_token("ibm,int-off");
706
707 for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
708 found = 1;
709 if (firmware_has_feature(FW_FEATURE_LPAR))
710 break;
711 xics_init_one_node(np, &indx);
712 }
713 if (found == 0)
714 return;
715
716 xics_init_host();
561 717
562 /* Find the server numbers for the boot cpu. */ 718 /* Find the server numbers for the boot cpu. */
563 for (np = of_find_node_by_type(NULL, "cpu"); 719 for (np = of_find_node_by_type(NULL, "cpu");
564 np; 720 np;
565 np = of_find_node_by_type(np, "cpu")) { 721 np = of_find_node_by_type(np, "cpu")) {
566 ireg = (uint *)get_property(np, "reg", &ilen); 722 ireg = (u32 *)get_property(np, "reg", &ilen);
567 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { 723 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
568 ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", 724 ireg = (u32 *)get_property(np,
569 &ilen); 725 "ibm,ppc-interrupt-gserver#s",
726 &ilen);
570 i = ilen / sizeof(int); 727 i = ilen / sizeof(int);
571 if (ireg && i > 0) { 728 if (ireg && i > 0) {
572 default_server = ireg[0]; 729 default_server = ireg[0];
573 default_distrib_server = ireg[i-1]; /* take last element */ 730 /* take last element */
731 default_distrib_server = ireg[i-1];
574 } 732 }
575 ireg = (uint *)get_property(np, 733 ireg = (u32 *)get_property(np,
576 "ibm,interrupt-server#-size", NULL); 734 "ibm,interrupt-server#-size", NULL);
577 if (ireg) 735 if (ireg)
578 interrupt_server_size = *ireg; 736 interrupt_server_size = *ireg;
@@ -581,102 +739,48 @@ nextnode:
581 } 739 }
582 of_node_put(np); 740 of_node_put(np);
583 741
584 intr_base = intnodes[0].addr; 742 if (firmware_has_feature(FW_FEATURE_LPAR))
585 intr_size = intnodes[0].size; 743 ppc_md.get_irq = xics_get_irq_lpar;
586 744 else
587 if (firmware_has_feature(FW_FEATURE_LPAR)) {
588 ppc_md.get_irq = xics_get_irq_lpar;
589 chip = &xics_pic_lpar;
590 } else {
591#ifdef CONFIG_SMP
592 for_each_possible_cpu(i) {
593 int hard_id;
594
595 /* FIXME: Do this dynamically! --RR */
596 if (!cpu_present(i))
597 continue;
598
599 hard_id = get_hard_smp_processor_id(i);
600 xics_per_cpu[i] = ioremap(intnodes[hard_id].addr,
601 intnodes[hard_id].size);
602 }
603#else
604 xics_per_cpu[0] = ioremap(intr_base, intr_size);
605#endif /* CONFIG_SMP */
606 ppc_md.get_irq = xics_get_irq_direct; 745 ppc_md.get_irq = xics_get_irq_direct;
607 chip = &xics_pic_direct;
608
609 }
610
611 for (i = irq_offset_value(); i < NR_IRQS; ++i) {
612 /* All IRQs on XICS are level for now. MSI code may want to modify
613 * that for reporting purposes
614 */
615 get_irq_desc(i)->status |= IRQ_LEVEL;
616 set_irq_chip_and_handler(i, chip, handle_fasteoi_irq);
617 }
618 746
619 xics_setup_cpu(); 747 xics_setup_cpu();
620 748
621 ppc64_boot_msg(0x21, "XICS Done"); 749 xics_setup_8259_cascade();
622}
623 750
624static int xics_setup_8259_cascade(void) 751 ppc64_boot_msg(0x21, "XICS Done");
625{
626 struct device_node *np;
627 uint *ireg;
628
629 np = of_find_node_by_type(NULL, "interrupt-controller");
630 if (np == NULL) {
631 printk(KERN_WARNING "xics: no ISA interrupt controller\n");
632 xics_irq_8259_cascade_real = -1;
633 xics_irq_8259_cascade = -1;
634 return 0;
635 }
636
637 ireg = (uint *) get_property(np, "interrupts", NULL);
638 if (!ireg)
639 panic("xics_init_IRQ: can't find ISA interrupts property");
640
641 xics_irq_8259_cascade_real = *ireg;
642 xics_irq_8259_cascade = irq_offset_up
643 (virt_irq_create_mapping(xics_irq_8259_cascade_real));
644 i8259_init(0, 0);
645 of_node_put(np);
646
647 xics_set_irq_revmap(xics_irq_8259_cascade);
648 set_irq_chained_handler(xics_irq_8259_cascade, pSeries_8259_cascade);
649
650 return 0;
651} 752}
652arch_initcall(xics_setup_8259_cascade);
653 753
654 754
655#ifdef CONFIG_SMP 755#ifdef CONFIG_SMP
656void xics_request_IPIs(void) 756void xics_request_IPIs(void)
657{ 757{
658 virt_irq_to_real_map[XICS_IPI] = XICS_IPI; 758 unsigned int ipi;
759
760 ipi = irq_create_mapping(xics_host, XICS_IPI, 0);
761 BUG_ON(ipi == NO_IRQ);
659 762
660 /* 763 /*
661 * IPIs are marked IRQF_DISABLED as they must run with irqs 764 * IPIs are marked IRQF_DISABLED as they must run with irqs
662 * disabled 765 * disabled
663 */ 766 */
664 set_irq_handler(irq_offset_up(XICS_IPI), handle_percpu_irq); 767 set_irq_handler(ipi, handle_percpu_irq);
665 if (firmware_has_feature(FW_FEATURE_LPAR)) 768 if (firmware_has_feature(FW_FEATURE_LPAR))
666 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action_lpar, 769 request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
667 SA_INTERRUPT, "IPI", NULL); 770 "IPI", NULL);
668 else 771 else
669 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action_direct, 772 request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
670 SA_INTERRUPT, "IPI", NULL); 773 "IPI", NULL);
671} 774}
672#endif /* CONFIG_SMP */ 775#endif /* CONFIG_SMP */
673 776
674void xics_teardown_cpu(int secondary) 777void xics_teardown_cpu(int secondary)
675{ 778{
676 struct irq_desc *desc = get_irq_desc(irq_offset_up(XICS_IPI));
677 int cpu = smp_processor_id(); 779 int cpu = smp_processor_id();
780 unsigned int ipi;
781 struct irq_desc *desc;
678 782
679 xics_set_cpu_priority(cpu, 0); 783 xics_set_cpu_priority(cpu, 0);
680 784
681 /* 785 /*
682 * we need to EOI the IPI if we got here from kexec down IPI 786 * we need to EOI the IPI if we got here from kexec down IPI
@@ -685,6 +789,11 @@ void xics_teardown_cpu(int secondary)
685 * should we be flagging idle loop instead? 789 * should we be flagging idle loop instead?
686 * or creating some task to be scheduled? 790 * or creating some task to be scheduled?
687 */ 791 */
792
793 ipi = irq_find_mapping(xics_host, XICS_IPI);
794 if (ipi == XICS_IRQ_SPURIOUS)
795 return;
796 desc = get_irq_desc(ipi);
688 if (desc->chip && desc->chip->eoi) 797 if (desc->chip && desc->chip->eoi)
689 desc->chip->eoi(XICS_IPI); 798 desc->chip->eoi(XICS_IPI);
690 799
@@ -694,8 +803,8 @@ void xics_teardown_cpu(int secondary)
694 */ 803 */
695 if (secondary) 804 if (secondary)
696 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 805 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
697 (1UL << interrupt_server_size) - 1 - 806 (1UL << interrupt_server_size) - 1 -
698 default_distrib_server, 0); 807 default_distrib_server, 0);
699} 808}
700 809
701#ifdef CONFIG_HOTPLUG_CPU 810#ifdef CONFIG_HOTPLUG_CPU
@@ -723,15 +832,15 @@ void xics_migrate_irqs_away(void)
723 unsigned long flags; 832 unsigned long flags;
724 833
725 /* We cant set affinity on ISA interrupts */ 834 /* We cant set affinity on ISA interrupts */
726 if (virq < irq_offset_value()) 835 if (virq < NUM_ISA_INTERRUPTS)
727 continue; 836 continue;
728 837 if (irq_map[virq].host != xics_host)
729 desc = get_irq_desc(virq); 838 continue;
730 irq = virt_irq_to_real(irq_offset_down(virq)); 839 irq = (unsigned int)irq_map[virq].hwirq;
731
732 /* We need to get IPIs still. */ 840 /* We need to get IPIs still. */
733 if (irq == XICS_IPI || irq == NO_IRQ) 841 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
734 continue; 842 continue;
843 desc = get_irq_desc(virq);
735 844
736 /* We only need to migrate enabled IRQS */ 845 /* We only need to migrate enabled IRQS */
737 if (desc == NULL || desc->chip == NULL 846 if (desc == NULL || desc->chip == NULL