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