Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[pandora-kernel.git] / arch / powerpc / platforms / cell / spufs / fault.c
index 825001c..8cb6260 100644 (file)
@@ -21,7 +21,6 @@
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
@@ -53,9 +52,10 @@ static void spufs_handle_event(struct spu_context *ctx,
                info.si_code = BUS_OBJERR;
                break;
        case SPE_EVENT_SPE_DATA_STORAGE:
-               info.si_signo = SIGBUS;
+               info.si_signo = SIGSEGV;
                info.si_addr = (void __user *)ea;
-               info.si_code = BUS_ADRERR;
+               info.si_code = SEGV_ACCERR;
+               ctx->ops->restart_dma(ctx);
                break;
        case SPE_EVENT_DMA_ALIGNMENT:
                info.si_signo = SIGBUS;
@@ -82,13 +82,18 @@ int spufs_handle_class0(struct spu_context *ctx)
                return 0;
 
        if (stat & CLASS0_DMA_ALIGNMENT_INTR)
-               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT);
+               spufs_handle_event(ctx, ctx->csa.class_0_dar,
+                       SPE_EVENT_DMA_ALIGNMENT);
 
        if (stat & CLASS0_INVALID_DMA_COMMAND_INTR)
-               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA);
+               spufs_handle_event(ctx, ctx->csa.class_0_dar,
+                       SPE_EVENT_INVALID_DMA);
 
        if (stat & CLASS0_SPU_ERROR_INTR)
-               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR);
+               spufs_handle_event(ctx, ctx->csa.class_0_dar,
+                       SPE_EVENT_SPE_ERROR);
+
+       ctx->csa.class_0_pending = 0;
 
        return -EIO;
 }
@@ -107,7 +112,7 @@ int spufs_handle_class1(struct spu_context *ctx)
        u64 ea, dsisr, access;
        unsigned long flags;
        unsigned flt = 0;
-       int ret, ret2;
+       int ret;
 
        /*
         * dar and dsisr get passed from the registers
@@ -118,15 +123,15 @@ int spufs_handle_class1(struct spu_context *ctx)
         * in time, we can still expect to get the same fault
         * the immediately after the context restore.
         */
-       ea = ctx->csa.dar;
-       dsisr = ctx->csa.dsisr;
+       ea = ctx->csa.class_1_dar;
+       dsisr = ctx->csa.class_1_dsisr;
 
        if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
                return 0;
 
        spuctx_switch_state(ctx, SPU_UTIL_IOWAIT);
 
-       pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
+       pr_debug("ctx %p: ea %016llx, dsisr %016llx state %d\n", ctx, ea,
                dsisr, ctx->state);
 
        ctx->stats.hash_flt++;
@@ -147,20 +152,17 @@ int spufs_handle_class1(struct spu_context *ctx)
                ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
        /*
-        * If spu_acquire fails due to a pending signal we just want to return
-        * EINTR to userspace even if that means missing the dma restart or
-        * updating the page fault statistics.
+        * This is nasty: we need the state_mutex for all the bookkeeping even
+        * if the syscall was interrupted by a signal. ewww.
         */
-       ret2 = spu_acquire(ctx);
-       if (ret2)
-               goto out;
+       mutex_lock(&ctx->state_mutex);
 
        /*
         * Clear dsisr under ctxt lock after handling the fault, so that
         * time slicing will not preempt the context while the page fault
         * handler is running. Context switch code removes mappings.
         */
-       ctx->csa.dar = ctx->csa.dsisr = 0;
+       ctx->csa.class_1_dar = ctx->csa.class_1_dsisr = 0;
 
        /*
         * If we handled the fault successfully and are in runnable
@@ -184,7 +186,6 @@ int spufs_handle_class1(struct spu_context *ctx)
        } else
                spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
- out:
        spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
        return ret;
 }