aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-10-13 20:10:35 -0400
committerRusty Russell <rusty@rustcorp.com.au>2014-10-14 19:54:55 -0400
commitc6716bae52f97347e25166c6270aa98693d9212c (patch)
tree0a8cf01f68e1eb0c0e403c24e9fbf1d76ccb3568
parent016c98c6fe0c914d12e2e242b2bccde6d6dea54b (diff)
virtio-pci: move freeze/restore to virtio core
This is in preparation to extending config changed event handling in core. Wrapping these in an API also seems to make for a cleaner code. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/virtio/virtio.c54
-rw-r--r--drivers/virtio/virtio_pci.c54
-rw-r--r--include/linux/virtio.h6
3 files changed, 62 insertions, 52 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 3980687401f6..8216b7311092 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -248,6 +248,60 @@ void virtio_config_changed(struct virtio_device *dev)
248} 248}
249EXPORT_SYMBOL_GPL(virtio_config_changed); 249EXPORT_SYMBOL_GPL(virtio_config_changed);
250 250
251#ifdef CONFIG_PM_SLEEP
252int virtio_device_freeze(struct virtio_device *dev)
253{
254 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
255
256 dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
257
258 if (drv && drv->freeze)
259 return drv->freeze(dev);
260
261 return 0;
262}
263EXPORT_SYMBOL_GPL(virtio_device_freeze);
264
265int virtio_device_restore(struct virtio_device *dev)
266{
267 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
268
269 /* We always start by resetting the device, in case a previous
270 * driver messed it up. */
271 dev->config->reset(dev);
272
273 /* Acknowledge that we've seen the device. */
274 add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
275
276 /* Maybe driver failed before freeze.
277 * Restore the failed status, for debugging. */
278 if (dev->failed)
279 add_status(dev, VIRTIO_CONFIG_S_FAILED);
280
281 if (!drv)
282 return 0;
283
284 /* We have a driver! */
285 add_status(dev, VIRTIO_CONFIG_S_DRIVER);
286
287 dev->config->finalize_features(dev);
288
289 if (drv->restore) {
290 int ret = drv->restore(dev);
291 if (ret) {
292 add_status(dev, VIRTIO_CONFIG_S_FAILED);
293 return ret;
294 }
295 }
296
297 /* Finally, tell the device we're all set */
298 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
299
300 return 0;
301}
302EXPORT_SYMBOL_GPL(virtio_device_restore);
303#endif
304
251static int virtio_init(void) 305static int virtio_init(void)
252{ 306{
253 if (bus_register(&virtio_bus) != 0) 307 if (bus_register(&virtio_bus) != 0)
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index f39f4e772e6a..d34ebfa604f3 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -57,9 +57,6 @@ struct virtio_pci_device
57 /* Vectors allocated, excluding per-vq vectors if any */ 57 /* Vectors allocated, excluding per-vq vectors if any */
58 unsigned msix_used_vectors; 58 unsigned msix_used_vectors;
59 59
60 /* Status saved during hibernate/restore */
61 u8 saved_status;
62
63 /* Whether we have vector per vq */ 60 /* Whether we have vector per vq */
64 bool per_vq_vectors; 61 bool per_vq_vectors;
65}; 62};
@@ -764,16 +761,9 @@ static int virtio_pci_freeze(struct device *dev)
764{ 761{
765 struct pci_dev *pci_dev = to_pci_dev(dev); 762 struct pci_dev *pci_dev = to_pci_dev(dev);
766 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); 763 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
767 struct virtio_driver *drv;
768 int ret; 764 int ret;
769 765
770 drv = container_of(vp_dev->vdev.dev.driver, 766 ret = virtio_device_freeze(&vp_dev->vdev);
771 struct virtio_driver, driver);
772
773 ret = 0;
774 vp_dev->saved_status = vp_get_status(&vp_dev->vdev);
775 if (drv && drv->freeze)
776 ret = drv->freeze(&vp_dev->vdev);
777 767
778 if (!ret) 768 if (!ret)
779 pci_disable_device(pci_dev); 769 pci_disable_device(pci_dev);
@@ -784,54 +774,14 @@ static int virtio_pci_restore(struct device *dev)
784{ 774{
785 struct pci_dev *pci_dev = to_pci_dev(dev); 775 struct pci_dev *pci_dev = to_pci_dev(dev);
786 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); 776 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
787 struct virtio_driver *drv;
788 unsigned status = 0;
789 int ret; 777 int ret;
790 778
791 drv = container_of(vp_dev->vdev.dev.driver,
792 struct virtio_driver, driver);
793
794 ret = pci_enable_device(pci_dev); 779 ret = pci_enable_device(pci_dev);
795 if (ret) 780 if (ret)
796 return ret; 781 return ret;
797 782
798 pci_set_master(pci_dev); 783 pci_set_master(pci_dev);
799 /* We always start by resetting the device, in case a previous 784 return virtio_device_restore(&vp_dev->vdev);
800 * driver messed it up. */
801 vp_reset(&vp_dev->vdev);
802
803 /* Acknowledge that we've seen the device. */
804 status |= VIRTIO_CONFIG_S_ACKNOWLEDGE;
805 vp_set_status(&vp_dev->vdev, status);
806
807 /* Maybe driver failed before freeze.
808 * Restore the failed status, for debugging. */
809 status |= vp_dev->saved_status & VIRTIO_CONFIG_S_FAILED;
810 vp_set_status(&vp_dev->vdev, status);
811
812 if (!drv)
813 return 0;
814
815 /* We have a driver! */
816 status |= VIRTIO_CONFIG_S_DRIVER;
817 vp_set_status(&vp_dev->vdev, status);
818
819 vp_finalize_features(&vp_dev->vdev);
820
821 if (drv->restore) {
822 ret = drv->restore(&vp_dev->vdev);
823 if (ret) {
824 status |= VIRTIO_CONFIG_S_FAILED;
825 vp_set_status(&vp_dev->vdev, status);
826 return ret;
827 }
828 }
829
830 /* Finally, tell the device we're all set */
831 status |= VIRTIO_CONFIG_S_DRIVER_OK;
832 vp_set_status(&vp_dev->vdev, status);
833
834 return ret;
835} 785}
836 786
837static const struct dev_pm_ops virtio_pci_pm_ops = { 787static const struct dev_pm_ops virtio_pci_pm_ops = {
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 3c19bd3189cb..8df7ba81e5c7 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -78,6 +78,7 @@ bool virtqueue_is_broken(struct virtqueue *vq);
78/** 78/**
79 * virtio_device - representation of a device using virtio 79 * virtio_device - representation of a device using virtio
80 * @index: unique position on the virtio bus 80 * @index: unique position on the virtio bus
81 * @failed: saved value for CONFIG_S_FAILED bit (for restore)
81 * @dev: underlying device. 82 * @dev: underlying device.
82 * @id: the device type identification (used to match it with a driver). 83 * @id: the device type identification (used to match it with a driver).
83 * @config: the configuration ops for this device. 84 * @config: the configuration ops for this device.
@@ -88,6 +89,7 @@ bool virtqueue_is_broken(struct virtqueue *vq);
88 */ 89 */
89struct virtio_device { 90struct virtio_device {
90 int index; 91 int index;
92 bool failed;
91 struct device dev; 93 struct device dev;
92 struct virtio_device_id id; 94 struct virtio_device_id id;
93 const struct virtio_config_ops *config; 95 const struct virtio_config_ops *config;
@@ -109,6 +111,10 @@ void unregister_virtio_device(struct virtio_device *dev);
109void virtio_break_device(struct virtio_device *dev); 111void virtio_break_device(struct virtio_device *dev);
110 112
111void virtio_config_changed(struct virtio_device *dev); 113void virtio_config_changed(struct virtio_device *dev);
114#ifdef CONFIG_PM_SLEEP
115int virtio_device_freeze(struct virtio_device *dev);
116int virtio_device_restore(struct virtio_device *dev);
117#endif
112 118
113/** 119/**
114 * virtio_driver - operations for a virtio I/O driver 120 * virtio_driver - operations for a virtio I/O driver