diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_syscalls.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spu_syscalls.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c new file mode 100644 index 00000000000..43e0b187ffd --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_syscalls.c @@ -0,0 +1,86 @@ +/* + * SPU file system -- system call stubs + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann <arndb@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/file.h> +#include <linux/module.h> +#include <linux/syscalls.h> + +#include <asm/spu.h> + +struct spufs_calls spufs_calls = { + .owner = NULL, +}; + +/* These stub syscalls are needed to have the actual implementation + * within a loadable module. When spufs is built into the kernel, + * this file is not used and the syscalls directly enter the fs code */ + +asmlinkage long sys_spu_create(const char __user *name, + unsigned int flags, mode_t mode) +{ + long ret; + + ret = -ENOSYS; + if (try_module_get(spufs_calls.owner)) { + ret = spufs_calls.create_thread(name, flags, mode); + module_put(spufs_calls.owner); + } + return ret; +} + +asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) +{ + long ret; + struct file *filp; + int fput_needed; + + ret = -ENOSYS; + if (try_module_get(spufs_calls.owner)) { + ret = -EBADF; + filp = fget_light(fd, &fput_needed); + if (filp) { + ret = spufs_calls.spu_run(filp, unpc, ustatus); + fput_light(filp, fput_needed); + } + module_put(spufs_calls.owner); + } + return ret; +} + +int register_spu_syscalls(struct spufs_calls *calls) +{ + if (spufs_calls.owner) + return -EBUSY; + + spufs_calls.create_thread = calls->create_thread; + spufs_calls.spu_run = calls->spu_run; + smp_mb(); + spufs_calls.owner = calls->owner; + return 0; +} +EXPORT_SYMBOL_GPL(register_spu_syscalls); + +void unregister_spu_syscalls(struct spufs_calls *calls) +{ + BUG_ON(spufs_calls.owner != calls->owner); + spufs_calls.owner = NULL; +} +EXPORT_SYMBOL_GPL(unregister_spu_syscalls); |