[POWERPC] cell: use ppc_md->power_save instead of cbe_idle_loop
[linux-2.6] / arch / powerpc / platforms / cell / spufs / inode.c
1 /*
2  * SPU file system
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
23 #include <linux/file.h>
24 #include <linux/fs.h>
25 #include <linux/backing-dev.h>
26 #include <linux/init.h>
27 #include <linux/ioctl.h>
28 #include <linux/module.h>
29 #include <linux/mount.h>
30 #include <linux/namei.h>
31 #include <linux/pagemap.h>
32 #include <linux/poll.h>
33 #include <linux/slab.h>
34 #include <linux/parser.h>
35
36 #include <asm/prom.h>
37 #include <asm/spu_priv1.h>
38 #include <asm/io.h>
39 #include <asm/semaphore.h>
40 #include <asm/spu.h>
41 #include <asm/uaccess.h>
42
43 #include "spufs.h"
44
45 static kmem_cache_t *spufs_inode_cache;
46 static char *isolated_loader;
47
48 static struct inode *
49 spufs_alloc_inode(struct super_block *sb)
50 {
51         struct spufs_inode_info *ei;
52
53         ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL);
54         if (!ei)
55                 return NULL;
56
57         ei->i_gang = NULL;
58         ei->i_ctx = NULL;
59
60         return &ei->vfs_inode;
61 }
62
63 static void
64 spufs_destroy_inode(struct inode *inode)
65 {
66         kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
67 }
68
69 static void
70 spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags)
71 {
72         struct spufs_inode_info *ei = p;
73
74         if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
75             SLAB_CTOR_CONSTRUCTOR) {
76                 inode_init_once(&ei->vfs_inode);
77         }
78 }
79
80 static struct inode *
81 spufs_new_inode(struct super_block *sb, int mode)
82 {
83         struct inode *inode;
84
85         inode = new_inode(sb);
86         if (!inode)
87                 goto out;
88
89         inode->i_mode = mode;
90         inode->i_uid = current->fsuid;
91         inode->i_gid = current->fsgid;
92         inode->i_blocks = 0;
93         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
94 out:
95         return inode;
96 }
97
98 static int
99 spufs_setattr(struct dentry *dentry, struct iattr *attr)
100 {
101         struct inode *inode = dentry->d_inode;
102
103         if ((attr->ia_valid & ATTR_SIZE) &&
104             (attr->ia_size != inode->i_size))
105                 return -EINVAL;
106         return inode_setattr(inode, attr);
107 }
108
109
110 static int
111 spufs_new_file(struct super_block *sb, struct dentry *dentry,
112                 const struct file_operations *fops, int mode,
113                 struct spu_context *ctx)
114 {
115         static struct inode_operations spufs_file_iops = {
116                 .setattr = spufs_setattr,
117         };
118         struct inode *inode;
119         int ret;
120
121         ret = -ENOSPC;
122         inode = spufs_new_inode(sb, S_IFREG | mode);
123         if (!inode)
124                 goto out;
125
126         ret = 0;
127         inode->i_op = &spufs_file_iops;
128         inode->i_fop = fops;
129         inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
130         d_add(dentry, inode);
131 out:
132         return ret;
133 }
134
135 static void
136 spufs_delete_inode(struct inode *inode)
137 {
138         struct spufs_inode_info *ei = SPUFS_I(inode);
139
140         if (ei->i_ctx)
141                 put_spu_context(ei->i_ctx);
142         if (ei->i_gang)
143                 put_spu_gang(ei->i_gang);
144         clear_inode(inode);
145 }
146
147 static void spufs_prune_dir(struct dentry *dir)
148 {
149         struct dentry *dentry, *tmp;
150
151         mutex_lock(&dir->d_inode->i_mutex);
152         list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
153                 spin_lock(&dcache_lock);
154                 spin_lock(&dentry->d_lock);
155                 if (!(d_unhashed(dentry)) && dentry->d_inode) {
156                         dget_locked(dentry);
157                         __d_drop(dentry);
158                         spin_unlock(&dentry->d_lock);
159                         simple_unlink(dir->d_inode, dentry);
160                         spin_unlock(&dcache_lock);
161                         dput(dentry);
162                 } else {
163                         spin_unlock(&dentry->d_lock);
164                         spin_unlock(&dcache_lock);
165                 }
166         }
167         shrink_dcache_parent(dir);
168         mutex_unlock(&dir->d_inode->i_mutex);
169 }
170
171 /* Caller must hold parent->i_mutex */
172 static int spufs_rmdir(struct inode *parent, struct dentry *dir)
173 {
174         /* remove all entries */
175         spufs_prune_dir(dir);
176
177         return simple_rmdir(parent, dir);
178 }
179
180 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
181                           int mode, struct spu_context *ctx)
182 {
183         struct dentry *dentry;
184         int ret;
185
186         while (files->name && files->name[0]) {
187                 ret = -ENOMEM;
188                 dentry = d_alloc_name(dir, files->name);
189                 if (!dentry)
190                         goto out;
191                 ret = spufs_new_file(dir->d_sb, dentry, files->ops,
192                                         files->mode & mode, ctx);
193                 if (ret)
194                         goto out;
195                 files++;
196         }
197         return 0;
198 out:
199         spufs_prune_dir(dir);
200         return ret;
201 }
202
203 static int spufs_dir_close(struct inode *inode, struct file *file)
204 {
205         struct spu_context *ctx;
206         struct inode *parent;
207         struct dentry *dir;
208         int ret;
209
210         dir = file->f_dentry;
211         parent = dir->d_parent->d_inode;
212         ctx = SPUFS_I(dir->d_inode)->i_ctx;
213
214         mutex_lock(&parent->i_mutex);
215         ret = spufs_rmdir(parent, dir);
216         mutex_unlock(&parent->i_mutex);
217         WARN_ON(ret);
218
219         /* We have to give up the mm_struct */
220         spu_forget(ctx);
221
222         return dcache_dir_close(inode, file);
223 }
224
225 struct inode_operations spufs_dir_inode_operations = {
226         .lookup = simple_lookup,
227 };
228
229 struct file_operations spufs_context_fops = {
230         .open           = dcache_dir_open,
231         .release        = spufs_dir_close,
232         .llseek         = dcache_dir_lseek,
233         .read           = generic_read_dir,
234         .readdir        = dcache_readdir,
235         .fsync          = simple_sync_file,
236 };
237
238 static int spu_setup_isolated(struct spu_context *ctx)
239 {
240         int ret;
241         u64 __iomem *mfc_cntl;
242         u64 sr1;
243         u32 status;
244         unsigned long timeout;
245         const u32 status_loading = SPU_STATUS_RUNNING
246                 | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
247
248         if (!isolated_loader)
249                 return -ENODEV;
250
251         if ((ret = spu_acquire_exclusive(ctx)) != 0)
252                 return ret;
253
254         mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
255
256         /* purge the MFC DMA queue to ensure no spurious accesses before we
257          * enter kernel mode */
258         timeout = jiffies + HZ;
259         out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
260         while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
261                         != MFC_CNTL_PURGE_DMA_COMPLETE) {
262                 if (time_after(jiffies, timeout)) {
263                         printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
264                                         __FUNCTION__);
265                         ret = -EIO;
266                         goto out_unlock;
267                 }
268                 cond_resched();
269         }
270
271         /* put the SPE in kernel mode to allow access to the loader */
272         sr1 = spu_mfc_sr1_get(ctx->spu);
273         sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
274         spu_mfc_sr1_set(ctx->spu, sr1);
275
276         /* start the loader */
277         ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
278         ctx->ops->signal2_write(ctx,
279                         (unsigned long)isolated_loader & 0xffffffff);
280
281         ctx->ops->runcntl_write(ctx,
282                         SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
283
284         ret = 0;
285         timeout = jiffies + HZ;
286         while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
287                                 status_loading) {
288                 if (time_after(jiffies, timeout)) {
289                         printk(KERN_ERR "%s: timeout waiting for loader\n",
290                                         __FUNCTION__);
291                         ret = -EIO;
292                         goto out_drop_priv;
293                 }
294                 cond_resched();
295         }
296
297         if (!(status & SPU_STATUS_RUNNING)) {
298                 /* If isolated LOAD has failed: run SPU, we will get a stop-and
299                  * signal later. */
300                 pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
301                 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
302                 ret = -EACCES;
303
304         } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
305                 /* This isn't allowed by the CBEA, but check anyway */
306                 pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
307                 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
308                 ret = -EINVAL;
309         }
310
311 out_drop_priv:
312         /* Finished accessing the loader. Drop kernel mode */
313         sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
314         spu_mfc_sr1_set(ctx->spu, sr1);
315
316 out_unlock:
317         spu_release_exclusive(ctx);
318         return ret;
319 }
320
321 int spu_recycle_isolated(struct spu_context *ctx)
322 {
323         ctx->ops->runcntl_stop(ctx);
324         return spu_setup_isolated(ctx);
325 }
326
327 static int
328 spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
329                 int mode)
330 {
331         int ret;
332         struct inode *inode;
333         struct spu_context *ctx;
334
335         ret = -ENOSPC;
336         inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
337         if (!inode)
338                 goto out;
339
340         if (dir->i_mode & S_ISGID) {
341                 inode->i_gid = dir->i_gid;
342                 inode->i_mode &= S_ISGID;
343         }
344         ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
345         SPUFS_I(inode)->i_ctx = ctx;
346         if (!ctx)
347                 goto out_iput;
348
349         ctx->flags = flags;
350         inode->i_op = &spufs_dir_inode_operations;
351         inode->i_fop = &simple_dir_operations;
352         if (flags & SPU_CREATE_NOSCHED)
353                 ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
354                                          mode, ctx);
355         else
356                 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
357
358         if (ret)
359                 goto out_free_ctx;
360
361         d_instantiate(dentry, inode);
362         dget(dentry);
363         dir->i_nlink++;
364         dentry->d_inode->i_nlink++;
365         goto out;
366
367 out_free_ctx:
368         put_spu_context(ctx);
369 out_iput:
370         iput(inode);
371 out:
372         return ret;
373 }
374
375 static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
376 {
377         int ret;
378         struct file *filp;
379
380         ret = get_unused_fd();
381         if (ret < 0) {
382                 dput(dentry);
383                 mntput(mnt);
384                 goto out;
385         }
386
387         filp = dentry_open(dentry, mnt, O_RDONLY);
388         if (IS_ERR(filp)) {
389                 put_unused_fd(ret);
390                 ret = PTR_ERR(filp);
391                 goto out;
392         }
393
394         filp->f_op = &spufs_context_fops;
395         fd_install(ret, filp);
396 out:
397         return ret;
398 }
399
400 static int spufs_create_context(struct inode *inode,
401                         struct dentry *dentry,
402                         struct vfsmount *mnt, int flags, int mode)
403 {
404         int ret;
405
406         ret = -EPERM;
407         if ((flags & SPU_CREATE_NOSCHED) &&
408             !capable(CAP_SYS_NICE))
409                 goto out_unlock;
410
411         ret = -EINVAL;
412         if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
413             == SPU_CREATE_ISOLATE)
414                 goto out_unlock;
415
416         ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
417         if (ret)
418                 goto out_unlock;
419
420         /*
421          * get references for dget and mntget, will be released
422          * in error path of *_open().
423          */
424         ret = spufs_context_open(dget(dentry), mntget(mnt));
425         if (ret < 0) {
426                 WARN_ON(spufs_rmdir(inode, dentry));
427                 mutex_unlock(&inode->i_mutex);
428                 spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
429                 goto out;
430         }
431
432 out_unlock:
433         mutex_unlock(&inode->i_mutex);
434 out:
435         if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) {
436                 int setup_err = spu_setup_isolated(
437                                 SPUFS_I(dentry->d_inode)->i_ctx);
438                 if (setup_err)
439                         ret = setup_err;
440         }
441
442         dput(dentry);
443         return ret;
444 }
445
446 static int spufs_rmgang(struct inode *root, struct dentry *dir)
447 {
448         /* FIXME: this fails if the dir is not empty,
449                   which causes a leak of gangs. */
450         return simple_rmdir(root, dir);
451 }
452
453 static int spufs_gang_close(struct inode *inode, struct file *file)
454 {
455         struct inode *parent;
456         struct dentry *dir;
457         int ret;
458
459         dir = file->f_dentry;
460         parent = dir->d_parent->d_inode;
461
462         ret = spufs_rmgang(parent, dir);
463         WARN_ON(ret);
464
465         return dcache_dir_close(inode, file);
466 }
467
468 struct file_operations spufs_gang_fops = {
469         .open           = dcache_dir_open,
470         .release        = spufs_gang_close,
471         .llseek         = dcache_dir_lseek,
472         .read           = generic_read_dir,
473         .readdir        = dcache_readdir,
474         .fsync          = simple_sync_file,
475 };
476
477 static int
478 spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
479 {
480         int ret;
481         struct inode *inode;
482         struct spu_gang *gang;
483
484         ret = -ENOSPC;
485         inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
486         if (!inode)
487                 goto out;
488
489         ret = 0;
490         if (dir->i_mode & S_ISGID) {
491                 inode->i_gid = dir->i_gid;
492                 inode->i_mode &= S_ISGID;
493         }
494         gang = alloc_spu_gang();
495         SPUFS_I(inode)->i_ctx = NULL;
496         SPUFS_I(inode)->i_gang = gang;
497         if (!gang)
498                 goto out_iput;
499
500         inode->i_op = &spufs_dir_inode_operations;
501         inode->i_fop = &simple_dir_operations;
502
503         d_instantiate(dentry, inode);
504         dget(dentry);
505         dir->i_nlink++;
506         dentry->d_inode->i_nlink++;
507         return ret;
508
509 out_iput:
510         iput(inode);
511 out:
512         return ret;
513 }
514
515 static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
516 {
517         int ret;
518         struct file *filp;
519
520         ret = get_unused_fd();
521         if (ret < 0) {
522                 dput(dentry);
523                 mntput(mnt);
524                 goto out;
525         }
526
527         filp = dentry_open(dentry, mnt, O_RDONLY);
528         if (IS_ERR(filp)) {
529                 put_unused_fd(ret);
530                 ret = PTR_ERR(filp);
531                 goto out;
532         }
533
534         filp->f_op = &spufs_gang_fops;
535         fd_install(ret, filp);
536 out:
537         return ret;
538 }
539
540 static int spufs_create_gang(struct inode *inode,
541                         struct dentry *dentry,
542                         struct vfsmount *mnt, int mode)
543 {
544         int ret;
545
546         ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
547         if (ret)
548                 goto out;
549
550         /*
551          * get references for dget and mntget, will be released
552          * in error path of *_open().
553          */
554         ret = spufs_gang_open(dget(dentry), mntget(mnt));
555         if (ret < 0)
556                 WARN_ON(spufs_rmgang(inode, dentry));
557
558 out:
559         mutex_unlock(&inode->i_mutex);
560         dput(dentry);
561         return ret;
562 }
563
564
565 static struct file_system_type spufs_type;
566
567 long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode)
568 {
569         struct dentry *dentry;
570         int ret;
571
572         ret = -EINVAL;
573         /* check if we are on spufs */
574         if (nd->dentry->d_sb->s_type != &spufs_type)
575                 goto out;
576
577         /* don't accept undefined flags */
578         if (flags & (~SPU_CREATE_FLAG_ALL))
579                 goto out;
580
581         /* only threads can be underneath a gang */
582         if (nd->dentry != nd->dentry->d_sb->s_root) {
583                 if ((flags & SPU_CREATE_GANG) ||
584                     !SPUFS_I(nd->dentry->d_inode)->i_gang)
585                         goto out;
586         }
587
588         dentry = lookup_create(nd, 1);
589         ret = PTR_ERR(dentry);
590         if (IS_ERR(dentry))
591                 goto out_dir;
592
593         ret = -EEXIST;
594         if (dentry->d_inode)
595                 goto out_dput;
596
597         mode &= ~current->fs->umask;
598
599         if (flags & SPU_CREATE_GANG)
600                 return spufs_create_gang(nd->dentry->d_inode,
601                                         dentry, nd->mnt, mode);
602         else
603                 return spufs_create_context(nd->dentry->d_inode,
604                                         dentry, nd->mnt, flags, mode);
605
606 out_dput:
607         dput(dentry);
608 out_dir:
609         mutex_unlock(&nd->dentry->d_inode->i_mutex);
610 out:
611         return ret;
612 }
613
614 /* File system initialization */
615 enum {
616         Opt_uid, Opt_gid, Opt_err,
617 };
618
619 static match_table_t spufs_tokens = {
620         { Opt_uid, "uid=%d" },
621         { Opt_gid, "gid=%d" },
622         { Opt_err, NULL  },
623 };
624
625 static int
626 spufs_parse_options(char *options, struct inode *root)
627 {
628         char *p;
629         substring_t args[MAX_OPT_ARGS];
630
631         while ((p = strsep(&options, ",")) != NULL) {
632                 int token, option;
633
634                 if (!*p)
635                         continue;
636
637                 token = match_token(p, spufs_tokens, args);
638                 switch (token) {
639                 case Opt_uid:
640                         if (match_int(&args[0], &option))
641                                 return 0;
642                         root->i_uid = option;
643                         break;
644                 case Opt_gid:
645                         if (match_int(&args[0], &option))
646                                 return 0;
647                         root->i_gid = option;
648                         break;
649                 default:
650                         return 0;
651                 }
652         }
653         return 1;
654 }
655
656 static void
657 spufs_init_isolated_loader(void)
658 {
659         struct device_node *dn;
660         const char *loader;
661         int size;
662
663         dn = of_find_node_by_path("/spu-isolation");
664         if (!dn)
665                 return;
666
667         loader = get_property(dn, "loader", &size);
668         if (!loader)
669                 return;
670
671         /* kmalloc should align on a 16 byte boundary..* */
672         isolated_loader = kmalloc(size, GFP_KERNEL);
673         if (!isolated_loader)
674                 return;
675
676         memcpy(isolated_loader, loader, size);
677         printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
678 }
679
680 static int
681 spufs_create_root(struct super_block *sb, void *data)
682 {
683         struct inode *inode;
684         int ret;
685
686         ret = -ENOMEM;
687         inode = spufs_new_inode(sb, S_IFDIR | 0775);
688         if (!inode)
689                 goto out;
690
691         inode->i_op = &spufs_dir_inode_operations;
692         inode->i_fop = &simple_dir_operations;
693         SPUFS_I(inode)->i_ctx = NULL;
694
695         ret = -EINVAL;
696         if (!spufs_parse_options(data, inode))
697                 goto out_iput;
698
699         ret = -ENOMEM;
700         sb->s_root = d_alloc_root(inode);
701         if (!sb->s_root)
702                 goto out_iput;
703
704         return 0;
705 out_iput:
706         iput(inode);
707 out:
708         return ret;
709 }
710
711 static int
712 spufs_fill_super(struct super_block *sb, void *data, int silent)
713 {
714         static struct super_operations s_ops = {
715                 .alloc_inode = spufs_alloc_inode,
716                 .destroy_inode = spufs_destroy_inode,
717                 .statfs = simple_statfs,
718                 .delete_inode = spufs_delete_inode,
719                 .drop_inode = generic_delete_inode,
720         };
721
722         sb->s_maxbytes = MAX_LFS_FILESIZE;
723         sb->s_blocksize = PAGE_CACHE_SIZE;
724         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
725         sb->s_magic = SPUFS_MAGIC;
726         sb->s_op = &s_ops;
727
728         return spufs_create_root(sb, data);
729 }
730
731 static int
732 spufs_get_sb(struct file_system_type *fstype, int flags,
733                 const char *name, void *data, struct vfsmount *mnt)
734 {
735         return get_sb_single(fstype, flags, data, spufs_fill_super, mnt);
736 }
737
738 static struct file_system_type spufs_type = {
739         .owner = THIS_MODULE,
740         .name = "spufs",
741         .get_sb = spufs_get_sb,
742         .kill_sb = kill_litter_super,
743 };
744
745 static int __init spufs_init(void)
746 {
747         int ret;
748         ret = -ENOMEM;
749         spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
750                         sizeof(struct spufs_inode_info), 0,
751                         SLAB_HWCACHE_ALIGN, spufs_init_once, NULL);
752
753         if (!spufs_inode_cache)
754                 goto out;
755         if (spu_sched_init() != 0) {
756                 kmem_cache_destroy(spufs_inode_cache);
757                 goto out;
758         }
759         ret = register_filesystem(&spufs_type);
760         if (ret)
761                 goto out_cache;
762         ret = register_spu_syscalls(&spufs_calls);
763         if (ret)
764                 goto out_fs;
765
766         spufs_init_isolated_loader();
767         return 0;
768 out_fs:
769         unregister_filesystem(&spufs_type);
770 out_cache:
771         kmem_cache_destroy(spufs_inode_cache);
772 out:
773         return ret;
774 }
775 module_init(spufs_init);
776
777 static void __exit spufs_exit(void)
778 {
779         spu_sched_exit();
780         unregister_spu_syscalls(&spufs_calls);
781         unregister_filesystem(&spufs_type);
782         kmem_cache_destroy(spufs_inode_cache);
783 }
784 module_exit(spufs_exit);
785
786 MODULE_LICENSE("GPL");
787 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
788