X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc64%2Fkernel%2Fxics.c;h=1d9cf20a29007258cd4af5ad82b16bf329317179;hb=5e3b93f248c98873cc843e83092bb8da92ac85a2;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..1d9cf20a2 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,14 +239,15 @@ 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 allcpus = CPU_MASK_ALL; + 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)) { + if (cpus_equal(cpumask, allcpus)) { server = default_distrib_server; } else { cpus_and(tmp, cpu_online_map, cpumask); @@ -274,7 +276,7 @@ static int get_irq_server(unsigned int irq) static void xics_enable_irq(unsigned int virq) { unsigned int irq; - int call_status; + long call_status; unsigned int server; irq = virt_irq_to_real(irq_offset_down(virq)); @@ -285,23 +287,23 @@ 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 " - "returned %x\n", irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_set_xive " + "returned %lx\n", irq, call_status); return; } /* 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 " - "returned %x\n", irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_int_on " + "returned %lx\n", irq, call_status); return; } } static void xics_disable_real_irq(unsigned int irq) { - int call_status; + long call_status; unsigned int server; if (irq == XICS_IPI) @@ -309,8 +311,8 @@ 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: " - "ibm_int_off returned %x\n", irq, call_status); + printk(KERN_ERR "xics_disable_real_irq: irq=%x: " + "ibm_int_off returned %lx\n", irq, call_status); return; } @@ -318,8 +320,8 @@ 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)" - " returned %x\n", irq, call_status); + printk(KERN_ERR "xics_disable_irq: irq=%x: ibm_set_xive(0xff)" + " returned %lx\n", irq, call_status); return; } } @@ -355,6 +357,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 +385,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 +396,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 +470,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 +485,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 +529,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 +559,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 +590,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 +605,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 @@ -596,25 +613,26 @@ void xics_request_IPIs(void) static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) { unsigned int irq; - int status; - int xics_status[2]; + long status; + unsigned long xics_status[2]; unsigned long newmask; + cpumask_t allcpus = CPU_MASK_ALL; cpumask_t tmp = CPU_MASK_NONE; irq = virt_irq_to_real(irq_offset_down(virq)); if (irq == XICS_IPI || irq == NO_IRQ) return; - status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); + status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, irq); if (status) { printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive " - "returns %d\n", irq, status); + "returns %ld\n", irq, status); return; } /* For the moment only implement delivery to all cpus or one cpu */ - if (cpus_equal(cpumask, CPU_MASK_ALL)) { + if (cpus_equal(cpumask, allcpus)) { newmask = default_distrib_server; } else { cpus_and(tmp, cpu_online_map, cpumask); @@ -627,8 +645,8 @@ 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 " - "returns %d\n", irq, status); + printk(KERN_ERR "xics_set_affinity irq=%d ibm,set-xive " + "returns %ld\n", irq, status); return; } } @@ -639,9 +657,11 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) 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(); + const unsigned long giqs = 9005UL; /* Global Interrupt Queue Server */ + unsigned long status = 0; + unsigned int irq, cpu = smp_processor_id(); + unsigned long xics_status[2]; + unsigned long flags; BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE); @@ -651,27 +671,19 @@ void xics_migrate_irqs_away(void) /* Refuse any new interrupts... */ rtas_call(set_indicator, 3, 1, &status, giqs, - hard_smp_processor_id(), 0); + hard_smp_processor_id(), 0UL); WARN_ON(status != 0); /* Allow IPIs again... */ 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 */ @@ -682,11 +694,12 @@ void xics_migrate_irqs_away(void) spin_lock_irqsave(&desc->lock, flags); - status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); + status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, + irq); if (status) { printk(KERN_ERR "migrate_irqs_away: irq=%d " - "ibm,get-xive returns %d\n", - virq, status); + "ibm,get-xive returns %ld\n", + irq, status); goto unlock; } @@ -699,20 +712,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 " - "ibm,set-xive returns %d\n", - virq, status); + printk(KERN_ERR "migrate_irqs_away irq=%d " + "ibm,set-xive returns %ld\n", + irq, status); unlock: spin_unlock_irqrestore(&desc->lock, flags); } + } #endif