[POWERPC] spufs: try to route SPU interrupts to local node
authorLuke Browning <lukebr@linux.vnet.ibm.com>
Mon, 28 Apr 2008 04:32:34 +0000 (14:32 +1000)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 5 May 2008 03:33:43 +0000 (13:33 +1000)
Currently, we re-route SPU interrupts to the current cpu, which may be
on a remote node. In the case of time slicing, all spu interrupts will
end up routed to the same cpu, where the spusched_tick occurs.

This change routes mfc interrupts to the cpu where the controlling
thread last ran, provided that cpu is on the same node as the spu
(otherwise don't reroute interrupts).

This should improve performance and provide a more predictable
environment for processing spu exceptions. In the past we have seen
concurrent delivery of spu exceptions to two cpus. This eliminates that
concern.

Signed-off-by: Luke Browning <lukebr@linux.vnet.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
arch/powerpc/platforms/cell/spu_priv1_mmio.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/cell/spufs/switch.c

index 67fa7247b80a4e0dac21d6702c2fcc0c1d6b1867..906a0a2a9fe18fc4273be7916f18df118c824dc1 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
+#include <linux/sched.h>
 
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
@@ -75,8 +76,19 @@ static u64 int_stat_get(struct spu *spu, int class)
 
 static void cpu_affinity_set(struct spu *spu, int cpu)
 {
-       u64 target = iic_get_target_id(cpu);
-       u64 route = target << 48 | target << 32 | target << 16;
+       u64 target;
+       u64 route;
+
+       if (nr_cpus_node(spu->node)) {
+               cpumask_t spumask = node_to_cpumask(spu->node);
+               cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu));
+
+               if (!cpus_intersects(spumask, cpumask))
+                       return;
+       }
+
+       target = iic_get_target_id(cpu);
+       route = target << 48 | target << 32 | target << 16;
        out_be64(&spu->priv1->int_route_RW, route);
 }
 
index 62280c292aac88b481291757a7e78aa094c3cf8f..1df7d6d152c7c7b0093e3e5ad132aff70d0c8ef3 100644 (file)
@@ -140,6 +140,9 @@ void __spu_update_sched_info(struct spu_context *ctx)
         * if it is timesliced or preempted.
         */
        ctx->cpus_allowed = current->cpus_allowed;
+
+       /* Save the current cpu id for spu interrupt routing. */
+       ctx->last_ran = raw_smp_processor_id();
 }
 
 void spu_update_sched_info(struct spu_context *ctx)
@@ -243,7 +246,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
        spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0);
        spu_restore(&ctx->csa, spu);
        spu->timestamp = jiffies;
-       spu_cpu_affinity_set(spu, raw_smp_processor_id());
        spu_switch_notify(spu, ctx);
        ctx->state = SPU_STATE_RUNNABLE;
 
index 7312745b7540d4586fd72c7e4b57e9b5a9abd641..dc3a215a6a22dfa1b48ecb6a6a1bd0b10af54095 100644 (file)
@@ -121,6 +121,7 @@ struct spu_context {
        cpumask_t cpus_allowed;
        int policy;
        int prio;
+       int last_ran;
 
        /* statistics */
        struct {
index 9748808b0f1916d5a57b699530571dba0d8ffda0..47c658051fcb713becaef6da1c00d7b70befda99 100644 (file)
@@ -1704,6 +1704,13 @@ static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu)
        eieio();
 }
 
+static inline void set_int_route(struct spu_state *csa, struct spu *spu)
+{
+       struct spu_context *ctx = spu->ctx;
+
+       spu_cpu_affinity_set(spu, ctx->last_ran);
+}
+
 static inline void restore_other_spu_access(struct spu_state *csa,
                                            struct spu *spu)
 {
@@ -2014,6 +2021,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu)
        check_ppuint_mb_stat(next, spu);        /* Step 67. */
        spu_invalidate_slbs(spu);               /* Modified Step 68. */
        restore_mfc_sr1(next, spu);             /* Step 69. */
+       set_int_route(next, spu);               /* NEW      */
        restore_other_spu_access(next, spu);    /* Step 70. */
        restore_spu_runcntl(next, spu);         /* Step 71. */
        restore_mfc_cntl(next, spu);            /* Step 72. */