sparc64: Fix IRQ ->set_affinity() methods.
David S. Miller [Thu, 21 Jan 2010 03:30:49 +0000 (19:30 -0800)]
As noted by Benjamin Herrenschmidt, the generic IRQ layer
only sets irq_desc[irq].affinity after ->set_affinity()
succeeds.

So we have to use the passed in cpumask.

Signed-off-by: David S. Miller <davem@davemloft.net>

arch/sparc/kernel/irq_64.c

index 8d6882b..f2179cc 100644 (file)
@@ -250,12 +250,12 @@ struct irq_handler_data {
 };
 
 #ifdef CONFIG_SMP
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
 {
        cpumask_t mask;
        int cpuid;
 
-       cpumask_copy(&mask, irq_desc[virt_irq].affinity);
+       cpumask_copy(&mask, affinity);
        if (cpus_equal(mask, cpu_online_map)) {
                cpuid = map_to_cpu(virt_irq);
        } else {
@@ -268,7 +268,7 @@ static int irq_choose_cpu(unsigned int virt_irq)
        return cpuid;
 }
 #else
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
 {
        return real_hard_smp_processor_id();
 }
@@ -282,7 +282,8 @@ static void sun4u_irq_enable(unsigned int virt_irq)
                unsigned long cpuid, imap, val;
                unsigned int tid;
 
-               cpuid = irq_choose_cpu(virt_irq);
+               cpuid = irq_choose_cpu(virt_irq,
+                                      irq_desc[virt_irq].affinity);
                imap = data->imap;
 
                tid = sun4u_compute_tid(imap, cpuid);
@@ -299,7 +300,24 @@ static void sun4u_irq_enable(unsigned int virt_irq)
 static int sun4u_set_affinity(unsigned int virt_irq,
                               const struct cpumask *mask)
 {
-       sun4u_irq_enable(virt_irq);
+       struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+
+       if (likely(data)) {
+               unsigned long cpuid, imap, val;
+               unsigned int tid;
+
+               cpuid = irq_choose_cpu(virt_irq, mask);
+               imap = data->imap;
+
+               tid = sun4u_compute_tid(imap, cpuid);
+
+               val = upa_readq(imap);
+               val &= ~(IMAP_TID_UPA | IMAP_TID_JBUS |
+                        IMAP_AID_SAFARI | IMAP_NID_SAFARI);
+               val |= tid | IMAP_VALID;
+               upa_writeq(val, imap);
+               upa_writeq(ICLR_IDLE, data->iclr);
+       }
 
        return 0;
 }
@@ -340,7 +358,8 @@ static void sun4u_irq_eoi(unsigned int virt_irq)
 static void sun4v_irq_enable(unsigned int virt_irq)
 {
        unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-       unsigned long cpuid = irq_choose_cpu(virt_irq);
+       unsigned long cpuid = irq_choose_cpu(virt_irq,
+                                            irq_desc[virt_irq].affinity);
        int err;
 
        err = sun4v_intr_settarget(ino, cpuid);
@@ -361,7 +380,7 @@ static int sun4v_set_affinity(unsigned int virt_irq,
                               const struct cpumask *mask)
 {
        unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-       unsigned long cpuid = irq_choose_cpu(virt_irq);
+       unsigned long cpuid = irq_choose_cpu(virt_irq, mask);
        int err;
 
        err = sun4v_intr_settarget(ino, cpuid);
@@ -403,7 +422,7 @@ static void sun4v_virq_enable(unsigned int virt_irq)
        unsigned long cpuid, dev_handle, dev_ino;
        int err;
 
-       cpuid = irq_choose_cpu(virt_irq);
+       cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity);
 
        dev_handle = virt_irq_table[virt_irq].dev_handle;
        dev_ino = virt_irq_table[virt_irq].dev_ino;
@@ -433,7 +452,7 @@ static int sun4v_virt_set_affinity(unsigned int virt_irq,
        unsigned long cpuid, dev_handle, dev_ino;
        int err;
 
-       cpuid = irq_choose_cpu(virt_irq);
+       cpuid = irq_choose_cpu(virt_irq, mask);
 
        dev_handle = virt_irq_table[virt_irq].dev_handle;
        dev_ino = virt_irq_table[virt_irq].dev_ino;