1 /* 2 * SPU file system -- system call stubs 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 #include <linux/file.h> 23 #include <linux/module.h> 24 #include <linux/syscalls.h> 25 26 #include <asm/spu.h> 27 28 struct spufs_calls spufs_calls = { 29 .owner = NULL, 30 }; 31 32 /* These stub syscalls are needed to have the actual implementation 33 * within a loadable module. When spufs is built into the kernel, 34 * this file is not used and the syscalls directly enter the fs code */ 35 36 asmlinkage long sys_spu_create(const char __user *name, 37 unsigned int flags, mode_t mode, int neighbor_fd) 38 { 39 long ret; 40 struct module *owner = spufs_calls.owner; 41 struct file *neighbor; 42 int fput_needed; 43 44 ret = -ENOSYS; 45 if (owner && try_module_get(owner)) { 46 if (flags & SPU_CREATE_AFFINITY_SPU) { 47 neighbor = fget_light(neighbor_fd, &fput_needed); 48 if (neighbor) { 49 ret = spufs_calls.create_thread(name, flags, 50 mode, neighbor); 51 fput_light(neighbor, fput_needed); 52 } 53 } 54 else { 55 ret = spufs_calls.create_thread(name, flags, 56 mode, NULL); 57 } 58 module_put(owner); 59 } 60 return ret; 61 } 62 63 asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) 64 { 65 long ret; 66 struct file *filp; 67 int fput_needed; 68 struct module *owner = spufs_calls.owner; 69 70 ret = -ENOSYS; 71 if (owner && try_module_get(owner)) { 72 ret = -EBADF; 73 filp = fget_light(fd, &fput_needed); 74 if (filp) { 75 ret = spufs_calls.spu_run(filp, unpc, ustatus); 76 fput_light(filp, fput_needed); 77 } 78 module_put(owner); 79 } 80 return ret; 81 } 82 83 int register_spu_syscalls(struct spufs_calls *calls) 84 { 85 if (spufs_calls.owner) 86 return -EBUSY; 87 88 spufs_calls.create_thread = calls->create_thread; 89 spufs_calls.spu_run = calls->spu_run; 90 smp_mb(); 91 spufs_calls.owner = calls->owner; 92 return 0; 93 } 94 EXPORT_SYMBOL_GPL(register_spu_syscalls); 95 96 void unregister_spu_syscalls(struct spufs_calls *calls) 97 { 98 BUG_ON(spufs_calls.owner != calls->owner); 99 spufs_calls.owner = NULL; 100 } 101 EXPORT_SYMBOL_GPL(unregister_spu_syscalls); 102