[POWERPC] ps3: smp interrupt fixes
authorGeoff Levand <geoffrey.levand@am.sony.com>
Sat, 27 Jan 2007 03:08:02 +0000 (19:08 -0800)
committerPaul Mackerras <paulus@samba.org>
Wed, 7 Feb 2007 03:03:18 +0000 (14:03 +1100)
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 <geoffrey.levand@am.sony.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/ps3/interrupt.c

index 9c8f3b5..7a4ca05 100644 (file)
@@ -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:"