diff mbox

powerpc/spufs: Add gang structure for standalone ctxts

Message ID 200809112037.46439.adetsch@br.ibm.com
State Superseded
Delegated to: Jeremy Kerr
Headers show

Commit Message

Andre Detsch Sept. 11, 2008, 11:37 p.m. UTC
All contexts should have a gang structure to provide a common
data abstraction for scheduling.  Standalone gangs are just gangs
of one.

Signed-off-by: Luke Browning <lukebrowning@us.ibm.com>
Signed-off-by: Andre Detsch <adetsch@br.ibm.com>
diff mbox

Patch

diff --git a/arch/powerpc/platforms/cell/spufs/context.c 
b/arch/powerpc/platforms/cell/spufs/context.c
index 6653ddb..ace2273 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -35,14 +35,28 @@  atomic_t nr_spu_contexts = ATOMIC_INIT(0);
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
+
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
 		goto out;
+
+	/* Allocate an anonymous gang if the caller did not explicitly
+	 * create one so that a common data abstraction exists for
+	 * the scheduler. Gangs are queued to the runqueue.  In this case,
+	 * the gang is a gang of one.
+	 */
+	if (!gang) {
+		gang = alloc_spu_gang();
+		if (!gang)
+			goto out_free;
+	}
+
 	/* Binding to physical processor deferred
 	 * until spu_activate().
 	 */
 	if (spu_init_csa(&ctx->csa))
-		goto out_free;
+		goto out_free_gang;
+
 	spin_lock_init(&ctx->mmio_lock);
 	mutex_init(&ctx->mapping_lock);
 	kref_init(&ctx->kref);
@@ -58,15 +72,16 @@  struct spu_context *alloc_spu_context(struct spu_gang 
*gang)
 	ctx->owner = get_task_mm(current);
 	INIT_LIST_HEAD(&ctx->rq);
 	INIT_LIST_HEAD(&ctx->aff_list);
-	if (gang)
-		spu_gang_add_ctx(gang, ctx);
-
+	spu_gang_add_ctx(gang, ctx);
 	__spu_update_sched_info(ctx);
 	spu_set_timeslice(ctx);
 	ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
 
 	atomic_inc(&nr_spu_contexts);
 	goto out;
+
+out_free_gang:
+	kfree(gang);
 out_free:
 	kfree(ctx);
 	ctx = NULL;
@@ -76,15 +91,18 @@  out:
 
 void destroy_spu_context(struct kref *kref)
 {
+	struct spu_gang *gang;
 	struct spu_context *ctx;
+
 	ctx = container_of(kref, struct spu_context, kref);
+	gang = ctx->gang;
+
 	spu_context_nospu_trace(destroy_spu_context__enter, ctx);
 	mutex_lock(&ctx->state_mutex);
 	spu_deactivate(ctx);
 	mutex_unlock(&ctx->state_mutex);
 	spu_fini_csa(&ctx->csa);
-	if (ctx->gang)
-		spu_gang_remove_ctx(ctx->gang, ctx);
+	spu_gang_remove_ctx(ctx->gang, ctx);
 	if (ctx->prof_priv_kref)
 		kref_put(ctx->prof_priv_kref, ctx->prof_priv_release);
 	BUG_ON(!list_empty(&ctx->rq));
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c 
b/arch/powerpc/platforms/cell/spufs/inode.c
index 690ca7b..cf97761 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -261,18 +261,30 @@  spufs_mkdir(struct inode *dir, struct dentry *dentry, 
unsigned int flags,
 {
 	int ret;
 	struct inode *inode;
-	struct spu_context *ctx;
+	struct spu_context *ctx, *gang_ctx;
+	struct spu_gang *gang;
 
 	ret = -ENOSPC;
 	inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
 	if (!inode)
 		goto out;
 
+	/* Can't mix sched and no-sched within the same gang. */
+	gang = SPUFS_I(dir)->i_gang;
+	if (gang) {
+		gang_ctx = list_first_entry(&gang->list, struct spu_context, gang_list);
+		if ((flags & SPU_CREATE_NOSCHED) ^
+		    (gang_ctx->flags & SPU_CREATE_NOSCHED)) {
+			ret = -EPERM;
+			goto out_iput;
+		}
+	}
+
 	if (dir->i_mode & S_ISGID) {
 		inode->i_gid = dir->i_gid;
 		inode->i_mode &= S_ISGID;
 	}
-	ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
+	ctx = alloc_spu_context(gang);
 	SPUFS_I(inode)->i_ctx = ctx;
 	if (!ctx)