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