]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/powerpc/platforms/cell/spufs/file.c
[POWERPC] spufs: support new OF device tree format
[mirror_ubuntu-bionic-kernel.git] / arch / powerpc / platforms / cell / spufs / file.c
CommitLineData
67207b96
AB
1/*
2 * SPU file system -- file contents
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
a33a7d73
AB
23#undef DEBUG
24
67207b96
AB
25#include <linux/fs.h>
26#include <linux/ioctl.h>
27#include <linux/module.h>
d88cfffa 28#include <linux/pagemap.h>
67207b96 29#include <linux/poll.h>
5110459f 30#include <linux/ptrace.h>
67207b96
AB
31
32#include <asm/io.h>
33#include <asm/semaphore.h>
34#include <asm/spu.h>
35#include <asm/uaccess.h>
36
37#include "spufs.h"
38
27d5bf2a
BH
39#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
40
8b3d6663 41
67207b96
AB
42static int
43spufs_mem_open(struct inode *inode, struct file *file)
44{
45 struct spufs_inode_info *i = SPUFS_I(inode);
6df10a82
MN
46 struct spu_context *ctx = i->i_ctx;
47 file->private_data = ctx;
48 file->f_mapping = inode->i_mapping;
49 ctx->local_store = inode->i_mapping;
67207b96
AB
50 return 0;
51}
52
53static ssize_t
54spufs_mem_read(struct file *file, char __user *buffer,
55 size_t size, loff_t *pos)
56{
8b3d6663
AB
57 struct spu_context *ctx = file->private_data;
58 char *local_store;
67207b96
AB
59 int ret;
60
8b3d6663 61 spu_acquire(ctx);
67207b96 62
8b3d6663
AB
63 local_store = ctx->ops->get_ls(ctx);
64 ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
67207b96 65
8b3d6663 66 spu_release(ctx);
67207b96
AB
67 return ret;
68}
69
70static ssize_t
71spufs_mem_write(struct file *file, const char __user *buffer,
72 size_t size, loff_t *pos)
73{
74 struct spu_context *ctx = file->private_data;
8b3d6663
AB
75 char *local_store;
76 int ret;
67207b96
AB
77
78 size = min_t(ssize_t, LS_SIZE - *pos, size);
79 if (size <= 0)
80 return -EFBIG;
81 *pos += size;
8b3d6663
AB
82
83 spu_acquire(ctx);
84
85 local_store = ctx->ops->get_ls(ctx);
86 ret = copy_from_user(local_store + *pos - size,
87 buffer, size) ? -EFAULT : size;
88
89 spu_release(ctx);
90 return ret;
67207b96
AB
91}
92
8b3d6663
AB
93static struct page *
94spufs_mem_mmap_nopage(struct vm_area_struct *vma,
95 unsigned long address, int *type)
96{
97 struct page *page = NOPAGE_SIGBUS;
98
99 struct spu_context *ctx = vma->vm_file->private_data;
100 unsigned long offset = address - vma->vm_start;
101 offset += vma->vm_pgoff << PAGE_SHIFT;
102
103 spu_acquire(ctx);
104
ac91cb8d
AB
105 if (ctx->state == SPU_STATE_SAVED) {
106 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
107 & ~(_PAGE_NO_CACHE | _PAGE_GUARDED));
8b3d6663 108 page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
ac91cb8d
AB
109 } else {
110 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
111 | _PAGE_NO_CACHE | _PAGE_GUARDED);
8b3d6663
AB
112 page = pfn_to_page((ctx->spu->local_store_phys + offset)
113 >> PAGE_SHIFT);
ac91cb8d 114 }
8b3d6663
AB
115 spu_release(ctx);
116
117 if (type)
118 *type = VM_FAULT_MINOR;
119
d88cfffa 120 page_cache_get(page);
8b3d6663
AB
121 return page;
122}
123
124static struct vm_operations_struct spufs_mem_mmap_vmops = {
125 .nopage = spufs_mem_mmap_nopage,
126};
127
67207b96
AB
128static int
129spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
130{
8b3d6663
AB
131 if (!(vma->vm_flags & VM_SHARED))
132 return -EINVAL;
67207b96 133
8b3d6663 134 /* FIXME: */
8b3d6663
AB
135 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
136 | _PAGE_NO_CACHE);
137
138 vma->vm_ops = &spufs_mem_mmap_vmops;
67207b96
AB
139 return 0;
140}
141
142static struct file_operations spufs_mem_fops = {
143 .open = spufs_mem_open,
144 .read = spufs_mem_read,
145 .write = spufs_mem_write,
8b3d6663 146 .llseek = generic_file_llseek,
67207b96 147 .mmap = spufs_mem_mmap,
8b3d6663
AB
148};
149
6df10a82
MN
150static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
151 unsigned long address,
27d5bf2a
BH
152 int *type, unsigned long ps_offs,
153 unsigned long ps_size)
6df10a82
MN
154{
155 struct page *page = NOPAGE_SIGBUS;
156 int fault_type = VM_FAULT_SIGBUS;
157 struct spu_context *ctx = vma->vm_file->private_data;
158 unsigned long offset = address - vma->vm_start;
159 unsigned long area;
160 int ret;
161
162 offset += vma->vm_pgoff << PAGE_SHIFT;
27d5bf2a 163 if (offset >= ps_size)
6df10a82
MN
164 goto out;
165
166 ret = spu_acquire_runnable(ctx);
167 if (ret)
168 goto out;
169
170 area = ctx->spu->problem_phys + ps_offs;
171 page = pfn_to_page((area + offset) >> PAGE_SHIFT);
172 fault_type = VM_FAULT_MINOR;
173 page_cache_get(page);
174
175 spu_release(ctx);
176
177 out:
178 if (type)
179 *type = fault_type;
180
181 return page;
182}
183
27d5bf2a 184#if SPUFS_MMAP_4K
6df10a82
MN
185static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
186 unsigned long address, int *type)
187{
27d5bf2a 188 return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
6df10a82
MN
189}
190
191static struct vm_operations_struct spufs_cntl_mmap_vmops = {
192 .nopage = spufs_cntl_mmap_nopage,
193};
194
195/*
196 * mmap support for problem state control area [0x4000 - 0x4fff].
6df10a82
MN
197 */
198static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
199{
200 if (!(vma->vm_flags & VM_SHARED))
201 return -EINVAL;
202
6df10a82
MN
203 vma->vm_flags |= VM_RESERVED;
204 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
23cc7701 205 | _PAGE_NO_CACHE | _PAGE_GUARDED);
6df10a82
MN
206
207 vma->vm_ops = &spufs_cntl_mmap_vmops;
208 return 0;
209}
27d5bf2a
BH
210#else /* SPUFS_MMAP_4K */
211#define spufs_cntl_mmap NULL
212#endif /* !SPUFS_MMAP_4K */
6df10a82 213
e1dbff2b 214static u64 spufs_cntl_get(void *data)
6df10a82 215{
e1dbff2b
AB
216 struct spu_context *ctx = data;
217 u64 val;
6df10a82 218
e1dbff2b
AB
219 spu_acquire(ctx);
220 val = ctx->ops->status_read(ctx);
221 spu_release(ctx);
222
223 return val;
6df10a82
MN
224}
225
e1dbff2b 226static void spufs_cntl_set(void *data, u64 val)
6df10a82 227{
e1dbff2b
AB
228 struct spu_context *ctx = data;
229
230 spu_acquire(ctx);
231 ctx->ops->runcntl_write(ctx, val);
232 spu_release(ctx);
6df10a82
MN
233}
234
e1dbff2b 235static int spufs_cntl_open(struct inode *inode, struct file *file)
6df10a82 236{
e1dbff2b
AB
237 struct spufs_inode_info *i = SPUFS_I(inode);
238 struct spu_context *ctx = i->i_ctx;
239
240 file->private_data = ctx;
241 file->f_mapping = inode->i_mapping;
242 ctx->cntl = inode->i_mapping;
243 return simple_attr_open(inode, file, spufs_cntl_get,
244 spufs_cntl_set, "0x%08lx");
6df10a82
MN
245}
246
247static struct file_operations spufs_cntl_fops = {
248 .open = spufs_cntl_open,
e1dbff2b
AB
249 .read = simple_attr_read,
250 .write = simple_attr_write,
6df10a82 251 .mmap = spufs_cntl_mmap,
6df10a82
MN
252};
253
8b3d6663
AB
254static int
255spufs_regs_open(struct inode *inode, struct file *file)
256{
257 struct spufs_inode_info *i = SPUFS_I(inode);
258 file->private_data = i->i_ctx;
259 return 0;
260}
261
262static ssize_t
263spufs_regs_read(struct file *file, char __user *buffer,
264 size_t size, loff_t *pos)
265{
266 struct spu_context *ctx = file->private_data;
267 struct spu_lscsa *lscsa = ctx->csa.lscsa;
268 int ret;
269
270 spu_acquire_saved(ctx);
271
272 ret = simple_read_from_buffer(buffer, size, pos,
273 lscsa->gprs, sizeof lscsa->gprs);
274
275 spu_release(ctx);
276 return ret;
277}
278
279static ssize_t
280spufs_regs_write(struct file *file, const char __user *buffer,
281 size_t size, loff_t *pos)
282{
283 struct spu_context *ctx = file->private_data;
284 struct spu_lscsa *lscsa = ctx->csa.lscsa;
285 int ret;
286
287 size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
288 if (size <= 0)
289 return -EFBIG;
290 *pos += size;
291
292 spu_acquire_saved(ctx);
293
294 ret = copy_from_user(lscsa->gprs + *pos - size,
295 buffer, size) ? -EFAULT : size;
296
297 spu_release(ctx);
298 return ret;
299}
300
301static struct file_operations spufs_regs_fops = {
302 .open = spufs_regs_open,
303 .read = spufs_regs_read,
304 .write = spufs_regs_write,
67207b96
AB
305 .llseek = generic_file_llseek,
306};
307
8b3d6663
AB
308static ssize_t
309spufs_fpcr_read(struct file *file, char __user * buffer,
310 size_t size, loff_t * pos)
311{
312 struct spu_context *ctx = file->private_data;
313 struct spu_lscsa *lscsa = ctx->csa.lscsa;
314 int ret;
315
316 spu_acquire_saved(ctx);
317
318 ret = simple_read_from_buffer(buffer, size, pos,
319 &lscsa->fpcr, sizeof(lscsa->fpcr));
320
321 spu_release(ctx);
322 return ret;
323}
324
325static ssize_t
326spufs_fpcr_write(struct file *file, const char __user * buffer,
327 size_t size, loff_t * pos)
328{
329 struct spu_context *ctx = file->private_data;
330 struct spu_lscsa *lscsa = ctx->csa.lscsa;
331 int ret;
332
333 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
334 if (size <= 0)
335 return -EFBIG;
336 *pos += size;
337
338 spu_acquire_saved(ctx);
339
340 ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
341 buffer, size) ? -EFAULT : size;
342
343 spu_release(ctx);
344 return ret;
345}
346
347static struct file_operations spufs_fpcr_fops = {
348 .open = spufs_regs_open,
349 .read = spufs_fpcr_read,
350 .write = spufs_fpcr_write,
351 .llseek = generic_file_llseek,
352};
353
67207b96
AB
354/* generic open function for all pipe-like files */
355static int spufs_pipe_open(struct inode *inode, struct file *file)
356{
357 struct spufs_inode_info *i = SPUFS_I(inode);
358 file->private_data = i->i_ctx;
359
360 return nonseekable_open(inode, file);
361}
362
cdcc89bb
AB
363/*
364 * Read as many bytes from the mailbox as possible, until
365 * one of the conditions becomes true:
366 *
367 * - no more data available in the mailbox
368 * - end of the user provided buffer
369 * - end of the mapped area
370 */
67207b96
AB
371static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
372 size_t len, loff_t *pos)
373{
8b3d6663 374 struct spu_context *ctx = file->private_data;
cdcc89bb
AB
375 u32 mbox_data, __user *udata;
376 ssize_t count;
67207b96
AB
377
378 if (len < 4)
379 return -EINVAL;
380
cdcc89bb
AB
381 if (!access_ok(VERIFY_WRITE, buf, len))
382 return -EFAULT;
383
384 udata = (void __user *)buf;
385
8b3d6663 386 spu_acquire(ctx);
cdcc89bb
AB
387 for (count = 0; count <= len; count += 4, udata++) {
388 int ret;
389 ret = ctx->ops->mbox_read(ctx, &mbox_data);
390 if (ret == 0)
391 break;
392
393 /*
394 * at the end of the mapped area, we can fault
395 * but still need to return the data we have
396 * read successfully so far.
397 */
398 ret = __put_user(mbox_data, udata);
399 if (ret) {
400 if (!count)
401 count = -EFAULT;
402 break;
403 }
404 }
8b3d6663 405 spu_release(ctx);
67207b96 406
cdcc89bb
AB
407 if (!count)
408 count = -EAGAIN;
67207b96 409
cdcc89bb 410 return count;
67207b96
AB
411}
412
413static struct file_operations spufs_mbox_fops = {
414 .open = spufs_pipe_open,
415 .read = spufs_mbox_read,
416};
417
418static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
419 size_t len, loff_t *pos)
420{
8b3d6663 421 struct spu_context *ctx = file->private_data;
67207b96
AB
422 u32 mbox_stat;
423
424 if (len < 4)
425 return -EINVAL;
426
8b3d6663
AB
427 spu_acquire(ctx);
428
429 mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
430
431 spu_release(ctx);
67207b96
AB
432
433 if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat))
434 return -EFAULT;
435
436 return 4;
437}
438
439static struct file_operations spufs_mbox_stat_fops = {
440 .open = spufs_pipe_open,
441 .read = spufs_mbox_stat_read,
442};
443
444/* low-level ibox access function */
8b3d6663 445size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
67207b96 446{
8b3d6663
AB
447 return ctx->ops->ibox_read(ctx, data);
448}
67207b96 449
8b3d6663
AB
450static int spufs_ibox_fasync(int fd, struct file *file, int on)
451{
452 struct spu_context *ctx = file->private_data;
67207b96 453
8b3d6663 454 return fasync_helper(fd, file, on, &ctx->ibox_fasync);
67207b96 455}
67207b96 456
8b3d6663
AB
457/* interrupt-level ibox callback function. */
458void spufs_ibox_callback(struct spu *spu)
67207b96 459{
8b3d6663
AB
460 struct spu_context *ctx = spu->ctx;
461
462 wake_up_all(&ctx->ibox_wq);
463 kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
67207b96
AB
464}
465
cdcc89bb
AB
466/*
467 * Read as many bytes from the interrupt mailbox as possible, until
468 * one of the conditions becomes true:
469 *
470 * - no more data available in the mailbox
471 * - end of the user provided buffer
472 * - end of the mapped area
473 *
474 * If the file is opened without O_NONBLOCK, we wait here until
475 * any data is available, but return when we have been able to
476 * read something.
477 */
67207b96
AB
478static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
479 size_t len, loff_t *pos)
480{
8b3d6663 481 struct spu_context *ctx = file->private_data;
cdcc89bb
AB
482 u32 ibox_data, __user *udata;
483 ssize_t count;
67207b96
AB
484
485 if (len < 4)
486 return -EINVAL;
487
cdcc89bb
AB
488 if (!access_ok(VERIFY_WRITE, buf, len))
489 return -EFAULT;
490
491 udata = (void __user *)buf;
492
8b3d6663 493 spu_acquire(ctx);
67207b96 494
cdcc89bb
AB
495 /* wait only for the first element */
496 count = 0;
67207b96 497 if (file->f_flags & O_NONBLOCK) {
8b3d6663 498 if (!spu_ibox_read(ctx, &ibox_data))
cdcc89bb 499 count = -EAGAIN;
67207b96 500 } else {
cdcc89bb 501 count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
67207b96 502 }
cdcc89bb
AB
503 if (count)
504 goto out;
67207b96 505
cdcc89bb
AB
506 /* if we can't write at all, return -EFAULT */
507 count = __put_user(ibox_data, udata);
508 if (count)
509 goto out;
8b3d6663 510
cdcc89bb
AB
511 for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
512 int ret;
513 ret = ctx->ops->ibox_read(ctx, &ibox_data);
514 if (ret == 0)
515 break;
516 /*
517 * at the end of the mapped area, we can fault
518 * but still need to return the data we have
519 * read successfully so far.
520 */
521 ret = __put_user(ibox_data, udata);
522 if (ret)
523 break;
524 }
67207b96 525
cdcc89bb
AB
526out:
527 spu_release(ctx);
67207b96 528
cdcc89bb 529 return count;
67207b96
AB
530}
531
532static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
533{
8b3d6663 534 struct spu_context *ctx = file->private_data;
67207b96
AB
535 unsigned int mask;
536
8b3d6663 537 poll_wait(file, &ctx->ibox_wq, wait);
67207b96 538
3a843d7c
AB
539 spu_acquire(ctx);
540 mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
541 spu_release(ctx);
67207b96
AB
542
543 return mask;
544}
545
546static struct file_operations spufs_ibox_fops = {
547 .open = spufs_pipe_open,
548 .read = spufs_ibox_read,
549 .poll = spufs_ibox_poll,
550 .fasync = spufs_ibox_fasync,
551};
552
553static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
554 size_t len, loff_t *pos)
555{
8b3d6663 556 struct spu_context *ctx = file->private_data;
67207b96
AB
557 u32 ibox_stat;
558
559 if (len < 4)
560 return -EINVAL;
561
8b3d6663
AB
562 spu_acquire(ctx);
563 ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
564 spu_release(ctx);
67207b96
AB
565
566 if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
567 return -EFAULT;
568
569 return 4;
570}
571
572static struct file_operations spufs_ibox_stat_fops = {
573 .open = spufs_pipe_open,
574 .read = spufs_ibox_stat_read,
575};
576
577/* low-level mailbox write */
8b3d6663 578size_t spu_wbox_write(struct spu_context *ctx, u32 data)
67207b96 579{
8b3d6663
AB
580 return ctx->ops->wbox_write(ctx, data);
581}
67207b96 582
8b3d6663
AB
583static int spufs_wbox_fasync(int fd, struct file *file, int on)
584{
585 struct spu_context *ctx = file->private_data;
586 int ret;
67207b96 587
8b3d6663 588 ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
67207b96 589
67207b96
AB
590 return ret;
591}
67207b96 592
8b3d6663
AB
593/* interrupt-level wbox callback function. */
594void spufs_wbox_callback(struct spu *spu)
67207b96 595{
8b3d6663
AB
596 struct spu_context *ctx = spu->ctx;
597
598 wake_up_all(&ctx->wbox_wq);
599 kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
67207b96
AB
600}
601
cdcc89bb
AB
602/*
603 * Write as many bytes to the interrupt mailbox as possible, until
604 * one of the conditions becomes true:
605 *
606 * - the mailbox is full
607 * - end of the user provided buffer
608 * - end of the mapped area
609 *
610 * If the file is opened without O_NONBLOCK, we wait here until
611 * space is availabyl, but return when we have been able to
612 * write something.
613 */
67207b96
AB
614static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
615 size_t len, loff_t *pos)
616{
8b3d6663 617 struct spu_context *ctx = file->private_data;
cdcc89bb
AB
618 u32 wbox_data, __user *udata;
619 ssize_t count;
67207b96
AB
620
621 if (len < 4)
622 return -EINVAL;
623
cdcc89bb
AB
624 udata = (void __user *)buf;
625 if (!access_ok(VERIFY_READ, buf, len))
626 return -EFAULT;
627
628 if (__get_user(wbox_data, udata))
67207b96
AB
629 return -EFAULT;
630
8b3d6663
AB
631 spu_acquire(ctx);
632
cdcc89bb
AB
633 /*
634 * make sure we can at least write one element, by waiting
635 * in case of !O_NONBLOCK
636 */
637 count = 0;
67207b96 638 if (file->f_flags & O_NONBLOCK) {
8b3d6663 639 if (!spu_wbox_write(ctx, wbox_data))
cdcc89bb 640 count = -EAGAIN;
67207b96 641 } else {
cdcc89bb 642 count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
67207b96
AB
643 }
644
cdcc89bb
AB
645 if (count)
646 goto out;
8b3d6663 647
cdcc89bb
AB
648 /* write aѕ much as possible */
649 for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
650 int ret;
651 ret = __get_user(wbox_data, udata);
652 if (ret)
653 break;
654
655 ret = spu_wbox_write(ctx, wbox_data);
656 if (ret == 0)
657 break;
658 }
659
660out:
661 spu_release(ctx);
662 return count;
67207b96
AB
663}
664
665static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
666{
8b3d6663 667 struct spu_context *ctx = file->private_data;
67207b96
AB
668 unsigned int mask;
669
8b3d6663 670 poll_wait(file, &ctx->wbox_wq, wait);
67207b96 671
3a843d7c
AB
672 spu_acquire(ctx);
673 mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
674 spu_release(ctx);
67207b96
AB
675
676 return mask;
677}
678
679static struct file_operations spufs_wbox_fops = {
680 .open = spufs_pipe_open,
681 .write = spufs_wbox_write,
682 .poll = spufs_wbox_poll,
683 .fasync = spufs_wbox_fasync,
684};
685
686static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
687 size_t len, loff_t *pos)
688{
8b3d6663 689 struct spu_context *ctx = file->private_data;
67207b96
AB
690 u32 wbox_stat;
691
692 if (len < 4)
693 return -EINVAL;
694
8b3d6663
AB
695 spu_acquire(ctx);
696 wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
697 spu_release(ctx);
67207b96
AB
698
699 if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
700 return -EFAULT;
701
702 return 4;
703}
704
705static struct file_operations spufs_wbox_stat_fops = {
706 .open = spufs_pipe_open,
707 .read = spufs_wbox_stat_read,
708};
709
6df10a82
MN
710static int spufs_signal1_open(struct inode *inode, struct file *file)
711{
712 struct spufs_inode_info *i = SPUFS_I(inode);
713 struct spu_context *ctx = i->i_ctx;
714 file->private_data = ctx;
715 file->f_mapping = inode->i_mapping;
716 ctx->signal1 = inode->i_mapping;
717 return nonseekable_open(inode, file);
718}
719
67207b96
AB
720static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
721 size_t len, loff_t *pos)
722{
8b3d6663 723 struct spu_context *ctx = file->private_data;
67207b96
AB
724 u32 data;
725
67207b96
AB
726 if (len < 4)
727 return -EINVAL;
728
8b3d6663
AB
729 spu_acquire(ctx);
730 data = ctx->ops->signal1_read(ctx);
731 spu_release(ctx);
732
67207b96
AB
733 if (copy_to_user(buf, &data, 4))
734 return -EFAULT;
735
736 return 4;
737}
738
739static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
740 size_t len, loff_t *pos)
741{
742 struct spu_context *ctx;
67207b96
AB
743 u32 data;
744
745 ctx = file->private_data;
67207b96
AB
746
747 if (len < 4)
748 return -EINVAL;
749
750 if (copy_from_user(&data, buf, 4))
751 return -EFAULT;
752
8b3d6663
AB
753 spu_acquire(ctx);
754 ctx->ops->signal1_write(ctx, data);
755 spu_release(ctx);
67207b96
AB
756
757 return 4;
758}
759
6df10a82
MN
760static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
761 unsigned long address, int *type)
762{
27d5bf2a
BH
763#if PAGE_SIZE == 0x1000
764 return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
765#elif PAGE_SIZE == 0x10000
766 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
767 * signal 1 and 2 area
768 */
769 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
770#else
771#error unsupported page size
772#endif
6df10a82
MN
773}
774
775static struct vm_operations_struct spufs_signal1_mmap_vmops = {
776 .nopage = spufs_signal1_mmap_nopage,
777};
778
779static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
780{
781 if (!(vma->vm_flags & VM_SHARED))
782 return -EINVAL;
783
784 vma->vm_flags |= VM_RESERVED;
785 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
23cc7701 786 | _PAGE_NO_CACHE | _PAGE_GUARDED);
6df10a82
MN
787
788 vma->vm_ops = &spufs_signal1_mmap_vmops;
789 return 0;
790}
6df10a82 791
67207b96 792static struct file_operations spufs_signal1_fops = {
6df10a82 793 .open = spufs_signal1_open,
67207b96
AB
794 .read = spufs_signal1_read,
795 .write = spufs_signal1_write,
6df10a82 796 .mmap = spufs_signal1_mmap,
67207b96
AB
797};
798
6df10a82
MN
799static int spufs_signal2_open(struct inode *inode, struct file *file)
800{
801 struct spufs_inode_info *i = SPUFS_I(inode);
802 struct spu_context *ctx = i->i_ctx;
803 file->private_data = ctx;
804 file->f_mapping = inode->i_mapping;
805 ctx->signal2 = inode->i_mapping;
806 return nonseekable_open(inode, file);
807}
808
67207b96
AB
809static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
810 size_t len, loff_t *pos)
811{
812 struct spu_context *ctx;
67207b96
AB
813 u32 data;
814
815 ctx = file->private_data;
67207b96
AB
816
817 if (len < 4)
818 return -EINVAL;
819
8b3d6663
AB
820 spu_acquire(ctx);
821 data = ctx->ops->signal2_read(ctx);
822 spu_release(ctx);
823
67207b96
AB
824 if (copy_to_user(buf, &data, 4))
825 return -EFAULT;
826
827 return 4;
828}
829
830static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
831 size_t len, loff_t *pos)
832{
833 struct spu_context *ctx;
67207b96
AB
834 u32 data;
835
836 ctx = file->private_data;
67207b96
AB
837
838 if (len < 4)
839 return -EINVAL;
840
841 if (copy_from_user(&data, buf, 4))
842 return -EFAULT;
843
8b3d6663
AB
844 spu_acquire(ctx);
845 ctx->ops->signal2_write(ctx, data);
846 spu_release(ctx);
67207b96
AB
847
848 return 4;
849}
850
27d5bf2a 851#if SPUFS_MMAP_4K
6df10a82
MN
852static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
853 unsigned long address, int *type)
854{
27d5bf2a
BH
855#if PAGE_SIZE == 0x1000
856 return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
857#elif PAGE_SIZE == 0x10000
858 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
859 * signal 1 and 2 area
860 */
861 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
862#else
863#error unsupported page size
864#endif
6df10a82
MN
865}
866
867static struct vm_operations_struct spufs_signal2_mmap_vmops = {
868 .nopage = spufs_signal2_mmap_nopage,
869};
870
871static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
872{
873 if (!(vma->vm_flags & VM_SHARED))
874 return -EINVAL;
875
876 /* FIXME: */
877 vma->vm_flags |= VM_RESERVED;
878 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
23cc7701 879 | _PAGE_NO_CACHE | _PAGE_GUARDED);
6df10a82
MN
880
881 vma->vm_ops = &spufs_signal2_mmap_vmops;
882 return 0;
883}
27d5bf2a
BH
884#else /* SPUFS_MMAP_4K */
885#define spufs_signal2_mmap NULL
886#endif /* !SPUFS_MMAP_4K */
6df10a82 887
67207b96 888static struct file_operations spufs_signal2_fops = {
6df10a82 889 .open = spufs_signal2_open,
67207b96
AB
890 .read = spufs_signal2_read,
891 .write = spufs_signal2_write,
6df10a82 892 .mmap = spufs_signal2_mmap,
67207b96
AB
893};
894
895static void spufs_signal1_type_set(void *data, u64 val)
896{
897 struct spu_context *ctx = data;
67207b96 898
8b3d6663
AB
899 spu_acquire(ctx);
900 ctx->ops->signal1_type_set(ctx, val);
901 spu_release(ctx);
67207b96
AB
902}
903
904static u64 spufs_signal1_type_get(void *data)
905{
906 struct spu_context *ctx = data;
8b3d6663
AB
907 u64 ret;
908
909 spu_acquire(ctx);
910 ret = ctx->ops->signal1_type_get(ctx);
911 spu_release(ctx);
912
913 return ret;
67207b96
AB
914}
915DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
916 spufs_signal1_type_set, "%llu");
917
918static void spufs_signal2_type_set(void *data, u64 val)
919{
920 struct spu_context *ctx = data;
67207b96 921
8b3d6663
AB
922 spu_acquire(ctx);
923 ctx->ops->signal2_type_set(ctx, val);
924 spu_release(ctx);
67207b96
AB
925}
926
927static u64 spufs_signal2_type_get(void *data)
928{
929 struct spu_context *ctx = data;
8b3d6663
AB
930 u64 ret;
931
932 spu_acquire(ctx);
933 ret = ctx->ops->signal2_type_get(ctx);
934 spu_release(ctx);
935
936 return ret;
67207b96
AB
937}
938DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
939 spufs_signal2_type_set, "%llu");
940
27d5bf2a 941#if SPUFS_MMAP_4K
d9379c4b
AB
942static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
943 unsigned long address, int *type)
944{
27d5bf2a 945 return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
d9379c4b
AB
946}
947
948static struct vm_operations_struct spufs_mss_mmap_vmops = {
949 .nopage = spufs_mss_mmap_nopage,
950};
951
952/*
953 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
d9379c4b
AB
954 */
955static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
956{
957 if (!(vma->vm_flags & VM_SHARED))
958 return -EINVAL;
959
d9379c4b
AB
960 vma->vm_flags |= VM_RESERVED;
961 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
23cc7701 962 | _PAGE_NO_CACHE | _PAGE_GUARDED);
d9379c4b
AB
963
964 vma->vm_ops = &spufs_mss_mmap_vmops;
965 return 0;
966}
27d5bf2a
BH
967#else /* SPUFS_MMAP_4K */
968#define spufs_mss_mmap NULL
969#endif /* !SPUFS_MMAP_4K */
d9379c4b
AB
970
971static int spufs_mss_open(struct inode *inode, struct file *file)
972{
973 struct spufs_inode_info *i = SPUFS_I(inode);
974
975 file->private_data = i->i_ctx;
976 return nonseekable_open(inode, file);
977}
978
979static struct file_operations spufs_mss_fops = {
980 .open = spufs_mss_open,
d9379c4b 981 .mmap = spufs_mss_mmap,
27d5bf2a
BH
982};
983
984static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
985 unsigned long address, int *type)
986{
987 return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
988}
989
990static struct vm_operations_struct spufs_psmap_mmap_vmops = {
991 .nopage = spufs_psmap_mmap_nopage,
992};
993
994/*
995 * mmap support for full problem state area [0x00000 - 0x1ffff].
996 */
997static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
998{
999 if (!(vma->vm_flags & VM_SHARED))
1000 return -EINVAL;
1001
1002 vma->vm_flags |= VM_RESERVED;
1003 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1004 | _PAGE_NO_CACHE | _PAGE_GUARDED);
1005
1006 vma->vm_ops = &spufs_psmap_mmap_vmops;
1007 return 0;
1008}
1009
1010static int spufs_psmap_open(struct inode *inode, struct file *file)
1011{
1012 struct spufs_inode_info *i = SPUFS_I(inode);
1013
1014 file->private_data = i->i_ctx;
1015 return nonseekable_open(inode, file);
1016}
1017
1018static struct file_operations spufs_psmap_fops = {
1019 .open = spufs_psmap_open,
1020 .mmap = spufs_psmap_mmap,
d9379c4b
AB
1021};
1022
1023
27d5bf2a 1024#if SPUFS_MMAP_4K
6df10a82
MN
1025static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
1026 unsigned long address, int *type)
1027{
27d5bf2a 1028 return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
6df10a82
MN
1029}
1030
1031static struct vm_operations_struct spufs_mfc_mmap_vmops = {
1032 .nopage = spufs_mfc_mmap_nopage,
1033};
1034
1035/*
1036 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
6df10a82
MN
1037 */
1038static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
1039{
1040 if (!(vma->vm_flags & VM_SHARED))
1041 return -EINVAL;
1042
6df10a82
MN
1043 vma->vm_flags |= VM_RESERVED;
1044 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
23cc7701 1045 | _PAGE_NO_CACHE | _PAGE_GUARDED);
6df10a82
MN
1046
1047 vma->vm_ops = &spufs_mfc_mmap_vmops;
1048 return 0;
1049}
27d5bf2a
BH
1050#else /* SPUFS_MMAP_4K */
1051#define spufs_mfc_mmap NULL
1052#endif /* !SPUFS_MMAP_4K */
a33a7d73
AB
1053
1054static int spufs_mfc_open(struct inode *inode, struct file *file)
1055{
1056 struct spufs_inode_info *i = SPUFS_I(inode);
1057 struct spu_context *ctx = i->i_ctx;
1058
1059 /* we don't want to deal with DMA into other processes */
1060 if (ctx->owner != current->mm)
1061 return -EINVAL;
1062
1063 if (atomic_read(&inode->i_count) != 1)
1064 return -EBUSY;
1065
1066 file->private_data = ctx;
1067 return nonseekable_open(inode, file);
1068}
1069
1070/* interrupt-level mfc callback function. */
1071void spufs_mfc_callback(struct spu *spu)
1072{
1073 struct spu_context *ctx = spu->ctx;
1074
1075 wake_up_all(&ctx->mfc_wq);
1076
1077 pr_debug("%s %s\n", __FUNCTION__, spu->name);
1078 if (ctx->mfc_fasync) {
1079 u32 free_elements, tagstatus;
1080 unsigned int mask;
1081
1082 /* no need for spu_acquire in interrupt context */
1083 free_elements = ctx->ops->get_mfc_free_elements(ctx);
1084 tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
1085
1086 mask = 0;
1087 if (free_elements & 0xffff)
1088 mask |= POLLOUT;
1089 if (tagstatus & ctx->tagwait)
1090 mask |= POLLIN;
1091
1092 kill_fasync(&ctx->mfc_fasync, SIGIO, mask);
1093 }
1094}
1095
1096static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status)
1097{
1098 /* See if there is one tag group is complete */
1099 /* FIXME we need locking around tagwait */
1100 *status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait;
1101 ctx->tagwait &= ~*status;
1102 if (*status)
1103 return 1;
1104
1105 /* enable interrupt waiting for any tag group,
1106 may silently fail if interrupts are already enabled */
1107 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
1108 return 0;
1109}
1110
1111static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
1112 size_t size, loff_t *pos)
1113{
1114 struct spu_context *ctx = file->private_data;
1115 int ret = -EINVAL;
1116 u32 status;
1117
1118 if (size != 4)
1119 goto out;
1120
1121 spu_acquire(ctx);
1122 if (file->f_flags & O_NONBLOCK) {
1123 status = ctx->ops->read_mfc_tagstatus(ctx);
1124 if (!(status & ctx->tagwait))
1125 ret = -EAGAIN;
1126 else
1127 ctx->tagwait &= ~status;
1128 } else {
1129 ret = spufs_wait(ctx->mfc_wq,
1130 spufs_read_mfc_tagstatus(ctx, &status));
1131 }
1132 spu_release(ctx);
1133
1134 if (ret)
1135 goto out;
1136
1137 ret = 4;
1138 if (copy_to_user(buffer, &status, 4))
1139 ret = -EFAULT;
1140
1141out:
1142 return ret;
1143}
1144
1145static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
1146{
1147 pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa,
1148 cmd->ea, cmd->size, cmd->tag, cmd->cmd);
1149
1150 switch (cmd->cmd) {
1151 case MFC_PUT_CMD:
1152 case MFC_PUTF_CMD:
1153 case MFC_PUTB_CMD:
1154 case MFC_GET_CMD:
1155 case MFC_GETF_CMD:
1156 case MFC_GETB_CMD:
1157 break;
1158 default:
1159 pr_debug("invalid DMA opcode %x\n", cmd->cmd);
1160 return -EIO;
1161 }
1162
1163 if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) {
1164 pr_debug("invalid DMA alignment, ea %lx lsa %x\n",
1165 cmd->ea, cmd->lsa);
1166 return -EIO;
1167 }
1168
1169 switch (cmd->size & 0xf) {
1170 case 1:
1171 break;
1172 case 2:
1173 if (cmd->lsa & 1)
1174 goto error;
1175 break;
1176 case 4:
1177 if (cmd->lsa & 3)
1178 goto error;
1179 break;
1180 case 8:
1181 if (cmd->lsa & 7)
1182 goto error;
1183 break;
1184 case 0:
1185 if (cmd->lsa & 15)
1186 goto error;
1187 break;
1188 error:
1189 default:
1190 pr_debug("invalid DMA alignment %x for size %x\n",
1191 cmd->lsa & 0xf, cmd->size);
1192 return -EIO;
1193 }
1194
1195 if (cmd->size > 16 * 1024) {
1196 pr_debug("invalid DMA size %x\n", cmd->size);
1197 return -EIO;
1198 }
1199
1200 if (cmd->tag & 0xfff0) {
1201 /* we reserve the higher tag numbers for kernel use */
1202 pr_debug("invalid DMA tag\n");
1203 return -EIO;
1204 }
1205
1206 if (cmd->class) {
1207 /* not supported in this version */
1208 pr_debug("invalid DMA class\n");
1209 return -EIO;
1210 }
1211
1212 return 0;
1213}
1214
1215static int spu_send_mfc_command(struct spu_context *ctx,
1216 struct mfc_dma_command cmd,
1217 int *error)
1218{
1219 *error = ctx->ops->send_mfc_command(ctx, &cmd);
1220 if (*error == -EAGAIN) {
1221 /* wait for any tag group to complete
1222 so we have space for the new command */
1223 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
1224 /* try again, because the queue might be
1225 empty again */
1226 *error = ctx->ops->send_mfc_command(ctx, &cmd);
1227 if (*error == -EAGAIN)
1228 return 0;
1229 }
1230 return 1;
1231}
1232
1233static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
1234 size_t size, loff_t *pos)
1235{
1236 struct spu_context *ctx = file->private_data;
1237 struct mfc_dma_command cmd;
1238 int ret = -EINVAL;
1239
1240 if (size != sizeof cmd)
1241 goto out;
1242
1243 ret = -EFAULT;
1244 if (copy_from_user(&cmd, buffer, sizeof cmd))
1245 goto out;
1246
1247 ret = spufs_check_valid_dma(&cmd);
1248 if (ret)
1249 goto out;
1250
1251 spu_acquire_runnable(ctx);
1252 if (file->f_flags & O_NONBLOCK) {
1253 ret = ctx->ops->send_mfc_command(ctx, &cmd);
1254 } else {
1255 int status;
1256 ret = spufs_wait(ctx->mfc_wq,
1257 spu_send_mfc_command(ctx, cmd, &status));
1258 if (status)
1259 ret = status;
1260 }
1261 spu_release(ctx);
1262
1263 if (ret)
1264 goto out;
1265
1266 ctx->tagwait |= 1 << cmd.tag;
1267
1268out:
1269 return ret;
1270}
1271
1272static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
1273{
1274 struct spu_context *ctx = file->private_data;
1275 u32 free_elements, tagstatus;
1276 unsigned int mask;
1277
1278 spu_acquire(ctx);
1279 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
1280 free_elements = ctx->ops->get_mfc_free_elements(ctx);
1281 tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
1282 spu_release(ctx);
1283
1284 poll_wait(file, &ctx->mfc_wq, wait);
1285
1286 mask = 0;
1287 if (free_elements & 0xffff)
1288 mask |= POLLOUT | POLLWRNORM;
1289 if (tagstatus & ctx->tagwait)
1290 mask |= POLLIN | POLLRDNORM;
1291
1292 pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
1293 free_elements, tagstatus, ctx->tagwait);
1294
1295 return mask;
1296}
1297
73b6af8a 1298static int spufs_mfc_flush(struct file *file, fl_owner_t id)
a33a7d73
AB
1299{
1300 struct spu_context *ctx = file->private_data;
1301 int ret;
1302
1303 spu_acquire(ctx);
1304#if 0
1305/* this currently hangs */
1306 ret = spufs_wait(ctx->mfc_wq,
1307 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2));
1308 if (ret)
1309 goto out;
1310 ret = spufs_wait(ctx->mfc_wq,
1311 ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait);
1312out:
1313#else
1314 ret = 0;
1315#endif
1316 spu_release(ctx);
1317
1318 return ret;
1319}
1320
1321static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
1322 int datasync)
1323{
73b6af8a 1324 return spufs_mfc_flush(file, NULL);
a33a7d73
AB
1325}
1326
1327static int spufs_mfc_fasync(int fd, struct file *file, int on)
1328{
1329 struct spu_context *ctx = file->private_data;
1330
1331 return fasync_helper(fd, file, on, &ctx->mfc_fasync);
1332}
1333
1334static struct file_operations spufs_mfc_fops = {
1335 .open = spufs_mfc_open,
1336 .read = spufs_mfc_read,
1337 .write = spufs_mfc_write,
1338 .poll = spufs_mfc_poll,
1339 .flush = spufs_mfc_flush,
1340 .fsync = spufs_mfc_fsync,
1341 .fasync = spufs_mfc_fasync,
6df10a82 1342 .mmap = spufs_mfc_mmap,
a33a7d73
AB
1343};
1344
67207b96
AB
1345static void spufs_npc_set(void *data, u64 val)
1346{
1347 struct spu_context *ctx = data;
8b3d6663
AB
1348 spu_acquire(ctx);
1349 ctx->ops->npc_write(ctx, val);
1350 spu_release(ctx);
67207b96
AB
1351}
1352
1353static u64 spufs_npc_get(void *data)
1354{
1355 struct spu_context *ctx = data;
1356 u64 ret;
8b3d6663
AB
1357 spu_acquire(ctx);
1358 ret = ctx->ops->npc_read(ctx);
1359 spu_release(ctx);
67207b96
AB
1360 return ret;
1361}
1362DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
1363
8b3d6663
AB
1364static void spufs_decr_set(void *data, u64 val)
1365{
1366 struct spu_context *ctx = data;
1367 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1368 spu_acquire_saved(ctx);
1369 lscsa->decr.slot[0] = (u32) val;
1370 spu_release(ctx);
1371}
1372
1373static u64 spufs_decr_get(void *data)
1374{
1375 struct spu_context *ctx = data;
1376 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1377 u64 ret;
1378 spu_acquire_saved(ctx);
1379 ret = lscsa->decr.slot[0];
1380 spu_release(ctx);
1381 return ret;
1382}
1383DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
1384 "%llx\n")
1385
1386static void spufs_decr_status_set(void *data, u64 val)
1387{
1388 struct spu_context *ctx = data;
1389 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1390 spu_acquire_saved(ctx);
1391 lscsa->decr_status.slot[0] = (u32) val;
1392 spu_release(ctx);
1393}
1394
1395static u64 spufs_decr_status_get(void *data)
1396{
1397 struct spu_context *ctx = data;
1398 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1399 u64 ret;
1400 spu_acquire_saved(ctx);
1401 ret = lscsa->decr_status.slot[0];
1402 spu_release(ctx);
1403 return ret;
1404}
1405DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
1406 spufs_decr_status_set, "%llx\n")
1407
1408static void spufs_spu_tag_mask_set(void *data, u64 val)
1409{
1410 struct spu_context *ctx = data;
1411 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1412 spu_acquire_saved(ctx);
1413 lscsa->tag_mask.slot[0] = (u32) val;
1414 spu_release(ctx);
1415}
1416
1417static u64 spufs_spu_tag_mask_get(void *data)
1418{
1419 struct spu_context *ctx = data;
1420 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1421 u64 ret;
1422 spu_acquire_saved(ctx);
1423 ret = lscsa->tag_mask.slot[0];
1424 spu_release(ctx);
1425 return ret;
1426}
1427DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
1428 spufs_spu_tag_mask_set, "%llx\n")
1429
1430static void spufs_event_mask_set(void *data, u64 val)
1431{
1432 struct spu_context *ctx = data;
1433 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1434 spu_acquire_saved(ctx);
1435 lscsa->event_mask.slot[0] = (u32) val;
1436 spu_release(ctx);
1437}
1438
1439static u64 spufs_event_mask_get(void *data)
1440{
1441 struct spu_context *ctx = data;
1442 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1443 u64 ret;
1444 spu_acquire_saved(ctx);
1445 ret = lscsa->event_mask.slot[0];
1446 spu_release(ctx);
1447 return ret;
1448}
1449DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
1450 spufs_event_mask_set, "%llx\n")
1451
1452static void spufs_srr0_set(void *data, u64 val)
1453{
1454 struct spu_context *ctx = data;
1455 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1456 spu_acquire_saved(ctx);
1457 lscsa->srr0.slot[0] = (u32) val;
1458 spu_release(ctx);
1459}
1460
1461static u64 spufs_srr0_get(void *data)
1462{
1463 struct spu_context *ctx = data;
1464 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1465 u64 ret;
1466 spu_acquire_saved(ctx);
1467 ret = lscsa->srr0.slot[0];
1468 spu_release(ctx);
1469 return ret;
1470}
1471DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
1472 "%llx\n")
1473
7b1a7014
AB
1474static u64 spufs_id_get(void *data)
1475{
1476 struct spu_context *ctx = data;
1477 u64 num;
1478
1479 spu_acquire(ctx);
1480 if (ctx->state == SPU_STATE_RUNNABLE)
1481 num = ctx->spu->number;
1482 else
1483 num = (unsigned int)-1;
1484 spu_release(ctx);
1485
1486 return num;
1487}
e45d6634 1488DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
7b1a7014 1489
67207b96
AB
1490struct tree_descr spufs_dir_contents[] = {
1491 { "mem", &spufs_mem_fops, 0666, },
8b3d6663 1492 { "regs", &spufs_regs_fops, 0666, },
67207b96
AB
1493 { "mbox", &spufs_mbox_fops, 0444, },
1494 { "ibox", &spufs_ibox_fops, 0444, },
1495 { "wbox", &spufs_wbox_fops, 0222, },
1496 { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
1497 { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
1498 { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
1499 { "signal1", &spufs_signal1_fops, 0666, },
1500 { "signal2", &spufs_signal2_fops, 0666, },
1501 { "signal1_type", &spufs_signal1_type, 0666, },
1502 { "signal2_type", &spufs_signal2_type, 0666, },
d9379c4b 1503 { "mss", &spufs_mss_fops, 0666, },
a33a7d73 1504 { "mfc", &spufs_mfc_fops, 0666, },
6df10a82 1505 { "cntl", &spufs_cntl_fops, 0666, },
67207b96 1506 { "npc", &spufs_npc_ops, 0666, },
8b3d6663
AB
1507 { "fpcr", &spufs_fpcr_fops, 0666, },
1508 { "decr", &spufs_decr_ops, 0666, },
1509 { "decr_status", &spufs_decr_status_ops, 0666, },
1510 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
1511 { "event_mask", &spufs_event_mask_ops, 0666, },
1512 { "srr0", &spufs_srr0_ops, 0666, },
7b1a7014 1513 { "phys-id", &spufs_id_ops, 0666, },
27d5bf2a 1514 { "psmap", &spufs_psmap_fops, 0666, },
67207b96
AB
1515 {},
1516};