xref: /linux/arch/powerpc/platforms/cell/spufs/gang.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
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/list.h>
24 #include <linux/slab.h>
25 
26 #include "spufs.h"
27 
28 struct spu_gang *alloc_spu_gang(void)
29 {
30 	struct spu_gang *gang;
31 
32 	gang = kzalloc(sizeof *gang, GFP_KERNEL);
33 	if (!gang)
34 		goto out;
35 
36 	kref_init(&gang->kref);
37 	mutex_init(&gang->mutex);
38 	INIT_LIST_HEAD(&gang->list);
39 
40 out:
41 	return gang;
42 }
43 
44 static void destroy_spu_gang(struct kref *kref)
45 {
46 	struct spu_gang *gang;
47 	gang = container_of(kref, struct spu_gang, kref);
48 	WARN_ON(gang->contexts || !list_empty(&gang->list));
49 	kfree(gang);
50 }
51 
52 struct spu_gang *get_spu_gang(struct spu_gang *gang)
53 {
54 	kref_get(&gang->kref);
55 	return gang;
56 }
57 
58 int put_spu_gang(struct spu_gang *gang)
59 {
60 	return kref_put(&gang->kref, &destroy_spu_gang);
61 }
62 
63 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx)
64 {
65 	mutex_lock(&gang->mutex);
66 	ctx->gang = get_spu_gang(gang);
67 	list_add(&ctx->gang_list, &gang->list);
68 	gang->contexts++;
69 	mutex_unlock(&gang->mutex);
70 }
71 
72 void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx)
73 {
74 	mutex_lock(&gang->mutex);
75 	WARN_ON(ctx->gang != gang);
76 	list_del_init(&ctx->gang_list);
77 	gang->contexts--;
78 	mutex_unlock(&gang->mutex);
79 
80 	put_spu_gang(gang);
81 }
82