xref: /linux/drivers/dibs/dibs_loopback.c (revision 719c3b67bb7ea95bb8158b03c75641c8fc8f94a0)
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 static const char dibs_lo_dev_name[] = "lo";
19 /* global loopback device */
20 static struct dibs_lo_dev *lo_dev;
21 
22 static u16 dibs_lo_get_fabric_id(struct dibs_dev *dibs)
23 {
24 	return DIBS_LOOPBACK_FABRIC;
25 }
26 
27 static int dibs_lo_query_rgid(struct dibs_dev *dibs, const uuid_t *rgid,
28 			      u32 vid_valid, u32 vid)
29 {
30 	/* rgid should be the same as lgid */
31 	if (!uuid_equal(rgid, &dibs->gid))
32 		return -ENETUNREACH;
33 	return 0;
34 }
35 
36 static const struct dibs_dev_ops dibs_lo_ops = {
37 	.get_fabric_id = dibs_lo_get_fabric_id,
38 	.query_remote_gid = dibs_lo_query_rgid,
39 };
40 
41 static int dibs_lo_dev_probe(void)
42 {
43 	struct dibs_lo_dev *ldev;
44 	struct dibs_dev *dibs;
45 	int ret;
46 
47 	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
48 	if (!ldev)
49 		return -ENOMEM;
50 
51 	dibs = dibs_dev_alloc();
52 	if (!dibs) {
53 		kfree(ldev);
54 		return -ENOMEM;
55 	}
56 
57 	ldev->dibs = dibs;
58 	dibs->drv_priv = ldev;
59 	uuid_gen(&dibs->gid);
60 	dibs->ops = &dibs_lo_ops;
61 
62 	dibs->dev.parent = NULL;
63 	dev_set_name(&dibs->dev, "%s", dibs_lo_dev_name);
64 
65 	ret = dibs_dev_add(dibs);
66 	if (ret)
67 		goto err_reg;
68 	lo_dev = ldev;
69 	return 0;
70 
71 err_reg:
72 	/* pairs with dibs_dev_alloc() */
73 	put_device(&dibs->dev);
74 	kfree(ldev);
75 
76 	return ret;
77 }
78 
79 static void dibs_lo_dev_remove(void)
80 {
81 	if (!lo_dev)
82 		return;
83 
84 	dibs_dev_del(lo_dev->dibs);
85 	/* pairs with dibs_dev_alloc() */
86 	put_device(&lo_dev->dibs->dev);
87 	kfree(lo_dev);
88 	lo_dev = NULL;
89 }
90 
91 int dibs_loopback_init(void)
92 {
93 	return dibs_lo_dev_probe();
94 }
95 
96 void dibs_loopback_exit(void)
97 {
98 	dibs_lo_dev_remove();
99 }
100