Skip to content

Commit

Permalink
[POWERPC] spufs: streamline locking for isolated spu setup
Browse files Browse the repository at this point in the history
For quite a while now spu state is protected by a simple mutex instead
of the old rw_semaphore, and this means we can simplify the locking
around spu_setup_isolated a lot.

Instead of doing an spu_release before entering spu_setup_isolated and
then calling the complicated spu_acquire_exclusive we can now simply
enter the function locked an in guaranteed runnable state, so that the
only bit of spu_acquire_exclusive that's left is the call to
spu_unmap_mappings.

Similarly there's no more need to unlock and reacquire the state_mutex
when spu_setup_isolated is done, but we can always return with the
lock held and only drop it in spu_run_init in the failure case.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
  • Loading branch information
Christoph Hellwig authored and Arnd Bergmann committed Apr 23, 2007
1 parent a475c2f commit 7ec18ab
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 55 deletions.
40 changes: 0 additions & 40 deletions arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,46 +121,6 @@ void spu_unmap_mappings(struct spu_context *ctx)
unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
}

/**
* spu_acquire_exclusive - lock spu contex and protect against userspace access
* @ctx: spu contex to lock
*
* Note:
* Returns 0 and with the context locked on success
* Returns negative error and with the context _unlocked_ on failure.
*/
int spu_acquire_exclusive(struct spu_context *ctx)
{
int ret = -EINVAL;

spu_acquire(ctx);
/*
* Context is about to be freed, so we can't acquire it anymore.
*/
if (!ctx->owner)
goto out_unlock;

if (ctx->state == SPU_STATE_SAVED) {
ret = spu_activate(ctx, 0);
if (ret)
goto out_unlock;
} else {
/*
* We need to exclude userspace access to the context.
*
* To protect against memory access we invalidate all ptes
* and make sure the pagefault handlers block on the mutex.
*/
spu_unmap_mappings(ctx);
}

return 0;

out_unlock:
spu_release(ctx);
return ret;
}

/**
* spu_acquire_runnable - lock spu contex and make sure it is in runnable state
* @ctx: spu contex to lock
Expand Down
30 changes: 16 additions & 14 deletions arch/powerpc/platforms/cell/spufs/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,18 @@ static int spu_setup_isolated(struct spu_context *ctx)
const u32 status_loading = SPU_STATUS_RUNNING
| SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;

ret = -ENODEV;
if (!isolated_loader)
return -ENODEV;

ret = spu_acquire_exclusive(ctx);
if (ret)
goto out;

/*
* We need to exclude userspace access to the context.
*
* To protect against memory access we invalidate all ptes
* and make sure the pagefault handlers block on the mutex.
*/
spu_unmap_mappings(ctx);

mfc_cntl = &ctx->spu->priv2->mfc_control_RW;

/* purge the MFC DMA queue to ensure no spurious accesses before we
Expand All @@ -82,7 +87,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
__FUNCTION__);
ret = -EIO;
goto out_unlock;
goto out;
}
cond_resched();
}
Expand Down Expand Up @@ -119,21 +124,22 @@ static int spu_setup_isolated(struct spu_context *ctx)
pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
ret = -EACCES;
goto out_drop_priv;
}

} else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
if (!(status & SPU_STATUS_ISOLATED_STATE)) {
/* This isn't allowed by the CBEA, but check anyway */
pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
ret = -EINVAL;
goto out_drop_priv;
}

out_drop_priv:
/* Finished accessing the loader. Drop kernel mode */
sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
spu_mfc_sr1_set(ctx->spu, sr1);

out_unlock:
spu_release(ctx);
out:
return ret;
}
Expand All @@ -149,13 +155,9 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc)

if (ctx->flags & SPU_CREATE_ISOLATE) {
if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
/* Need to release ctx, because spu_setup_isolated will
* acquire it exclusively.
*/
spu_release(ctx);
ret = spu_setup_isolated(ctx);
if (!ret)
ret = spu_acquire_runnable(ctx, 0);
if (ret)
spu_release(ctx);
}

/* if userspace has set the runcntrl register (eg, to issue an
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ void spu_unmap_mappings(struct spu_context *ctx);
void spu_forget(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, unsigned long flags);
void spu_deactivate(struct spu_context *ctx);
Expand Down

0 comments on commit 7ec18ab

Please sign in to comment.