xref: /linux/drivers/dibs/dibs_main.c (revision cb990a45d7f6eb6dc495d2226a3005b284a5ee4f)
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