xref: /linux/drivers/dibs/dibs_loopback.c (revision 69baaac9361edd169713562f088829a1be9c51a9)
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 u16 dibs_lo_get_fabric_id(struct dibs_dev *dibs)
22 {
23 	return DIBS_LOOPBACK_FABRIC;
24 }
25 
26 static const struct dibs_dev_ops dibs_lo_ops = {
27 	.get_fabric_id = dibs_lo_get_fabric_id,
28 };
29 
30 static void dibs_lo_dev_exit(struct dibs_lo_dev *ldev)
31 {
32 	dibs_dev_del(ldev->dibs);
33 }
34 
35 static int dibs_lo_dev_probe(void)
36 {
37 	struct dibs_lo_dev *ldev;
38 	struct dibs_dev *dibs;
39 	int ret;
40 
41 	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
42 	if (!ldev)
43 		return -ENOMEM;
44 
45 	dibs = dibs_dev_alloc();
46 	if (!dibs) {
47 		kfree(ldev);
48 		return -ENOMEM;
49 	}
50 
51 	ldev->dibs = dibs;
52 	dibs->drv_priv = ldev;
53 	dibs->ops = &dibs_lo_ops;
54 
55 	ret = dibs_dev_add(dibs);
56 	if (ret)
57 		goto err_reg;
58 	lo_dev = ldev;
59 	return 0;
60 
61 err_reg:
62 	/* pairs with dibs_dev_alloc() */
63 	kfree(dibs);
64 	kfree(ldev);
65 
66 	return ret;
67 }
68 
69 static void dibs_lo_dev_remove(void)
70 {
71 	if (!lo_dev)
72 		return;
73 
74 	dibs_lo_dev_exit(lo_dev);
75 	/* pairs with dibs_dev_alloc() */
76 	kfree(lo_dev->dibs);
77 	kfree(lo_dev);
78 	lo_dev = NULL;
79 }
80 
81 int dibs_loopback_init(void)
82 {
83 	return dibs_lo_dev_probe();
84 }
85 
86 void dibs_loopback_exit(void)
87 {
88 	dibs_lo_dev_remove();
89 }
90