[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230219083908.40013-3-brett.creeley@amd.com>
Date: Sun, 19 Feb 2023 00:39:03 -0800
From: Brett Creeley <brett.creeley@....com>
To: <kvm@...r.kernel.org>, <netdev@...r.kernel.org>,
<alex.williamson@...hat.com>, <cohuck@...hat.com>,
<jgg@...dia.com>, <yishaih@...dia.com>,
<shameerali.kolothum.thodi@...wei.com>, <kevin.tian@...el.com>
CC: <shannon.nelson@....com>, <drivers@...sando.io>,
<brett.creeley@....com>
Subject: [PATCH v3 2/7] vfio/pds: Add support to register as PDS client
The pds_core driver will create auxiliary devices for each PCI device
supported by pds_vfio. In order to communicate with the device, the
pds_vfio driver needs to register as an auxiliary driver for the
previously mentioned auxiliary device. Once the auxiliary device
is probed, the pds_vfio driver can send admin queue commands and
receive events from the device by way of pds_core.
Use the following commands to enable a VF and tell pds_core to
create its corresponding auxiliary device:
echo 1 > /sys/bus/pci/drivers/pds_core/$PF_BDF/sriov_numvfs
devlink dev param set pci/$PF_BDF name enable_migration value true cmode runtime
This functionality is needed to support live migration commands, which
are added later in the series.
Signed-off-by: Brett Creeley <brett.creeley@....com>
Signed-off-by: Shannon Nelson <shannon.nelson@....com>
---
drivers/vfio/pci/pds/Makefile | 2 +
drivers/vfio/pci/pds/aux_drv.c | 148 ++++++++++++++++++++++++++++++++
drivers/vfio/pci/pds/aux_drv.h | 27 ++++++
drivers/vfio/pci/pds/cmds.c | 30 +++++++
drivers/vfio/pci/pds/cmds.h | 14 +++
drivers/vfio/pci/pds/pci_drv.c | 17 ++++
drivers/vfio/pci/pds/pci_drv.h | 14 +++
drivers/vfio/pci/pds/vfio_dev.c | 6 ++
drivers/vfio/pci/pds/vfio_dev.h | 1 +
include/linux/pds/pds_lm.h | 12 +++
10 files changed, 271 insertions(+)
create mode 100644 drivers/vfio/pci/pds/aux_drv.c
create mode 100644 drivers/vfio/pci/pds/aux_drv.h
create mode 100644 drivers/vfio/pci/pds/cmds.c
create mode 100644 drivers/vfio/pci/pds/cmds.h
create mode 100644 drivers/vfio/pci/pds/pci_drv.h
create mode 100644 include/linux/pds/pds_lm.h
diff --git a/drivers/vfio/pci/pds/Makefile b/drivers/vfio/pci/pds/Makefile
index e1a55ae0f079..92cc392fd487 100644
--- a/drivers/vfio/pci/pds/Makefile
+++ b/drivers/vfio/pci/pds/Makefile
@@ -4,5 +4,7 @@
obj-$(CONFIG_PDS_VFIO_PCI) += pds_vfio.o
pds_vfio-y := \
+ aux_drv.o \
+ cmds.o \
pci_drv.o \
vfio_dev.o
diff --git a/drivers/vfio/pci/pds/aux_drv.c b/drivers/vfio/pci/pds/aux_drv.c
new file mode 100644
index 000000000000..eda262e7d895
--- /dev/null
+++ b/drivers/vfio/pci/pds/aux_drv.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+#include <linux/pds/pds_lm.h>
+
+#include "aux_drv.h"
+#include "vfio_dev.h"
+#include "pci_drv.h"
+#include "cmds.h"
+
+static const
+struct auxiliary_device_id pds_vfio_aux_id_table[] = {
+ { .name = PDS_LM_DEV_NAME, },
+ {},
+};
+
+static void
+pds_vfio_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_dbg(dev, "%s: event code %d\n", __func__, ecode);
+}
+
+static int
+pds_vfio_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 pds_vfio_pci_device *pds_vfio;
+ struct device *dev = &aux_dev->dev;
+ struct pds_vfio_aux *vfio_aux;
+ struct pci_dev *pdev;
+ struct pci_bus *bus;
+ int busnr;
+ u16 devfn;
+ int err;
+
+ /* 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);
+
+ if (!pds_vfio_is_vfio_pci_driver(pdev)) {
+ dev_dbg(&aux_dev->dev, "unbind %s from %s driver and bind to %s driver for live migration support\n",
+ pci_name(pdev), dev_driver_string(&pdev->dev), PDS_VFIO_DRV_NAME);
+ return -EPROBE_DEFER;
+ }
+
+ pds_vfio = pci_get_drvdata(pdev);
+ if (!pds_vfio) {
+ dev_dbg(&pdev->dev, "PCI device not probed yet, defer until PCI device is probed by %s driver\n",
+ PDS_VFIO_DRV_NAME);
+ return -EPROBE_DEFER;
+ }
+
+ vfio_aux = kzalloc(sizeof(*vfio_aux), GFP_KERNEL);
+ if (!vfio_aux)
+ return -ENOMEM;
+
+ vfio_aux->padev = padev;
+ vfio_aux->pds_vfio = pds_vfio;
+ auxiliary_set_drvdata(aux_dev, vfio_aux);
+
+ dev_dbg(dev, "%s: id %#04x busnr %#x devfn %#x bus %p pds_vfio %p\n",
+ __func__, padev->id, busnr, devfn, bus, vfio_aux->pds_vfio);
+
+ vfio_aux->pds_vfio->vfio_aux = vfio_aux;
+
+ vfio_aux->padrv.event_handler = pds_vfio_aux_notify_handler;
+ err = pds_vfio_register_client_cmd(vfio_aux->pds_vfio);
+ if (err) {
+ dev_err(dev, "failed to register as client: %pe\n",
+ ERR_PTR(err));
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ auxiliary_set_drvdata(aux_dev, NULL);
+ kfree(vfio_aux);
+
+ return err;
+}
+
+static void
+pds_vfio_aux_remove(struct auxiliary_device *aux_dev)
+{
+ struct pds_vfio_aux *vfio_aux = auxiliary_get_drvdata(aux_dev);
+ struct pds_vfio_pci_device *pds_vfio = vfio_aux->pds_vfio;
+
+ if (pds_vfio) {
+ pds_vfio_unregister_client_cmd(pds_vfio);
+ vfio_aux->pds_vfio->vfio_aux = NULL;
+ pci_dev_put(pds_vfio->pdev);
+ }
+
+ kfree(vfio_aux);
+ auxiliary_set_drvdata(aux_dev, NULL);
+}
+
+static struct auxiliary_driver
+pds_vfio_aux_driver = {
+ .name = PDS_DEV_TYPE_LM_STR,
+ .probe = pds_vfio_aux_probe,
+ .remove = pds_vfio_aux_remove,
+ .id_table = pds_vfio_aux_id_table,
+};
+
+struct auxiliary_driver *
+pds_vfio_aux_driver_info(void)
+{
+ return &pds_vfio_aux_driver;
+}
+
+static int
+pds_vfio_aux_match_id(struct device *dev, const void *data)
+{
+ dev_dbg(dev, "%s: %s\n", __func__, (char *)data);
+ return !strcmp(dev_name(dev), data);
+}
+
+struct pds_vfio_aux *
+pds_vfio_aux_get_drvdata(int vf_pci_id)
+{
+ struct auxiliary_device *aux_dev;
+ char name[32];
+
+ snprintf(name, sizeof(name), "%s.%d", PDS_LM_DEV_NAME, vf_pci_id);
+ aux_dev = auxiliary_find_device(NULL, name, pds_vfio_aux_match_id);
+ if (!aux_dev)
+ return NULL;
+
+ return auxiliary_get_drvdata(aux_dev);
+}
diff --git a/drivers/vfio/pci/pds/aux_drv.h b/drivers/vfio/pci/pds/aux_drv.h
new file mode 100644
index 000000000000..be5948575a0c
--- /dev/null
+++ b/drivers/vfio/pci/pds/aux_drv.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
+
+#ifndef _AUX_DRV_H_
+#define _AUX_DRV_H_
+
+#include <linux/auxiliary_bus.h>
+
+#include <linux/pds/pds_intr.h>
+#include <linux/pds/pds_common.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+struct pds_vfio_pci_device;
+
+struct pds_vfio_aux {
+ struct pds_auxiliary_dev *padev;
+ struct pds_auxiliary_drv padrv;
+ struct pds_vfio_pci_device *pds_vfio;
+};
+
+struct auxiliary_driver *
+pds_vfio_aux_driver_info(void);
+struct pds_vfio_aux *
+pds_vfio_aux_get_drvdata(int vf_pci_id);
+
+#endif /* _AUX_DRV_H_ */
diff --git a/drivers/vfio/pci/pds/cmds.c b/drivers/vfio/pci/pds/cmds.c
new file mode 100644
index 000000000000..6ac39703cb54
--- /dev/null
+++ b/drivers/vfio/pci/pds/cmds.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+#include <linux/pds/pds_core_if.h>
+#include <linux/pds/pds_adminq.h>
+#include <linux/pds/pds_auxbus.h>
+
+#include "vfio_dev.h"
+#include "aux_drv.h"
+#include "cmds.h"
+
+int
+pds_vfio_register_client_cmd(struct pds_vfio_pci_device *pds_vfio)
+{
+ struct pds_vfio_aux *vfio_aux = pds_vfio->vfio_aux;
+ struct pds_auxiliary_dev *padev = vfio_aux->padev;
+
+ return padev->ops->register_client(padev, &vfio_aux->padrv);
+}
+
+void
+pds_vfio_unregister_client_cmd(struct pds_vfio_pci_device *pds_vfio)
+{
+ struct pds_auxiliary_dev *padev = pds_vfio->vfio_aux->padev;
+
+ padev->ops->unregister_client(padev);
+}
diff --git a/drivers/vfio/pci/pds/cmds.h b/drivers/vfio/pci/pds/cmds.h
new file mode 100644
index 000000000000..eb39a3ad5089
--- /dev/null
+++ b/drivers/vfio/pci/pds/cmds.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
+
+#ifndef _CMDS_H_
+#define _CMDS_H_
+
+struct pds_vfio_pci_device;
+
+int
+pds_vfio_register_client_cmd(struct pds_vfio_pci_device *pds_vfio);
+void
+pds_vfio_unregister_client_cmd(struct pds_vfio_pci_device *pds_vfio);
+
+#endif /* _CMDS_H_ */
diff --git a/drivers/vfio/pci/pds/pci_drv.c b/drivers/vfio/pci/pds/pci_drv.c
index 96e155598a50..3861a80c4706 100644
--- a/drivers/vfio/pci/pds/pci_drv.c
+++ b/drivers/vfio/pci/pds/pci_drv.c
@@ -11,6 +11,8 @@
#include <linux/pds/pds_core_if.h>
#include "vfio_dev.h"
+#include "aux_drv.h"
+#include "pci_drv.h"
#define PDS_VFIO_DRV_NAME "pds_vfio"
#define PDS_VFIO_DRV_DESCRIPTION "AMD/Pensando VFIO Device Driver"
@@ -67,9 +69,17 @@ pds_vfio_pci_driver = {
.driver_managed_dma = true,
};
+bool
+pds_vfio_is_vfio_pci_driver(struct pci_dev *pdev)
+{
+ return (to_pci_driver(pdev->dev.driver) == &pds_vfio_pci_driver);
+}
+
static void __exit
pds_vfio_pci_cleanup(void)
{
+ auxiliary_driver_unregister(pds_vfio_aux_driver_info());
+
pci_unregister_driver(&pds_vfio_pci_driver);
}
module_exit(pds_vfio_pci_cleanup);
@@ -85,6 +95,13 @@ pds_vfio_pci_init(void)
return err;
}
+ err = auxiliary_driver_register(pds_vfio_aux_driver_info());
+ if (err) {
+ pr_err("aux driver register failed: %pe\n", ERR_PTR(err));
+ pci_unregister_driver(&pds_vfio_pci_driver);
+ return err;
+ }
+
return 0;
}
module_init(pds_vfio_pci_init);
diff --git a/drivers/vfio/pci/pds/pci_drv.h b/drivers/vfio/pci/pds/pci_drv.h
new file mode 100644
index 000000000000..3394715bfe7b
--- /dev/null
+++ b/drivers/vfio/pci/pds/pci_drv.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
+
+#ifndef _PCI_DRV_H
+#define _PCI_DRV_H
+
+#include <linux/pci.h>
+
+#define PDS_VFIO_DRV_NAME "pds_vfio"
+
+bool
+pds_vfio_is_vfio_pci_driver(struct pci_dev *pdev);
+
+#endif /* _PCI_DRV_H */
diff --git a/drivers/vfio/pci/pds/vfio_dev.c b/drivers/vfio/pci/pds/vfio_dev.c
index f1221f14e4f6..e882276f9788 100644
--- a/drivers/vfio/pci/pds/vfio_dev.c
+++ b/drivers/vfio/pci/pds/vfio_dev.c
@@ -5,6 +5,7 @@
#include <linux/vfio_pci_core.h>
#include "vfio_dev.h"
+#include "aux_drv.h"
struct pds_vfio_pci_device *
pds_vfio_pci_drvdata(struct pci_dev *pdev)
@@ -31,6 +32,11 @@ pds_vfio_init_device(struct vfio_device *vdev)
pds_vfio->vf_id = pci_iov_vf_id(pdev);
pds_vfio->pci_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ dev_dbg(&pdev->dev, "%s: PF %#04x VF %#04x (%d) vf_id %d domain %d pds_vfio %p\n",
+ __func__, pci_dev_id(pdev->physfn),
+ pds_vfio->pci_id, pds_vfio->pci_id, pds_vfio->vf_id,
+ pci_domain_nr(pdev->bus), pds_vfio);
+
return 0;
}
diff --git a/drivers/vfio/pci/pds/vfio_dev.h b/drivers/vfio/pci/pds/vfio_dev.h
index 4d497695c4e9..48083002d1ad 100644
--- a/drivers/vfio/pci/pds/vfio_dev.h
+++ b/drivers/vfio/pci/pds/vfio_dev.h
@@ -10,6 +10,7 @@
struct pds_vfio_pci_device {
struct vfio_pci_core_device vfio_coredev;
struct pci_dev *pdev;
+ struct pds_vfio_aux *vfio_aux;
int vf_id;
int pci_id;
diff --git a/include/linux/pds/pds_lm.h b/include/linux/pds/pds_lm.h
new file mode 100644
index 000000000000..fdaf2bf71d35
--- /dev/null
+++ b/include/linux/pds/pds_lm.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2022 Pensando Systems, Inc */
+
+#ifndef _PDS_LM_H_
+#define _PDS_LM_H_
+
+#include "pds_common.h"
+
+#define PDS_DEV_TYPE_LM_STR "LM"
+#define PDS_LM_DEV_NAME PDS_CORE_DRV_NAME "." PDS_DEV_TYPE_LM_STR
+
+#endif /* _PDS_LM_H_ */
--
2.17.1
Powered by blists - more mailing lists