From: Christoph Hellwig Date: Mon, 23 Apr 2007 19:08:06 +0000 (+0200) Subject: [POWERPC] spufs: use cancel_rearming_delayed_workqueue when stopping spu contexts X-Git-Tag: v2.6.22-rc1~1109^2~72^2~23 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=0887309589824fb1c3744c69a330c99c369124a0;p=linux-2.6-omap-h63xx.git [POWERPC] spufs: use cancel_rearming_delayed_workqueue when stopping spu contexts The scheduler workqueue may rearm itself and deadlock when we try to stop it. Put a flag in place to avoid skip the work if we're tearing down the context. Signed-off-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index c9561582ce2..003e330fc76 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -71,14 +71,25 @@ static inline int node_allowed(int node) void spu_start_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * Make sure the exiting bit is cleared. + */ + clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); + } } void spu_stop_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * While the work can be rearming normally setting this flag + * makes sure it does not rearm itself anymore. + */ + set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); cancel_delayed_work(&ctx->sched_work); + } } void spu_sched_tick(struct work_struct *work) @@ -88,6 +99,14 @@ void spu_sched_tick(struct work_struct *work) struct spu *spu; int rearm = 1; + /* + * If this context is being stopped avoid rescheduling from the + * scheduler tick because we would block on the state_mutex. + * The caller will yield the spu later on anyway. + */ + if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) + return; + mutex_lock(&ctx->state_mutex); spu = ctx->spu; if (spu) { @@ -377,7 +396,7 @@ static struct spu *find_victim(struct spu_context *ctx) * @ctx: spu context to schedule * @flags: flags (currently ignored) * - * Tries to find a free spu to run @ctx. If no free spu is availble + * Tries to find a free spu to run @ctx. If no free spu is available * add the context to the runqueue so it gets woken up once an spu * is available. */ diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 5c4e47d69d7..f418378abdf 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -41,7 +41,7 @@ struct spu_gang; /* ctx->sched_flags */ enum { - SPU_SCHED_WAKE = 0, /* currently unused */ + SPU_SCHED_EXITING = 0, }; struct spu_context {