167207b96SArnd Bergmann /* 267207b96SArnd Bergmann * SPU file system -- file contents 367207b96SArnd Bergmann * 467207b96SArnd Bergmann * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 567207b96SArnd Bergmann * 667207b96SArnd Bergmann * Author: Arnd Bergmann <arndb@de.ibm.com> 767207b96SArnd Bergmann * 867207b96SArnd Bergmann * This program is free software; you can redistribute it and/or modify 967207b96SArnd Bergmann * it under the terms of the GNU General Public License as published by 1067207b96SArnd Bergmann * the Free Software Foundation; either version 2, or (at your option) 1167207b96SArnd Bergmann * any later version. 1267207b96SArnd Bergmann * 1367207b96SArnd Bergmann * This program is distributed in the hope that it will be useful, 1467207b96SArnd Bergmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 1567207b96SArnd Bergmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1667207b96SArnd Bergmann * GNU General Public License for more details. 1767207b96SArnd Bergmann * 1867207b96SArnd Bergmann * You should have received a copy of the GNU General Public License 1967207b96SArnd Bergmann * along with this program; if not, write to the Free Software 2067207b96SArnd Bergmann * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2167207b96SArnd Bergmann */ 2267207b96SArnd Bergmann 2367207b96SArnd Bergmann #include <linux/fs.h> 2467207b96SArnd Bergmann #include <linux/ioctl.h> 2567207b96SArnd Bergmann #include <linux/module.h> 26d88cfffaSArnd Bergmann #include <linux/pagemap.h> 2767207b96SArnd Bergmann #include <linux/poll.h> 2867207b96SArnd Bergmann 2967207b96SArnd Bergmann #include <asm/io.h> 3067207b96SArnd Bergmann #include <asm/semaphore.h> 3167207b96SArnd Bergmann #include <asm/spu.h> 3267207b96SArnd Bergmann #include <asm/uaccess.h> 3367207b96SArnd Bergmann 3467207b96SArnd Bergmann #include "spufs.h" 3567207b96SArnd Bergmann 368b3d6663SArnd Bergmann 3767207b96SArnd Bergmann static int 3867207b96SArnd Bergmann spufs_mem_open(struct inode *inode, struct file *file) 3967207b96SArnd Bergmann { 4067207b96SArnd Bergmann struct spufs_inode_info *i = SPUFS_I(inode); 4167207b96SArnd Bergmann file->private_data = i->i_ctx; 428b3d6663SArnd Bergmann file->f_mapping = i->i_ctx->local_store; 4367207b96SArnd Bergmann return 0; 4467207b96SArnd Bergmann } 4567207b96SArnd Bergmann 4667207b96SArnd Bergmann static ssize_t 4767207b96SArnd Bergmann spufs_mem_read(struct file *file, char __user *buffer, 4867207b96SArnd Bergmann size_t size, loff_t *pos) 4967207b96SArnd Bergmann { 508b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 518b3d6663SArnd Bergmann char *local_store; 5267207b96SArnd Bergmann int ret; 5367207b96SArnd Bergmann 548b3d6663SArnd Bergmann spu_acquire(ctx); 5567207b96SArnd Bergmann 568b3d6663SArnd Bergmann local_store = ctx->ops->get_ls(ctx); 578b3d6663SArnd Bergmann ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE); 5867207b96SArnd Bergmann 598b3d6663SArnd Bergmann spu_release(ctx); 6067207b96SArnd Bergmann return ret; 6167207b96SArnd Bergmann } 6267207b96SArnd Bergmann 6367207b96SArnd Bergmann static ssize_t 6467207b96SArnd Bergmann spufs_mem_write(struct file *file, const char __user *buffer, 6567207b96SArnd Bergmann size_t size, loff_t *pos) 6667207b96SArnd Bergmann { 6767207b96SArnd Bergmann struct spu_context *ctx = file->private_data; 688b3d6663SArnd Bergmann char *local_store; 698b3d6663SArnd Bergmann int ret; 7067207b96SArnd Bergmann 7167207b96SArnd Bergmann size = min_t(ssize_t, LS_SIZE - *pos, size); 7267207b96SArnd Bergmann if (size <= 0) 7367207b96SArnd Bergmann return -EFBIG; 7467207b96SArnd Bergmann *pos += size; 758b3d6663SArnd Bergmann 768b3d6663SArnd Bergmann spu_acquire(ctx); 778b3d6663SArnd Bergmann 788b3d6663SArnd Bergmann local_store = ctx->ops->get_ls(ctx); 798b3d6663SArnd Bergmann ret = copy_from_user(local_store + *pos - size, 8067207b96SArnd Bergmann buffer, size) ? -EFAULT : size; 818b3d6663SArnd Bergmann 828b3d6663SArnd Bergmann spu_release(ctx); 838b3d6663SArnd Bergmann return ret; 8467207b96SArnd Bergmann } 8567207b96SArnd Bergmann 868b3d6663SArnd Bergmann #ifdef CONFIG_SPARSEMEM 878b3d6663SArnd Bergmann static struct page * 888b3d6663SArnd Bergmann spufs_mem_mmap_nopage(struct vm_area_struct *vma, 898b3d6663SArnd Bergmann unsigned long address, int *type) 908b3d6663SArnd Bergmann { 918b3d6663SArnd Bergmann struct page *page = NOPAGE_SIGBUS; 928b3d6663SArnd Bergmann 938b3d6663SArnd Bergmann struct spu_context *ctx = vma->vm_file->private_data; 948b3d6663SArnd Bergmann unsigned long offset = address - vma->vm_start; 958b3d6663SArnd Bergmann offset += vma->vm_pgoff << PAGE_SHIFT; 968b3d6663SArnd Bergmann 978b3d6663SArnd Bergmann spu_acquire(ctx); 988b3d6663SArnd Bergmann 998b3d6663SArnd Bergmann if (ctx->state == SPU_STATE_SAVED) 1008b3d6663SArnd Bergmann page = vmalloc_to_page(ctx->csa.lscsa->ls + offset); 1018b3d6663SArnd Bergmann else 1028b3d6663SArnd Bergmann page = pfn_to_page((ctx->spu->local_store_phys + offset) 1038b3d6663SArnd Bergmann >> PAGE_SHIFT); 1048b3d6663SArnd Bergmann 1058b3d6663SArnd Bergmann spu_release(ctx); 1068b3d6663SArnd Bergmann 1078b3d6663SArnd Bergmann if (type) 1088b3d6663SArnd Bergmann *type = VM_FAULT_MINOR; 1098b3d6663SArnd Bergmann 110d88cfffaSArnd Bergmann page_cache_get(page); 1118b3d6663SArnd Bergmann return page; 1128b3d6663SArnd Bergmann } 1138b3d6663SArnd Bergmann 1148b3d6663SArnd Bergmann static struct vm_operations_struct spufs_mem_mmap_vmops = { 1158b3d6663SArnd Bergmann .nopage = spufs_mem_mmap_nopage, 1168b3d6663SArnd Bergmann }; 1178b3d6663SArnd Bergmann 11867207b96SArnd Bergmann static int 11967207b96SArnd Bergmann spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) 12067207b96SArnd Bergmann { 1218b3d6663SArnd Bergmann if (!(vma->vm_flags & VM_SHARED)) 1228b3d6663SArnd Bergmann return -EINVAL; 12367207b96SArnd Bergmann 1248b3d6663SArnd Bergmann /* FIXME: */ 12567207b96SArnd Bergmann vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 12667207b96SArnd Bergmann | _PAGE_NO_CACHE); 1278b3d6663SArnd Bergmann 1288b3d6663SArnd Bergmann vma->vm_ops = &spufs_mem_mmap_vmops; 12967207b96SArnd Bergmann return 0; 13067207b96SArnd Bergmann } 1318b3d6663SArnd Bergmann #endif 13267207b96SArnd Bergmann 13367207b96SArnd Bergmann static struct file_operations spufs_mem_fops = { 13467207b96SArnd Bergmann .open = spufs_mem_open, 13567207b96SArnd Bergmann .read = spufs_mem_read, 13667207b96SArnd Bergmann .write = spufs_mem_write, 1378b3d6663SArnd Bergmann .llseek = generic_file_llseek, 1388b3d6663SArnd Bergmann #ifdef CONFIG_SPARSEMEM 13967207b96SArnd Bergmann .mmap = spufs_mem_mmap, 1408b3d6663SArnd Bergmann #endif 1418b3d6663SArnd Bergmann }; 1428b3d6663SArnd Bergmann 1438b3d6663SArnd Bergmann static int 1448b3d6663SArnd Bergmann spufs_regs_open(struct inode *inode, struct file *file) 1458b3d6663SArnd Bergmann { 1468b3d6663SArnd Bergmann struct spufs_inode_info *i = SPUFS_I(inode); 1478b3d6663SArnd Bergmann file->private_data = i->i_ctx; 1488b3d6663SArnd Bergmann return 0; 1498b3d6663SArnd Bergmann } 1508b3d6663SArnd Bergmann 1518b3d6663SArnd Bergmann static ssize_t 1528b3d6663SArnd Bergmann spufs_regs_read(struct file *file, char __user *buffer, 1538b3d6663SArnd Bergmann size_t size, loff_t *pos) 1548b3d6663SArnd Bergmann { 1558b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 1568b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 1578b3d6663SArnd Bergmann int ret; 1588b3d6663SArnd Bergmann 1598b3d6663SArnd Bergmann spu_acquire_saved(ctx); 1608b3d6663SArnd Bergmann 1618b3d6663SArnd Bergmann ret = simple_read_from_buffer(buffer, size, pos, 1628b3d6663SArnd Bergmann lscsa->gprs, sizeof lscsa->gprs); 1638b3d6663SArnd Bergmann 1648b3d6663SArnd Bergmann spu_release(ctx); 1658b3d6663SArnd Bergmann return ret; 1668b3d6663SArnd Bergmann } 1678b3d6663SArnd Bergmann 1688b3d6663SArnd Bergmann static ssize_t 1698b3d6663SArnd Bergmann spufs_regs_write(struct file *file, const char __user *buffer, 1708b3d6663SArnd Bergmann size_t size, loff_t *pos) 1718b3d6663SArnd Bergmann { 1728b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 1738b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 1748b3d6663SArnd Bergmann int ret; 1758b3d6663SArnd Bergmann 1768b3d6663SArnd Bergmann size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size); 1778b3d6663SArnd Bergmann if (size <= 0) 1788b3d6663SArnd Bergmann return -EFBIG; 1798b3d6663SArnd Bergmann *pos += size; 1808b3d6663SArnd Bergmann 1818b3d6663SArnd Bergmann spu_acquire_saved(ctx); 1828b3d6663SArnd Bergmann 1838b3d6663SArnd Bergmann ret = copy_from_user(lscsa->gprs + *pos - size, 1848b3d6663SArnd Bergmann buffer, size) ? -EFAULT : size; 1858b3d6663SArnd Bergmann 1868b3d6663SArnd Bergmann spu_release(ctx); 1878b3d6663SArnd Bergmann return ret; 1888b3d6663SArnd Bergmann } 1898b3d6663SArnd Bergmann 1908b3d6663SArnd Bergmann static struct file_operations spufs_regs_fops = { 1918b3d6663SArnd Bergmann .open = spufs_regs_open, 1928b3d6663SArnd Bergmann .read = spufs_regs_read, 1938b3d6663SArnd Bergmann .write = spufs_regs_write, 1948b3d6663SArnd Bergmann .llseek = generic_file_llseek, 1958b3d6663SArnd Bergmann }; 1968b3d6663SArnd Bergmann 1978b3d6663SArnd Bergmann static ssize_t 1988b3d6663SArnd Bergmann spufs_fpcr_read(struct file *file, char __user * buffer, 1998b3d6663SArnd Bergmann size_t size, loff_t * pos) 2008b3d6663SArnd Bergmann { 2018b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 2028b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 2038b3d6663SArnd Bergmann int ret; 2048b3d6663SArnd Bergmann 2058b3d6663SArnd Bergmann spu_acquire_saved(ctx); 2068b3d6663SArnd Bergmann 2078b3d6663SArnd Bergmann ret = simple_read_from_buffer(buffer, size, pos, 2088b3d6663SArnd Bergmann &lscsa->fpcr, sizeof(lscsa->fpcr)); 2098b3d6663SArnd Bergmann 2108b3d6663SArnd Bergmann spu_release(ctx); 2118b3d6663SArnd Bergmann return ret; 2128b3d6663SArnd Bergmann } 2138b3d6663SArnd Bergmann 2148b3d6663SArnd Bergmann static ssize_t 2158b3d6663SArnd Bergmann spufs_fpcr_write(struct file *file, const char __user * buffer, 2168b3d6663SArnd Bergmann size_t size, loff_t * pos) 2178b3d6663SArnd Bergmann { 2188b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 2198b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 2208b3d6663SArnd Bergmann int ret; 2218b3d6663SArnd Bergmann 2228b3d6663SArnd Bergmann size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size); 2238b3d6663SArnd Bergmann if (size <= 0) 2248b3d6663SArnd Bergmann return -EFBIG; 2258b3d6663SArnd Bergmann *pos += size; 2268b3d6663SArnd Bergmann 2278b3d6663SArnd Bergmann spu_acquire_saved(ctx); 2288b3d6663SArnd Bergmann 2298b3d6663SArnd Bergmann ret = copy_from_user((char *)&lscsa->fpcr + *pos - size, 2308b3d6663SArnd Bergmann buffer, size) ? -EFAULT : size; 2318b3d6663SArnd Bergmann 2328b3d6663SArnd Bergmann spu_release(ctx); 2338b3d6663SArnd Bergmann return ret; 2348b3d6663SArnd Bergmann } 2358b3d6663SArnd Bergmann 2368b3d6663SArnd Bergmann static struct file_operations spufs_fpcr_fops = { 2378b3d6663SArnd Bergmann .open = spufs_regs_open, 2388b3d6663SArnd Bergmann .read = spufs_fpcr_read, 2398b3d6663SArnd Bergmann .write = spufs_fpcr_write, 24067207b96SArnd Bergmann .llseek = generic_file_llseek, 24167207b96SArnd Bergmann }; 24267207b96SArnd Bergmann 24367207b96SArnd Bergmann /* generic open function for all pipe-like files */ 24467207b96SArnd Bergmann static int spufs_pipe_open(struct inode *inode, struct file *file) 24567207b96SArnd Bergmann { 24667207b96SArnd Bergmann struct spufs_inode_info *i = SPUFS_I(inode); 24767207b96SArnd Bergmann file->private_data = i->i_ctx; 24867207b96SArnd Bergmann 24967207b96SArnd Bergmann return nonseekable_open(inode, file); 25067207b96SArnd Bergmann } 25167207b96SArnd Bergmann 25267207b96SArnd Bergmann static ssize_t spufs_mbox_read(struct file *file, char __user *buf, 25367207b96SArnd Bergmann size_t len, loff_t *pos) 25467207b96SArnd Bergmann { 2558b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 25667207b96SArnd Bergmann u32 mbox_data; 2578b3d6663SArnd Bergmann int ret; 25867207b96SArnd Bergmann 25967207b96SArnd Bergmann if (len < 4) 26067207b96SArnd Bergmann return -EINVAL; 26167207b96SArnd Bergmann 2628b3d6663SArnd Bergmann spu_acquire(ctx); 2638b3d6663SArnd Bergmann ret = ctx->ops->mbox_read(ctx, &mbox_data); 2648b3d6663SArnd Bergmann spu_release(ctx); 26567207b96SArnd Bergmann 2668b3d6663SArnd Bergmann if (!ret) 2678b3d6663SArnd Bergmann return -EAGAIN; 26867207b96SArnd Bergmann 26967207b96SArnd Bergmann if (copy_to_user(buf, &mbox_data, sizeof mbox_data)) 27067207b96SArnd Bergmann return -EFAULT; 27167207b96SArnd Bergmann 27267207b96SArnd Bergmann return 4; 27367207b96SArnd Bergmann } 27467207b96SArnd Bergmann 27567207b96SArnd Bergmann static struct file_operations spufs_mbox_fops = { 27667207b96SArnd Bergmann .open = spufs_pipe_open, 27767207b96SArnd Bergmann .read = spufs_mbox_read, 27867207b96SArnd Bergmann }; 27967207b96SArnd Bergmann 28067207b96SArnd Bergmann static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, 28167207b96SArnd Bergmann size_t len, loff_t *pos) 28267207b96SArnd Bergmann { 2838b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 28467207b96SArnd Bergmann u32 mbox_stat; 28567207b96SArnd Bergmann 28667207b96SArnd Bergmann if (len < 4) 28767207b96SArnd Bergmann return -EINVAL; 28867207b96SArnd Bergmann 2898b3d6663SArnd Bergmann spu_acquire(ctx); 2908b3d6663SArnd Bergmann 2918b3d6663SArnd Bergmann mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff; 2928b3d6663SArnd Bergmann 2938b3d6663SArnd Bergmann spu_release(ctx); 29467207b96SArnd Bergmann 29567207b96SArnd Bergmann if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat)) 29667207b96SArnd Bergmann return -EFAULT; 29767207b96SArnd Bergmann 29867207b96SArnd Bergmann return 4; 29967207b96SArnd Bergmann } 30067207b96SArnd Bergmann 30167207b96SArnd Bergmann static struct file_operations spufs_mbox_stat_fops = { 30267207b96SArnd Bergmann .open = spufs_pipe_open, 30367207b96SArnd Bergmann .read = spufs_mbox_stat_read, 30467207b96SArnd Bergmann }; 30567207b96SArnd Bergmann 3068b3d6663SArnd Bergmann /* 3078b3d6663SArnd Bergmann * spufs_wait 3088b3d6663SArnd Bergmann * Same as wait_event_interruptible(), except that here 3098b3d6663SArnd Bergmann * we need to call spu_release(ctx) before sleeping, and 3108b3d6663SArnd Bergmann * then spu_acquire(ctx) when awoken. 3118b3d6663SArnd Bergmann */ 3128b3d6663SArnd Bergmann 3138b3d6663SArnd Bergmann #define spufs_wait(wq, condition) \ 3148b3d6663SArnd Bergmann ({ \ 3158b3d6663SArnd Bergmann int __ret = 0; \ 3168b3d6663SArnd Bergmann DEFINE_WAIT(__wait); \ 3178b3d6663SArnd Bergmann for (;;) { \ 3188b3d6663SArnd Bergmann prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ 3198b3d6663SArnd Bergmann if (condition) \ 3208b3d6663SArnd Bergmann break; \ 3218b3d6663SArnd Bergmann if (!signal_pending(current)) { \ 3228b3d6663SArnd Bergmann spu_release(ctx); \ 3238b3d6663SArnd Bergmann schedule(); \ 3248b3d6663SArnd Bergmann spu_acquire(ctx); \ 3258b3d6663SArnd Bergmann continue; \ 3268b3d6663SArnd Bergmann } \ 3278b3d6663SArnd Bergmann __ret = -ERESTARTSYS; \ 3288b3d6663SArnd Bergmann break; \ 3298b3d6663SArnd Bergmann } \ 3308b3d6663SArnd Bergmann finish_wait(&(wq), &__wait); \ 3318b3d6663SArnd Bergmann __ret; \ 3328b3d6663SArnd Bergmann }) 3338b3d6663SArnd Bergmann 33467207b96SArnd Bergmann /* low-level ibox access function */ 3358b3d6663SArnd Bergmann size_t spu_ibox_read(struct spu_context *ctx, u32 *data) 33667207b96SArnd Bergmann { 3378b3d6663SArnd Bergmann return ctx->ops->ibox_read(ctx, data); 33867207b96SArnd Bergmann } 33967207b96SArnd Bergmann 34067207b96SArnd Bergmann static int spufs_ibox_fasync(int fd, struct file *file, int on) 34167207b96SArnd Bergmann { 3428b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 3438b3d6663SArnd Bergmann 3448b3d6663SArnd Bergmann return fasync_helper(fd, file, on, &ctx->ibox_fasync); 3458b3d6663SArnd Bergmann } 3468b3d6663SArnd Bergmann 3478b3d6663SArnd Bergmann /* interrupt-level ibox callback function. */ 3488b3d6663SArnd Bergmann void spufs_ibox_callback(struct spu *spu) 3498b3d6663SArnd Bergmann { 3508b3d6663SArnd Bergmann struct spu_context *ctx = spu->ctx; 3518b3d6663SArnd Bergmann 3528b3d6663SArnd Bergmann wake_up_all(&ctx->ibox_wq); 3538b3d6663SArnd Bergmann kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN); 35467207b96SArnd Bergmann } 35567207b96SArnd Bergmann 35667207b96SArnd Bergmann static ssize_t spufs_ibox_read(struct file *file, char __user *buf, 35767207b96SArnd Bergmann size_t len, loff_t *pos) 35867207b96SArnd Bergmann { 3598b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 36067207b96SArnd Bergmann u32 ibox_data; 36167207b96SArnd Bergmann ssize_t ret; 36267207b96SArnd Bergmann 36367207b96SArnd Bergmann if (len < 4) 36467207b96SArnd Bergmann return -EINVAL; 36567207b96SArnd Bergmann 3668b3d6663SArnd Bergmann spu_acquire(ctx); 36767207b96SArnd Bergmann 36867207b96SArnd Bergmann ret = 0; 36967207b96SArnd Bergmann if (file->f_flags & O_NONBLOCK) { 3708b3d6663SArnd Bergmann if (!spu_ibox_read(ctx, &ibox_data)) 37167207b96SArnd Bergmann ret = -EAGAIN; 37267207b96SArnd Bergmann } else { 3738b3d6663SArnd Bergmann ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data)); 37467207b96SArnd Bergmann } 37567207b96SArnd Bergmann 3768b3d6663SArnd Bergmann spu_release(ctx); 3778b3d6663SArnd Bergmann 37867207b96SArnd Bergmann if (ret) 37967207b96SArnd Bergmann return ret; 38067207b96SArnd Bergmann 38167207b96SArnd Bergmann ret = 4; 38267207b96SArnd Bergmann if (copy_to_user(buf, &ibox_data, sizeof ibox_data)) 38367207b96SArnd Bergmann ret = -EFAULT; 38467207b96SArnd Bergmann 38567207b96SArnd Bergmann return ret; 38667207b96SArnd Bergmann } 38767207b96SArnd Bergmann 38867207b96SArnd Bergmann static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait) 38967207b96SArnd Bergmann { 3908b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 39167207b96SArnd Bergmann u32 mbox_stat; 39267207b96SArnd Bergmann unsigned int mask; 39367207b96SArnd Bergmann 3948b3d6663SArnd Bergmann spu_acquire(ctx); 39567207b96SArnd Bergmann 3968b3d6663SArnd Bergmann mbox_stat = ctx->ops->mbox_stat_read(ctx); 3978b3d6663SArnd Bergmann 3988b3d6663SArnd Bergmann spu_release(ctx); 3998b3d6663SArnd Bergmann 4008b3d6663SArnd Bergmann poll_wait(file, &ctx->ibox_wq, wait); 40167207b96SArnd Bergmann 40267207b96SArnd Bergmann mask = 0; 40367207b96SArnd Bergmann if (mbox_stat & 0xff0000) 40467207b96SArnd Bergmann mask |= POLLIN | POLLRDNORM; 40567207b96SArnd Bergmann 40667207b96SArnd Bergmann return mask; 40767207b96SArnd Bergmann } 40867207b96SArnd Bergmann 40967207b96SArnd Bergmann static struct file_operations spufs_ibox_fops = { 41067207b96SArnd Bergmann .open = spufs_pipe_open, 41167207b96SArnd Bergmann .read = spufs_ibox_read, 41267207b96SArnd Bergmann .poll = spufs_ibox_poll, 41367207b96SArnd Bergmann .fasync = spufs_ibox_fasync, 41467207b96SArnd Bergmann }; 41567207b96SArnd Bergmann 41667207b96SArnd Bergmann static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, 41767207b96SArnd Bergmann size_t len, loff_t *pos) 41867207b96SArnd Bergmann { 4198b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 42067207b96SArnd Bergmann u32 ibox_stat; 42167207b96SArnd Bergmann 42267207b96SArnd Bergmann if (len < 4) 42367207b96SArnd Bergmann return -EINVAL; 42467207b96SArnd Bergmann 4258b3d6663SArnd Bergmann spu_acquire(ctx); 4268b3d6663SArnd Bergmann ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff; 4278b3d6663SArnd Bergmann spu_release(ctx); 42867207b96SArnd Bergmann 42967207b96SArnd Bergmann if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat)) 43067207b96SArnd Bergmann return -EFAULT; 43167207b96SArnd Bergmann 43267207b96SArnd Bergmann return 4; 43367207b96SArnd Bergmann } 43467207b96SArnd Bergmann 43567207b96SArnd Bergmann static struct file_operations spufs_ibox_stat_fops = { 43667207b96SArnd Bergmann .open = spufs_pipe_open, 43767207b96SArnd Bergmann .read = spufs_ibox_stat_read, 43867207b96SArnd Bergmann }; 43967207b96SArnd Bergmann 44067207b96SArnd Bergmann /* low-level mailbox write */ 4418b3d6663SArnd Bergmann size_t spu_wbox_write(struct spu_context *ctx, u32 data) 44267207b96SArnd Bergmann { 4438b3d6663SArnd Bergmann return ctx->ops->wbox_write(ctx, data); 44467207b96SArnd Bergmann } 44567207b96SArnd Bergmann 44667207b96SArnd Bergmann static int spufs_wbox_fasync(int fd, struct file *file, int on) 44767207b96SArnd Bergmann { 4488b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 4498b3d6663SArnd Bergmann int ret; 4508b3d6663SArnd Bergmann 4518b3d6663SArnd Bergmann ret = fasync_helper(fd, file, on, &ctx->wbox_fasync); 4528b3d6663SArnd Bergmann 4538b3d6663SArnd Bergmann return ret; 4548b3d6663SArnd Bergmann } 4558b3d6663SArnd Bergmann 4568b3d6663SArnd Bergmann /* interrupt-level wbox callback function. */ 4578b3d6663SArnd Bergmann void spufs_wbox_callback(struct spu *spu) 4588b3d6663SArnd Bergmann { 4598b3d6663SArnd Bergmann struct spu_context *ctx = spu->ctx; 4608b3d6663SArnd Bergmann 4618b3d6663SArnd Bergmann wake_up_all(&ctx->wbox_wq); 4628b3d6663SArnd Bergmann kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT); 46367207b96SArnd Bergmann } 46467207b96SArnd Bergmann 46567207b96SArnd Bergmann static ssize_t spufs_wbox_write(struct file *file, const char __user *buf, 46667207b96SArnd Bergmann size_t len, loff_t *pos) 46767207b96SArnd Bergmann { 4688b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 46967207b96SArnd Bergmann u32 wbox_data; 47067207b96SArnd Bergmann int ret; 47167207b96SArnd Bergmann 47267207b96SArnd Bergmann if (len < 4) 47367207b96SArnd Bergmann return -EINVAL; 47467207b96SArnd Bergmann 47567207b96SArnd Bergmann if (copy_from_user(&wbox_data, buf, sizeof wbox_data)) 47667207b96SArnd Bergmann return -EFAULT; 47767207b96SArnd Bergmann 4788b3d6663SArnd Bergmann spu_acquire(ctx); 4798b3d6663SArnd Bergmann 48067207b96SArnd Bergmann ret = 0; 48167207b96SArnd Bergmann if (file->f_flags & O_NONBLOCK) { 4828b3d6663SArnd Bergmann if (!spu_wbox_write(ctx, wbox_data)) 48367207b96SArnd Bergmann ret = -EAGAIN; 48467207b96SArnd Bergmann } else { 4858b3d6663SArnd Bergmann ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data)); 48667207b96SArnd Bergmann } 48767207b96SArnd Bergmann 4888b3d6663SArnd Bergmann spu_release(ctx); 4898b3d6663SArnd Bergmann 49067207b96SArnd Bergmann return ret ? ret : sizeof wbox_data; 49167207b96SArnd Bergmann } 49267207b96SArnd Bergmann 49367207b96SArnd Bergmann static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait) 49467207b96SArnd Bergmann { 4958b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 49667207b96SArnd Bergmann u32 mbox_stat; 49767207b96SArnd Bergmann unsigned int mask; 49867207b96SArnd Bergmann 4998b3d6663SArnd Bergmann spu_acquire(ctx); 5008b3d6663SArnd Bergmann mbox_stat = ctx->ops->mbox_stat_read(ctx); 5018b3d6663SArnd Bergmann spu_release(ctx); 50267207b96SArnd Bergmann 5038b3d6663SArnd Bergmann poll_wait(file, &ctx->wbox_wq, wait); 50467207b96SArnd Bergmann 50567207b96SArnd Bergmann mask = 0; 50667207b96SArnd Bergmann if (mbox_stat & 0x00ff00) 50767207b96SArnd Bergmann mask = POLLOUT | POLLWRNORM; 50867207b96SArnd Bergmann 50967207b96SArnd Bergmann return mask; 51067207b96SArnd Bergmann } 51167207b96SArnd Bergmann 51267207b96SArnd Bergmann static struct file_operations spufs_wbox_fops = { 51367207b96SArnd Bergmann .open = spufs_pipe_open, 51467207b96SArnd Bergmann .write = spufs_wbox_write, 51567207b96SArnd Bergmann .poll = spufs_wbox_poll, 51667207b96SArnd Bergmann .fasync = spufs_wbox_fasync, 51767207b96SArnd Bergmann }; 51867207b96SArnd Bergmann 51967207b96SArnd Bergmann static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, 52067207b96SArnd Bergmann size_t len, loff_t *pos) 52167207b96SArnd Bergmann { 5228b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 52367207b96SArnd Bergmann u32 wbox_stat; 52467207b96SArnd Bergmann 52567207b96SArnd Bergmann if (len < 4) 52667207b96SArnd Bergmann return -EINVAL; 52767207b96SArnd Bergmann 5288b3d6663SArnd Bergmann spu_acquire(ctx); 5298b3d6663SArnd Bergmann wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff; 5308b3d6663SArnd Bergmann spu_release(ctx); 53167207b96SArnd Bergmann 53267207b96SArnd Bergmann if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat)) 53367207b96SArnd Bergmann return -EFAULT; 53467207b96SArnd Bergmann 53567207b96SArnd Bergmann return 4; 53667207b96SArnd Bergmann } 53767207b96SArnd Bergmann 53867207b96SArnd Bergmann static struct file_operations spufs_wbox_stat_fops = { 53967207b96SArnd Bergmann .open = spufs_pipe_open, 54067207b96SArnd Bergmann .read = spufs_wbox_stat_read, 54167207b96SArnd Bergmann }; 54267207b96SArnd Bergmann 54367207b96SArnd Bergmann long spufs_run_spu(struct file *file, struct spu_context *ctx, 54467207b96SArnd Bergmann u32 *npc, u32 *status) 54567207b96SArnd Bergmann { 54667207b96SArnd Bergmann int ret; 54767207b96SArnd Bergmann 5488b3d6663SArnd Bergmann ret = spu_acquire_runnable(ctx); 5498b3d6663SArnd Bergmann if (ret) 5508b3d6663SArnd Bergmann return ret; 55167207b96SArnd Bergmann 5528b3d6663SArnd Bergmann ctx->ops->npc_write(ctx, *npc); 55367207b96SArnd Bergmann 55467207b96SArnd Bergmann ret = spu_run(ctx->spu); 55567207b96SArnd Bergmann 5568b3d6663SArnd Bergmann if (!ret) 5578b3d6663SArnd Bergmann ret = ctx->ops->status_read(ctx); 55867207b96SArnd Bergmann 5598b3d6663SArnd Bergmann *npc = ctx->ops->npc_read(ctx); 56067207b96SArnd Bergmann 5618b3d6663SArnd Bergmann spu_release(ctx); 5628b3d6663SArnd Bergmann spu_yield(ctx); 56367207b96SArnd Bergmann return ret; 56467207b96SArnd Bergmann } 56567207b96SArnd Bergmann 56667207b96SArnd Bergmann static ssize_t spufs_signal1_read(struct file *file, char __user *buf, 56767207b96SArnd Bergmann size_t len, loff_t *pos) 56867207b96SArnd Bergmann { 5698b3d6663SArnd Bergmann struct spu_context *ctx = file->private_data; 57067207b96SArnd Bergmann u32 data; 57167207b96SArnd Bergmann 57267207b96SArnd Bergmann if (len < 4) 57367207b96SArnd Bergmann return -EINVAL; 57467207b96SArnd Bergmann 5758b3d6663SArnd Bergmann spu_acquire(ctx); 5768b3d6663SArnd Bergmann data = ctx->ops->signal1_read(ctx); 5778b3d6663SArnd Bergmann spu_release(ctx); 5788b3d6663SArnd Bergmann 57967207b96SArnd Bergmann if (copy_to_user(buf, &data, 4)) 58067207b96SArnd Bergmann return -EFAULT; 58167207b96SArnd Bergmann 58267207b96SArnd Bergmann return 4; 58367207b96SArnd Bergmann } 58467207b96SArnd Bergmann 58567207b96SArnd Bergmann static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, 58667207b96SArnd Bergmann size_t len, loff_t *pos) 58767207b96SArnd Bergmann { 58867207b96SArnd Bergmann struct spu_context *ctx; 58967207b96SArnd Bergmann u32 data; 59067207b96SArnd Bergmann 59167207b96SArnd Bergmann ctx = file->private_data; 59267207b96SArnd Bergmann 59367207b96SArnd Bergmann if (len < 4) 59467207b96SArnd Bergmann return -EINVAL; 59567207b96SArnd Bergmann 59667207b96SArnd Bergmann if (copy_from_user(&data, buf, 4)) 59767207b96SArnd Bergmann return -EFAULT; 59867207b96SArnd Bergmann 5998b3d6663SArnd Bergmann spu_acquire(ctx); 6008b3d6663SArnd Bergmann ctx->ops->signal1_write(ctx, data); 6018b3d6663SArnd Bergmann spu_release(ctx); 60267207b96SArnd Bergmann 60367207b96SArnd Bergmann return 4; 60467207b96SArnd Bergmann } 60567207b96SArnd Bergmann 60667207b96SArnd Bergmann static struct file_operations spufs_signal1_fops = { 60767207b96SArnd Bergmann .open = spufs_pipe_open, 60867207b96SArnd Bergmann .read = spufs_signal1_read, 60967207b96SArnd Bergmann .write = spufs_signal1_write, 61067207b96SArnd Bergmann }; 61167207b96SArnd Bergmann 61267207b96SArnd Bergmann static ssize_t spufs_signal2_read(struct file *file, char __user *buf, 61367207b96SArnd Bergmann size_t len, loff_t *pos) 61467207b96SArnd Bergmann { 61567207b96SArnd Bergmann struct spu_context *ctx; 61667207b96SArnd Bergmann u32 data; 61767207b96SArnd Bergmann 61867207b96SArnd Bergmann ctx = file->private_data; 61967207b96SArnd Bergmann 62067207b96SArnd Bergmann if (len < 4) 62167207b96SArnd Bergmann return -EINVAL; 62267207b96SArnd Bergmann 6238b3d6663SArnd Bergmann spu_acquire(ctx); 6248b3d6663SArnd Bergmann data = ctx->ops->signal2_read(ctx); 6258b3d6663SArnd Bergmann spu_release(ctx); 6268b3d6663SArnd Bergmann 62767207b96SArnd Bergmann if (copy_to_user(buf, &data, 4)) 62867207b96SArnd Bergmann return -EFAULT; 62967207b96SArnd Bergmann 63067207b96SArnd Bergmann return 4; 63167207b96SArnd Bergmann } 63267207b96SArnd Bergmann 63367207b96SArnd Bergmann static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, 63467207b96SArnd Bergmann size_t len, loff_t *pos) 63567207b96SArnd Bergmann { 63667207b96SArnd Bergmann struct spu_context *ctx; 63767207b96SArnd Bergmann u32 data; 63867207b96SArnd Bergmann 63967207b96SArnd Bergmann ctx = file->private_data; 64067207b96SArnd Bergmann 64167207b96SArnd Bergmann if (len < 4) 64267207b96SArnd Bergmann return -EINVAL; 64367207b96SArnd Bergmann 64467207b96SArnd Bergmann if (copy_from_user(&data, buf, 4)) 64567207b96SArnd Bergmann return -EFAULT; 64667207b96SArnd Bergmann 6478b3d6663SArnd Bergmann spu_acquire(ctx); 6488b3d6663SArnd Bergmann ctx->ops->signal2_write(ctx, data); 6498b3d6663SArnd Bergmann spu_release(ctx); 65067207b96SArnd Bergmann 65167207b96SArnd Bergmann return 4; 65267207b96SArnd Bergmann } 65367207b96SArnd Bergmann 65467207b96SArnd Bergmann static struct file_operations spufs_signal2_fops = { 65567207b96SArnd Bergmann .open = spufs_pipe_open, 65667207b96SArnd Bergmann .read = spufs_signal2_read, 65767207b96SArnd Bergmann .write = spufs_signal2_write, 65867207b96SArnd Bergmann }; 65967207b96SArnd Bergmann 66067207b96SArnd Bergmann static void spufs_signal1_type_set(void *data, u64 val) 66167207b96SArnd Bergmann { 66267207b96SArnd Bergmann struct spu_context *ctx = data; 66367207b96SArnd Bergmann 6648b3d6663SArnd Bergmann spu_acquire(ctx); 6658b3d6663SArnd Bergmann ctx->ops->signal1_type_set(ctx, val); 6668b3d6663SArnd Bergmann spu_release(ctx); 66767207b96SArnd Bergmann } 66867207b96SArnd Bergmann 66967207b96SArnd Bergmann static u64 spufs_signal1_type_get(void *data) 67067207b96SArnd Bergmann { 67167207b96SArnd Bergmann struct spu_context *ctx = data; 6728b3d6663SArnd Bergmann u64 ret; 6738b3d6663SArnd Bergmann 6748b3d6663SArnd Bergmann spu_acquire(ctx); 6758b3d6663SArnd Bergmann ret = ctx->ops->signal1_type_get(ctx); 6768b3d6663SArnd Bergmann spu_release(ctx); 6778b3d6663SArnd Bergmann 6788b3d6663SArnd Bergmann return ret; 67967207b96SArnd Bergmann } 68067207b96SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get, 68167207b96SArnd Bergmann spufs_signal1_type_set, "%llu"); 68267207b96SArnd Bergmann 68367207b96SArnd Bergmann static void spufs_signal2_type_set(void *data, u64 val) 68467207b96SArnd Bergmann { 68567207b96SArnd Bergmann struct spu_context *ctx = data; 68667207b96SArnd Bergmann 6878b3d6663SArnd Bergmann spu_acquire(ctx); 6888b3d6663SArnd Bergmann ctx->ops->signal2_type_set(ctx, val); 6898b3d6663SArnd Bergmann spu_release(ctx); 69067207b96SArnd Bergmann } 69167207b96SArnd Bergmann 69267207b96SArnd Bergmann static u64 spufs_signal2_type_get(void *data) 69367207b96SArnd Bergmann { 69467207b96SArnd Bergmann struct spu_context *ctx = data; 6958b3d6663SArnd Bergmann u64 ret; 6968b3d6663SArnd Bergmann 6978b3d6663SArnd Bergmann spu_acquire(ctx); 6988b3d6663SArnd Bergmann ret = ctx->ops->signal2_type_get(ctx); 6998b3d6663SArnd Bergmann spu_release(ctx); 7008b3d6663SArnd Bergmann 7018b3d6663SArnd Bergmann return ret; 70267207b96SArnd Bergmann } 70367207b96SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, 70467207b96SArnd Bergmann spufs_signal2_type_set, "%llu"); 70567207b96SArnd Bergmann 70667207b96SArnd Bergmann static void spufs_npc_set(void *data, u64 val) 70767207b96SArnd Bergmann { 70867207b96SArnd Bergmann struct spu_context *ctx = data; 7098b3d6663SArnd Bergmann spu_acquire(ctx); 7108b3d6663SArnd Bergmann ctx->ops->npc_write(ctx, val); 7118b3d6663SArnd Bergmann spu_release(ctx); 71267207b96SArnd Bergmann } 71367207b96SArnd Bergmann 71467207b96SArnd Bergmann static u64 spufs_npc_get(void *data) 71567207b96SArnd Bergmann { 71667207b96SArnd Bergmann struct spu_context *ctx = data; 71767207b96SArnd Bergmann u64 ret; 7188b3d6663SArnd Bergmann spu_acquire(ctx); 7198b3d6663SArnd Bergmann ret = ctx->ops->npc_read(ctx); 7208b3d6663SArnd Bergmann spu_release(ctx); 72167207b96SArnd Bergmann return ret; 72267207b96SArnd Bergmann } 72367207b96SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n") 72467207b96SArnd Bergmann 7258b3d6663SArnd Bergmann static void spufs_decr_set(void *data, u64 val) 7268b3d6663SArnd Bergmann { 7278b3d6663SArnd Bergmann struct spu_context *ctx = data; 7288b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7298b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7308b3d6663SArnd Bergmann lscsa->decr.slot[0] = (u32) val; 7318b3d6663SArnd Bergmann spu_release(ctx); 7328b3d6663SArnd Bergmann } 7338b3d6663SArnd Bergmann 7348b3d6663SArnd Bergmann static u64 spufs_decr_get(void *data) 7358b3d6663SArnd Bergmann { 7368b3d6663SArnd Bergmann struct spu_context *ctx = data; 7378b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7388b3d6663SArnd Bergmann u64 ret; 7398b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7408b3d6663SArnd Bergmann ret = lscsa->decr.slot[0]; 7418b3d6663SArnd Bergmann spu_release(ctx); 7428b3d6663SArnd Bergmann return ret; 7438b3d6663SArnd Bergmann } 7448b3d6663SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, 7458b3d6663SArnd Bergmann "%llx\n") 7468b3d6663SArnd Bergmann 7478b3d6663SArnd Bergmann static void spufs_decr_status_set(void *data, u64 val) 7488b3d6663SArnd Bergmann { 7498b3d6663SArnd Bergmann struct spu_context *ctx = data; 7508b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7518b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7528b3d6663SArnd Bergmann lscsa->decr_status.slot[0] = (u32) val; 7538b3d6663SArnd Bergmann spu_release(ctx); 7548b3d6663SArnd Bergmann } 7558b3d6663SArnd Bergmann 7568b3d6663SArnd Bergmann static u64 spufs_decr_status_get(void *data) 7578b3d6663SArnd Bergmann { 7588b3d6663SArnd Bergmann struct spu_context *ctx = data; 7598b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7608b3d6663SArnd Bergmann u64 ret; 7618b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7628b3d6663SArnd Bergmann ret = lscsa->decr_status.slot[0]; 7638b3d6663SArnd Bergmann spu_release(ctx); 7648b3d6663SArnd Bergmann return ret; 7658b3d6663SArnd Bergmann } 7668b3d6663SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, 7678b3d6663SArnd Bergmann spufs_decr_status_set, "%llx\n") 7688b3d6663SArnd Bergmann 7698b3d6663SArnd Bergmann static void spufs_spu_tag_mask_set(void *data, u64 val) 7708b3d6663SArnd Bergmann { 7718b3d6663SArnd Bergmann struct spu_context *ctx = data; 7728b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7738b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7748b3d6663SArnd Bergmann lscsa->tag_mask.slot[0] = (u32) val; 7758b3d6663SArnd Bergmann spu_release(ctx); 7768b3d6663SArnd Bergmann } 7778b3d6663SArnd Bergmann 7788b3d6663SArnd Bergmann static u64 spufs_spu_tag_mask_get(void *data) 7798b3d6663SArnd Bergmann { 7808b3d6663SArnd Bergmann struct spu_context *ctx = data; 7818b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7828b3d6663SArnd Bergmann u64 ret; 7838b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7848b3d6663SArnd Bergmann ret = lscsa->tag_mask.slot[0]; 7858b3d6663SArnd Bergmann spu_release(ctx); 7868b3d6663SArnd Bergmann return ret; 7878b3d6663SArnd Bergmann } 7888b3d6663SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get, 7898b3d6663SArnd Bergmann spufs_spu_tag_mask_set, "%llx\n") 7908b3d6663SArnd Bergmann 7918b3d6663SArnd Bergmann static void spufs_event_mask_set(void *data, u64 val) 7928b3d6663SArnd Bergmann { 7938b3d6663SArnd Bergmann struct spu_context *ctx = data; 7948b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 7958b3d6663SArnd Bergmann spu_acquire_saved(ctx); 7968b3d6663SArnd Bergmann lscsa->event_mask.slot[0] = (u32) val; 7978b3d6663SArnd Bergmann spu_release(ctx); 7988b3d6663SArnd Bergmann } 7998b3d6663SArnd Bergmann 8008b3d6663SArnd Bergmann static u64 spufs_event_mask_get(void *data) 8018b3d6663SArnd Bergmann { 8028b3d6663SArnd Bergmann struct spu_context *ctx = data; 8038b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 8048b3d6663SArnd Bergmann u64 ret; 8058b3d6663SArnd Bergmann spu_acquire_saved(ctx); 8068b3d6663SArnd Bergmann ret = lscsa->event_mask.slot[0]; 8078b3d6663SArnd Bergmann spu_release(ctx); 8088b3d6663SArnd Bergmann return ret; 8098b3d6663SArnd Bergmann } 8108b3d6663SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, 8118b3d6663SArnd Bergmann spufs_event_mask_set, "%llx\n") 8128b3d6663SArnd Bergmann 8138b3d6663SArnd Bergmann static void spufs_srr0_set(void *data, u64 val) 8148b3d6663SArnd Bergmann { 8158b3d6663SArnd Bergmann struct spu_context *ctx = data; 8168b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 8178b3d6663SArnd Bergmann spu_acquire_saved(ctx); 8188b3d6663SArnd Bergmann lscsa->srr0.slot[0] = (u32) val; 8198b3d6663SArnd Bergmann spu_release(ctx); 8208b3d6663SArnd Bergmann } 8218b3d6663SArnd Bergmann 8228b3d6663SArnd Bergmann static u64 spufs_srr0_get(void *data) 8238b3d6663SArnd Bergmann { 8248b3d6663SArnd Bergmann struct spu_context *ctx = data; 8258b3d6663SArnd Bergmann struct spu_lscsa *lscsa = ctx->csa.lscsa; 8268b3d6663SArnd Bergmann u64 ret; 8278b3d6663SArnd Bergmann spu_acquire_saved(ctx); 8288b3d6663SArnd Bergmann ret = lscsa->srr0.slot[0]; 8298b3d6663SArnd Bergmann spu_release(ctx); 8308b3d6663SArnd Bergmann return ret; 8318b3d6663SArnd Bergmann } 8328b3d6663SArnd Bergmann DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, 8338b3d6663SArnd Bergmann "%llx\n") 8348b3d6663SArnd Bergmann 83567207b96SArnd Bergmann struct tree_descr spufs_dir_contents[] = { 83667207b96SArnd Bergmann { "mem", &spufs_mem_fops, 0666, }, 8378b3d6663SArnd Bergmann { "regs", &spufs_regs_fops, 0666, }, 83867207b96SArnd Bergmann { "mbox", &spufs_mbox_fops, 0444, }, 83967207b96SArnd Bergmann { "ibox", &spufs_ibox_fops, 0444, }, 84067207b96SArnd Bergmann { "wbox", &spufs_wbox_fops, 0222, }, 84167207b96SArnd Bergmann { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, 84267207b96SArnd Bergmann { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, 84367207b96SArnd Bergmann { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, 84467207b96SArnd Bergmann { "signal1", &spufs_signal1_fops, 0666, }, 84567207b96SArnd Bergmann { "signal2", &spufs_signal2_fops, 0666, }, 84667207b96SArnd Bergmann { "signal1_type", &spufs_signal1_type, 0666, }, 84767207b96SArnd Bergmann { "signal2_type", &spufs_signal2_type, 0666, }, 84867207b96SArnd Bergmann { "npc", &spufs_npc_ops, 0666, }, 8498b3d6663SArnd Bergmann { "fpcr", &spufs_fpcr_fops, 0666, }, 8508b3d6663SArnd Bergmann { "decr", &spufs_decr_ops, 0666, }, 8518b3d6663SArnd Bergmann { "decr_status", &spufs_decr_status_ops, 0666, }, 8528b3d6663SArnd Bergmann { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, 8538b3d6663SArnd Bergmann { "event_mask", &spufs_event_mask_ops, 0666, }, 8548b3d6663SArnd Bergmann { "srr0", &spufs_srr0_ops, 0666, }, 85567207b96SArnd Bergmann {}, 85667207b96SArnd Bergmann }; 857