Hello, Turns out S3 is not different from S4 for virtio devices: the device is assumed to be reset, so the host and guest state are to be assumed to be out of sync upon resume. We handle the S4 case with exactly the same scenario, so just point the suspend/resume routines to the freeze/restore ones. Once that is done, we also use the PM API's macro to initialise the sleep functions. A couple of cleanups are included: there's no need for special thaw processing in the balloon driver, so that's addressed in patches 1 and 2. Testing: both S3 and S4 support have been tested using these patches using a similar method used earlier during S4 patch development: a guest is started with virtio-blk as the only disk, a virtio network card, a virtio-serial port and a virtio balloon device. Ping from guest to host, dd /dev/zero to a file on the disk, and IO from the host on the virtio-serial port, all at once, while exercising S4 and S3 (separately) were tested. They all continue to work fine after resume. virtio balloon values too were tested by inflating and deflating the balloon. Please review and apply, Thanks, Amit Shah (5): virtio: balloon: Allow stats update after restore from S4 virtio: drop thaw PM operation virtio-pci: drop restore_common() virtio-pci: S3 support virtio-pci: switch to PM ops macro to initialise PM functions drivers/virtio/virtio_balloon.c | 14 ------- drivers/virtio/virtio_pci.c | 74 ++++---------------------------------- include/linux/virtio.h | 1 - 3 files changed, 8 insertions(+), 81 deletions(-) -- 1.7.7.6
Amit Shah
2012-Mar-29 08:28 UTC
[PATCH 1/5] virtio: balloon: Allow stats update after restore from S4
There's no reason stats update after restore can't work. If a host requested for stats, and before servicing the request, the guest entered S4, upon restore, the stats request can still be processed and sent off to the host. Signed-off-by: Amit Shah <amit.shah at redhat.com> --- drivers/virtio/virtio_balloon.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 958e512..9f1bb36 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -405,14 +405,6 @@ static int virtballoon_thaw(struct virtio_device *vdev) static int virtballoon_restore(struct virtio_device *vdev) { - struct virtio_balloon *vb = vdev->priv; - - /* - * If a request wasn't complete at the time of freezing, this - * could have been set. - */ - vb->need_stats_update = 0; - return restore_common(vdev); } #endif -- 1.7.7.6
The thaw operation was used by the balloon driver, but after the last commit there's no reason to have separate thaw and restore callbacks. Signed-off-by: Amit Shah <amit.shah at redhat.com> --- drivers/virtio/virtio_balloon.c | 6 ------ drivers/virtio/virtio_pci.c | 28 +--------------------------- include/linux/virtio.h | 1 - 3 files changed, 1 insertions(+), 34 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 9f1bb36..05f0a80 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -398,11 +398,6 @@ static int restore_common(struct virtio_device *vdev) return 0; } -static int virtballoon_thaw(struct virtio_device *vdev) -{ - return restore_common(vdev); -} - static int virtballoon_restore(struct virtio_device *vdev) { return restore_common(vdev); @@ -426,7 +421,6 @@ static struct virtio_driver virtio_balloon_driver = { #ifdef CONFIG_PM .freeze = virtballoon_freeze, .restore = virtballoon_restore, - .thaw = virtballoon_thaw, #endif }; diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 635e1ef..a35a402 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -773,32 +773,6 @@ static int restore_common(struct device *dev) return ret; } -static int virtio_pci_thaw(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct virtio_driver *drv; - int ret; - - ret = restore_common(dev); - if (ret) - return ret; - - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); - - if (drv && drv->thaw) - ret = drv->thaw(&vp_dev->vdev); - else if (drv && drv->restore) - ret = drv->restore(&vp_dev->vdev); - - /* Finally, tell the device we're all set */ - if (!ret) - vp_set_status(&vp_dev->vdev, vp_dev->saved_status); - - return ret; -} - static int virtio_pci_restore(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -824,7 +798,7 @@ static const struct dev_pm_ops virtio_pci_pm_ops = { .suspend = virtio_pci_suspend, .resume = virtio_pci_resume, .freeze = virtio_pci_freeze, - .thaw = virtio_pci_thaw, + .thaw = virtio_pci_restore, .restore = virtio_pci_restore, .poweroff = virtio_pci_suspend, }; diff --git a/include/linux/virtio.h b/include/linux/virtio.h index d0018d2..8efd28a 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -96,7 +96,6 @@ struct virtio_driver { void (*config_changed)(struct virtio_device *dev); #ifdef CONFIG_PM int (*freeze)(struct virtio_device *dev); - int (*thaw)(struct virtio_device *dev); int (*restore)(struct virtio_device *dev); #endif }; -- 1.7.7.6
restore_common() was shared between restore and thaw callbacks. With thaw gone, we don't need restore_common() anymore. Signed-off-by: Amit Shah <amit.shah at redhat.com> --- drivers/virtio/virtio_pci.c | 23 +++++++---------------- 1 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index a35a402..982d6c9 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -758,33 +758,24 @@ static int virtio_pci_freeze(struct device *dev) return ret; } -static int restore_common(struct device *dev) +static int virtio_pci_restore(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + struct virtio_driver *drv; int ret; + drv = container_of(vp_dev->vdev.dev.driver, + struct virtio_driver, driver); + ret = pci_enable_device(pci_dev); if (ret) return ret; + pci_set_master(pci_dev); vp_finalize_features(&vp_dev->vdev); - return ret; -} - -static int virtio_pci_restore(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct virtio_driver *drv; - int ret; - - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); - - ret = restore_common(dev); - if (!ret && drv && drv->restore) + if (drv && drv->restore) ret = drv->restore(&vp_dev->vdev); /* Finally, tell the device we're all set */ -- 1.7.7.6
There's no difference in supporting S3 and S4 for virtio devices: the vqs have to be re-created as the device has to be assumed to be reset at restore-time. Since S4 already handles this situation, we can directly use the same code and callbacks for S3 support. Signed-off-by: Amit Shah <amit.shah at redhat.com> --- drivers/virtio/virtio_pci.c | 24 +++--------------------- 1 files changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 982d6c9..0fa4f85 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -720,24 +720,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) } #ifdef CONFIG_PM -static int virtio_pci_suspend(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - - pci_save_state(pci_dev); - pci_set_power_state(pci_dev, PCI_D3hot); - return 0; -} - -static int virtio_pci_resume(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - - pci_restore_state(pci_dev); - pci_set_power_state(pci_dev, PCI_D0); - return 0; -} - static int virtio_pci_freeze(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -786,12 +768,12 @@ static int virtio_pci_restore(struct device *dev) } static const struct dev_pm_ops virtio_pci_pm_ops = { - .suspend = virtio_pci_suspend, - .resume = virtio_pci_resume, + .suspend = virtio_pci_freeze, + .resume = virtio_pci_restore, .freeze = virtio_pci_freeze, .thaw = virtio_pci_restore, .restore = virtio_pci_restore, - .poweroff = virtio_pci_suspend, + .poweroff = virtio_pci_freeze, }; #endif -- 1.7.7.6
Amit Shah
2012-Mar-29 08:28 UTC
[PATCH 5/5] virtio-pci: switch to PM ops macro to initialise PM functions
Use the SET_SYSTEM_SLEEP_PM_OPS macro to initialise the suspend/resume functions in the new PM API. Signed-off-by: Amit Shah <amit.shah at redhat.com> --- drivers/virtio/virtio_pci.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 0fa4f85..2e03d41 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -768,12 +768,7 @@ static int virtio_pci_restore(struct device *dev) } static const struct dev_pm_ops virtio_pci_pm_ops = { - .suspend = virtio_pci_freeze, - .resume = virtio_pci_restore, - .freeze = virtio_pci_freeze, - .thaw = virtio_pci_restore, - .restore = virtio_pci_restore, - .poweroff = virtio_pci_freeze, + SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) }; #endif -- 1.7.7.6