xref: /linux/drivers/infiniband/core/ucaps.c (revision 4a1b1ac2744694a2ecd66a84bdb1445f4ef24bee)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved
4  */
5 
6 #include <linux/kref.h>
7 #include <linux/cdev.h>
8 #include <linux/mutex.h>
9 #include <linux/file.h>
10 #include <linux/fs.h>
11 #include <rdma/ib_ucaps.h>
12 
13 #define RDMA_UCAP_FIRST RDMA_UCAP_MLX5_CTRL_LOCAL
14 
15 static DEFINE_MUTEX(ucaps_mutex);
16 static struct ib_ucap *ucaps_list[RDMA_UCAP_MAX];
17 static bool ucaps_class_is_registered;
18 static dev_t ucaps_base_dev;
19 
20 struct ib_ucap {
21 	struct cdev cdev;
22 	struct device dev;
23 	struct kref ref;
24 };
25 
26 static const char *ucap_names[RDMA_UCAP_MAX] = {
27 	[RDMA_UCAP_MLX5_CTRL_LOCAL] = "mlx5_perm_ctrl_local",
28 	[RDMA_UCAP_MLX5_CTRL_OTHER_VHCA] = "mlx5_perm_ctrl_other_vhca"
29 };
30 
31 static char *ucaps_devnode(const struct device *dev, umode_t *mode)
32 {
33 	if (mode)
34 		*mode = 0600;
35 
36 	return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
37 }
38 
39 static const struct class ucaps_class = {
40 	.name = "infiniband_ucaps",
41 	.devnode = ucaps_devnode,
42 };
43 
44 static const struct file_operations ucaps_cdev_fops = {
45 	.owner = THIS_MODULE,
46 	.open = simple_open,
47 };
48 
49 /**
50  * ib_cleanup_ucaps - cleanup all API resources and class.
51  *
52  * This is called once, when removing the ib_uverbs module.
53  */
54 void ib_cleanup_ucaps(void)
55 {
56 	mutex_lock(&ucaps_mutex);
57 	if (!ucaps_class_is_registered) {
58 		mutex_unlock(&ucaps_mutex);
59 		return;
60 	}
61 
62 	for (int i = RDMA_UCAP_FIRST; i < RDMA_UCAP_MAX; i++)
63 		WARN_ON(ucaps_list[i]);
64 
65 	class_unregister(&ucaps_class);
66 	ucaps_class_is_registered = false;
67 	unregister_chrdev_region(ucaps_base_dev, RDMA_UCAP_MAX);
68 	mutex_unlock(&ucaps_mutex);
69 }
70 
71 static int get_ucap_from_devt(dev_t devt, u64 *idx_mask)
72 {
73 	for (int type = RDMA_UCAP_FIRST; type < RDMA_UCAP_MAX; type++) {
74 		if (ucaps_list[type] && ucaps_list[type]->dev.devt == devt) {
75 			*idx_mask |= 1 << type;
76 			return 0;
77 		}
78 	}
79 
80 	return -EINVAL;
81 }
82 
83 static int get_devt_from_fd(unsigned int fd, dev_t *ret_dev)
84 {
85 	CLASS(fd, f)(fd);
86 
87 	if (fd_empty(f) || fd_file(f)->f_op != &ucaps_cdev_fops)
88 		return -EBADF;
89 
90 	*ret_dev = file_inode(fd_file(f))->i_rdev;
91 	return 0;
92 }
93 
94 /**
95  * ib_ucaps_init - Initialization required before ucap creation.
96  *
97  * Return: 0 on success, or a negative errno value on failure
98  */
99 static int ib_ucaps_init(void)
100 {
101 	int ret = 0;
102 
103 	if (ucaps_class_is_registered)
104 		return ret;
105 
106 	ret = class_register(&ucaps_class);
107 	if (ret)
108 		return ret;
109 
110 	ret = alloc_chrdev_region(&ucaps_base_dev, 0, RDMA_UCAP_MAX,
111 				  ucaps_class.name);
112 	if (ret < 0) {
113 		class_unregister(&ucaps_class);
114 		return ret;
115 	}
116 
117 	ucaps_class_is_registered = true;
118 
119 	return 0;
120 }
121 
122 static void ucap_dev_release(struct device *device)
123 {
124 	struct ib_ucap *ucap = container_of(device, struct ib_ucap, dev);
125 
126 	kfree(ucap);
127 }
128 
129 /**
130  * ib_create_ucap - Add a ucap character device
131  * @type: UCAP type
132  *
133  * Creates a ucap character device in the /dev/infiniband directory. By default,
134  * the device has root-only read-write access.
135  *
136  * A driver may call this multiple times with the same UCAP type. A reference
137  * count tracks creations and deletions.
138  *
139  * Return: 0 on success, or a negative errno value on failure
140  */
141 int ib_create_ucap(enum rdma_user_cap type)
142 {
143 	struct ib_ucap *ucap;
144 	int ret;
145 
146 	if (type >= RDMA_UCAP_MAX)
147 		return -EINVAL;
148 
149 	mutex_lock(&ucaps_mutex);
150 	ret = ib_ucaps_init();
151 	if (ret)
152 		goto unlock;
153 
154 	ucap = ucaps_list[type];
155 	if (ucap) {
156 		kref_get(&ucap->ref);
157 		mutex_unlock(&ucaps_mutex);
158 		return 0;
159 	}
160 
161 	ucap = kzalloc_obj(*ucap);
162 	if (!ucap) {
163 		ret = -ENOMEM;
164 		goto unlock;
165 	}
166 
167 	device_initialize(&ucap->dev);
168 	ucap->dev.class = &ucaps_class;
169 	ucap->dev.devt = MKDEV(MAJOR(ucaps_base_dev), type);
170 	ucap->dev.release = ucap_dev_release;
171 	ret = dev_set_name(&ucap->dev, "%s", ucap_names[type]);
172 	if (ret)
173 		goto err_device;
174 
175 	cdev_init(&ucap->cdev, &ucaps_cdev_fops);
176 	ucap->cdev.owner = THIS_MODULE;
177 
178 	ret = cdev_device_add(&ucap->cdev, &ucap->dev);
179 	if (ret)
180 		goto err_device;
181 
182 	kref_init(&ucap->ref);
183 	ucaps_list[type] = ucap;
184 	mutex_unlock(&ucaps_mutex);
185 
186 	return 0;
187 
188 err_device:
189 	put_device(&ucap->dev);
190 unlock:
191 	mutex_unlock(&ucaps_mutex);
192 	return ret;
193 }
194 EXPORT_SYMBOL(ib_create_ucap);
195 
196 static void ib_release_ucap(struct kref *ref)
197 {
198 	struct ib_ucap *ucap = container_of(ref, struct ib_ucap, ref);
199 	enum rdma_user_cap type;
200 
201 	for (type = RDMA_UCAP_FIRST; type < RDMA_UCAP_MAX; type++) {
202 		if (ucaps_list[type] == ucap)
203 			break;
204 	}
205 	WARN_ON(type == RDMA_UCAP_MAX);
206 
207 	ucaps_list[type] = NULL;
208 	cdev_device_del(&ucap->cdev, &ucap->dev);
209 	put_device(&ucap->dev);
210 }
211 
212 /**
213  * ib_remove_ucap - Remove a ucap character device
214  * @type: User cap type
215  *
216  * Removes the ucap character device according to type. The device is completely
217  * removed from the filesystem when its reference count reaches 0.
218  */
219 void ib_remove_ucap(enum rdma_user_cap type)
220 {
221 	struct ib_ucap *ucap;
222 
223 	mutex_lock(&ucaps_mutex);
224 	ucap = ucaps_list[type];
225 	if (WARN_ON(!ucap))
226 		goto end;
227 
228 	kref_put(&ucap->ref, ib_release_ucap);
229 end:
230 	mutex_unlock(&ucaps_mutex);
231 }
232 EXPORT_SYMBOL(ib_remove_ucap);
233 
234 /**
235  * ib_get_ucaps - Get bitmask of ucap types from file descriptors
236  * @fds: Array of file descriptors
237  * @fd_count: Number of file descriptors in the array
238  * @idx_mask: Bitmask to be updated based on the ucaps in the fd list
239  *
240  * Given an array of file descriptors, this function returns a bitmask of
241  * the ucaps where a bit is set if an FD for that ucap type was in the array.
242  *
243  * Return: 0 on success, or a negative errno value on failure
244  */
245 int ib_get_ucaps(int *fds, int fd_count, uint64_t *idx_mask)
246 {
247 	int ret = 0;
248 	dev_t dev;
249 
250 	*idx_mask = 0;
251 	mutex_lock(&ucaps_mutex);
252 	for (int i = 0; i < fd_count; i++) {
253 		ret = get_devt_from_fd(fds[i], &dev);
254 		if (ret)
255 			goto end;
256 
257 		ret = get_ucap_from_devt(dev, idx_mask);
258 		if (ret)
259 			goto end;
260 	}
261 
262 end:
263 	mutex_unlock(&ucaps_mutex);
264 	return ret;
265 }
266