mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 18:36:00 +00:00
cdd30ebb1b
Clean up the existing export namespace code along the same lines of commit 33def8498fdd ("treewide: Convert macro and uses of __section(foo) to __section("foo")") and for the same reason, it is not desired for the namespace argument to be a macro expansion itself. Scripted using git grep -l -e MODULE_IMPORT_NS -e EXPORT_SYMBOL_NS | while read file; do awk -i inplace ' /^#define EXPORT_SYMBOL_NS/ { gsub(/__stringify\(ns\)/, "ns"); print; next; } /^#define MODULE_IMPORT_NS/ { gsub(/__stringify\(ns\)/, "ns"); print; next; } /MODULE_IMPORT_NS/ { $0 = gensub(/MODULE_IMPORT_NS\(([^)]*)\)/, "MODULE_IMPORT_NS(\"\\1\")", "g"); } /EXPORT_SYMBOL_NS/ { if ($0 ~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+),/) { if ($0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/ && $0 !~ /(EXPORT_SYMBOL_NS[^(]*)\(\)/ && $0 !~ /^my/) { getline line; gsub(/[[:space:]]*\\$/, ""); gsub(/[[:space:]]/, "", line); $0 = $0 " " line; } $0 = gensub(/(EXPORT_SYMBOL_NS[^(]*)\(([^,]+), ([^)]+)\)/, "\\1(\\2, \"\\3\")", "g"); } } { print }' $file; done Requested-by: Masahiro Yamada <masahiroy@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://mail.google.com/mail/u/2/#inbox/FMfcgzQXKWgMmjdFwwdsfgxzKpVHWPlc Acked-by: Greg KH <gregkh@linuxfoundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
194 lines
5.5 KiB
C
194 lines
5.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/types.h>
|
|
#include <linux/vfio.h>
|
|
|
|
#include <linux/pds/pds_common.h>
|
|
#include <linux/pds/pds_core_if.h>
|
|
#include <linux/pds/pds_adminq.h>
|
|
|
|
#include "vfio_dev.h"
|
|
#include "pci_drv.h"
|
|
#include "cmds.h"
|
|
|
|
#define PDS_VFIO_DRV_DESCRIPTION "AMD/Pensando VFIO Device Driver"
|
|
#define PCI_VENDOR_ID_PENSANDO 0x1dd8
|
|
|
|
static void pds_vfio_recovery(struct pds_vfio_pci_device *pds_vfio)
|
|
{
|
|
/*
|
|
* Documentation states that the kernel migration driver must not
|
|
* generate asynchronous device state transitions outside of
|
|
* manipulation by the user or the VFIO_DEVICE_RESET ioctl.
|
|
*
|
|
* Since recovery is an asynchronous event received from the device,
|
|
* initiate a reset in the following situations:
|
|
* 1. Migration is in progress, which will cause the next step of
|
|
* the migration to fail.
|
|
* 2. If the device is in a state that will be set to
|
|
* VFIO_DEVICE_STATE_RUNNING on the next action (i.e. VM is
|
|
* shutdown and device is in VFIO_DEVICE_STATE_STOP).
|
|
*/
|
|
mutex_lock(&pds_vfio->state_mutex);
|
|
if ((pds_vfio->state != VFIO_DEVICE_STATE_RUNNING &&
|
|
pds_vfio->state != VFIO_DEVICE_STATE_ERROR) ||
|
|
(pds_vfio->state == VFIO_DEVICE_STATE_RUNNING &&
|
|
pds_vfio_dirty_is_enabled(pds_vfio)))
|
|
pds_vfio_reset(pds_vfio, VFIO_DEVICE_STATE_ERROR);
|
|
mutex_unlock(&pds_vfio->state_mutex);
|
|
}
|
|
|
|
static int pds_vfio_pci_notify_handler(struct notifier_block *nb,
|
|
unsigned long ecode, void *data)
|
|
{
|
|
struct pds_vfio_pci_device *pds_vfio =
|
|
container_of(nb, struct pds_vfio_pci_device, nb);
|
|
struct device *dev = pds_vfio_to_dev(pds_vfio);
|
|
union pds_core_notifyq_comp *event = data;
|
|
|
|
dev_dbg(dev, "%s: event code %lu\n", __func__, ecode);
|
|
|
|
/*
|
|
* We don't need to do anything for RESET state==0 as there is no notify
|
|
* or feedback mechanism available, and it is possible that we won't
|
|
* even see a state==0 event since the pds_core recovery is pending.
|
|
*
|
|
* Any requests from VFIO while state==0 will fail, which will return
|
|
* error and may cause migration to fail.
|
|
*/
|
|
if (ecode == PDS_EVENT_RESET) {
|
|
dev_info(dev, "%s: PDS_EVENT_RESET event received, state==%d\n",
|
|
__func__, event->reset.state);
|
|
/*
|
|
* pds_core device finished recovery and sent us the
|
|
* notification (state == 1) to allow us to recover
|
|
*/
|
|
if (event->reset.state == 1)
|
|
pds_vfio_recovery(pds_vfio);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
pds_vfio_pci_register_event_handler(struct pds_vfio_pci_device *pds_vfio)
|
|
{
|
|
struct device *dev = pds_vfio_to_dev(pds_vfio);
|
|
struct notifier_block *nb = &pds_vfio->nb;
|
|
int err;
|
|
|
|
if (!nb->notifier_call) {
|
|
nb->notifier_call = pds_vfio_pci_notify_handler;
|
|
err = pdsc_register_notify(nb);
|
|
if (err) {
|
|
nb->notifier_call = NULL;
|
|
dev_err(dev,
|
|
"failed to register pds event handler: %pe\n",
|
|
ERR_PTR(err));
|
|
return -EINVAL;
|
|
}
|
|
dev_dbg(dev, "pds event handler registered\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
pds_vfio_pci_unregister_event_handler(struct pds_vfio_pci_device *pds_vfio)
|
|
{
|
|
if (pds_vfio->nb.notifier_call) {
|
|
pdsc_unregister_notify(&pds_vfio->nb);
|
|
pds_vfio->nb.notifier_call = NULL;
|
|
}
|
|
}
|
|
|
|
static int pds_vfio_pci_probe(struct pci_dev *pdev,
|
|
const struct pci_device_id *id)
|
|
{
|
|
struct pds_vfio_pci_device *pds_vfio;
|
|
int err;
|
|
|
|
pds_vfio = vfio_alloc_device(pds_vfio_pci_device, vfio_coredev.vdev,
|
|
&pdev->dev, pds_vfio_ops_info());
|
|
if (IS_ERR(pds_vfio))
|
|
return PTR_ERR(pds_vfio);
|
|
|
|
dev_set_drvdata(&pdev->dev, &pds_vfio->vfio_coredev);
|
|
|
|
err = vfio_pci_core_register_device(&pds_vfio->vfio_coredev);
|
|
if (err)
|
|
goto out_put_vdev;
|
|
|
|
err = pds_vfio_register_client_cmd(pds_vfio);
|
|
if (err) {
|
|
dev_err(&pdev->dev, "failed to register as client: %pe\n",
|
|
ERR_PTR(err));
|
|
goto out_unregister_coredev;
|
|
}
|
|
|
|
err = pds_vfio_pci_register_event_handler(pds_vfio);
|
|
if (err)
|
|
goto out_unregister_client;
|
|
|
|
return 0;
|
|
|
|
out_unregister_client:
|
|
pds_vfio_unregister_client_cmd(pds_vfio);
|
|
out_unregister_coredev:
|
|
vfio_pci_core_unregister_device(&pds_vfio->vfio_coredev);
|
|
out_put_vdev:
|
|
vfio_put_device(&pds_vfio->vfio_coredev.vdev);
|
|
return err;
|
|
}
|
|
|
|
static void pds_vfio_pci_remove(struct pci_dev *pdev)
|
|
{
|
|
struct pds_vfio_pci_device *pds_vfio = pds_vfio_pci_drvdata(pdev);
|
|
|
|
pds_vfio_pci_unregister_event_handler(pds_vfio);
|
|
pds_vfio_unregister_client_cmd(pds_vfio);
|
|
vfio_pci_core_unregister_device(&pds_vfio->vfio_coredev);
|
|
vfio_put_device(&pds_vfio->vfio_coredev.vdev);
|
|
}
|
|
|
|
static const struct pci_device_id pds_vfio_pci_table[] = {
|
|
{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_PENSANDO, 0x1003) }, /* Ethernet VF */
|
|
{ 0, }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, pds_vfio_pci_table);
|
|
|
|
static void pds_vfio_pci_aer_reset_done(struct pci_dev *pdev)
|
|
{
|
|
struct pds_vfio_pci_device *pds_vfio = pds_vfio_pci_drvdata(pdev);
|
|
|
|
mutex_lock(&pds_vfio->state_mutex);
|
|
pds_vfio_reset(pds_vfio, VFIO_DEVICE_STATE_RUNNING);
|
|
mutex_unlock(&pds_vfio->state_mutex);
|
|
}
|
|
|
|
static const struct pci_error_handlers pds_vfio_pci_err_handlers = {
|
|
.reset_done = pds_vfio_pci_aer_reset_done,
|
|
.error_detected = vfio_pci_core_aer_err_detected,
|
|
};
|
|
|
|
static struct pci_driver pds_vfio_pci_driver = {
|
|
.name = KBUILD_MODNAME,
|
|
.id_table = pds_vfio_pci_table,
|
|
.probe = pds_vfio_pci_probe,
|
|
.remove = pds_vfio_pci_remove,
|
|
.err_handler = &pds_vfio_pci_err_handlers,
|
|
.driver_managed_dma = true,
|
|
};
|
|
|
|
module_pci_driver(pds_vfio_pci_driver);
|
|
|
|
MODULE_IMPORT_NS("IOMMUFD");
|
|
MODULE_DESCRIPTION(PDS_VFIO_DRV_DESCRIPTION);
|
|
MODULE_AUTHOR("Brett Creeley <brett.creeley@amd.com>");
|
|
MODULE_LICENSE("GPL");
|