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