Commit 7ec18ab9 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Arnd Bergmann

[POWERPC] spufs: streamline locking for isolated spu setup

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd.bergmann@de.ibm.com>
parent a475c2f4
...@@ -121,46 +121,6 @@ void spu_unmap_mappings(struct spu_context *ctx) ...@@ -121,46 +121,6 @@ void spu_unmap_mappings(struct spu_context *ctx)
unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); 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 * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
* @ctx: spu contex to lock * @ctx: spu contex to lock
......
...@@ -63,13 +63,18 @@ static int spu_setup_isolated(struct spu_context *ctx) ...@@ -63,13 +63,18 @@ static int spu_setup_isolated(struct spu_context *ctx)
const u32 status_loading = SPU_STATUS_RUNNING const u32 status_loading = SPU_STATUS_RUNNING
| SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
ret = -ENODEV;
if (!isolated_loader) if (!isolated_loader)
return -ENODEV;
ret = spu_acquire_exclusive(ctx);
if (ret)
goto out; 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; mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
/* purge the MFC DMA queue to ensure no spurious accesses before we /* purge the MFC DMA queue to ensure no spurious accesses before we
...@@ -82,7 +87,7 @@ static int spu_setup_isolated(struct spu_context *ctx) ...@@ -82,7 +87,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
__FUNCTION__); __FUNCTION__);
ret = -EIO; ret = -EIO;
goto out_unlock; goto out;
} }
cond_resched(); cond_resched();
} }
...@@ -119,12 +124,15 @@ static int spu_setup_isolated(struct spu_context *ctx) ...@@ -119,12 +124,15 @@ static int spu_setup_isolated(struct spu_context *ctx)
pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
ret = -EACCES; 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 */ /* This isn't allowed by the CBEA, but check anyway */
pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
ret = -EINVAL; ret = -EINVAL;
goto out_drop_priv;
} }
out_drop_priv: out_drop_priv:
...@@ -132,8 +140,6 @@ static int spu_setup_isolated(struct spu_context *ctx) ...@@ -132,8 +140,6 @@ static int spu_setup_isolated(struct spu_context *ctx)
sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
spu_mfc_sr1_set(ctx->spu, sr1); spu_mfc_sr1_set(ctx->spu, sr1);
out_unlock:
spu_release(ctx);
out: out:
return ret; return ret;
} }
...@@ -149,13 +155,9 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) ...@@ -149,13 +155,9 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
if (ctx->flags & SPU_CREATE_ISOLATE) { if (ctx->flags & SPU_CREATE_ISOLATE) {
if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { 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); ret = spu_setup_isolated(ctx);
if (!ret) if (ret)
ret = spu_acquire_runnable(ctx, 0); spu_release(ctx);
} }
/* if userspace has set the runcntrl register (eg, to issue an /* if userspace has set the runcntrl register (eg, to issue an
......
...@@ -192,7 +192,6 @@ void spu_unmap_mappings(struct spu_context *ctx); ...@@ -192,7 +192,6 @@ void spu_unmap_mappings(struct spu_context *ctx);
void spu_forget(struct spu_context *ctx); void spu_forget(struct spu_context *ctx);
int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags);
void spu_acquire_saved(struct spu_context *ctx); 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); int spu_activate(struct spu_context *ctx, unsigned long flags);
void spu_deactivate(struct spu_context *ctx); void spu_deactivate(struct spu_context *ctx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment