]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/powerpc/platforms/cell/spufs/context.c
[CELL] spufs: make sure context are scheduled again after spu_acquire_saved
[mv-sheeva.git] / arch / powerpc / platforms / cell / spufs / context.c
index 065147fb1cc2d3fead081acb9e23c759d4280d43..6b091ea1d1923c7e27f3b348657055c95c0b7c36 100644 (file)
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <asm/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
+
+atomic_t nr_spu_contexts = ATOMIC_INIT(0);
+
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
        struct spu_context *ctx;
@@ -36,15 +40,13 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        /* Binding to physical processor deferred
         * until spu_activate().
         */
-       spu_init_csa(&ctx->csa);
-       if (!ctx->csa.lscsa) {
+       if (spu_init_csa(&ctx->csa))
                goto out_free;
-       }
        spin_lock_init(&ctx->mmio_lock);
-       spin_lock_init(&ctx->mapping_lock);
+       mutex_init(&ctx->mapping_lock);
        kref_init(&ctx->kref);
        mutex_init(&ctx->state_mutex);
-       init_MUTEX(&ctx->run_sema);
+       mutex_init(&ctx->run_mutex);
        init_waitqueue_head(&ctx->ibox_wq);
        init_waitqueue_head(&ctx->wbox_wq);
        init_waitqueue_head(&ctx->stop_wq);
@@ -55,10 +57,11 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        INIT_LIST_HEAD(&ctx->rq);
        if (gang)
                spu_gang_add_ctx(gang, ctx);
-       ctx->rt_priority = current->rt_priority;
-       ctx->policy = current->policy;
-       ctx->prio = current->prio;
-       INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
+       ctx->cpus_allowed = current->cpus_allowed;
+       spu_set_timeslice(ctx);
+       ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
+
+       atomic_inc(&nr_spu_contexts);
        goto out;
 out_free:
        kfree(ctx);
@@ -78,6 +81,7 @@ void destroy_spu_context(struct kref *kref)
        if (ctx->gang)
                spu_gang_remove_ctx(ctx->gang, ctx);
        BUG_ON(!list_empty(&ctx->rq));
+       atomic_dec(&nr_spu_contexts);
        kfree(ctx);
 }
 
@@ -105,6 +109,7 @@ void spu_forget(struct spu_context *ctx)
 
 void spu_unmap_mappings(struct spu_context *ctx)
 {
+       mutex_lock(&ctx->mapping_lock);
        if (ctx->local_store)
                unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
        if (ctx->mfc)
@@ -119,46 +124,7 @@ void spu_unmap_mappings(struct spu_context *ctx)
                unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
        if (ctx->psmap)
                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;
+       mutex_unlock(&ctx->mapping_lock);
 }
 
 /**
@@ -199,6 +165,22 @@ int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags)
 void spu_acquire_saved(struct spu_context *ctx)
 {
        spu_acquire(ctx);
-       if (ctx->state != SPU_STATE_SAVED)
+       if (ctx->state != SPU_STATE_SAVED) {
+               set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
                spu_deactivate(ctx);
+       }
+}
+
+/**
+ * spu_release_saved - unlock spu context and return it to the runqueue
+ * @ctx:       context to unlock
+ */
+void spu_release_saved(struct spu_context *ctx)
+{
+       BUG_ON(ctx->state != SPU_STATE_SAVED);
+
+       if (test_and_clear_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags))
+               spu_activate(ctx, 0);
+
+       spu_release(ctx);
 }