diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2014-10-13 20:10:35 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2014-10-14 19:54:55 -0400 |
commit | c6716bae52f97347e25166c6270aa98693d9212c (patch) | |
tree | 0a8cf01f68e1eb0c0e403c24e9fbf1d76ccb3568 | |
parent | 016c98c6fe0c914d12e2e242b2bccde6d6dea54b (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.c | 54 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 54 | ||||
-rw-r--r-- | include/linux/virtio.h | 6 |
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 | } |
249 | EXPORT_SYMBOL_GPL(virtio_config_changed); | 249 | EXPORT_SYMBOL_GPL(virtio_config_changed); |
250 | 250 | ||
251 | #ifdef CONFIG_PM_SLEEP | ||
252 | int 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 | } | ||
263 | EXPORT_SYMBOL_GPL(virtio_device_freeze); | ||
264 | |||
265 | int 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 | } | ||
302 | EXPORT_SYMBOL_GPL(virtio_device_restore); | ||
303 | #endif | ||
304 | |||
251 | static int virtio_init(void) | 305 | static 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 | ||
837 | static const struct dev_pm_ops virtio_pci_pm_ops = { | 787 | static 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 | */ |
89 | struct virtio_device { | 90 | struct 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); | |||
109 | void virtio_break_device(struct virtio_device *dev); | 111 | void virtio_break_device(struct virtio_device *dev); |
110 | 112 | ||
111 | void virtio_config_changed(struct virtio_device *dev); | 113 | void virtio_config_changed(struct virtio_device *dev); |
114 | #ifdef CONFIG_PM_SLEEP | ||
115 | int virtio_device_freeze(struct virtio_device *dev); | ||
116 | int 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 |