Subject: spufs: block in spu_acquire_runnable From: Arnd Bergmann This patch disables the logic that under the covers faults in spu contexts from the page fault handler. For the upstream version, we want something similar, but this is a relatively straightforward patch to make the review easier. Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/platforms/cell/spufs/context.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/context.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/context.c @@ -52,6 +52,7 @@ struct spu_context *alloc_spu_context(st init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); init_waitqueue_head(&ctx->mfc_wq); + init_waitqueue_head(&ctx->run_wq); ctx->state = SPU_STATE_SAVED; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c @@ -236,21 +236,31 @@ static unsigned long spufs_ps_nopfn(stru { struct spu_context *ctx = vma->vm_file->private_data; unsigned long area, offset = address - vma->vm_start; - int ret; offset += vma->vm_pgoff << PAGE_SHIFT; if (offset >= ps_size) return NOPFN_SIGBUS; - /* error here usually means a signal.. we might want to test - * the error code more precisely though + /* + * We have to wait for context to be loaded before we have + * pages to hand out to the user, but we don't want to wait + * with the mmap_sem held. + * It is possible to drop the mmap_sem here, but then we need + * to return NOPFN_REFAULT because the mappings may have + * hanged. */ - ret = spu_acquire_runnable(ctx, 0); - if (ret) - return NOPFN_REFAULT; + spu_acquire(ctx); + if (ctx->state == SPU_STATE_SAVED) { + up_read(¤t->mm->mmap_sem); + spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); + down_read(¤t->mm->mmap_sem); + goto out; + } area = ctx->spu->problem_phys + ps_offs; vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); + +out: spu_release(ctx); return NOPFN_REFAULT; @@ -1500,7 +1510,8 @@ static ssize_t spufs_mfc_write(struct fi if (ret) goto out; - ret = spu_acquire_runnable(ctx, 0); + spu_acquire(ctx); + ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); if (ret) goto out; Index: linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/sched.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/sched.c @@ -667,6 +667,7 @@ int spu_activate(struct spu_context *ctx spu_bind_context(spu, ctx); cbe_spu_info[node].nr_active++; mutex_unlock(&cbe_spu_info[node].list_mutex); + wake_up_all(&ctx->run_wq); return 0; } Index: linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/spufs.h +++ linux-2.6/arch/powerpc/platforms/cell/spufs/spufs.h @@ -71,6 +71,7 @@ struct spu_context { wait_queue_head_t wbox_wq; wait_queue_head_t stop_wq; wait_queue_head_t mfc_wq; + wait_queue_head_t run_wq; struct fasync_struct *ibox_fasync; struct fasync_struct *wbox_fasync; struct fasync_struct *mfc_fasync;