From patchwork Thu Sep 11 23:37:46 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: powerpc/spufs: Add gang structure for standalone ctxts From: Andre Detsch X-Patchwork-Id: 250 Message-Id: <200809112037.46439.adetsch@br.ibm.com> To: cbe-oss-dev@ozlabs.org Cc: LukeBrowning@us.ibm.com, Jeremy Kerr Date: Thu, 11 Sep 2008 20:37:46 -0300 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 Signed-off-by: Andre Detsch 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)