ps3: smp interrupt fixes
Subsystems (2)
PATCH 7/16 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 <[email protected]>
--- arch/powerpc/platforms/ps3/interrupt.c | 64 +++++++++++++++------------------ 1 files changed, 31 insertions(+), 33 deletions(-)
arch/powerpc/platforms/ps3/interrupt.c +31 -33
@@ -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 vspin_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 intspin_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 irq_hw_number_t hwirq) {int result; -unsigned int cpu; +struct ps3_private *pd = &__get_cpu_var (ps3_private); + +pr_debug ("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n" , __func__, + __LINE__, pd->node, pd->cpu, hwirq, virq); -pr_debug (" -> %s:%d\n" , __func__, __LINE__); -pr_debug ("%s:%d: hwirq %lu => virq %u\n" , __func__, __LINE__, hwirq, - virq); - -/* bind this virq to a cpu */ - -preempt_disable (); - cpu =smp_processor_id (); - result =lv1_connect_irq_plug (virq, hwirq); -preempt_enable (); +/* Binds this virq to pd->cpu (current cpu) */ + + 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:"