]> git.karo-electronics.de Git - linux-beck.git/commitdiff
vfio, platform: make reset driver a requirement by default
authorSinan Kaya <okaya@codeaurora.org>
Tue, 19 Jul 2016 13:01:47 +0000 (09:01 -0400)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 19 Jul 2016 16:26:46 +0000 (10:26 -0600)
The code was allowing platform devices to be used without a supporting
VFIO reset driver. The hardware can be left in some inconsistent state
after a guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Adding a new reset_required kernel module option to platform VFIO drivers.
The default value is true for the DT and ACPI based drivers.
The reset requirement value for AMBA drivers is set to false and is
unchangeable to maintain the existing functionality.

New requirements are:
1. A reset function needs to be implemented by the corresponding driver
via DT/ACPI.
2. The reset function needs to be discovered via DT/ACPI.

The probe of the driver will fail if any of the above conditions are
not satisfied.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/platform/vfio_amba.c
drivers/vfio/platform/vfio_platform.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/platform/vfio_platform_private.h

index a66479bd0edf968c8209b384264052f79a6ec272..31372fbf6c5bab9edb4de52b62d662ec8e3cc2d1 100644 (file)
@@ -68,6 +68,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
        vdev->get_resource = get_amba_resource;
        vdev->get_irq = get_amba_irq;
        vdev->parent_module = THIS_MODULE;
+       vdev->reset_required = false;
 
        ret = vfio_platform_probe_common(vdev, &adev->dev);
        if (ret) {
index b1cc3a768784426fbf7616316aa9731f21b77ddb..6561751a1063ee291ffa7a7c6bb58e2caef56e2b 100644 (file)
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0444);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the linux platform bus */
 
 static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
@@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
        vdev->get_resource = get_platform_resource;
        vdev->get_irq = get_platform_irq;
        vdev->parent_module = THIS_MODULE;
+       vdev->reset_required = reset_required;
 
        ret = vfio_platform_probe_common(vdev, &pdev->dev);
        if (ret)
index a15a69b5208039b0f69f7a09b1c60b15e7e84d72..d8755d2c60538f2888357090f2232bf3cc335af9 100644 (file)
@@ -115,10 +115,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
        return vdev->of_reset ? true : false;
 }
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
        if (VFIO_PLATFORM_IS_ACPI(vdev))
-               return;
+               return vfio_platform_acpi_has_reset(vdev) ? 0 : -ENOENT;
 
        vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
                                                    &vdev->reset_module);
@@ -127,6 +127,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
                vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
                                                        &vdev->reset_module);
        }
+
+       return vdev->of_reset ? 0 : -ENOENT;
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
@@ -667,6 +669,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 
        vdev->device = dev;
 
+       ret = vfio_platform_get_reset(vdev);
+       if (ret && vdev->reset_required) {
+               pr_err("vfio: no reset function found for device %s\n",
+                      vdev->name);
+               return ret;
+       }
+
        group = vfio_iommu_group_get(dev);
        if (!group) {
                pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
@@ -679,8 +688,6 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
                return ret;
        }
 
-       vfio_platform_get_reset(vdev);
-
        mutex_init(&vdev->igate);
 
        return 0;
index ba9e4f8b074608b50a881edbc5805ea1488da73e..85ffe5d9d1abd94e851a456301c4253935767c6e 100644 (file)
@@ -73,6 +73,8 @@ struct vfio_platform_device {
                (*get_resource)(struct vfio_platform_device *vdev, int i);
        int     (*get_irq)(struct vfio_platform_device *vdev, int i);
        int     (*of_reset)(struct vfio_platform_device *vdev);
+
+       bool                            reset_required;
 };
 
 typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);