#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>
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);
}
* 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)
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;
cpumask_t cpus_allowed;
int policy;
int prio;
+ int last_ran;
/* statistics */
struct {
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)
{
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. */