1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * SPU file system
4  *
5  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
6  *
7  * Author: Arnd Bergmann <[email protected]>
8  */
9 
10 #include <linux/list.h>
11 #include <linux/slab.h>
12 
13 #include "spufs.h"
14 
alloc_spu_gang(void)15 struct spu_gang *alloc_spu_gang(void)
16 {
17 	struct spu_gang *gang;
18 
19 	gang = kzalloc(sizeof *gang, GFP_KERNEL);
20 	if (!gang)
21 		goto out;
22 
23 	kref_init(&gang->kref);
24 	mutex_init(&gang->mutex);
25 	mutex_init(&gang->aff_mutex);
26 	INIT_LIST_HEAD(&gang->list);
27 	INIT_LIST_HEAD(&gang->aff_list_head);
28 	gang->alive = 1;
29 
30 out:
31 	return gang;
32 }
33 
destroy_spu_gang(struct kref * kref)34 static void destroy_spu_gang(struct kref *kref)
35 {
36 	struct spu_gang *gang;
37 	gang = container_of(kref, struct spu_gang, kref);
38 	WARN_ON(gang->contexts || !list_empty(&gang->list));
39 	kfree(gang);
40 }
41 
get_spu_gang(struct spu_gang * gang)42 struct spu_gang *get_spu_gang(struct spu_gang *gang)
43 {
44 	kref_get(&gang->kref);
45 	return gang;
46 }
47 
put_spu_gang(struct spu_gang * gang)48 int put_spu_gang(struct spu_gang *gang)
49 {
50 	return kref_put(&gang->kref, &destroy_spu_gang);
51 }
52 
spu_gang_add_ctx(struct spu_gang * gang,struct spu_context * ctx)53 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx)
54 {
55 	mutex_lock(&gang->mutex);
56 	ctx->gang = get_spu_gang(gang);
57 	list_add(&ctx->gang_list, &gang->list);
58 	gang->contexts++;
59 	mutex_unlock(&gang->mutex);
60 }
61 
spu_gang_remove_ctx(struct spu_gang * gang,struct spu_context * ctx)62 void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx)
63 {
64 	mutex_lock(&gang->mutex);
65 	WARN_ON(ctx->gang != gang);
66 	if (!list_empty(&ctx->aff_list)) {
67 		list_del_init(&ctx->aff_list);
68 		gang->aff_flags &= ~AFF_OFFSETS_SET;
69 	}
70 	list_del_init(&ctx->gang_list);
71 	gang->contexts--;
72 	mutex_unlock(&gang->mutex);
73 
74 	put_spu_gang(gang);
75 }
76