0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/fs.h>
0011 #include <linux/mm.h>
0012 #include <linux/slab.h>
0013 #include <linux/atomic.h>
0014 #include <linux/sched.h>
0015 #include <linux/sched/mm.h>
0016
0017 #include <asm/spu.h>
0018 #include <asm/spu_csa.h>
0019 #include "spufs.h"
0020 #include "sputrace.h"
0021
0022
0023 atomic_t nr_spu_contexts = ATOMIC_INIT(0);
0024
0025 struct spu_context *alloc_spu_context(struct spu_gang *gang)
0026 {
0027 struct spu_context *ctx;
0028
0029 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
0030 if (!ctx)
0031 goto out;
0032
0033
0034
0035 if (spu_init_csa(&ctx->csa))
0036 goto out_free;
0037 spin_lock_init(&ctx->mmio_lock);
0038 mutex_init(&ctx->mapping_lock);
0039 kref_init(&ctx->kref);
0040 mutex_init(&ctx->state_mutex);
0041 mutex_init(&ctx->run_mutex);
0042 init_waitqueue_head(&ctx->ibox_wq);
0043 init_waitqueue_head(&ctx->wbox_wq);
0044 init_waitqueue_head(&ctx->stop_wq);
0045 init_waitqueue_head(&ctx->mfc_wq);
0046 init_waitqueue_head(&ctx->run_wq);
0047 ctx->state = SPU_STATE_SAVED;
0048 ctx->ops = &spu_backing_ops;
0049 ctx->owner = get_task_mm(current);
0050 INIT_LIST_HEAD(&ctx->rq);
0051 INIT_LIST_HEAD(&ctx->aff_list);
0052 if (gang)
0053 spu_gang_add_ctx(gang, ctx);
0054
0055 __spu_update_sched_info(ctx);
0056 spu_set_timeslice(ctx);
0057 ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
0058 ctx->stats.tstamp = ktime_get_ns();
0059
0060 atomic_inc(&nr_spu_contexts);
0061 goto out;
0062 out_free:
0063 kfree(ctx);
0064 ctx = NULL;
0065 out:
0066 return ctx;
0067 }
0068
0069 void destroy_spu_context(struct kref *kref)
0070 {
0071 struct spu_context *ctx;
0072 ctx = container_of(kref, struct spu_context, kref);
0073 spu_context_nospu_trace(destroy_spu_context__enter, ctx);
0074 mutex_lock(&ctx->state_mutex);
0075 spu_deactivate(ctx);
0076 mutex_unlock(&ctx->state_mutex);
0077 spu_fini_csa(&ctx->csa);
0078 if (ctx->gang)
0079 spu_gang_remove_ctx(ctx->gang, ctx);
0080 if (ctx->prof_priv_kref)
0081 kref_put(ctx->prof_priv_kref, ctx->prof_priv_release);
0082 BUG_ON(!list_empty(&ctx->rq));
0083 atomic_dec(&nr_spu_contexts);
0084 kfree(ctx->switch_log);
0085 kfree(ctx);
0086 }
0087
0088 struct spu_context * get_spu_context(struct spu_context *ctx)
0089 {
0090 kref_get(&ctx->kref);
0091 return ctx;
0092 }
0093
0094 int put_spu_context(struct spu_context *ctx)
0095 {
0096 return kref_put(&ctx->kref, &destroy_spu_context);
0097 }
0098
0099
0100 void spu_forget(struct spu_context *ctx)
0101 {
0102 struct mm_struct *mm;
0103
0104
0105
0106
0107
0108
0109 mutex_lock(&ctx->state_mutex);
0110 if (ctx->state != SPU_STATE_SAVED)
0111 spu_deactivate(ctx);
0112
0113 mm = ctx->owner;
0114 ctx->owner = NULL;
0115 mmput(mm);
0116 spu_release(ctx);
0117 }
0118
0119 void spu_unmap_mappings(struct spu_context *ctx)
0120 {
0121 mutex_lock(&ctx->mapping_lock);
0122 if (ctx->local_store)
0123 unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
0124 if (ctx->mfc)
0125 unmap_mapping_range(ctx->mfc, 0, SPUFS_MFC_MAP_SIZE, 1);
0126 if (ctx->cntl)
0127 unmap_mapping_range(ctx->cntl, 0, SPUFS_CNTL_MAP_SIZE, 1);
0128 if (ctx->signal1)
0129 unmap_mapping_range(ctx->signal1, 0, SPUFS_SIGNAL_MAP_SIZE, 1);
0130 if (ctx->signal2)
0131 unmap_mapping_range(ctx->signal2, 0, SPUFS_SIGNAL_MAP_SIZE, 1);
0132 if (ctx->mss)
0133 unmap_mapping_range(ctx->mss, 0, SPUFS_MSS_MAP_SIZE, 1);
0134 if (ctx->psmap)
0135 unmap_mapping_range(ctx->psmap, 0, SPUFS_PS_MAP_SIZE, 1);
0136 mutex_unlock(&ctx->mapping_lock);
0137 }
0138
0139
0140
0141
0142
0143 int spu_acquire_saved(struct spu_context *ctx)
0144 {
0145 int ret;
0146
0147 spu_context_nospu_trace(spu_acquire_saved__enter, ctx);
0148
0149 ret = spu_acquire(ctx);
0150 if (ret)
0151 return ret;
0152
0153 if (ctx->state != SPU_STATE_SAVED) {
0154 set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
0155 spu_deactivate(ctx);
0156 }
0157
0158 return 0;
0159 }
0160
0161
0162
0163
0164
0165 void spu_release_saved(struct spu_context *ctx)
0166 {
0167 BUG_ON(ctx->state != SPU_STATE_SAVED);
0168
0169 if (test_and_clear_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags) &&
0170 test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags))
0171 spu_activate(ctx, 0);
0172
0173 spu_release(ctx);
0174 }
0175