2005-11-15 23:53:48 +03:00
/*
* 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 0213 9 , 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 ,
2007-07-20 23:39:47 +04:00
unsigned int flags , mode_t mode , int neighbor_fd )
2005-11-15 23:53:48 +03:00
{
long ret ;
2005-12-06 06:52:23 +03:00
struct module * owner = spufs_calls . owner ;
2007-07-20 23:39:47 +04:00
struct file * neighbor ;
int fput_needed ;
2005-11-15 23:53:48 +03:00
ret = - ENOSYS ;
2005-12-09 21:04:15 +03:00
if ( owner & & try_module_get ( owner ) ) {
2007-07-20 23:39:47 +04:00
if ( flags & SPU_CREATE_AFFINITY_SPU ) {
neighbor = fget_light ( neighbor_fd , & fput_needed ) ;
2007-08-13 07:22:44 +04:00
ret = - EBADF ;
2007-07-20 23:39:47 +04:00
if ( neighbor ) {
ret = spufs_calls . create_thread ( name , flags ,
mode , neighbor ) ;
fput_light ( neighbor , fput_needed ) ;
}
}
else {
ret = spufs_calls . create_thread ( name , flags ,
mode , NULL ) ;
}
2005-12-06 06:52:23 +03:00
module_put ( owner ) ;
2005-11-15 23:53:48 +03:00
}
return ret ;
}
asmlinkage long sys_spu_run ( int fd , __u32 __user * unpc , __u32 __user * ustatus )
{
long ret ;
struct file * filp ;
int fput_needed ;
2005-12-06 06:52:23 +03:00
struct module * owner = spufs_calls . owner ;
2005-11-15 23:53:48 +03:00
ret = - ENOSYS ;
2005-12-06 06:52:23 +03:00
if ( owner & & try_module_get ( owner ) ) {
2005-11-15 23:53:48 +03:00
ret = - EBADF ;
filp = fget_light ( fd , & fput_needed ) ;
if ( filp ) {
ret = spufs_calls . spu_run ( filp , unpc , ustatus ) ;
fput_light ( filp , fput_needed ) ;
}
2005-12-06 06:52:23 +03:00
module_put ( owner ) ;
2005-11-15 23:53:48 +03:00
}
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 ) ;