Skip to content

Commit

Permalink
[POWERPC] spufs: try to route SPU interrupts to local node
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Luke Browning authored and Jeremy Kerr committed May 5, 2008
1 parent 093c16b commit 7a21420
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 3 deletions.
16 changes: 14 additions & 2 deletions arch/powerpc/platforms/cell/spu_priv1_mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
}

Expand Down
4 changes: 3 additions & 1 deletion arch/powerpc/platforms/cell/spufs/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ struct spu_context {
cpumask_t cpus_allowed;
int policy;
int prio;
int last_ran;

/* statistics */
struct {
Expand Down
8 changes: 8 additions & 0 deletions arch/powerpc/platforms/cell/spufs/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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. */
Expand Down

0 comments on commit 7a21420

Please sign in to comment.