[RFC PATCH 06/10] vfio: Add device_reset callback to VFIODeviceIOOps

Scott J. Goldman posted 10 patches 6 days, 11 hours ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, John Levon <john.levon@nutanix.com>, Thanos Makatos <thanos.makatos@nutanix.com>, "Cédric Le Goater" <clg@redhat.com>, Alex Williamson <alex@shazbot.org>, Tony Krowiak <akrowiak@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Jason Herne <jjherne@linux.ibm.com>, Cornelia Huck <cohuck@redhat.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, "Scott J. Goldman" <scottjgo@gmail.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>
[RFC PATCH 06/10] vfio: Add device_reset callback to VFIODeviceIOOps
Posted by Scott J. Goldman 6 days, 11 hours ago
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)