From 407e24a0c78f585c228ec7e1152a9b23e262b200 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 26 Jan 2007 19:08:02 -0800 Subject: [PATCH] [POWERPC] ps3: smp interrupt fixes PS3 fixups for interrups on SMP. Fixes the alignment of the interrupt status bitmap, changes the hypervisor interrupt calls to the '_ext' versions that take an explicit processor thread ID. Signed-off-by: Geoff Levand Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/ps3/interrupt.c | 60 +++++++++++++------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 9c8f3b568a..7a4ca056dd 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -317,22 +317,23 @@ struct ps3_bmp { unsigned long unused_1[3]; unsigned long mask; unsigned long unused_2[3]; - } __attribute__ ((packed)); + } __attribute__ ((aligned (64))); + spinlock_t lock; unsigned long ipi_debug_brk_mask; }; /** * struct ps3_private - a per cpu data structure - * @node: HV node id - * @cpu: HV thread id - * @bmp: an HV ps3_bmp structure + * @bmp: ps3_bmp structure + * @node: HV logical_ppe_id + * @cpu: HV thread_id */ struct ps3_private { + struct ps3_bmp bmp; unsigned long node; unsigned int cpu; - struct ps3_bmp bmp; }; #if defined(DEBUG) @@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int virq) spin_lock_irqsave(&pd->bmp.lock, flags); pd->bmp.mask &= ~(0x8000000000000000UL >> virq); - spin_unlock_irqrestore(&pd->bmp.lock, flags); - lv1_did_update_interrupt_mask(pd->node, pd->cpu); + spin_unlock_irqrestore(&pd->bmp.lock, flags); } static void ps3_chip_unmask(unsigned int virq) @@ -406,14 +406,14 @@ static void ps3_chip_unmask(unsigned int virq) spin_lock_irqsave(&pd->bmp.lock, flags); pd->bmp.mask |= (0x8000000000000000UL >> virq); - spin_unlock_irqrestore(&pd->bmp.lock, flags); - lv1_did_update_interrupt_mask(pd->node, pd->cpu); + spin_unlock_irqrestore(&pd->bmp.lock, flags); } static void ps3_chip_eoi(unsigned int virq) { - lv1_end_of_interrupt(virq); + const struct ps3_private *pd = get_irq_chip_data(virq); + lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq); } static struct irq_chip irq_chip = { @@ -426,10 +426,12 @@ static struct irq_chip irq_chip = { static void ps3_host_unmap(struct irq_host *h, unsigned int virq) { int result; + const struct ps3_private *pd = get_irq_chip_data(virq); - pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq); + pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, + pd->node, pd->cpu, virq); - lv1_disconnect_irq_plug(virq); + lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); result = set_irq_chip_data(virq, NULL); BUG_ON(result); @@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hwirq) { int result; - unsigned int cpu; + struct ps3_private *pd = &__get_cpu_var(ps3_private); - pr_debug(" -> %s:%d\n", __func__, __LINE__); - pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq, - virq); + pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__, + __LINE__, pd->node, pd->cpu, hwirq, virq); - /* bind this virq to a cpu */ + /* Binds this virq to pd->cpu (current cpu) */ - preempt_disable(); - cpu = smp_processor_id(); - result = lv1_connect_irq_plug(virq, hwirq); - preempt_enable(); + result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0); if (result) { - pr_info("%s:%d: lv1_connect_irq_plug failed:" + pr_info("%s:%d: lv1_connect_irq_plug_ext failed:" " %s\n", __func__, __LINE__, ps3_result(result)); return -EPERM; } - result = set_irq_chip_data(virq, &per_cpu(ps3_private, cpu)); + result = set_irq_chip_data(virq, pd); BUG_ON(result); set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); - pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void) void __init ps3_init_IRQ(void) { int result; - unsigned long node; unsigned cpu; struct irq_host *host; - lv1_get_logical_ppe_id(&node); - host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, PS3_INVALID_OUTLET); irq_set_default_host(host); @@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void) for_each_possible_cpu(cpu) { struct ps3_private *pd = &per_cpu(ps3_private, cpu); - pd->node = node; - pd->cpu = cpu; + lv1_get_logical_ppe_id(&pd->node); + pd->cpu = get_hard_smp_processor_id(cpu); spin_lock_init(&pd->bmp.lock); - result = lv1_configure_irq_state_bitmap(node, cpu, - ps3_mm_phys_to_lpar(__pa(&pd->bmp.status))); + pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__, + __LINE__, pd->node, pd->cpu, + ps3_mm_phys_to_lpar(__pa(&pd->bmp))); + + result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu, + ps3_mm_phys_to_lpar(__pa(&pd->bmp))); if (result) pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" -- 2.39.5