Patchwork [14/18] powerpc/spufs: Fix gang deactivation when gang grows or shrinks

login
register
mail settings
Submitter Andre Detsch
Date Dec. 10, 2008, 7:40 p.m.
Message ID <200812101740.46064.adetsch@br.ibm.com>
Download mbox | patch
Permalink /patch/13320/
State RFC
Headers show

Comments

Andre Detsch - Dec. 10, 2008, 7:40 p.m.
The gang deactivation must be done in the same critical section
as the list_add/list_del operation, otherwise there is no guarantee
that the grow/shrink is correctly done.

Signed-off-by: Andre Detsch <adetsch@br.ibm.com>
---
 arch/powerpc/platforms/cell/spufs/context.c |   19 -------------------
 arch/powerpc/platforms/cell/spufs/gang.c    |   11 +++++++++++
 2 files changed, 11 insertions(+), 19 deletions(-)

Patch

diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0e37eff..ef81894 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -79,17 +79,6 @@  struct spu_context *alloc_spu_context(struct spu_gang *gang)
 
 	inc_active_gangs(gang);
 
-	/* If the gang is running, it needs to be stopped, since we have a
-	 * new context that needs to be gang scheduled.  Gangs are allowed
-	 * to grow and shrink over time, but they are unscheduled when it
-	 * happens as the gang may need to migrated to a different node.
-	 */
-	if (atomic_read(&gang->nstarted)) {
-		mutex_lock(&gang->mutex);
-		spu_deactivate(gang);
-		mutex_unlock(&gang->mutex);
-	}
-
 	spin_lock_init(&ctx->mmio_lock);
 	mutex_init(&ctx->mapping_lock);
 	kref_init(&ctx->kref);
@@ -141,14 +130,6 @@  void destroy_spu_context(struct kref *kref)
 
 	spu_context_nospu_trace(destroy_spu_context__enter, ctx);
 
-	/*
-	 * Deactivate and make it non-runnable while we work on it.
-	 */
-	mutex_lock(&gang->mutex);
-	WARN_ON(ctx->gang != gang);
-	spu_deactivate(gang);
-	mutex_unlock(&gang->mutex);
-
 	spu_fini_csa(&ctx->csa);
 	spu_gang_remove_ctx(ctx->gang, ctx);
 	if (ctx->prof_priv_kref)
diff --git a/arch/powerpc/platforms/cell/spufs/gang.c b/arch/powerpc/platforms/cell/spufs/gang.c
index 7b1513d..7e9ab01 100644
--- a/arch/powerpc/platforms/cell/spufs/gang.c
+++ b/arch/powerpc/platforms/cell/spufs/gang.c
@@ -90,6 +90,15 @@  int put_spu_gang(struct spu_gang *gang)
 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx)
 {
 	mutex_lock(&gang->mutex);
+	/*
+	 * If the gang is running, it needs to be stopped, since we have a
+	 * new context that needs to be gang scheduled.  Gangs are allowed
+	 * to grow and shrink over time, but they are unscheduled when it
+	 * happens as the gang may need to migrated to a different node.
+	 */
+	if (atomic_read(&gang->nstarted))
+		spu_deactivate(gang);
+
 	ctx->gang = get_spu_gang(gang);
 	list_add(&ctx->gang_list, &gang->list);
 	gang->contexts++;
@@ -115,7 +124,9 @@  void update_gang_stats(struct spu_gang *gang, struct spu_context *ctx)
 void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx)
 {
 	mutex_lock(&gang->mutex);
+	/* Deactivate and make it non-runnable while we work on it. */
 	WARN_ON(ctx->gang != gang);
+	spu_deactivate(gang);
 	if (!list_empty(&ctx->aff_list)) {
 		list_del_init(&ctx->aff_list);
 		gang->aff_flags &= ~AFF_OFFSETS_SET;