diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 48 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/syscalls.c | 7 |
6 files changed, 54 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 5931973845b1..bfbd0455d8a7 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -46,21 +46,21 @@ EXPORT_SYMBOL_GPL(spu_priv1_ops); | |||
46 | static int __spu_trap_invalid_dma(struct spu *spu) | 46 | static int __spu_trap_invalid_dma(struct spu *spu) |
47 | { | 47 | { |
48 | pr_debug("%s\n", __FUNCTION__); | 48 | pr_debug("%s\n", __FUNCTION__); |
49 | force_sig(SIGBUS, /* info, */ current); | 49 | spu->dma_callback(spu, SPE_EVENT_INVALID_DMA); |
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | 52 | ||
53 | static int __spu_trap_dma_align(struct spu *spu) | 53 | static int __spu_trap_dma_align(struct spu *spu) |
54 | { | 54 | { |
55 | pr_debug("%s\n", __FUNCTION__); | 55 | pr_debug("%s\n", __FUNCTION__); |
56 | force_sig(SIGBUS, /* info, */ current); | 56 | spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT); |
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static int __spu_trap_error(struct spu *spu) | 60 | static int __spu_trap_error(struct spu *spu) |
61 | { | 61 | { |
62 | pr_debug("%s\n", __FUNCTION__); | 62 | pr_debug("%s\n", __FUNCTION__); |
63 | force_sig(SIGILL, /* info, */ current); | 63 | spu->dma_callback(spu, SPE_EVENT_SPE_ERROR); |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 3950ddccb2c8..8cc615ff3637 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -224,7 +224,8 @@ struct file_operations spufs_context_fops = { | |||
224 | }; | 224 | }; |
225 | 225 | ||
226 | static int | 226 | static int |
227 | spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 227 | spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, |
228 | int mode) | ||
228 | { | 229 | { |
229 | int ret; | 230 | int ret; |
230 | struct inode *inode; | 231 | struct inode *inode; |
@@ -244,6 +245,8 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
244 | if (!ctx) | 245 | if (!ctx) |
245 | goto out_iput; | 246 | goto out_iput; |
246 | 247 | ||
248 | ctx->flags = flags; | ||
249 | |||
247 | inode->i_op = &spufs_dir_inode_operations; | 250 | inode->i_op = &spufs_dir_inode_operations; |
248 | inode->i_fop = &simple_dir_operations; | 251 | inode->i_fop = &simple_dir_operations; |
249 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | 252 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); |
@@ -304,7 +307,7 @@ long spufs_create_thread(struct nameidata *nd, | |||
304 | goto out; | 307 | goto out; |
305 | 308 | ||
306 | /* all flags are reserved */ | 309 | /* all flags are reserved */ |
307 | if (flags) | 310 | if (flags & (~SPU_CREATE_FLAG_ALL)) |
308 | goto out; | 311 | goto out; |
309 | 312 | ||
310 | dentry = lookup_create(nd, 1); | 313 | dentry = lookup_create(nd, 1); |
@@ -317,7 +320,7 @@ long spufs_create_thread(struct nameidata *nd, | |||
317 | goto out_dput; | 320 | goto out_dput; |
318 | 321 | ||
319 | mode &= ~current->fs->umask; | 322 | mode &= ~current->fs->umask; |
320 | ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO); | 323 | ret = spufs_mkdir(nd->dentry->d_inode, dentry, flags, mode & S_IRWXUGO); |
321 | if (ret) | 324 | if (ret) |
322 | goto out_dput; | 325 | goto out_dput; |
323 | 326 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 483c8b76232c..63df8cf4ba16 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -14,6 +14,26 @@ void spufs_stop_callback(struct spu *spu) | |||
14 | wake_up_all(&ctx->stop_wq); | 14 | wake_up_all(&ctx->stop_wq); |
15 | } | 15 | } |
16 | 16 | ||
17 | void spufs_dma_callback(struct spu *spu, int type) | ||
18 | { | ||
19 | struct spu_context *ctx = spu->ctx; | ||
20 | |||
21 | if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { | ||
22 | ctx->event_return |= type; | ||
23 | wake_up_all(&ctx->stop_wq); | ||
24 | } else { | ||
25 | switch (type) { | ||
26 | case SPE_EVENT_DMA_ALIGNMENT: | ||
27 | case SPE_EVENT_INVALID_DMA: | ||
28 | force_sig(SIGBUS, /* info, */ current); | ||
29 | break; | ||
30 | case SPE_EVENT_SPE_ERROR: | ||
31 | force_sig(SIGILL, /* info */ current); | ||
32 | break; | ||
33 | } | ||
34 | } | ||
35 | } | ||
36 | |||
17 | static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | 37 | static inline int spu_stopped(struct spu_context *ctx, u32 * stat) |
18 | { | 38 | { |
19 | struct spu *spu; | 39 | struct spu *spu; |
@@ -28,8 +48,7 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | |||
28 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; | 48 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; |
29 | } | 49 | } |
30 | 50 | ||
31 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc, | 51 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc) |
32 | u32 * status) | ||
33 | { | 52 | { |
34 | int ret; | 53 | int ret; |
35 | 54 | ||
@@ -72,7 +91,7 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, | |||
72 | SPU_STATUS_STOPPED_BY_HALT)) { | 91 | SPU_STATUS_STOPPED_BY_HALT)) { |
73 | return *status; | 92 | return *status; |
74 | } | 93 | } |
75 | if ((ret = spu_run_init(ctx, npc, status)) != 0) | 94 | if ((ret = spu_run_init(ctx, npc)) != 0) |
76 | return ret; | 95 | return ret; |
77 | return 0; | 96 | return 0; |
78 | } | 97 | } |
@@ -177,46 +196,49 @@ static inline int spu_process_events(struct spu_context *ctx) | |||
177 | } | 196 | } |
178 | 197 | ||
179 | long spufs_run_spu(struct file *file, struct spu_context *ctx, | 198 | long spufs_run_spu(struct file *file, struct spu_context *ctx, |
180 | u32 * npc, u32 * status) | 199 | u32 *npc, u32 *event) |
181 | { | 200 | { |
182 | int ret; | 201 | int ret; |
202 | u32 status; | ||
183 | 203 | ||
184 | if (down_interruptible(&ctx->run_sema)) | 204 | if (down_interruptible(&ctx->run_sema)) |
185 | return -ERESTARTSYS; | 205 | return -ERESTARTSYS; |
186 | 206 | ||
187 | ret = spu_run_init(ctx, npc, status); | 207 | ctx->event_return = 0; |
208 | ret = spu_run_init(ctx, npc); | ||
188 | if (ret) | 209 | if (ret) |
189 | goto out; | 210 | goto out; |
190 | 211 | ||
191 | do { | 212 | do { |
192 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); | 213 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); |
193 | if (unlikely(ret)) | 214 | if (unlikely(ret)) |
194 | break; | 215 | break; |
195 | if ((*status & SPU_STATUS_STOPPED_BY_STOP) && | 216 | if ((status & SPU_STATUS_STOPPED_BY_STOP) && |
196 | (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { | 217 | (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { |
197 | ret = spu_process_callback(ctx); | 218 | ret = spu_process_callback(ctx); |
198 | if (ret) | 219 | if (ret) |
199 | break; | 220 | break; |
200 | *status &= ~SPU_STATUS_STOPPED_BY_STOP; | 221 | status &= ~SPU_STATUS_STOPPED_BY_STOP; |
201 | } | 222 | } |
202 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 223 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
203 | ret = spu_reacquire_runnable(ctx, npc, status); | 224 | ret = spu_reacquire_runnable(ctx, npc, &status); |
204 | if (ret) | 225 | if (ret) |
205 | goto out; | 226 | goto out; |
206 | continue; | 227 | continue; |
207 | } | 228 | } |
208 | ret = spu_process_events(ctx); | 229 | ret = spu_process_events(ctx); |
209 | 230 | ||
210 | } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP | | 231 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | |
211 | SPU_STATUS_STOPPED_BY_HALT))); | 232 | SPU_STATUS_STOPPED_BY_HALT))); |
212 | 233 | ||
213 | ctx->ops->runcntl_stop(ctx); | 234 | ctx->ops->runcntl_stop(ctx); |
214 | ret = spu_run_fini(ctx, npc, status); | 235 | ret = spu_run_fini(ctx, npc, &status); |
215 | if (!ret) | 236 | if (!ret) |
216 | ret = *status; | 237 | ret = status; |
217 | spu_yield(ctx); | 238 | spu_yield(ctx); |
218 | 239 | ||
219 | out: | 240 | out: |
241 | *event = ctx->event_return; | ||
220 | up(&ctx->run_sema); | 242 | up(&ctx->run_sema); |
221 | return ret; | 243 | return ret; |
222 | } | 244 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index bd4e2c3d5d08..a824b6051164 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -81,7 +81,6 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx) | |||
81 | spu->number, spu->node); | 81 | spu->number, spu->node); |
82 | spu->ctx = ctx; | 82 | spu->ctx = ctx; |
83 | spu->flags = 0; | 83 | spu->flags = 0; |
84 | ctx->flags = 0; | ||
85 | ctx->spu = spu; | 84 | ctx->spu = spu; |
86 | ctx->ops = &spu_hw_ops; | 85 | ctx->ops = &spu_hw_ops; |
87 | spu->pid = current->pid; | 86 | spu->pid = current->pid; |
@@ -92,6 +91,7 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx) | |||
92 | spu->wbox_callback = spufs_wbox_callback; | 91 | spu->wbox_callback = spufs_wbox_callback; |
93 | spu->stop_callback = spufs_stop_callback; | 92 | spu->stop_callback = spufs_stop_callback; |
94 | spu->mfc_callback = spufs_mfc_callback; | 93 | spu->mfc_callback = spufs_mfc_callback; |
94 | spu->dma_callback = spufs_dma_callback; | ||
95 | mb(); | 95 | mb(); |
96 | spu_unmap_mappings(ctx); | 96 | spu_unmap_mappings(ctx); |
97 | spu_restore(&ctx->csa, spu); | 97 | spu_restore(&ctx->csa, spu); |
@@ -111,12 +111,12 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx) | |||
111 | spu->wbox_callback = NULL; | 111 | spu->wbox_callback = NULL; |
112 | spu->stop_callback = NULL; | 112 | spu->stop_callback = NULL; |
113 | spu->mfc_callback = NULL; | 113 | spu->mfc_callback = NULL; |
114 | spu->dma_callback = NULL; | ||
114 | spu->mm = NULL; | 115 | spu->mm = NULL; |
115 | spu->pid = 0; | 116 | spu->pid = 0; |
116 | spu->prio = MAX_PRIO; | 117 | spu->prio = MAX_PRIO; |
117 | ctx->ops = &spu_backing_ops; | 118 | ctx->ops = &spu_backing_ops; |
118 | ctx->spu = NULL; | 119 | ctx->spu = NULL; |
119 | ctx->flags = 0; | ||
120 | spu->flags = 0; | 120 | spu->flags = 0; |
121 | spu->ctx = NULL; | 121 | spu->ctx = NULL; |
122 | } | 122 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 4485738e2102..2fb6a0099112 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -66,7 +66,8 @@ struct spu_context { | |||
66 | u32 tagwait; | 66 | u32 tagwait; |
67 | struct spu_context_ops *ops; | 67 | struct spu_context_ops *ops; |
68 | struct work_struct reap_work; | 68 | struct work_struct reap_work; |
69 | u64 flags; | 69 | unsigned long flags; |
70 | unsigned long event_return; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | struct mfc_dma_command { | 73 | struct mfc_dma_command { |
@@ -183,5 +184,6 @@ void spufs_ibox_callback(struct spu *spu); | |||
183 | void spufs_wbox_callback(struct spu *spu); | 184 | void spufs_wbox_callback(struct spu *spu); |
184 | void spufs_stop_callback(struct spu *spu); | 185 | void spufs_stop_callback(struct spu *spu); |
185 | void spufs_mfc_callback(struct spu *spu); | 186 | void spufs_mfc_callback(struct spu *spu); |
187 | void spufs_dma_callback(struct spu *spu, int type); | ||
186 | 188 | ||
187 | #endif | 189 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index e6565a949ddc..ef33a0ca2036 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c | |||
@@ -38,7 +38,7 @@ static long do_spu_run(struct file *filp, | |||
38 | u32 npc, status; | 38 | u32 npc, status; |
39 | 39 | ||
40 | ret = -EFAULT; | 40 | ret = -EFAULT; |
41 | if (get_user(npc, unpc) || get_user(status, ustatus)) | 41 | if (get_user(npc, unpc)) |
42 | goto out; | 42 | goto out; |
43 | 43 | ||
44 | /* check if this file was created by spu_create */ | 44 | /* check if this file was created by spu_create */ |
@@ -49,7 +49,10 @@ static long do_spu_run(struct file *filp, | |||
49 | i = SPUFS_I(filp->f_dentry->d_inode); | 49 | i = SPUFS_I(filp->f_dentry->d_inode); |
50 | ret = spufs_run_spu(filp, i->i_ctx, &npc, &status); | 50 | ret = spufs_run_spu(filp, i->i_ctx, &npc, &status); |
51 | 51 | ||
52 | if (put_user(npc, unpc) || put_user(status, ustatus)) | 52 | if (put_user(npc, unpc)) |
53 | ret = -EFAULT; | ||
54 | |||
55 | if (ustatus && put_user(status, ustatus)) | ||
53 | ret = -EFAULT; | 56 | ret = -EFAULT; |
54 | out: | 57 | out: |
55 | return ret; | 58 | return ret; |