141 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright(c) 2023 Advanced Micro Devices, Inc */3 4#include <linux/auxiliary_bus.h>5#include <linux/pci.h>6#include <linux/vdpa.h>7#include <linux/virtio_pci_modern.h>8 9#include <linux/pds/pds_common.h>10#include <linux/pds/pds_core_if.h>11#include <linux/pds/pds_adminq.h>12#include <linux/pds/pds_auxbus.h>13 14#include "aux_drv.h"15#include "debugfs.h"16#include "vdpa_dev.h"17 18static const struct auxiliary_device_id pds_vdpa_id_table[] = {19 { .name = PDS_VDPA_DEV_NAME, },20 {},21};22 23static int pds_vdpa_device_id_check(struct pci_dev *pdev)24{25 if (pdev->device != PCI_DEVICE_ID_PENSANDO_VDPA_VF ||26 pdev->vendor != PCI_VENDOR_ID_PENSANDO)27 return -ENODEV;28 29 return PCI_DEVICE_ID_PENSANDO_VDPA_VF;30}31 32static int pds_vdpa_probe(struct auxiliary_device *aux_dev,33 const struct auxiliary_device_id *id)34 35{36 struct pds_auxiliary_dev *padev =37 container_of(aux_dev, struct pds_auxiliary_dev, aux_dev);38 struct device *dev = &aux_dev->dev;39 struct pds_vdpa_aux *vdpa_aux;40 int err;41 42 vdpa_aux = kzalloc(sizeof(*vdpa_aux), GFP_KERNEL);43 if (!vdpa_aux)44 return -ENOMEM;45 46 vdpa_aux->padev = padev;47 vdpa_aux->vf_id = pci_iov_vf_id(padev->vf_pdev);48 auxiliary_set_drvdata(aux_dev, vdpa_aux);49 50 /* Get device ident info and set up the vdpa_mgmt_dev */51 err = pds_vdpa_get_mgmt_info(vdpa_aux);52 if (err)53 goto err_free_mem;54 55 /* Find the virtio configuration */56 vdpa_aux->vd_mdev.pci_dev = padev->vf_pdev;57 vdpa_aux->vd_mdev.device_id_check = pds_vdpa_device_id_check;58 vdpa_aux->vd_mdev.dma_mask = DMA_BIT_MASK(PDS_CORE_ADDR_LEN);59 err = vp_modern_probe(&vdpa_aux->vd_mdev);60 if (err) {61 dev_err(dev, "Unable to probe for virtio configuration: %pe\n",62 ERR_PTR(err));63 goto err_free_mgmt_info;64 }65 66 /* Let vdpa know that we can provide devices */67 err = vdpa_mgmtdev_register(&vdpa_aux->vdpa_mdev);68 if (err) {69 dev_err(dev, "%s: Failed to initialize vdpa_mgmt interface: %pe\n",70 __func__, ERR_PTR(err));71 goto err_free_virtio;72 }73 74 pds_vdpa_debugfs_add_pcidev(vdpa_aux);75 pds_vdpa_debugfs_add_ident(vdpa_aux);76 77 return 0;78 79err_free_virtio:80 vp_modern_remove(&vdpa_aux->vd_mdev);81err_free_mgmt_info:82 pci_free_irq_vectors(padev->vf_pdev);83err_free_mem:84 kfree(vdpa_aux);85 auxiliary_set_drvdata(aux_dev, NULL);86 87 return err;88}89 90static void pds_vdpa_remove(struct auxiliary_device *aux_dev)91{92 struct pds_vdpa_aux *vdpa_aux = auxiliary_get_drvdata(aux_dev);93 struct device *dev = &aux_dev->dev;94 95 vdpa_mgmtdev_unregister(&vdpa_aux->vdpa_mdev);96 pds_vdpa_release_irqs(vdpa_aux->pdsv);97 vp_modern_remove(&vdpa_aux->vd_mdev);98 99 pds_vdpa_debugfs_del_vdpadev(vdpa_aux);100 kfree(vdpa_aux);101 auxiliary_set_drvdata(aux_dev, NULL);102 103 dev_info(dev, "Removed\n");104}105 106static struct auxiliary_driver pds_vdpa_driver = {107 .name = PDS_DEV_TYPE_VDPA_STR,108 .probe = pds_vdpa_probe,109 .remove = pds_vdpa_remove,110 .id_table = pds_vdpa_id_table,111};112 113static void __exit pds_vdpa_cleanup(void)114{115 auxiliary_driver_unregister(&pds_vdpa_driver);116 117 pds_vdpa_debugfs_destroy();118}119module_exit(pds_vdpa_cleanup);120 121static int __init pds_vdpa_init(void)122{123 int err;124 125 pds_vdpa_debugfs_create();126 127 err = auxiliary_driver_register(&pds_vdpa_driver);128 if (err) {129 pr_err("%s: aux driver register failed: %pe\n",130 PDS_VDPA_DRV_NAME, ERR_PTR(err));131 pds_vdpa_debugfs_destroy();132 }133 134 return err;135}136module_init(pds_vdpa_init);137 138MODULE_DESCRIPTION(PDS_VDPA_DRV_DESCRIPTION);139MODULE_AUTHOR("Advanced Micro Devices, Inc");140MODULE_LICENSE("GPL");141