@@ -3,6 +3,7 @@
obj-$(CONFIG_PDS_VDPA) := pds_vdpa.o
-pds_vdpa-y := pci_drv.o \
+pds_vdpa-y := aux_drv.o \
+ pci_drv.o \
debugfs.o \
virtio_pci.o
new file mode 100644
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Pensando Systems, Inc */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/vdpa.h>
+
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+#include <linux/pds/pds_vdpa.h>
+
+#include "aux_drv.h"
+#include "pci_drv.h"
+#include "debugfs.h"
+
+static const
+struct auxiliary_device_id pds_vdpa_aux_id_table[] = {
+ { .name = PDS_VDPA_DEV_NAME, },
+ {},
+};
+
+static void
+pds_vdpa_aux_notify_handler(struct pds_auxiliary_dev *padev,
+ union pds_core_notifyq_comp *event)
+{
+ struct device *dev = &padev->aux_dev.dev;
+ u16 ecode = le16_to_cpu(event->ecode);
+
+ dev_info(dev, "%s: event code %d\n", __func__, ecode);
+}
+
+static int
+pds_vdpa_aux_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);
+ struct device *dev = &aux_dev->dev;
+ struct pds_vdpa_aux *vdpa_aux;
+ struct pci_dev *pdev;
+ struct pci_bus *bus;
+ int busnr;
+ u16 devfn;
+ int err;
+
+ vdpa_aux = kzalloc(sizeof(*vdpa_aux), GFP_KERNEL);
+ if (!vdpa_aux)
+ return -ENOMEM;
+
+ vdpa_aux->padev = padev;
+ auxiliary_set_drvdata(aux_dev, vdpa_aux);
+
+ /* Find our VF PCI device */
+ busnr = PCI_BUS_NUM(padev->id);
+ devfn = padev->id & 0xff;
+ bus = pci_find_bus(0, busnr);
+ pdev = pci_get_slot(bus, devfn);
+
+ vdpa_aux->vdpa_vf = pci_get_drvdata(pdev);
+ vdpa_aux->vdpa_vf->vdpa_aux = vdpa_aux;
+ pdev = vdpa_aux->vdpa_vf->pdev;
+ if (!pds_vdpa_is_vdpa_pci_driver(pdev)) {
+ dev_err(&pdev->dev, "%s: PCI driver is not pds_vdpa_pci_driver\n", __func__);
+ err = -EINVAL;
+ goto err_invalid_driver;
+ }
+
+ dev_info(dev, "%s: id %#04x busnr %#x devfn %#x bus %p vdpa_vf %p\n",
+ __func__, padev->id, busnr, devfn, bus, vdpa_aux->vdpa_vf);
+
+ /* Register our PDS client with the pds_core */
+ vdpa_aux->padrv.event_handler = pds_vdpa_aux_notify_handler;
+ err = padev->ops->register_client(padev, &vdpa_aux->padrv);
+ if (err) {
+ dev_err(dev, "%s: Failed to register as client: %pe\n",
+ __func__, ERR_PTR(err));
+ goto err_register_client;
+ }
+
+ pds_vdpa_debugfs_add_ident(vdpa_aux);
+
+ return 0;
+
+err_register_client:
+ auxiliary_set_drvdata(aux_dev, NULL);
+err_invalid_driver:
+ kfree(vdpa_aux);
+
+ return err;
+}
+
+static void
+pds_vdpa_aux_remove(struct auxiliary_device *aux_dev)
+{
+ struct pds_vdpa_aux *vdpa_aux = auxiliary_get_drvdata(aux_dev);
+ struct device *dev = &aux_dev->dev;
+
+ vdpa_aux->padev->ops->unregister_client(vdpa_aux->padev);
+ if (vdpa_aux->vdpa_vf)
+ pci_dev_put(vdpa_aux->vdpa_vf->pdev);
+
+ kfree(vdpa_aux);
+ auxiliary_set_drvdata(aux_dev, NULL);
+
+ dev_info(dev, "Removed\n");
+}
+
+static struct auxiliary_driver
+pds_vdpa_aux_driver = {
+ .name = PDS_DEV_TYPE_VDPA_STR,
+ .probe = pds_vdpa_aux_probe,
+ .remove = pds_vdpa_aux_remove,
+ .id_table = pds_vdpa_aux_id_table,
+};
+
+struct auxiliary_driver *
+pds_vdpa_aux_driver_info(void)
+{
+ return &pds_vdpa_aux_driver;
+}
new file mode 100644
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2022 Pensando Systems, Inc */
+
+#ifndef _AUX_DRV_H_
+#define _AUX_DRV_H_
+
+#include <linux/auxiliary_bus.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+struct pds_vdpa_pci_device;
+
+struct pds_vdpa_aux {
+ struct pds_auxiliary_dev *padev;
+ struct pds_auxiliary_drv padrv;
+
+ struct pds_vdpa_pci_device *vdpa_vf;
+ struct vdpa_mgmt_dev vdpa_mdev;
+ struct pds_vdpa_device *pdsv;
+
+ struct pds_vdpa_ident ident;
+ bool local_mac_bit;
+};
+
+struct auxiliary_driver *
+pds_vdpa_aux_driver_info(void);
+
+#endif /* _AUX_DRV_H_ */
@@ -4,10 +4,14 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/types.h>
+#include <linux/vdpa.h>
#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
#include <linux/pds/pds_vdpa.h>
+#include "aux_drv.h"
#include "pci_drv.h"
#include "debugfs.h"
@@ -41,4 +45,23 @@ pds_vdpa_debugfs_del_pcidev(struct pds_vdpa_pci_device *vdpa_pdev)
vdpa_pdev->dentry = NULL;
}
+static int
+identity_show(struct seq_file *seq, void *v)
+{
+ struct pds_vdpa_aux *vdpa_aux = seq->private;
+
+ seq_printf(seq, "aux_dev: %s\n",
+ dev_name(&vdpa_aux->padev->aux_dev.dev));
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(identity);
+
+void
+pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux)
+{
+ debugfs_create_file("identity", 0400, vdpa_aux->vdpa_vf->dentry,
+ vdpa_aux, &identity_fops);
+}
+
#endif /* CONFIG_DEBUG_FS */
@@ -12,11 +12,13 @@ void pds_vdpa_debugfs_create(void);
void pds_vdpa_debugfs_destroy(void);
void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_pci_device *vdpa_pdev);
void pds_vdpa_debugfs_del_pcidev(struct pds_vdpa_pci_device *vdpa_pdev);
+void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux);
#else
static inline void pds_vdpa_debugfs_create(void) { }
static inline void pds_vdpa_debugfs_destroy(void) { }
static inline void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_pci_device *vdpa_pdev) { }
static inline void pds_vdpa_debugfs_del_pcidev(struct pds_vdpa_pci_device *vdpa_pdev) { }
+static inline void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux) { }
#endif
#endif /* _PDS_VDPA_DEBUGFS_H_ */
@@ -6,11 +6,15 @@
#include <linux/aer.h>
#include <linux/types.h>
#include <linux/vdpa.h>
+#include <linux/auxiliary_bus.h>
#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
#include <linux/pds/pds_vdpa.h>
#include "pci_drv.h"
+#include "aux_drv.h"
#include "debugfs.h"
static void
@@ -118,9 +122,16 @@ pds_vdpa_pci_driver = {
.remove = pds_vdpa_pci_remove
};
+bool
+pds_vdpa_is_vdpa_pci_driver(struct pci_dev *pdev)
+{
+ return (to_pci_driver(pdev->dev.driver) == &pds_vdpa_pci_driver);
+}
+
static void __exit
pds_vdpa_pci_cleanup(void)
{
+ auxiliary_driver_unregister(pds_vdpa_aux_driver_info());
pci_unregister_driver(&pds_vdpa_pci_driver);
pds_vdpa_debugfs_destroy();
@@ -140,8 +151,16 @@ pds_vdpa_pci_init(void)
goto err_pci;
}
+ err = auxiliary_driver_register(pds_vdpa_aux_driver_info());
+ if (err) {
+ pr_err("%s: aux driver register failed: %pe\n", __func__, ERR_PTR(err));
+ goto err_aux;
+ }
+
return 0;
+err_aux:
+ pci_unregister_driver(&pds_vdpa_pci_driver);
err_pci:
pds_vdpa_debugfs_destroy();
return err;
@@ -43,6 +43,7 @@ struct pds_vdpa_pci_device {
struct virtio_pci_modern_device vd_mdev;
};
+bool pds_vdpa_is_vdpa_pci_driver(struct pci_dev *pdev);
int pds_vdpa_probe_virtio(struct virtio_pci_modern_device *mdev);
void pds_vdpa_remove_virtio(struct virtio_pci_modern_device *mdev);
#endif /* _PCI_DRV_H */
The auxiliary_bus driver is registered after the PCI driver is loaded, and when the pds_core has created a device for it, after the VF has been enabled, this driver gets probed. It then registers itself with the DSC through the pds_core in order to start the firmware services for this device. Signed-off-by: Shannon Nelson <snelson@pensando.io> --- drivers/vdpa/pds/Makefile | 3 +- drivers/vdpa/pds/aux_drv.c | 123 +++++++++++++++++++++++++++++++++++++ drivers/vdpa/pds/aux_drv.h | 28 +++++++++ drivers/vdpa/pds/debugfs.c | 23 +++++++ drivers/vdpa/pds/debugfs.h | 2 + drivers/vdpa/pds/pci_drv.c | 19 ++++++ drivers/vdpa/pds/pci_drv.h | 1 + 7 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 drivers/vdpa/pds/aux_drv.c create mode 100644 drivers/vdpa/pds/aux_drv.h