diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 21 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 19 |
2 files changed, 28 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index b7493b865812..f7edba6cb795 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -27,7 +27,6 @@ void spufs_stop_callback(struct spu *spu, int irq) | |||
27 | switch(irq) { | 27 | switch(irq) { |
28 | case 0 : | 28 | case 0 : |
29 | ctx->csa.class_0_pending = spu->class_0_pending; | 29 | ctx->csa.class_0_pending = spu->class_0_pending; |
30 | ctx->csa.class_0_dsisr = spu->class_0_dsisr; | ||
31 | ctx->csa.class_0_dar = spu->class_0_dar; | 30 | ctx->csa.class_0_dar = spu->class_0_dar; |
32 | break; | 31 | break; |
33 | case 1 : | 32 | case 1 : |
@@ -51,18 +50,22 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) | |||
51 | u64 dsisr; | 50 | u64 dsisr; |
52 | u32 stopped; | 51 | u32 stopped; |
53 | 52 | ||
54 | *stat = ctx->ops->status_read(ctx); | ||
55 | |||
56 | if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags)) | ||
57 | return 1; | ||
58 | |||
59 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | | 53 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | |
60 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; | 54 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; |
61 | if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) | 55 | |
56 | top: | ||
57 | *stat = ctx->ops->status_read(ctx); | ||
58 | if (*stat & stopped) { | ||
59 | /* | ||
60 | * If the spu hasn't finished stopping, we need to | ||
61 | * re-read the register to get the stopped value. | ||
62 | */ | ||
63 | if (*stat & SPU_STATUS_RUNNING) | ||
64 | goto top; | ||
62 | return 1; | 65 | return 1; |
66 | } | ||
63 | 67 | ||
64 | dsisr = ctx->csa.class_0_dsisr; | 68 | if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags)) |
65 | if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) | ||
66 | return 1; | 69 | return 1; |
67 | 70 | ||
68 | dsisr = ctx->csa.class_1_dsisr; | 71 | dsisr = ctx->csa.class_1_dsisr; |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 745dd51ec37f..e929e70a84e3 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -230,19 +230,23 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
230 | ctx->stats.slb_flt_base = spu->stats.slb_flt; | 230 | ctx->stats.slb_flt_base = spu->stats.slb_flt; |
231 | ctx->stats.class2_intr_base = spu->stats.class2_intr; | 231 | ctx->stats.class2_intr_base = spu->stats.class2_intr; |
232 | 232 | ||
233 | spu_associate_mm(spu, ctx->owner); | ||
234 | |||
235 | spin_lock_irq(&spu->register_lock); | ||
233 | spu->ctx = ctx; | 236 | spu->ctx = ctx; |
234 | spu->flags = 0; | 237 | spu->flags = 0; |
235 | ctx->spu = spu; | 238 | ctx->spu = spu; |
236 | ctx->ops = &spu_hw_ops; | 239 | ctx->ops = &spu_hw_ops; |
237 | spu->pid = current->pid; | 240 | spu->pid = current->pid; |
238 | spu->tgid = current->tgid; | 241 | spu->tgid = current->tgid; |
239 | spu_associate_mm(spu, ctx->owner); | ||
240 | spu->ibox_callback = spufs_ibox_callback; | 242 | spu->ibox_callback = spufs_ibox_callback; |
241 | spu->wbox_callback = spufs_wbox_callback; | 243 | spu->wbox_callback = spufs_wbox_callback; |
242 | spu->stop_callback = spufs_stop_callback; | 244 | spu->stop_callback = spufs_stop_callback; |
243 | spu->mfc_callback = spufs_mfc_callback; | 245 | spu->mfc_callback = spufs_mfc_callback; |
244 | mb(); | 246 | spin_unlock_irq(&spu->register_lock); |
247 | |||
245 | spu_unmap_mappings(ctx); | 248 | spu_unmap_mappings(ctx); |
249 | |||
246 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); | 250 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); |
247 | spu_restore(&ctx->csa, spu); | 251 | spu_restore(&ctx->csa, spu); |
248 | spu->timestamp = jiffies; | 252 | spu->timestamp = jiffies; |
@@ -403,6 +407,8 @@ static int has_affinity(struct spu_context *ctx) | |||
403 | */ | 407 | */ |
404 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | 408 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) |
405 | { | 409 | { |
410 | u32 status; | ||
411 | |||
406 | spu_context_trace(spu_unbind_context__enter, ctx, spu); | 412 | spu_context_trace(spu_unbind_context__enter, ctx, spu); |
407 | 413 | ||
408 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 414 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
@@ -423,18 +429,22 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
423 | spu_unmap_mappings(ctx); | 429 | spu_unmap_mappings(ctx); |
424 | spu_save(&ctx->csa, spu); | 430 | spu_save(&ctx->csa, spu); |
425 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_STOP, 0); | 431 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_STOP, 0); |
432 | |||
433 | spin_lock_irq(&spu->register_lock); | ||
426 | spu->timestamp = jiffies; | 434 | spu->timestamp = jiffies; |
427 | ctx->state = SPU_STATE_SAVED; | 435 | ctx->state = SPU_STATE_SAVED; |
428 | spu->ibox_callback = NULL; | 436 | spu->ibox_callback = NULL; |
429 | spu->wbox_callback = NULL; | 437 | spu->wbox_callback = NULL; |
430 | spu->stop_callback = NULL; | 438 | spu->stop_callback = NULL; |
431 | spu->mfc_callback = NULL; | 439 | spu->mfc_callback = NULL; |
432 | spu_associate_mm(spu, NULL); | ||
433 | spu->pid = 0; | 440 | spu->pid = 0; |
434 | spu->tgid = 0; | 441 | spu->tgid = 0; |
435 | ctx->ops = &spu_backing_ops; | 442 | ctx->ops = &spu_backing_ops; |
436 | spu->flags = 0; | 443 | spu->flags = 0; |
437 | spu->ctx = NULL; | 444 | spu->ctx = NULL; |
445 | spin_unlock_irq(&spu->register_lock); | ||
446 | |||
447 | spu_associate_mm(spu, NULL); | ||
438 | 448 | ||
439 | ctx->stats.slb_flt += | 449 | ctx->stats.slb_flt += |
440 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); | 450 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); |
@@ -444,6 +454,9 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
444 | /* This maps the underlying spu state to idle */ | 454 | /* This maps the underlying spu state to idle */ |
445 | spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); | 455 | spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); |
446 | ctx->spu = NULL; | 456 | ctx->spu = NULL; |
457 | |||
458 | if (spu_stopped(ctx, &status)) | ||
459 | wake_up_all(&ctx->stop_wq); | ||
447 | } | 460 | } |
448 | 461 | ||
449 | /** | 462 | /** |