2023-05-20 00:56:24 +03:00
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2023 Advanced Micro Devices, Inc */
# include <linux/auxiliary_bus.h>
# include <linux/pci.h>
2023-05-20 00:56:27 +03:00
# include <linux/vdpa.h>
2023-05-20 00:56:28 +03:00
# include <linux/virtio_pci_modern.h>
2023-05-20 00:56:24 +03:00
# include <linux/pds/pds_common.h>
# include <linux/pds/pds_core_if.h>
# include <linux/pds/pds_adminq.h>
# include <linux/pds/pds_auxbus.h>
# include "aux_drv.h"
# include "debugfs.h"
2023-05-20 00:56:27 +03:00
# include "vdpa_dev.h"
2023-05-20 00:56:24 +03:00
static const struct auxiliary_device_id pds_vdpa_id_table [ ] = {
{ . name = PDS_VDPA_DEV_NAME , } ,
{ } ,
} ;
2023-05-20 00:56:28 +03:00
static int pds_vdpa_device_id_check ( struct pci_dev * pdev )
{
if ( pdev - > device ! = PCI_DEVICE_ID_PENSANDO_VDPA_VF | |
pdev - > vendor ! = PCI_VENDOR_ID_PENSANDO )
return - ENODEV ;
return PCI_DEVICE_ID_PENSANDO_VDPA_VF ;
}
2023-05-20 00:56:24 +03:00
static int pds_vdpa_probe ( struct auxiliary_device * aux_dev ,
const struct auxiliary_device_id * id )
{
struct pds_auxiliary_dev * padev =
container_of ( aux_dev , struct pds_auxiliary_dev , aux_dev ) ;
2023-05-20 00:56:28 +03:00
struct device * dev = & aux_dev - > dev ;
2023-05-20 00:56:24 +03:00
struct pds_vdpa_aux * vdpa_aux ;
2023-05-20 00:56:27 +03:00
int err ;
2023-05-20 00:56:24 +03:00
vdpa_aux = kzalloc ( sizeof ( * vdpa_aux ) , GFP_KERNEL ) ;
if ( ! vdpa_aux )
return - ENOMEM ;
vdpa_aux - > padev = padev ;
2023-05-20 00:56:27 +03:00
vdpa_aux - > vf_id = pci_iov_vf_id ( padev - > vf_pdev ) ;
2023-05-20 00:56:24 +03:00
auxiliary_set_drvdata ( aux_dev , vdpa_aux ) ;
2023-05-20 00:56:27 +03:00
/* Get device ident info and set up the vdpa_mgmt_dev */
err = pds_vdpa_get_mgmt_info ( vdpa_aux ) ;
if ( err )
goto err_free_mem ;
2023-05-20 00:56:28 +03:00
/* Find the virtio configuration */
vdpa_aux - > vd_mdev . pci_dev = padev - > vf_pdev ;
vdpa_aux - > vd_mdev . device_id_check = pds_vdpa_device_id_check ;
vdpa_aux - > vd_mdev . dma_mask = DMA_BIT_MASK ( PDS_CORE_ADDR_LEN ) ;
err = vp_modern_probe ( & vdpa_aux - > vd_mdev ) ;
if ( err ) {
dev_err ( dev , " Unable to probe for virtio configuration: %pe \n " ,
ERR_PTR ( err ) ) ;
goto err_free_mgmt_info ;
}
2023-05-20 00:56:30 +03:00
/* Let vdpa know that we can provide devices */
err = vdpa_mgmtdev_register ( & vdpa_aux - > vdpa_mdev ) ;
if ( err ) {
dev_err ( dev , " %s: Failed to initialize vdpa_mgmt interface: %pe \n " ,
__func__ , ERR_PTR ( err ) ) ;
goto err_free_virtio ;
}
pds_vdpa_debugfs_add_pcidev ( vdpa_aux ) ;
pds_vdpa_debugfs_add_ident ( vdpa_aux ) ;
2023-05-20 00:56:24 +03:00
return 0 ;
2023-05-20 00:56:27 +03:00
2023-05-20 00:56:30 +03:00
err_free_virtio :
vp_modern_remove ( & vdpa_aux - > vd_mdev ) ;
2023-05-20 00:56:28 +03:00
err_free_mgmt_info :
pci_free_irq_vectors ( padev - > vf_pdev ) ;
2023-05-20 00:56:27 +03:00
err_free_mem :
kfree ( vdpa_aux ) ;
auxiliary_set_drvdata ( aux_dev , NULL ) ;
return err ;
2023-05-20 00:56:24 +03:00
}
static void pds_vdpa_remove ( struct auxiliary_device * aux_dev )
{
struct pds_vdpa_aux * vdpa_aux = auxiliary_get_drvdata ( aux_dev ) ;
struct device * dev = & aux_dev - > dev ;
2023-05-20 00:56:30 +03:00
vdpa_mgmtdev_unregister ( & vdpa_aux - > vdpa_mdev ) ;
2024-02-20 04:10:50 +03:00
pds_vdpa_release_irqs ( vdpa_aux - > pdsv ) ;
2023-05-20 00:56:28 +03:00
vp_modern_remove ( & vdpa_aux - > vd_mdev ) ;
2023-05-20 00:56:27 +03:00
2023-05-20 00:56:30 +03:00
pds_vdpa_debugfs_del_vdpadev ( vdpa_aux ) ;
2023-05-20 00:56:24 +03:00
kfree ( vdpa_aux ) ;
auxiliary_set_drvdata ( aux_dev , NULL ) ;
dev_info ( dev , " Removed \n " ) ;
}
static struct auxiliary_driver pds_vdpa_driver = {
. name = PDS_DEV_TYPE_VDPA_STR ,
. probe = pds_vdpa_probe ,
. remove = pds_vdpa_remove ,
. id_table = pds_vdpa_id_table ,
} ;
static void __exit pds_vdpa_cleanup ( void )
{
auxiliary_driver_unregister ( & pds_vdpa_driver ) ;
pds_vdpa_debugfs_destroy ( ) ;
}
module_exit ( pds_vdpa_cleanup ) ;
static int __init pds_vdpa_init ( void )
{
int err ;
pds_vdpa_debugfs_create ( ) ;
err = auxiliary_driver_register ( & pds_vdpa_driver ) ;
if ( err ) {
pr_err ( " %s: aux driver register failed: %pe \n " ,
PDS_VDPA_DRV_NAME , ERR_PTR ( err ) ) ;
pds_vdpa_debugfs_destroy ( ) ;
}
return err ;
}
module_init ( pds_vdpa_init ) ;
MODULE_DESCRIPTION ( PDS_VDPA_DRV_DESCRIPTION ) ;
MODULE_AUTHOR ( " Advanced Micro Devices, Inc " ) ;
MODULE_LICENSE ( " GPL " ) ;