|
@@ -789,6 +789,7 @@ 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;
|
|
|
+ unsigned status = 0;
|
|
|
int ret;
|
|
|
|
|
|
drv = container_of(vp_dev->vdev.dev.driver,
|
|
@@ -799,14 +800,40 @@ static int virtio_pci_restore(struct device *dev)
|
|
|
return ret;
|
|
|
|
|
|
pci_set_master(pci_dev);
|
|
|
+ /* We always start by resetting the device, in case a previous
|
|
|
+ * driver messed it up. */
|
|
|
+ vp_reset(&vp_dev->vdev);
|
|
|
+
|
|
|
+ /* Acknowledge that we've seen the device. */
|
|
|
+ status |= VIRTIO_CONFIG_S_ACKNOWLEDGE;
|
|
|
+ vp_set_status(&vp_dev->vdev, status);
|
|
|
+
|
|
|
+ /* Maybe driver failed before freeze.
|
|
|
+ * Restore the failed status, for debugging. */
|
|
|
+ status |= vp_dev->saved_status & VIRTIO_CONFIG_S_FAILED;
|
|
|
+ vp_set_status(&vp_dev->vdev, status);
|
|
|
+
|
|
|
+ if (!drv)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* We have a driver! */
|
|
|
+ status |= VIRTIO_CONFIG_S_DRIVER;
|
|
|
+ vp_set_status(&vp_dev->vdev, status);
|
|
|
+
|
|
|
vp_finalize_features(&vp_dev->vdev);
|
|
|
|
|
|
- if (drv && drv->restore)
|
|
|
+ if (drv->restore) {
|
|
|
ret = drv->restore(&vp_dev->vdev);
|
|
|
+ if (ret) {
|
|
|
+ status |= VIRTIO_CONFIG_S_FAILED;
|
|
|
+ vp_set_status(&vp_dev->vdev, status);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Finally, tell the device we're all set */
|
|
|
- if (!ret)
|
|
|
- vp_set_status(&vp_dev->vdev, vp_dev->saved_status);
|
|
|
+ status |= VIRTIO_CONFIG_S_DRIVER_OK;
|
|
|
+ vp_set_status(&vp_dev->vdev, status);
|
|
|
|
|
|
return ret;
|
|
|
}
|