Route all VFIO_DEVICE_RESET ioctl calls through a new device_reset
io_ops callback, matching the pattern established for region_map and
region_unmap. This allows non-Linux backends to provide their own
reset implementation.
The Linux ioctl backend implements the callback by issuing the
VFIO_DEVICE_RESET ioctl. All existing callsites in pci.c, ccw.c,
ap.c, and migration.c are converted to use the callback.
Signed-off-by: Scott J. Goldman <scottjgo@gmail.com>
---
hw/vfio/ap.c | 4 ++--
hw/vfio/ccw.c | 2 +-
hw/vfio/device.c | 8 ++++++++
hw/vfio/migration.c | 5 +++--
hw/vfio/pci.c | 6 ++++--
include/hw/vfio/vfio-device.h | 11 +++++++++++
6 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 5c8f305653..2f2f17e666 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -290,10 +290,10 @@ static void vfio_ap_reset(DeviceState *dev)
int ret;
VFIOAPDevice *vapdev = VFIO_AP_DEVICE(dev);
- ret = ioctl(vapdev->vdev.fd, VFIO_DEVICE_RESET);
+ ret = vapdev->vdev.io_ops->device_reset(&vapdev->vdev);
if (ret) {
error_report("%s: failed to reset %s device: %s", __func__,
- vapdev->vdev.name, strerror(errno));
+ vapdev->vdev.name, strerror(-ret));
}
}
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index ce9c014e6a..330b733b7e 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -242,7 +242,7 @@ static void vfio_ccw_reset(DeviceState *dev)
{
VFIOCCWDevice *vcdev = VFIO_CCW(dev);
- ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
+ vcdev->vdev.io_ops->device_reset(&vcdev->vdev);
}
static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev)
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 1b703dcbec..cf3953d975 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -657,6 +657,13 @@ static int vfio_device_io_region_write(VFIODevice *vbasedev, uint8_t index,
return ret < 0 ? -errno : ret;
}
+static int vfio_device_io_device_reset(VFIODevice *vbasedev)
+{
+ int ret = ioctl(vbasedev->fd, VFIO_DEVICE_RESET);
+
+ return ret < 0 ? -errno : ret;
+}
+
static int vfio_device_io_region_map(VFIODevice *vbasedev, VFIORegion *region)
{
return vfio_region_mmap_fd(region);
@@ -673,6 +680,7 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl = {
.get_region_info = vfio_device_io_get_region_info,
.get_irq_info = vfio_device_io_get_irq_info,
.set_irqs = vfio_device_io_set_irqs,
+ .device_reset = vfio_device_io_device_reset,
.region_read = vfio_device_io_region_read,
.region_write = vfio_device_io_region_write,
.region_map = vfio_device_io_region_map,
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 83327b6573..b31253ea90 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -216,9 +216,10 @@ int vfio_migration_set_state(VFIODevice *vbasedev,
return 0;
reset_device:
- if (ioctl(vbasedev->fd, VFIO_DEVICE_RESET)) {
+ ret = vbasedev->io_ops->device_reset(vbasedev);
+ if (ret) {
hw_error("%s: Failed resetting device, err: %s", vbasedev->name,
- strerror(errno));
+ strerror(-ret));
}
vfio_migration_set_device_state(vbasedev, VFIO_DEVICE_STATE_RUNNING);
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index cf817d9ae7..458b3400cc 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3691,7 +3691,8 @@ static void vfio_pci_reset(DeviceState *dev)
if (vdev->vbasedev.reset_works &&
(vdev->has_flr || !vdev->has_pm_reset) &&
- !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
+ vdev->vbasedev.io_ops && vdev->vbasedev.io_ops->device_reset &&
+ !vdev->vbasedev.io_ops->device_reset(&vdev->vbasedev)) {
trace_vfio_pci_reset_flr(vdev->vbasedev.name);
goto post_reset;
}
@@ -3703,7 +3704,8 @@ static void vfio_pci_reset(DeviceState *dev)
/* If nothing else works and the device supports PM reset, use it */
if (vdev->vbasedev.reset_works && vdev->has_pm_reset &&
- !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
+ vdev->vbasedev.io_ops && vdev->vbasedev.io_ops->device_reset &&
+ !vdev->vbasedev.io_ops->device_reset(&vdev->vbasedev)) {
trace_vfio_pci_reset_pm(vdev->vbasedev.name);
goto post_reset;
}
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 1a3b42bcaf..0e6bff774e 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -262,6 +262,17 @@ struct VFIODeviceIOOps {
int (*region_write)(VFIODevice *vdev, uint8_t nr, off_t off, uint32_t size,
void *data, bool post);
+ /**
+ * @device_reset
+ *
+ * Reset the device.
+ *
+ * @vdev: #VFIODevice to reset
+ *
+ * Returns 0 on success or -errno.
+ */
+ int (*device_reset)(VFIODevice *vdev);
+
/**
* @region_map
*
--
2.50.1 (Apple Git-155)