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>
This commit is contained in:
Родитель
016c98c6fe
Коммит
c6716bae52
|
@ -248,6 +248,60 @@ void virtio_config_changed(struct virtio_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(virtio_config_changed);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int virtio_device_freeze(struct virtio_device *dev)
|
||||
{
|
||||
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
|
||||
|
||||
dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
|
||||
|
||||
if (drv && drv->freeze)
|
||||
return drv->freeze(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(virtio_device_freeze);
|
||||
|
||||
int virtio_device_restore(struct virtio_device *dev)
|
||||
{
|
||||
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
|
||||
|
||||
/* We always start by resetting the device, in case a previous
|
||||
* driver messed it up. */
|
||||
dev->config->reset(dev);
|
||||
|
||||
/* Acknowledge that we've seen the device. */
|
||||
add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
|
||||
|
||||
/* Maybe driver failed before freeze.
|
||||
* Restore the failed status, for debugging. */
|
||||
if (dev->failed)
|
||||
add_status(dev, VIRTIO_CONFIG_S_FAILED);
|
||||
|
||||
if (!drv)
|
||||
return 0;
|
||||
|
||||
/* We have a driver! */
|
||||
add_status(dev, VIRTIO_CONFIG_S_DRIVER);
|
||||
|
||||
dev->config->finalize_features(dev);
|
||||
|
||||
if (drv->restore) {
|
||||
int ret = drv->restore(dev);
|
||||
if (ret) {
|
||||
add_status(dev, VIRTIO_CONFIG_S_FAILED);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, tell the device we're all set */
|
||||
add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(virtio_device_restore);
|
||||
#endif
|
||||
|
||||
static int virtio_init(void)
|
||||
{
|
||||
if (bus_register(&virtio_bus) != 0)
|
||||
|
|
|
@ -57,9 +57,6 @@ struct virtio_pci_device
|
|||
/* Vectors allocated, excluding per-vq vectors if any */
|
||||
unsigned msix_used_vectors;
|
||||
|
||||
/* Status saved during hibernate/restore */
|
||||
u8 saved_status;
|
||||
|
||||
/* Whether we have vector per vq */
|
||||
bool per_vq_vectors;
|
||||
};
|
||||
|
@ -764,16 +761,9 @@ static int virtio_pci_freeze(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 = 0;
|
||||
vp_dev->saved_status = vp_get_status(&vp_dev->vdev);
|
||||
if (drv && drv->freeze)
|
||||
ret = drv->freeze(&vp_dev->vdev);
|
||||
ret = virtio_device_freeze(&vp_dev->vdev);
|
||||
|
||||
if (!ret)
|
||||
pci_disable_device(pci_dev);
|
||||
|
@ -784,54 +774,14 @@ 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,
|
||||
struct virtio_driver, driver);
|
||||
|
||||
ret = pci_enable_device(pci_dev);
|
||||
if (ret)
|
||||
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->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 */
|
||||
status |= VIRTIO_CONFIG_S_DRIVER_OK;
|
||||
vp_set_status(&vp_dev->vdev, status);
|
||||
|
||||
return ret;
|
||||
return virtio_device_restore(&vp_dev->vdev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops virtio_pci_pm_ops = {
|
||||
|
|
|
@ -78,6 +78,7 @@ bool virtqueue_is_broken(struct virtqueue *vq);
|
|||
/**
|
||||
* virtio_device - representation of a device using virtio
|
||||
* @index: unique position on the virtio bus
|
||||
* @failed: saved value for CONFIG_S_FAILED bit (for restore)
|
||||
* @dev: underlying device.
|
||||
* @id: the device type identification (used to match it with a driver).
|
||||
* @config: the configuration ops for this device.
|
||||
|
@ -88,6 +89,7 @@ bool virtqueue_is_broken(struct virtqueue *vq);
|
|||
*/
|
||||
struct virtio_device {
|
||||
int index;
|
||||
bool failed;
|
||||
struct device dev;
|
||||
struct virtio_device_id id;
|
||||
const struct virtio_config_ops *config;
|
||||
|
@ -109,6 +111,10 @@ void unregister_virtio_device(struct virtio_device *dev);
|
|||
void virtio_break_device(struct virtio_device *dev);
|
||||
|
||||
void virtio_config_changed(struct virtio_device *dev);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int virtio_device_freeze(struct virtio_device *dev);
|
||||
int virtio_device_restore(struct virtio_device *dev);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* virtio_driver - operations for a virtio I/O driver
|
||||
|
|
Загрузка…
Ссылка в новой задаче