If a device is part of a PM Domain (e.g. power and/or clock domain), its power state is managed using Runtime PM. Without Runtime PM, the device may not be powered up, causing subtle failures, crashes, or system lock-ups when the device is accessed by the guest. Fix this by adding Runtime PM support, powering the device when the VFIO device is opened by the guest. Note that while more fine-grained power management could be implemented on the guest side, if exported, this would be inherently unsafe, as abusing it may kill the whole system. Signed-off-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx> --- This depends on "[PATCH v3 2/2] vfio: platform: Add generic DT reset support" due to a small contextual change (addition of "#include <linux/reset.h>"). drivers/vfio/platform/vfio_platform_common.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index ef9b9e3220ebe939..4db0a143992c3353 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -17,6 +17,7 @@ #include <linux/iommu.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/slab.h> #include <linux/types.h> @@ -249,6 +250,8 @@ static void vfio_platform_release(void *device_data) const char *extra_dbg = NULL; int ret; + pm_runtime_put(vdev->device); + ret = vfio_platform_call_reset(vdev, &extra_dbg); if (ret && vdev->reset_required) { dev_warn(vdev->device, "reset driver is required and reset call failed in release (%d) %s\n", @@ -291,6 +294,10 @@ static int vfio_platform_open(void *device_data) ret, extra_dbg ? extra_dbg : ""); goto err_rst; } + + ret = pm_runtime_get_sync(vdev->device); + if (ret < 0) + goto err_rst; } vdev->refcnt++; @@ -706,6 +713,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, mutex_init(&vdev->igate); + pm_runtime_enable(vdev->device); return 0; put_iommu: @@ -723,6 +731,7 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev) vdev = vfio_del_group_dev(dev); if (vdev) { + pm_runtime_disable(vdev->device); vfio_platform_put_reset(vdev); vfio_iommu_group_put(dev->iommu_group, dev); } -- 2.7.4