aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c9
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c48
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h4
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c7
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);
46static int __spu_trap_invalid_dma(struct spu *spu) 46static 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
53static int __spu_trap_dma_align(struct spu *spu) 53static 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
60static int __spu_trap_error(struct spu *spu) 60static 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
226static int 226static int
227spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 227spufs_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
17void 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
17static inline int spu_stopped(struct spu_context *ctx, u32 * stat) 37static 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
31static inline int spu_run_init(struct spu_context *ctx, u32 * npc, 51static 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
179long spufs_run_spu(struct file *file, struct spu_context *ctx, 198long 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
219out: 240out:
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
72struct mfc_dma_command { 73struct mfc_dma_command {
@@ -183,5 +184,6 @@ void spufs_ibox_callback(struct spu *spu);
183void spufs_wbox_callback(struct spu *spu); 184void spufs_wbox_callback(struct spu *spu);
184void spufs_stop_callback(struct spu *spu); 185void spufs_stop_callback(struct spu *spu);
185void spufs_mfc_callback(struct spu *spu); 186void spufs_mfc_callback(struct spu *spu);
187void 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;
54out: 57out:
55 return ret; 58 return ret;