1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3 4 #include <linux/kernel.h> 5 #include "ionic.h" 6 #include "ionic_lif.h" 7 #include "ionic_aux.h" 8 9 static DEFINE_IDA(aux_ida); 10 11 static void ionic_auxbus_release(struct device *dev) 12 { 13 struct ionic_aux_dev *ionic_adev; 14 15 ionic_adev = container_of(dev, struct ionic_aux_dev, adev.dev); 16 ida_free(&aux_ida, ionic_adev->adev.id); 17 kfree(ionic_adev); 18 } 19 20 int ionic_auxbus_register(struct ionic_lif *lif) 21 { 22 struct ionic_aux_dev *ionic_adev; 23 struct auxiliary_device *aux_dev; 24 int err, id; 25 26 if (!(le64_to_cpu(lif->ionic->ident.lif.capabilities) & IONIC_LIF_CAP_RDMA)) 27 return 0; 28 29 ionic_adev = kzalloc(sizeof(*ionic_adev), GFP_KERNEL); 30 if (!ionic_adev) 31 return -ENOMEM; 32 33 aux_dev = &ionic_adev->adev; 34 35 id = ida_alloc(&aux_ida, GFP_KERNEL); 36 if (id < 0) { 37 dev_err(lif->ionic->dev, "Failed to allocate aux id: %d\n", id); 38 kfree(ionic_adev); 39 return id; 40 } 41 42 aux_dev->id = id; 43 aux_dev->name = "rdma"; 44 aux_dev->dev.parent = &lif->ionic->pdev->dev; 45 aux_dev->dev.release = ionic_auxbus_release; 46 ionic_adev->lif = lif; 47 err = auxiliary_device_init(aux_dev); 48 if (err) { 49 dev_err(lif->ionic->dev, "Failed to initialize %s aux device: %d\n", 50 aux_dev->name, err); 51 ida_free(&aux_ida, id); 52 kfree(ionic_adev); 53 return err; 54 } 55 56 err = auxiliary_device_add(aux_dev); 57 if (err) { 58 dev_err(lif->ionic->dev, "Failed to add %s aux device: %d\n", 59 aux_dev->name, err); 60 auxiliary_device_uninit(aux_dev); 61 return err; 62 } 63 64 lif->ionic_adev = ionic_adev; 65 return 0; 66 } 67 68 void ionic_auxbus_unregister(struct ionic_lif *lif) 69 { 70 mutex_lock(&lif->adev_lock); 71 if (!lif->ionic_adev) 72 goto out; 73 74 auxiliary_device_delete(&lif->ionic_adev->adev); 75 auxiliary_device_uninit(&lif->ionic_adev->adev); 76 77 lif->ionic_adev = NULL; 78 out: 79 mutex_unlock(&lif->adev_lock); 80 } 81 82 void ionic_request_rdma_reset(struct ionic_lif *lif) 83 { 84 struct ionic *ionic = lif->ionic; 85 int err; 86 87 union ionic_dev_cmd cmd = { 88 .cmd.opcode = IONIC_CMD_RDMA_RESET_LIF, 89 .cmd.lif_index = cpu_to_le16(lif->index), 90 }; 91 92 mutex_lock(&ionic->dev_cmd_lock); 93 94 ionic_dev_cmd_go(&ionic->idev, &cmd); 95 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); 96 97 mutex_unlock(&ionic->dev_cmd_lock); 98 99 if (err) 100 pr_warn("%s request_reset: error %d\n", __func__, err); 101 } 102 EXPORT_SYMBOL_NS(ionic_request_rdma_reset, "NET_IONIC"); 103