diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 88a8871863039a42f64c7f00abe1dc89b511e1ee..056a8ad0238530c8b7aee3e257679a00ed1d4c34 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -163,7 +163,7 @@ int spu_acquire_exclusive(struct spu_context *ctx) * Returns 0 and with the context locked on success * Returns negative error and with the context _unlocked_ on failure. */ -int spu_acquire_runnable(struct spu_context *ctx) +int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags) { int ret = -EINVAL; @@ -174,7 +174,7 @@ int spu_acquire_runnable(struct spu_context *ctx) */ if (!ctx->owner) goto out_unlock; - ret = spu_activate(ctx, 0); + ret = spu_activate(ctx, flags); if (ret) goto out_unlock; } diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index a528020baa1868ccd5097eee96ad11189aaf2bd9..c729813043a61ffee1a8ad390ecb11cfc776ba98 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -164,7 +164,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, /* error here usually means a signal.. we might want to test * the error code more precisely though */ - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, 0); if (ret) return NOPFN_REFAULT; @@ -1306,7 +1306,7 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, if (ret) goto out; - spu_acquire_runnable(ctx); + spu_acquire_runnable(ctx, 0); if (file->f_flags & O_NONBLOCK) { ret = ctx->ops->send_mfc_command(ctx, &cmd); } else { diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index e1647311044bda7579c311787b1e1a18fbd3d951..a973e79e9fdceb6e9c4b04457d9129b027b0a448 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -143,7 +143,7 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) int ret; unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE); if (ret) return ret; @@ -155,7 +155,7 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) spu_release(ctx); ret = spu_setup_isolated(ctx); if (!ret) - ret = spu_acquire_runnable(ctx); + ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE); } /* if userspace has set the runcntrl register (eg, to issue an diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 6f8e2257c5a6ee664379eafd5847b472fa03c384..07d0d095c62a4d64add130ae0c3c70b8d3bccd11 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -247,8 +247,8 @@ static void spu_prio_wait(struct spu_context *ctx) { DEFINE_WAIT(wait); + set_bit(SPU_SCHED_WAKE, &ctx->sched_flags); prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE); - if (!signal_pending(current)) { mutex_unlock(&ctx->state_mutex); schedule(); @@ -256,6 +256,7 @@ static void spu_prio_wait(struct spu_context *ctx) } __set_current_state(TASK_RUNNING); remove_wait_queue(&ctx->stop_wq, &wait); + clear_bit(SPU_SCHED_WAKE, &ctx->sched_flags); } /** @@ -275,7 +276,7 @@ static void spu_reschedule(struct spu *spu) best = sched_find_first_bit(spu_prio->bitmap); if (best < MAX_PRIO) { struct spu_context *ctx = spu_grab_context(best); - if (ctx) + if (ctx && test_bit(SPU_SCHED_WAKE, &ctx->sched_flags)) wake_up(&ctx->stop_wq); } spin_unlock(&spu_prio->runq_lock); @@ -315,7 +316,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) * add the context to the runqueue so it gets woken up once an spu * is available. */ -int spu_activate(struct spu_context *ctx, u64 flags) +int spu_activate(struct spu_context *ctx, unsigned long flags) { if (ctx->spu) @@ -331,7 +332,8 @@ int spu_activate(struct spu_context *ctx, u64 flags) } spu_add_to_rq(ctx); - spu_prio_wait(ctx); + if (!(flags & SPU_ACTIVATE_NOWAKE)) + spu_prio_wait(ctx); spu_del_from_rq(ctx); } while (!signal_pending(current)); diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 7f5a4fc03c0005fac3a858f20fa8d85b28f4448b..421f59167c559d94b97412c4f94bb80dac177a98 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -39,6 +39,11 @@ enum { struct spu_context_ops; struct spu_gang; +/* ctx->sched_flags */ +enum { + SPU_SCHED_WAKE = 0, +}; + struct spu_context { struct spu *spu; /* pointer to a physical SPU */ struct spu_state csa; /* SPU context save area. */ @@ -77,6 +82,7 @@ struct spu_context { /* scheduler fields */ struct list_head rq; + unsigned long sched_flags; int prio; }; @@ -179,10 +185,13 @@ int put_spu_context(struct spu_context *ctx); void spu_unmap_mappings(struct spu_context *ctx); void spu_forget(struct spu_context *ctx); -int spu_acquire_runnable(struct spu_context *ctx); +int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); void spu_acquire_saved(struct spu_context *ctx); int spu_acquire_exclusive(struct spu_context *ctx); -int spu_activate(struct spu_context *ctx, u64 flags); +enum { + SPU_ACTIVATE_NOWAKE = 1, +}; +int spu_activate(struct spu_context *ctx, unsigned long flags); void spu_deactivate(struct spu_context *ctx); void spu_yield(struct spu_context *ctx); int __init spu_sched_init(void);