// SPDX-License-Identifier: GPL-2.0 /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ #include #include "ionic.h" #include "ionic_lif.h" #include "ionic_aux.h" static DEFINE_IDA(aux_ida); static void ionic_auxbus_release(struct device *dev) { struct ionic_aux_dev *ionic_adev; ionic_adev = container_of(dev, struct ionic_aux_dev, adev.dev); ida_free(&aux_ida, ionic_adev->adev.id); kfree(ionic_adev); } int ionic_auxbus_register(struct ionic_lif *lif) { struct ionic_aux_dev *ionic_adev; struct auxiliary_device *aux_dev; int err, id; if (!(le64_to_cpu(lif->ionic->ident.lif.capabilities) & IONIC_LIF_CAP_RDMA)) return 0; ionic_adev = kzalloc(sizeof(*ionic_adev), GFP_KERNEL); if (!ionic_adev) return -ENOMEM; aux_dev = &ionic_adev->adev; id = ida_alloc(&aux_ida, GFP_KERNEL); if (id < 0) { dev_err(lif->ionic->dev, "Failed to allocate aux id: %d\n", id); kfree(ionic_adev); return id; } aux_dev->id = id; aux_dev->name = "rdma"; aux_dev->dev.parent = &lif->ionic->pdev->dev; aux_dev->dev.release = ionic_auxbus_release; ionic_adev->lif = lif; err = auxiliary_device_init(aux_dev); if (err) { dev_err(lif->ionic->dev, "Failed to initialize %s aux device: %d\n", aux_dev->name, err); ida_free(&aux_ida, id); kfree(ionic_adev); return err; } err = auxiliary_device_add(aux_dev); if (err) { dev_err(lif->ionic->dev, "Failed to add %s aux device: %d\n", aux_dev->name, err); auxiliary_device_uninit(aux_dev); return err; } lif->ionic_adev = ionic_adev; return 0; } void ionic_auxbus_unregister(struct ionic_lif *lif) { mutex_lock(&lif->adev_lock); if (!lif->ionic_adev) goto out; auxiliary_device_delete(&lif->ionic_adev->adev); auxiliary_device_uninit(&lif->ionic_adev->adev); lif->ionic_adev = NULL; out: mutex_unlock(&lif->adev_lock); } void ionic_request_rdma_reset(struct ionic_lif *lif) { struct ionic *ionic = lif->ionic; int err; union ionic_dev_cmd cmd = { .cmd.opcode = IONIC_CMD_RDMA_RESET_LIF, .cmd.lif_index = cpu_to_le16(lif->index), }; mutex_lock(&ionic->dev_cmd_lock); ionic_dev_cmd_go(&ionic->idev, &cmd); err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); mutex_unlock(&ionic->dev_cmd_lock); if (err) pr_warn("%s request_reset: error %d\n", __func__, err); } EXPORT_SYMBOL_NS(ionic_request_rdma_reset, "NET_IONIC");