1cb990a45SAlexandra Winter // SPDX-License-Identifier: GPL-2.0 2cb990a45SAlexandra Winter /* 3cb990a45SAlexandra Winter * Functions for dibs loopback/loopback-ism device. 4cb990a45SAlexandra Winter * 5cb990a45SAlexandra Winter * Copyright (c) 2024, Alibaba Inc. 6cb990a45SAlexandra Winter * 7cb990a45SAlexandra Winter * Author: Wen Gu <guwen@linux.alibaba.com> 8cb990a45SAlexandra Winter * Tony Lu <tonylu@linux.alibaba.com> 9cb990a45SAlexandra Winter * 10cb990a45SAlexandra Winter */ 11cb990a45SAlexandra Winter 12cb990a45SAlexandra Winter #include <linux/dibs.h> 13cb990a45SAlexandra Winter #include <linux/slab.h> 14cb990a45SAlexandra Winter #include <linux/types.h> 15cb990a45SAlexandra Winter 16cb990a45SAlexandra Winter #include "dibs_loopback.h" 17cb990a45SAlexandra Winter 18845c334aSJulian Ruess static const char dibs_lo_dev_name[] = "lo"; 19cb990a45SAlexandra Winter /* global loopback device */ 20cb990a45SAlexandra Winter static struct dibs_lo_dev *lo_dev; 21cb990a45SAlexandra Winter 2269baaac9SAlexandra Winter static u16 dibs_lo_get_fabric_id(struct dibs_dev *dibs) 2369baaac9SAlexandra Winter { 2469baaac9SAlexandra Winter return DIBS_LOOPBACK_FABRIC; 2569baaac9SAlexandra Winter } 2669baaac9SAlexandra Winter 27*719c3b67SAlexandra Winter static int dibs_lo_query_rgid(struct dibs_dev *dibs, const uuid_t *rgid, 28*719c3b67SAlexandra Winter u32 vid_valid, u32 vid) 29*719c3b67SAlexandra Winter { 30*719c3b67SAlexandra Winter /* rgid should be the same as lgid */ 31*719c3b67SAlexandra Winter if (!uuid_equal(rgid, &dibs->gid)) 32*719c3b67SAlexandra Winter return -ENETUNREACH; 33*719c3b67SAlexandra Winter return 0; 34*719c3b67SAlexandra Winter } 35*719c3b67SAlexandra Winter 3669baaac9SAlexandra Winter static const struct dibs_dev_ops dibs_lo_ops = { 3769baaac9SAlexandra Winter .get_fabric_id = dibs_lo_get_fabric_id, 38*719c3b67SAlexandra Winter .query_remote_gid = dibs_lo_query_rgid, 3969baaac9SAlexandra Winter }; 4069baaac9SAlexandra Winter 41cb990a45SAlexandra Winter static int dibs_lo_dev_probe(void) 42cb990a45SAlexandra Winter { 43cb990a45SAlexandra Winter struct dibs_lo_dev *ldev; 44cb990a45SAlexandra Winter struct dibs_dev *dibs; 45cb990a45SAlexandra Winter int ret; 46cb990a45SAlexandra Winter 47cb990a45SAlexandra Winter ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); 48cb990a45SAlexandra Winter if (!ldev) 49cb990a45SAlexandra Winter return -ENOMEM; 50cb990a45SAlexandra Winter 51cb990a45SAlexandra Winter dibs = dibs_dev_alloc(); 52cb990a45SAlexandra Winter if (!dibs) { 53cb990a45SAlexandra Winter kfree(ldev); 54cb990a45SAlexandra Winter return -ENOMEM; 55cb990a45SAlexandra Winter } 56cb990a45SAlexandra Winter 57cb990a45SAlexandra Winter ldev->dibs = dibs; 5869baaac9SAlexandra Winter dibs->drv_priv = ldev; 5905e68d8dSAlexandra Winter uuid_gen(&dibs->gid); 6069baaac9SAlexandra Winter dibs->ops = &dibs_lo_ops; 61cb990a45SAlexandra Winter 62845c334aSJulian Ruess dibs->dev.parent = NULL; 63845c334aSJulian Ruess dev_set_name(&dibs->dev, "%s", dibs_lo_dev_name); 64845c334aSJulian Ruess 65cb990a45SAlexandra Winter ret = dibs_dev_add(dibs); 66cb990a45SAlexandra Winter if (ret) 67cb990a45SAlexandra Winter goto err_reg; 68cb990a45SAlexandra Winter lo_dev = ldev; 69cb990a45SAlexandra Winter return 0; 70cb990a45SAlexandra Winter 71cb990a45SAlexandra Winter err_reg: 72cb990a45SAlexandra Winter /* pairs with dibs_dev_alloc() */ 73845c334aSJulian Ruess put_device(&dibs->dev); 74cb990a45SAlexandra Winter kfree(ldev); 75cb990a45SAlexandra Winter 76cb990a45SAlexandra Winter return ret; 77cb990a45SAlexandra Winter } 78cb990a45SAlexandra Winter 79cb990a45SAlexandra Winter static void dibs_lo_dev_remove(void) 80cb990a45SAlexandra Winter { 81cb990a45SAlexandra Winter if (!lo_dev) 82cb990a45SAlexandra Winter return; 83cb990a45SAlexandra Winter 84845c334aSJulian Ruess dibs_dev_del(lo_dev->dibs); 85cb990a45SAlexandra Winter /* pairs with dibs_dev_alloc() */ 86845c334aSJulian Ruess put_device(&lo_dev->dibs->dev); 87cb990a45SAlexandra Winter kfree(lo_dev); 88cb990a45SAlexandra Winter lo_dev = NULL; 89cb990a45SAlexandra Winter } 90cb990a45SAlexandra Winter 91cb990a45SAlexandra Winter int dibs_loopback_init(void) 92cb990a45SAlexandra Winter { 93cb990a45SAlexandra Winter return dibs_lo_dev_probe(); 94cb990a45SAlexandra Winter } 95cb990a45SAlexandra Winter 96cb990a45SAlexandra Winter void dibs_loopback_exit(void) 97cb990a45SAlexandra Winter { 98cb990a45SAlexandra Winter dibs_lo_dev_remove(); 99cb990a45SAlexandra Winter } 100