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