1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * DIBS - Direct Internal Buffer Sharing 4 * 5 * Implementation of the DIBS class module 6 * 7 * Copyright IBM Corp. 2025 8 */ 9 #define KMSG_COMPONENT "dibs" 10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11 12 #include <linux/module.h> 13 #include <linux/types.h> 14 #include <linux/slab.h> 15 #include <linux/err.h> 16 #include <linux/dibs.h> 17 18 #include "dibs_loopback.h" 19 20 MODULE_DESCRIPTION("Direct Internal Buffer Sharing class"); 21 MODULE_LICENSE("GPL"); 22 23 /* use an array rather a list for fast mapping: */ 24 static struct dibs_client *clients[MAX_DIBS_CLIENTS]; 25 static u8 max_client; 26 static DEFINE_MUTEX(clients_lock); 27 struct dibs_dev_list { 28 struct list_head list; 29 struct mutex mutex; /* protects dibs device list */ 30 }; 31 32 static struct dibs_dev_list dibs_dev_list = { 33 .list = LIST_HEAD_INIT(dibs_dev_list.list), 34 .mutex = __MUTEX_INITIALIZER(dibs_dev_list.mutex), 35 }; 36 37 int dibs_register_client(struct dibs_client *client) 38 { 39 int i, rc = -ENOSPC; 40 41 mutex_lock(&clients_lock); 42 for (i = 0; i < MAX_DIBS_CLIENTS; ++i) { 43 if (!clients[i]) { 44 clients[i] = client; 45 client->id = i; 46 if (i == max_client) 47 max_client++; 48 rc = 0; 49 break; 50 } 51 } 52 mutex_unlock(&clients_lock); 53 54 return rc; 55 } 56 EXPORT_SYMBOL_GPL(dibs_register_client); 57 58 int dibs_unregister_client(struct dibs_client *client) 59 { 60 int rc = 0; 61 62 mutex_lock(&clients_lock); 63 clients[client->id] = NULL; 64 if (client->id + 1 == max_client) 65 max_client--; 66 mutex_unlock(&clients_lock); 67 return rc; 68 } 69 EXPORT_SYMBOL_GPL(dibs_unregister_client); 70 71 struct dibs_dev *dibs_dev_alloc(void) 72 { 73 struct dibs_dev *dibs; 74 75 dibs = kzalloc(sizeof(*dibs), GFP_KERNEL); 76 77 return dibs; 78 } 79 EXPORT_SYMBOL_GPL(dibs_dev_alloc); 80 81 int dibs_dev_add(struct dibs_dev *dibs) 82 { 83 mutex_lock(&dibs_dev_list.mutex); 84 list_add(&dibs->list, &dibs_dev_list.list); 85 mutex_unlock(&dibs_dev_list.mutex); 86 87 return 0; 88 } 89 EXPORT_SYMBOL_GPL(dibs_dev_add); 90 91 void dibs_dev_del(struct dibs_dev *dibs) 92 { 93 mutex_lock(&dibs_dev_list.mutex); 94 list_del_init(&dibs->list); 95 mutex_unlock(&dibs_dev_list.mutex); 96 } 97 EXPORT_SYMBOL_GPL(dibs_dev_del); 98 99 static int __init dibs_init(void) 100 { 101 int rc; 102 103 memset(clients, 0, sizeof(clients)); 104 max_client = 0; 105 106 rc = dibs_loopback_init(); 107 if (rc) 108 pr_err("%s fails with %d\n", __func__, rc); 109 110 return rc; 111 } 112 113 static void __exit dibs_exit(void) 114 { 115 dibs_loopback_exit(); 116 } 117 118 module_init(dibs_init); 119 module_exit(dibs_exit); 120