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 <arndb@de.ibm.com> 8 */ 9 10 #include <linux/list.h> 11 #include <linux/slab.h> 12 13 #include "spufs.h" 14 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 29 out: 30 return gang; 31 } 32 33 static void destroy_spu_gang(struct kref *kref) 34 { 35 struct spu_gang *gang; 36 gang = container_of(kref, struct spu_gang, kref); 37 WARN_ON(gang->contexts || !list_empty(&gang->list)); 38 kfree(gang); 39 } 40 41 struct spu_gang *get_spu_gang(struct spu_gang *gang) 42 { 43 kref_get(&gang->kref); 44 return gang; 45 } 46 47 int put_spu_gang(struct spu_gang *gang) 48 { 49 return kref_put(&gang->kref, &destroy_spu_gang); 50 } 51 52 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx) 53 { 54 mutex_lock(&gang->mutex); 55 ctx->gang = get_spu_gang(gang); 56 list_add(&ctx->gang_list, &gang->list); 57 gang->contexts++; 58 mutex_unlock(&gang->mutex); 59 } 60 61 void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx) 62 { 63 mutex_lock(&gang->mutex); 64 WARN_ON(ctx->gang != gang); 65 if (!list_empty(&ctx->aff_list)) { 66 list_del_init(&ctx->aff_list); 67 gang->aff_flags &= ~AFF_OFFSETS_SET; 68 } 69 list_del_init(&ctx->gang_list); 70 gang->contexts--; 71 mutex_unlock(&gang->mutex); 72 73 put_spu_gang(gang); 74 } 75