]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/platforms/pseries/xics.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / pseries / xics.c
index 9ecf75fe9b1485a9f710011effc8ee018243ceec..ebebc28fe89545c8658c6410bb70203fe51bcda3 100644 (file)
@@ -9,7 +9,6 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
 
 #include <linux/types.h>
 #include <linux/threads.h>
@@ -160,6 +159,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
 
 /* High level handlers and init code */
 
+static void xics_update_irq_servers(void)
+{
+       int i, j;
+       struct device_node *np;
+       u32 ilen;
+       const u32 *ireg, *isize;
+       u32 hcpuid;
+
+       /* Find the server numbers for the boot cpu. */
+       np = of_get_cpu_node(boot_cpuid, NULL);
+       BUG_ON(!np);
+
+       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+       if (!ireg) {
+               of_node_put(np);
+               return;
+       }
+
+       i = ilen / sizeof(int);
+       hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+       /* Global interrupt distribution server is specified in the last
+        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+        * entry fom this property for current boot cpu id and use it as
+        * default distribution server
+        */
+       for (j = 0; j < i; j += 2) {
+               if (ireg[j] == hcpuid) {
+                       default_server = hcpuid;
+                       default_distrib_server = ireg[j+1];
+
+                       isize = of_get_property(np,
+                                       "ibm,interrupt-server#-size", NULL);
+                       if (isize)
+                               interrupt_server_size = *isize;
+               }
+       }
+
+       of_node_put(np);
+}
 
 #ifdef CONFIG_SMP
 static int get_irq_server(unsigned int virq, unsigned int strict_check)
@@ -169,6 +208,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
        cpumask_t cpumask = irq_desc[virq].affinity;
        cpumask_t tmp = CPU_MASK_NONE;
 
+       if (! cpu_isset(default_server, cpu_online_map))
+               xics_update_irq_servers();
+
        if (!distribute_irqs)
                return default_server;
 
@@ -473,6 +515,8 @@ static struct irq_chip xics_pic_lpar = {
        .set_affinity = xics_set_affinity
 };
 
+/* Points to the irq_chip we're actually using */
+static struct irq_chip *xics_irq_chip;
 
 static int xics_host_match(struct irq_host *h, struct device_node *node)
 {
@@ -483,23 +527,13 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
        return !of_device_is_compatible(node, "chrp,iic");
 }
 
-static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
-                               irq_hw_number_t hw)
-{
-       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
-
-       get_irq_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
-       return 0;
-}
-
-static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
-                             irq_hw_number_t hw)
+static int xics_host_map(struct irq_host *h, unsigned int virq,
+                        irq_hw_number_t hw)
 {
-       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
+       pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
 
        get_irq_desc(virq)->status |= IRQ_LEVEL;
-       set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
+       set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
        return 0;
 }
 
@@ -518,27 +552,20 @@ static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
        return 0;
 }
 
-static struct irq_host_ops xics_host_direct_ops = {
-       .match = xics_host_match,
-       .map = xics_host_map_direct,
-       .xlate = xics_host_xlate,
-};
-
-static struct irq_host_ops xics_host_lpar_ops = {
+static struct irq_host_ops xics_host_ops = {
        .match = xics_host_match,
-       .map = xics_host_map_lpar,
+       .map = xics_host_map,
        .xlate = xics_host_xlate,
 };
 
 static void __init xics_init_host(void)
 {
-       struct irq_host_ops *ops;
-
        if (firmware_has_feature(FW_FEATURE_LPAR))
-               ops = &xics_host_lpar_ops;
+               xics_irq_chip = &xics_pic_lpar;
        else
-               ops = &xics_host_direct_ops;
-       xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops,
+               xics_irq_chip = &xics_pic_direct;
+
+       xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
                                   XICS_IRQ_SPURIOUS);
        BUG_ON(xics_host == NULL);
        irq_set_default_host(xics_host);
@@ -612,60 +639,11 @@ static void __init xics_init_one_node(struct device_node *np,
        }
 }
 
-
-static void __init xics_setup_8259_cascade(void)
-{
-       struct device_node *np, *old, *found = NULL;
-       int cascade, naddr;
-       const u32 *addrp;
-       unsigned long intack = 0;
-
-       for_each_node_by_type(np, "interrupt-controller")
-               if (of_device_is_compatible(np, "chrp,iic")) {
-                       found = np;
-                       break;
-               }
-       if (found == NULL) {
-               printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
-               return;
-       }
-       cascade = irq_of_parse_and_map(found, 0);
-       if (cascade == NO_IRQ) {
-               printk(KERN_ERR "xics: failed to map cascade interrupt");
-               return;
-       }
-       pr_debug("xics: cascade mapped to irq %d\n", cascade);
-
-       for (old = of_node_get(found); old != NULL ; old = np) {
-               np = of_get_parent(old);
-               of_node_put(old);
-               if (np == NULL)
-                       break;
-               if (strcmp(np->name, "pci") != 0)
-                       continue;
-               addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
-               if (addrp == NULL)
-                       continue;
-               naddr = of_n_addr_cells(np);
-               intack = addrp[naddr-1];
-               if (naddr > 1)
-                       intack |= ((unsigned long)addrp[naddr-2]) << 32;
-       }
-       if (intack)
-               printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack);
-       i8259_init(found, intack);
-       of_node_put(found);
-       set_irq_chained_handler(cascade, pseries_8259_cascade);
-}
-
 void __init xics_init_IRQ(void)
 {
-       int i, j;
        struct device_node *np;
-       u32 ilen, indx = 0;
-       const u32 *ireg, *isize;
+       u32 indx = 0;
        int found = 0;
-       u32 hcpuid;
 
        ppc64_boot_msg(0x20, "XICS Init");
 
@@ -684,34 +662,7 @@ void __init xics_init_IRQ(void)
                return;
 
        xics_init_host();
-
-       /* Find the server numbers for the boot cpu. */
-       np = of_get_cpu_node(boot_cpuid, NULL);
-       BUG_ON(!np);
-       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
-       if (!ireg)
-               goto skip_gserver_check;
-       i = ilen / sizeof(int);
-       hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
-       /* Global interrupt distribution server is specified in the last
-        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
-        * entry fom this property for current boot cpu id and use it as
-        * default distribution server
-        */
-       for (j = 0; j < i; j += 2) {
-               if (ireg[j] == hcpuid) {
-                       default_server = hcpuid;
-                       default_distrib_server = ireg[j+1];
-
-                       isize = of_get_property(np,
-                                       "ibm,interrupt-server#-size", NULL);
-                       if (isize)
-                               interrupt_server_size = *isize;
-               }
-       }
-skip_gserver_check:
-       of_node_put(np);
+       xics_update_irq_servers();
 
        if (firmware_has_feature(FW_FEATURE_LPAR))
                ppc_md.get_irq = xics_get_irq_lpar;
@@ -720,8 +671,6 @@ skip_gserver_check:
 
        xics_setup_cpu();
 
-       xics_setup_8259_cascade();
-
        ppc64_boot_msg(0x21, "XICS Done");
 }
 
@@ -750,7 +699,7 @@ void xics_request_IPIs(void)
 }
 #endif /* CONFIG_SMP */
 
-void xics_teardown_cpu()
+void xics_teardown_cpu(void)
 {
        int cpu = smp_processor_id();