aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spufs/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/context.c')
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c137
1 files changed, 68 insertions, 69 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0870009f56db..04ad2e364e97 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -42,7 +42,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
42 } 42 }
43 spin_lock_init(&ctx->mmio_lock); 43 spin_lock_init(&ctx->mmio_lock);
44 kref_init(&ctx->kref); 44 kref_init(&ctx->kref);
45 init_rwsem(&ctx->state_sema); 45 mutex_init(&ctx->state_mutex);
46 init_MUTEX(&ctx->run_sema); 46 init_MUTEX(&ctx->run_sema);
47 init_waitqueue_head(&ctx->ibox_wq); 47 init_waitqueue_head(&ctx->ibox_wq);
48 init_waitqueue_head(&ctx->wbox_wq); 48 init_waitqueue_head(&ctx->wbox_wq);
@@ -53,6 +53,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
53 ctx->owner = get_task_mm(current); 53 ctx->owner = get_task_mm(current);
54 if (gang) 54 if (gang)
55 spu_gang_add_ctx(gang, ctx); 55 spu_gang_add_ctx(gang, ctx);
56 ctx->rt_priority = current->rt_priority;
57 ctx->policy = current->policy;
58 ctx->prio = current->prio;
59 INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
56 goto out; 60 goto out;
57out_free: 61out_free:
58 kfree(ctx); 62 kfree(ctx);
@@ -65,9 +69,9 @@ void destroy_spu_context(struct kref *kref)
65{ 69{
66 struct spu_context *ctx; 70 struct spu_context *ctx;
67 ctx = container_of(kref, struct spu_context, kref); 71 ctx = container_of(kref, struct spu_context, kref);
68 down_write(&ctx->state_sema); 72 mutex_lock(&ctx->state_mutex);
69 spu_deactivate(ctx); 73 spu_deactivate(ctx);
70 up_write(&ctx->state_sema); 74 mutex_unlock(&ctx->state_mutex);
71 spu_fini_csa(&ctx->csa); 75 spu_fini_csa(&ctx->csa);
72 if (ctx->gang) 76 if (ctx->gang)
73 spu_gang_remove_ctx(ctx->gang, ctx); 77 spu_gang_remove_ctx(ctx->gang, ctx);
@@ -96,107 +100,102 @@ void spu_forget(struct spu_context *ctx)
96 spu_release(ctx); 100 spu_release(ctx);
97} 101}
98 102
99void spu_acquire(struct spu_context *ctx)
100{
101 down_read(&ctx->state_sema);
102}
103
104void spu_release(struct spu_context *ctx)
105{
106 up_read(&ctx->state_sema);
107}
108
109void spu_unmap_mappings(struct spu_context *ctx) 103void spu_unmap_mappings(struct spu_context *ctx)
110{ 104{
111 if (ctx->local_store) 105 if (ctx->local_store)
112 unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); 106 unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
113 if (ctx->mfc) 107 if (ctx->mfc)
114 unmap_mapping_range(ctx->mfc, 0, 0x4000, 1); 108 unmap_mapping_range(ctx->mfc, 0, 0x1000, 1);
115 if (ctx->cntl) 109 if (ctx->cntl)
116 unmap_mapping_range(ctx->cntl, 0, 0x4000, 1); 110 unmap_mapping_range(ctx->cntl, 0, 0x1000, 1);
117 if (ctx->signal1) 111 if (ctx->signal1)
118 unmap_mapping_range(ctx->signal1, 0, 0x4000, 1); 112 unmap_mapping_range(ctx->signal1, 0, PAGE_SIZE, 1);
119 if (ctx->signal2) 113 if (ctx->signal2)
120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); 114 unmap_mapping_range(ctx->signal2, 0, PAGE_SIZE, 1);
115 if (ctx->mss)
116 unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
117 if (ctx->psmap)
118 unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
121} 119}
122 120
121/**
122 * spu_acquire_exclusive - lock spu contex and protect against userspace access
123 * @ctx: spu contex to lock
124 *
125 * Note:
126 * Returns 0 and with the context locked on success
127 * Returns negative error and with the context _unlocked_ on failure.
128 */
123int spu_acquire_exclusive(struct spu_context *ctx) 129int spu_acquire_exclusive(struct spu_context *ctx)
124{ 130{
125 int ret = 0; 131 int ret = -EINVAL;
126 132
127 down_write(&ctx->state_sema); 133 spu_acquire(ctx);
128 /* ctx is about to be freed, can't acquire any more */ 134 /*
129 if (!ctx->owner) { 135 * Context is about to be freed, so we can't acquire it anymore.
130 ret = -EINVAL; 136 */
131 goto out; 137 if (!ctx->owner)
132 } 138 goto out_unlock;
133 139
134 if (ctx->state == SPU_STATE_SAVED) { 140 if (ctx->state == SPU_STATE_SAVED) {
135 ret = spu_activate(ctx, 0); 141 ret = spu_activate(ctx, 0);
136 if (ret) 142 if (ret)
137 goto out; 143 goto out_unlock;
138 ctx->state = SPU_STATE_RUNNABLE;
139 } else { 144 } else {
140 /* We need to exclude userspace access to the context. */ 145 /*
146 * We need to exclude userspace access to the context.
147 *
148 * To protect against memory access we invalidate all ptes
149 * and make sure the pagefault handlers block on the mutex.
150 */
141 spu_unmap_mappings(ctx); 151 spu_unmap_mappings(ctx);
142 } 152 }
143 153
144out: 154 return 0;
145 if (ret) 155
146 up_write(&ctx->state_sema); 156 out_unlock:
157 spu_release(ctx);
147 return ret; 158 return ret;
148} 159}
149 160
150int spu_acquire_runnable(struct spu_context *ctx) 161/**
162 * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
163 * @ctx: spu contex to lock
164 *
165 * Note:
166 * Returns 0 and with the context locked on success
167 * Returns negative error and with the context _unlocked_ on failure.
168 */
169int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags)
151{ 170{
152 int ret = 0; 171 int ret = -EINVAL;
153
154 down_read(&ctx->state_sema);
155 if (ctx->state == SPU_STATE_RUNNABLE) {
156 ctx->spu->prio = current->prio;
157 return 0;
158 }
159 up_read(&ctx->state_sema);
160
161 down_write(&ctx->state_sema);
162 /* ctx is about to be freed, can't acquire any more */
163 if (!ctx->owner) {
164 ret = -EINVAL;
165 goto out;
166 }
167 172
173 spu_acquire(ctx);
168 if (ctx->state == SPU_STATE_SAVED) { 174 if (ctx->state == SPU_STATE_SAVED) {
169 ret = spu_activate(ctx, 0); 175 /*
176 * Context is about to be freed, so we can't acquire it anymore.
177 */
178 if (!ctx->owner)
179 goto out_unlock;
180 ret = spu_activate(ctx, flags);
170 if (ret) 181 if (ret)
171 goto out; 182 goto out_unlock;
172 ctx->state = SPU_STATE_RUNNABLE;
173 } 183 }
174 184
175 downgrade_write(&ctx->state_sema); 185 return 0;
176 /* On success, we return holding the lock */
177
178 return ret;
179out:
180 /* Release here, to simplify calling code. */
181 up_write(&ctx->state_sema);
182 186
187 out_unlock:
188 spu_release(ctx);
183 return ret; 189 return ret;
184} 190}
185 191
192/**
193 * spu_acquire_saved - lock spu contex and make sure it is in saved state
194 * @ctx: spu contex to lock
195 */
186void spu_acquire_saved(struct spu_context *ctx) 196void spu_acquire_saved(struct spu_context *ctx)
187{ 197{
188 down_read(&ctx->state_sema); 198 spu_acquire(ctx);
189 199 if (ctx->state != SPU_STATE_SAVED)
190 if (ctx->state == SPU_STATE_SAVED)
191 return;
192
193 up_read(&ctx->state_sema);
194 down_write(&ctx->state_sema);
195
196 if (ctx->state == SPU_STATE_RUNNABLE) {
197 spu_deactivate(ctx); 200 spu_deactivate(ctx);
198 ctx->state = SPU_STATE_SAVED;
199 }
200
201 downgrade_write(&ctx->state_sema);
202} 201}