2022-06-21 12:00:17

by Stephan Gerhold

[permalink] [raw]
Subject: [PATCH 0/2] virtio_mmio: Fix suspend to disk (hibernation)

At the moment suspend to disk (hibernation) works correctly when using
virtio_pci, but not when using virtio_mmio. This is because virtio_mmio
does not call the freeze/restore callbacks provided by most virtio
drivers.

Fix this by adding the missing PM calls to virtio_mmio and restore
the guest page size for the legacy version of virtio_mmio.

Stephan Gerhold (2):
virtio_mmio: Add missing PM calls to freeze/restore
virtio_mmio: Restore guest page size on resume

drivers/virtio/virtio_mmio.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

--
2.30.2


2022-06-21 12:01:48

by Stephan Gerhold

[permalink] [raw]
Subject: [PATCH 1/2] virtio_mmio: Add missing PM calls to freeze/restore

Most virtio drivers provide freeze/restore callbacks to finish up
device usage before suspend and to reinitialize the virtio device after
resume. However, these callbacks are currently only called when using
virtio_pci. virtio_mmio does not have any PM ops defined.

This causes problems for example after suspend to disk (hibernation),
since the virtio devices might lose their state after the VMM is
restarted. Calling virtio_device_freeze()/restore() ensures that
the virtio devices are re-initialized correctly.

Fix this by implementing the dev_pm_ops for virtio_mmio,
similar to virtio_pci_common.

Signed-off-by: Stephan Gerhold <[email protected]>
---
drivers/virtio/virtio_mmio.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index c9bec3813e94..980dffd69586 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -62,6 +62,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/virtio.h>
@@ -556,6 +557,25 @@ static const struct virtio_config_ops virtio_mmio_config_ops = {
.synchronize_cbs = vm_synchronize_cbs,
};

+#ifdef CONFIG_PM_SLEEP
+static int virtio_mmio_freeze(struct device *dev)
+{
+ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+ return virtio_device_freeze(&vm_dev->vdev);
+}
+
+static int virtio_mmio_restore(struct device *dev)
+{
+ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+ return virtio_device_restore(&vm_dev->vdev);
+}
+
+static const struct dev_pm_ops virtio_mmio_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
+};
+#endif

static void virtio_mmio_release_dev(struct device *_d)
{
@@ -799,6 +819,9 @@ static struct platform_driver virtio_mmio_driver = {
.name = "virtio-mmio",
.of_match_table = virtio_mmio_match,
.acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
+#ifdef CONFIG_PM_SLEEP
+ .pm = &virtio_mmio_pm_ops,
+#endif
},
};

--
2.30.2