xref: /linux/drivers/dibs/dibs_loopback.c (revision cb990a45d7f6eb6dc495d2226a3005b284a5ee4f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Functions for dibs loopback/loopback-ism device.
4  *
5  *  Copyright (c) 2024, Alibaba Inc.
6  *
7  *  Author: Wen Gu <guwen@linux.alibaba.com>
8  *          Tony Lu <tonylu@linux.alibaba.com>
9  *
10  */
11 
12 #include <linux/dibs.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 
16 #include "dibs_loopback.h"
17 
18 /* global loopback device */
19 static struct dibs_lo_dev *lo_dev;
20 
21 static void dibs_lo_dev_exit(struct dibs_lo_dev *ldev)
22 {
23 	dibs_dev_del(ldev->dibs);
24 }
25 
26 static int dibs_lo_dev_probe(void)
27 {
28 	struct dibs_lo_dev *ldev;
29 	struct dibs_dev *dibs;
30 	int ret;
31 
32 	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
33 	if (!ldev)
34 		return -ENOMEM;
35 
36 	dibs = dibs_dev_alloc();
37 	if (!dibs) {
38 		kfree(ldev);
39 		return -ENOMEM;
40 	}
41 
42 	ldev->dibs = dibs;
43 
44 	ret = dibs_dev_add(dibs);
45 	if (ret)
46 		goto err_reg;
47 	lo_dev = ldev;
48 	return 0;
49 
50 err_reg:
51 	/* pairs with dibs_dev_alloc() */
52 	kfree(dibs);
53 	kfree(ldev);
54 
55 	return ret;
56 }
57 
58 static void dibs_lo_dev_remove(void)
59 {
60 	if (!lo_dev)
61 		return;
62 
63 	dibs_lo_dev_exit(lo_dev);
64 	/* pairs with dibs_dev_alloc() */
65 	kfree(lo_dev->dibs);
66 	kfree(lo_dev);
67 	lo_dev = NULL;
68 }
69 
70 int dibs_loopback_init(void)
71 {
72 	return dibs_lo_dev_probe();
73 }
74 
75 void dibs_loopback_exit(void)
76 {
77 	dibs_lo_dev_remove();
78 }
79