X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc64%2Fkernel%2Fxics.c;h=35785ac01f06f6f5bbc768bc638271238f073468;hb=90ad8654ffeb336af8c878fdf7bc72e2ac72467a;hp=c9f950c2cea37e5d3b5ed401ec96900213a95a88;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index c9f950c2c..35785ac01 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -189,7 +190,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value) val64); } -void pSeriesLP_cppr_info(int n_cpu, u8 value) +static void pSeriesLP_cppr_info(int n_cpu, u8 value) { unsigned long lpar_rc; @@ -238,13 +239,13 @@ static unsigned int real_irq_to_virt(unsigned int real_irq) #ifdef CONFIG_SMP static int get_irq_server(unsigned int irq) { + cpumask_t cpumask = irq_affinity[irq]; + cpumask_t tmp = CPU_MASK_NONE; unsigned int server; #ifdef CONFIG_IRQ_ALL_CPUS /* For the moment only implement delivery to all cpus or one cpu */ if (smp_threads_ready) { - cpumask_t cpumask = irq_affinity[irq]; - cpumask_t tmp = CPU_MASK_NONE; if (cpus_equal(cpumask, CPU_MASK_ALL)) { server = default_distrib_server; } else { @@ -285,7 +286,7 @@ static void xics_enable_irq(unsigned int virq) call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive " + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_set_xive " "returned %x\n", irq, call_status); return; } @@ -293,7 +294,7 @@ static void xics_enable_irq(unsigned int virq) /* Now unmask the interrupt (often a no-op) */ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on " + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_int_on " "returned %x\n", irq, call_status); return; } @@ -309,7 +310,7 @@ static void xics_disable_real_irq(unsigned int irq) call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); if (call_status != 0) { - printk(KERN_ERR "xics_disable_real_irq: irq=%d: " + printk(KERN_ERR "xics_disable_real_irq: irq=%x: " "ibm_int_off returned %x\n", irq, call_status); return; } @@ -318,7 +319,7 @@ static void xics_disable_real_irq(unsigned int irq) /* Have to set XIVE to 0xff to be able to remove a slot */ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff); if (call_status != 0) { - printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)" + printk(KERN_ERR "xics_disable_irq: irq=%x: ibm_set_xive(0xff)" " returned %x\n", irq, call_status); return; } @@ -355,6 +356,8 @@ static void xics_mask_and_ack_irq(unsigned int irq) } } +extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); + int xics_get_irq(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); @@ -381,7 +384,7 @@ int xics_get_irq(struct pt_regs *regs) if (irq == NO_IRQ) irq = real_irq_to_virt_slowpath(vec); if (irq == NO_IRQ) { - printk(KERN_ERR "Interrupt %d (real) is invalid," + printk(KERN_ERR "Interrupt 0x%x (real) is invalid," " disabling it.\n", vec); xics_disable_real_irq(vec); } else @@ -392,6 +395,8 @@ int xics_get_irq(struct pt_regs *regs) #ifdef CONFIG_SMP +extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; + irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -464,11 +469,13 @@ void xics_init_IRQ(void) ibm_int_off = rtas_token("ibm,int-off"); np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); - if (!np) - panic("xics_init_IRQ: can't find interrupt presentation"); - + if (!np) { + printk(KERN_WARNING "Can't find Interrupt Presentation\n"); + udbg_printf("Can't find Interrupt Presentation\n"); + while (1); + } nextnode: - ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); + ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", 0); if (ireg) { /* * set node starting index for this node @@ -477,8 +484,11 @@ nextnode: } ireg = (uint *)get_property(np, "reg", &ilen); - if (!ireg) - panic("xics_init_IRQ: can't find interrupt reg property"); + if (!ireg) { + printk(KERN_WARNING "Can't find Interrupt Reg Property\n"); + udbg_printf("Can't find Interrupt Reg Property\n"); + while (1); + } while (ilen) { inodes[indx].addr = (unsigned long long)*ireg++ << 32; @@ -518,14 +528,16 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA interrupt controller\n"); + printk(KERN_WARNING "xics: no ISA Interrupt Controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { - ireg = (uint *) get_property(np, "interrupts", NULL); - if (!ireg) - panic("xics_init_IRQ: can't find ISA interrupts property"); - + ireg = (uint *) get_property(np, "interrupts", 0); + if (!ireg) { + printk(KERN_WARNING "Can't find ISA Interrupts Property\n"); + udbg_printf("Can't find ISA Interrupts Property\n"); + while (1); + } xics_irq_8259_cascade_real = *ireg; xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); @@ -546,8 +558,13 @@ nextnode: xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC_PSERIES + /* actually iSeries does not use any of xics...but it has link dependencies + * for now, except this new one... + */ } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; +#endif } xics_8259_pic.enable = i8259_pic.enable; @@ -572,9 +589,8 @@ static int __init xics_setup_i8259(void) if (naca->interrupt_controller == IC_PPC_XIC && xics_irq_8259_cascade != -1) { if (request_irq(irq_offset_up(xics_irq_8259_cascade), - no_action, 0, "8259 cascade", NULL)) - printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " - "cascade\n"); + no_action, 0, "8259 cascade", 0)) + printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); i8259_init(); } return 0; @@ -588,7 +604,7 @@ void xics_request_IPIs(void) /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT, - "IPI", NULL); + "IPI", 0); get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU; } #endif @@ -627,7 +643,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) irq, newmask, xics_status[1]); if (status) { - printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive " + printk(KERN_ERR "xics_set_affinity irq=%d ibm,set-xive " "returns %d\n", irq, status); return; } @@ -641,7 +657,9 @@ void xics_migrate_irqs_away(void) int set_indicator = rtas_token("set-indicator"); const unsigned int giqs = 9005UL; /* Global Interrupt Queue Server */ int status = 0; - unsigned int irq, virq, cpu = smp_processor_id(); + unsigned int irq, cpu = smp_processor_id(); + int xics_status[2]; + unsigned long flags; BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE); @@ -658,20 +676,12 @@ void xics_migrate_irqs_away(void) ops->cppr_info(cpu, DEFAULT_PRIORITY); iosync(); - for_each_irq(virq) { - irq_desc_t *desc; - int xics_status[2]; - unsigned long flags; - - /* We cant set affinity on ISA interrupts */ - if (virq < irq_offset_value()) - continue; - - desc = get_irq_desc(virq); - irq = virt_irq_to_real(irq_offset_down(virq)); + printk(KERN_WARNING "HOTPLUG: Migrating IRQs away\n"); + for_each_irq(irq) { + irq_desc_t *desc = get_irq_desc(irq); /* We need to get IPIs still. */ - if (irq == XICS_IPI || irq == NO_IRQ) + if (irq_offset_down(irq) == XICS_IPI) continue; /* We only need to migrate enabled IRQS */ @@ -686,7 +696,7 @@ void xics_migrate_irqs_away(void) if (status) { printk(KERN_ERR "migrate_irqs_away: irq=%d " "ibm,get-xive returns %d\n", - virq, status); + irq, status); goto unlock; } @@ -699,20 +709,21 @@ void xics_migrate_irqs_away(void) goto unlock; printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n", - virq, cpu); + irq, cpu); /* Reset affinity to all cpus */ xics_status[0] = default_distrib_server; - status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, - xics_status[0], xics_status[1]); + status = rtas_call(ibm_set_xive, 3, 1, NULL, + irq, xics_status[0], xics_status[1]); if (status) - printk(KERN_ERR "migrate_irqs_away: irq=%d " + printk(KERN_ERR "migrate_irqs_away irq=%d " "ibm,set-xive returns %d\n", - virq, status); + irq, status); unlock: spin_unlock_irqrestore(&desc->lock, flags); } + } #endif