diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/context.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 137 |
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; |
57 | out_free: | 61 | out_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 | ||
99 | void spu_acquire(struct spu_context *ctx) | ||
100 | { | ||
101 | down_read(&ctx->state_sema); | ||
102 | } | ||
103 | |||
104 | void spu_release(struct spu_context *ctx) | ||
105 | { | ||
106 | up_read(&ctx->state_sema); | ||
107 | } | ||
108 | |||
109 | void spu_unmap_mappings(struct spu_context *ctx) | 103 | void 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 | */ | ||
123 | int spu_acquire_exclusive(struct spu_context *ctx) | 129 | int 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 | ||
144 | out: | 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 | ||
150 | int 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 | */ | ||
169 | int 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; | ||
179 | out: | ||
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 | */ | ||
186 | void spu_acquire_saved(struct spu_context *ctx) | 196 | void 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 | } |