1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
4 #include <linux/auxiliary_bus.h>
6 #include <linux/vdpa.h>
7 #include <linux/virtio_pci_modern.h>
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>
18 static const struct auxiliary_device_id pds_vdpa_id_table
[] = {
19 { .name
= PDS_VDPA_DEV_NAME
, },
23 static int pds_vdpa_device_id_check(struct pci_dev
*pdev
)
25 if (pdev
->device
!= PCI_DEVICE_ID_PENSANDO_VDPA_VF
||
26 pdev
->vendor
!= PCI_VENDOR_ID_PENSANDO
)
29 return PCI_DEVICE_ID_PENSANDO_VDPA_VF
;
32 static int pds_vdpa_probe(struct auxiliary_device
*aux_dev
,
33 const struct auxiliary_device_id
*id
)
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
;
42 vdpa_aux
= kzalloc(sizeof(*vdpa_aux
), GFP_KERNEL
);
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
);
50 /* Get device ident info and set up the vdpa_mgmt_dev */
51 err
= pds_vdpa_get_mgmt_info(vdpa_aux
);
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
);
61 dev_err(dev
, "Unable to probe for virtio configuration: %pe\n",
63 goto err_free_mgmt_info
;
66 /* Let vdpa know that we can provide devices */
67 err
= vdpa_mgmtdev_register(&vdpa_aux
->vdpa_mdev
);
69 dev_err(dev
, "%s: Failed to initialize vdpa_mgmt interface: %pe\n",
70 __func__
, ERR_PTR(err
));
74 pds_vdpa_debugfs_add_pcidev(vdpa_aux
);
75 pds_vdpa_debugfs_add_ident(vdpa_aux
);
80 vp_modern_remove(&vdpa_aux
->vd_mdev
);
82 pci_free_irq_vectors(padev
->vf_pdev
);
85 auxiliary_set_drvdata(aux_dev
, NULL
);
90 static void pds_vdpa_remove(struct auxiliary_device
*aux_dev
)
92 struct pds_vdpa_aux
*vdpa_aux
= auxiliary_get_drvdata(aux_dev
);
93 struct device
*dev
= &aux_dev
->dev
;
95 vdpa_mgmtdev_unregister(&vdpa_aux
->vdpa_mdev
);
96 pds_vdpa_release_irqs(vdpa_aux
->pdsv
);
97 vp_modern_remove(&vdpa_aux
->vd_mdev
);
99 pds_vdpa_debugfs_del_vdpadev(vdpa_aux
);
101 auxiliary_set_drvdata(aux_dev
, NULL
);
103 dev_info(dev
, "Removed\n");
106 static 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
,
113 static void __exit
pds_vdpa_cleanup(void)
115 auxiliary_driver_unregister(&pds_vdpa_driver
);
117 pds_vdpa_debugfs_destroy();
119 module_exit(pds_vdpa_cleanup
);
121 static int __init
pds_vdpa_init(void)
125 pds_vdpa_debugfs_create();
127 err
= auxiliary_driver_register(&pds_vdpa_driver
);
129 pr_err("%s: aux driver register failed: %pe\n",
130 PDS_VDPA_DRV_NAME
, ERR_PTR(err
));
131 pds_vdpa_debugfs_destroy();
136 module_init(pds_vdpa_init
);
138 MODULE_DESCRIPTION(PDS_VDPA_DRV_DESCRIPTION
);
139 MODULE_AUTHOR("Advanced Micro Devices, Inc");
140 MODULE_LICENSE("GPL");