xref: /linux-6.15/drivers/net/netdevsim/bus.c (revision f5cd2160)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2017 Netronome Systems, Inc.
3  * Copyright (C) 2019 Mellanox Technologies. All rights reserved
4  */
5 
6 #include <linux/device.h>
7 #include <linux/idr.h>
8 #include <linux/kernel.h>
9 #include <linux/list.h>
10 #include <linux/mutex.h>
11 #include <linux/rtnetlink.h>
12 #include <linux/slab.h>
13 #include <linux/sysfs.h>
14 
15 #include "netdevsim.h"
16 
17 static DEFINE_IDA(nsim_bus_dev_ids);
18 static LIST_HEAD(nsim_bus_dev_list);
19 static DEFINE_MUTEX(nsim_bus_dev_list_lock);
20 static bool nsim_bus_enable;
21 
22 static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev)
23 {
24 	return container_of(dev, struct nsim_bus_dev, dev);
25 }
26 
27 static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev,
28 				   unsigned int num_vfs)
29 {
30 	nsim_bus_dev->vfconfigs = kcalloc(num_vfs,
31 					  sizeof(struct nsim_vf_config),
32 					  GFP_KERNEL);
33 	if (!nsim_bus_dev->vfconfigs)
34 		return -ENOMEM;
35 	nsim_bus_dev->num_vfs = num_vfs;
36 
37 	return 0;
38 }
39 
40 static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev)
41 {
42 	kfree(nsim_bus_dev->vfconfigs);
43 	nsim_bus_dev->vfconfigs = NULL;
44 	nsim_bus_dev->num_vfs = 0;
45 }
46 
47 static ssize_t
48 nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
49 			  const char *buf, size_t count)
50 {
51 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
52 	unsigned int num_vfs;
53 	int ret;
54 
55 	ret = kstrtouint(buf, 0, &num_vfs);
56 	if (ret)
57 		return ret;
58 
59 	rtnl_lock();
60 	if (nsim_bus_dev->num_vfs == num_vfs)
61 		goto exit_good;
62 	if (nsim_bus_dev->num_vfs && num_vfs) {
63 		ret = -EBUSY;
64 		goto exit_unlock;
65 	}
66 
67 	if (num_vfs) {
68 		ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs);
69 		if (ret)
70 			goto exit_unlock;
71 	} else {
72 		nsim_bus_dev_vfs_disable(nsim_bus_dev);
73 	}
74 exit_good:
75 	ret = count;
76 exit_unlock:
77 	rtnl_unlock();
78 
79 	return ret;
80 }
81 
82 static ssize_t
83 nsim_bus_dev_numvfs_show(struct device *dev,
84 			 struct device_attribute *attr, char *buf)
85 {
86 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
87 
88 	return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs);
89 }
90 
91 static struct device_attribute nsim_bus_dev_numvfs_attr =
92 	__ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
93 	       nsim_bus_dev_numvfs_store);
94 
95 static ssize_t
96 new_port_store(struct device *dev, struct device_attribute *attr,
97 	       const char *buf, size_t count)
98 {
99 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
100 	unsigned int port_index;
101 	int ret;
102 
103 	/* Prevent to use nsim_bus_dev before initialization. */
104 	if (!smp_load_acquire(&nsim_bus_dev->init))
105 		return -EBUSY;
106 	ret = kstrtouint(buf, 0, &port_index);
107 	if (ret)
108 		return ret;
109 	ret = nsim_dev_port_add(nsim_bus_dev, port_index);
110 	return ret ? ret : count;
111 }
112 
113 static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
114 
115 static ssize_t
116 del_port_store(struct device *dev, struct device_attribute *attr,
117 	       const char *buf, size_t count)
118 {
119 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
120 	unsigned int port_index;
121 	int ret;
122 
123 	/* Prevent to use nsim_bus_dev before initialization. */
124 	if (!smp_load_acquire(&nsim_bus_dev->init))
125 		return -EBUSY;
126 	ret = kstrtouint(buf, 0, &port_index);
127 	if (ret)
128 		return ret;
129 	ret = nsim_dev_port_del(nsim_bus_dev, port_index);
130 	return ret ? ret : count;
131 }
132 
133 static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
134 
135 static struct attribute *nsim_bus_dev_attrs[] = {
136 	&nsim_bus_dev_numvfs_attr.attr,
137 	&nsim_bus_dev_new_port_attr.attr,
138 	&nsim_bus_dev_del_port_attr.attr,
139 	NULL,
140 };
141 
142 static const struct attribute_group nsim_bus_dev_attr_group = {
143 	.attrs = nsim_bus_dev_attrs,
144 };
145 
146 static const struct attribute_group *nsim_bus_dev_attr_groups[] = {
147 	&nsim_bus_dev_attr_group,
148 	NULL,
149 };
150 
151 static void nsim_bus_dev_release(struct device *dev)
152 {
153 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
154 
155 	nsim_bus_dev_vfs_disable(nsim_bus_dev);
156 }
157 
158 static struct device_type nsim_bus_dev_type = {
159 	.groups = nsim_bus_dev_attr_groups,
160 	.release = nsim_bus_dev_release,
161 };
162 
163 static struct nsim_bus_dev *
164 nsim_bus_dev_new(unsigned int id, unsigned int port_count);
165 
166 static ssize_t
167 new_device_store(struct bus_type *bus, const char *buf, size_t count)
168 {
169 	struct nsim_bus_dev *nsim_bus_dev;
170 	unsigned int port_count;
171 	unsigned int id;
172 	int err;
173 
174 	err = sscanf(buf, "%u %u", &id, &port_count);
175 	switch (err) {
176 	case 1:
177 		port_count = 1;
178 		/* fall through */
179 	case 2:
180 		if (id > INT_MAX) {
181 			pr_err("Value of \"id\" is too big.\n");
182 			return -EINVAL;
183 		}
184 		break;
185 	default:
186 		pr_err("Format for adding new device is \"id port_count\" (uint uint).\n");
187 		return -EINVAL;
188 	}
189 
190 	mutex_lock(&nsim_bus_dev_list_lock);
191 	/* Prevent to use resource before initialization. */
192 	if (!smp_load_acquire(&nsim_bus_enable)) {
193 		err = -EBUSY;
194 		goto err;
195 	}
196 
197 	nsim_bus_dev = nsim_bus_dev_new(id, port_count);
198 	if (IS_ERR(nsim_bus_dev)) {
199 		err = PTR_ERR(nsim_bus_dev);
200 		goto err;
201 	}
202 
203 	/* Allow using nsim_bus_dev */
204 	smp_store_release(&nsim_bus_dev->init, true);
205 
206 	list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list);
207 	mutex_unlock(&nsim_bus_dev_list_lock);
208 
209 	return count;
210 err:
211 	mutex_unlock(&nsim_bus_dev_list_lock);
212 	return err;
213 }
214 static BUS_ATTR_WO(new_device);
215 
216 static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
217 
218 static ssize_t
219 del_device_store(struct bus_type *bus, const char *buf, size_t count)
220 {
221 	struct nsim_bus_dev *nsim_bus_dev, *tmp;
222 	unsigned int id;
223 	int err;
224 
225 	err = sscanf(buf, "%u", &id);
226 	switch (err) {
227 	case 1:
228 		if (id > INT_MAX) {
229 			pr_err("Value of \"id\" is too big.\n");
230 			return -EINVAL;
231 		}
232 		break;
233 	default:
234 		pr_err("Format for deleting device is \"id\" (uint).\n");
235 		return -EINVAL;
236 	}
237 
238 	err = -ENOENT;
239 	mutex_lock(&nsim_bus_dev_list_lock);
240 	/* Prevent to use resource before initialization. */
241 	if (!smp_load_acquire(&nsim_bus_enable)) {
242 		mutex_unlock(&nsim_bus_dev_list_lock);
243 		return -EBUSY;
244 	}
245 	list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
246 		if (nsim_bus_dev->dev.id != id)
247 			continue;
248 		list_del(&nsim_bus_dev->list);
249 		nsim_bus_dev_del(nsim_bus_dev);
250 		err = 0;
251 		break;
252 	}
253 	mutex_unlock(&nsim_bus_dev_list_lock);
254 	return !err ? count : err;
255 }
256 static BUS_ATTR_WO(del_device);
257 
258 static struct attribute *nsim_bus_attrs[] = {
259 	&bus_attr_new_device.attr,
260 	&bus_attr_del_device.attr,
261 	NULL
262 };
263 ATTRIBUTE_GROUPS(nsim_bus);
264 
265 static int nsim_bus_probe(struct device *dev)
266 {
267 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
268 
269 	return nsim_dev_probe(nsim_bus_dev);
270 }
271 
272 static int nsim_bus_remove(struct device *dev)
273 {
274 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
275 
276 	nsim_dev_remove(nsim_bus_dev);
277 	return 0;
278 }
279 
280 static int nsim_num_vf(struct device *dev)
281 {
282 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
283 
284 	return nsim_bus_dev->num_vfs;
285 }
286 
287 static struct bus_type nsim_bus = {
288 	.name		= DRV_NAME,
289 	.dev_name	= DRV_NAME,
290 	.bus_groups	= nsim_bus_groups,
291 	.probe		= nsim_bus_probe,
292 	.remove		= nsim_bus_remove,
293 	.num_vf		= nsim_num_vf,
294 };
295 
296 static struct nsim_bus_dev *
297 nsim_bus_dev_new(unsigned int id, unsigned int port_count)
298 {
299 	struct nsim_bus_dev *nsim_bus_dev;
300 	int err;
301 
302 	nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL);
303 	if (!nsim_bus_dev)
304 		return ERR_PTR(-ENOMEM);
305 
306 	err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL);
307 	if (err < 0)
308 		goto err_nsim_bus_dev_free;
309 	nsim_bus_dev->dev.id = err;
310 	nsim_bus_dev->dev.bus = &nsim_bus;
311 	nsim_bus_dev->dev.type = &nsim_bus_dev_type;
312 	nsim_bus_dev->port_count = port_count;
313 	nsim_bus_dev->initial_net = current->nsproxy->net_ns;
314 	/* Disallow using nsim_bus_dev */
315 	smp_store_release(&nsim_bus_dev->init, false);
316 
317 	err = device_register(&nsim_bus_dev->dev);
318 	if (err)
319 		goto err_nsim_bus_dev_id_free;
320 	return nsim_bus_dev;
321 
322 err_nsim_bus_dev_id_free:
323 	ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
324 err_nsim_bus_dev_free:
325 	kfree(nsim_bus_dev);
326 	return ERR_PTR(err);
327 }
328 
329 static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
330 {
331 	/* Disallow using nsim_bus_dev */
332 	smp_store_release(&nsim_bus_dev->init, false);
333 	device_unregister(&nsim_bus_dev->dev);
334 	ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
335 	kfree(nsim_bus_dev);
336 }
337 
338 static struct device_driver nsim_driver = {
339 	.name		= DRV_NAME,
340 	.bus		= &nsim_bus,
341 	.owner		= THIS_MODULE,
342 };
343 
344 int nsim_bus_init(void)
345 {
346 	int err;
347 
348 	err = bus_register(&nsim_bus);
349 	if (err)
350 		return err;
351 	err = driver_register(&nsim_driver);
352 	if (err)
353 		goto err_bus_unregister;
354 	/* Allow using resources */
355 	smp_store_release(&nsim_bus_enable, true);
356 	return 0;
357 
358 err_bus_unregister:
359 	bus_unregister(&nsim_bus);
360 	return err;
361 }
362 
363 void nsim_bus_exit(void)
364 {
365 	struct nsim_bus_dev *nsim_bus_dev, *tmp;
366 
367 	/* Disallow using resources */
368 	smp_store_release(&nsim_bus_enable, false);
369 
370 	mutex_lock(&nsim_bus_dev_list_lock);
371 	list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
372 		list_del(&nsim_bus_dev->list);
373 		nsim_bus_dev_del(nsim_bus_dev);
374 	}
375 	mutex_unlock(&nsim_bus_dev_list_lock);
376 
377 	driver_unregister(&nsim_driver);
378 	bus_unregister(&nsim_bus);
379 }
380