root/arch/powerpc/platforms/cell/spu_syscalls.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spufs_calls_get
  2. spufs_calls_put
  3. spufs_calls_get
  4. spufs_calls_put
  5. SYSCALL_DEFINE4
  6. SYSCALL_DEFINE3
  7. elf_coredump_extra_notes_size
  8. elf_coredump_extra_notes_write
  9. notify_spus_active
  10. register_spu_syscalls
  11. unregister_spu_syscalls

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * SPU file system -- system call stubs
   4  *
   5  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
   6  * (C) Copyright 2006-2007, IBM Corporation
   7  *
   8  * Author: Arnd Bergmann <arndb@de.ibm.com>
   9  */
  10 #include <linux/file.h>
  11 #include <linux/fs.h>
  12 #include <linux/module.h>
  13 #include <linux/syscalls.h>
  14 #include <linux/rcupdate.h>
  15 #include <linux/binfmts.h>
  16 
  17 #include <asm/spu.h>
  18 
  19 /* protected by rcu */
  20 static struct spufs_calls *spufs_calls;
  21 
  22 #ifdef CONFIG_SPU_FS_MODULE
  23 
  24 static inline struct spufs_calls *spufs_calls_get(void)
  25 {
  26         struct spufs_calls *calls = NULL;
  27 
  28         rcu_read_lock();
  29         calls = rcu_dereference(spufs_calls);
  30         if (calls && !try_module_get(calls->owner))
  31                 calls = NULL;
  32         rcu_read_unlock();
  33 
  34         return calls;
  35 }
  36 
  37 static inline void spufs_calls_put(struct spufs_calls *calls)
  38 {
  39         BUG_ON(calls != spufs_calls);
  40 
  41         /* we don't need to rcu this, as we hold a reference to the module */
  42         module_put(spufs_calls->owner);
  43 }
  44 
  45 #else /* !defined CONFIG_SPU_FS_MODULE */
  46 
  47 static inline struct spufs_calls *spufs_calls_get(void)
  48 {
  49         return spufs_calls;
  50 }
  51 
  52 static inline void spufs_calls_put(struct spufs_calls *calls) { }
  53 
  54 #endif /* CONFIG_SPU_FS_MODULE */
  55 
  56 SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
  57         umode_t, mode, int, neighbor_fd)
  58 {
  59         long ret;
  60         struct spufs_calls *calls;
  61 
  62         calls = spufs_calls_get();
  63         if (!calls)
  64                 return -ENOSYS;
  65 
  66         if (flags & SPU_CREATE_AFFINITY_SPU) {
  67                 struct fd neighbor = fdget(neighbor_fd);
  68                 ret = -EBADF;
  69                 if (neighbor.file) {
  70                         ret = calls->create_thread(name, flags, mode, neighbor.file);
  71                         fdput(neighbor);
  72                 }
  73         } else
  74                 ret = calls->create_thread(name, flags, mode, NULL);
  75 
  76         spufs_calls_put(calls);
  77         return ret;
  78 }
  79 
  80 SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
  81 {
  82         long ret;
  83         struct fd arg;
  84         struct spufs_calls *calls;
  85 
  86         calls = spufs_calls_get();
  87         if (!calls)
  88                 return -ENOSYS;
  89 
  90         ret = -EBADF;
  91         arg = fdget(fd);
  92         if (arg.file) {
  93                 ret = calls->spu_run(arg.file, unpc, ustatus);
  94                 fdput(arg);
  95         }
  96 
  97         spufs_calls_put(calls);
  98         return ret;
  99 }
 100 
 101 #ifdef CONFIG_COREDUMP
 102 int elf_coredump_extra_notes_size(void)
 103 {
 104         struct spufs_calls *calls;
 105         int ret;
 106 
 107         calls = spufs_calls_get();
 108         if (!calls)
 109                 return 0;
 110 
 111         ret = calls->coredump_extra_notes_size();
 112 
 113         spufs_calls_put(calls);
 114 
 115         return ret;
 116 }
 117 
 118 int elf_coredump_extra_notes_write(struct coredump_params *cprm)
 119 {
 120         struct spufs_calls *calls;
 121         int ret;
 122 
 123         calls = spufs_calls_get();
 124         if (!calls)
 125                 return 0;
 126 
 127         ret = calls->coredump_extra_notes_write(cprm);
 128 
 129         spufs_calls_put(calls);
 130 
 131         return ret;
 132 }
 133 #endif
 134 
 135 void notify_spus_active(void)
 136 {
 137         struct spufs_calls *calls;
 138 
 139         calls = spufs_calls_get();
 140         if (!calls)
 141                 return;
 142 
 143         calls->notify_spus_active();
 144         spufs_calls_put(calls);
 145 
 146         return;
 147 }
 148 
 149 int register_spu_syscalls(struct spufs_calls *calls)
 150 {
 151         if (spufs_calls)
 152                 return -EBUSY;
 153 
 154         rcu_assign_pointer(spufs_calls, calls);
 155         return 0;
 156 }
 157 EXPORT_SYMBOL_GPL(register_spu_syscalls);
 158 
 159 void unregister_spu_syscalls(struct spufs_calls *calls)
 160 {
 161         BUG_ON(spufs_calls->owner != calls->owner);
 162         RCU_INIT_POINTER(spufs_calls, NULL);
 163         synchronize_rcu();
 164 }
 165 EXPORT_SYMBOL_GPL(unregister_spu_syscalls);

/* [<][>][^][v][top][bottom][index][help] */