You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
virtio: reset function
A reset function solves three problems: 1) It allows us to renegotiate features, eg. if we want to upgrade a guest driver without rebooting the guest. 2) It gives us a clean way of shutting down virtqueues: after a reset, we know that the buffers won't be used by the host, and 3) It helps the guest recover from messed-up drivers. So we remove the ->shutdown hook, and the only way we now remove feature bits is via reset. We leave it to the driver to do the reset before it deletes queues: the balloon driver, for example, needs to chat to the host in its remove function. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
+10
-2
@@ -102,9 +102,13 @@ static int virtio_dev_remove(struct device *_d)
|
||||
struct virtio_driver *drv = container_of(dev->dev.driver,
|
||||
struct virtio_driver, driver);
|
||||
|
||||
dev->config->set_status(dev, dev->config->get_status(dev)
|
||||
& ~VIRTIO_CONFIG_S_DRIVER);
|
||||
drv->remove(dev);
|
||||
|
||||
/* Driver should have reset device. */
|
||||
BUG_ON(dev->config->get_status(dev));
|
||||
|
||||
/* Acknowledge the device's existence again. */
|
||||
add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -130,6 +134,10 @@ int register_virtio_device(struct virtio_device *dev)
|
||||
dev->dev.bus = &virtio_bus;
|
||||
sprintf(dev->dev.bus_id, "%u", dev->index);
|
||||
|
||||
/* We always start by resetting the device, in case a previous
|
||||
* driver messed it up. This also tests that code path a little. */
|
||||
dev->config->reset(dev);
|
||||
|
||||
/* Acknowledge that we've seen the device. */
|
||||
add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
|
||||
|
||||
|
||||
@@ -173,16 +173,6 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
|
||||
vq->num_free++;
|
||||
}
|
||||
|
||||
/* FIXME: We need to tell other side about removal, to synchronize. */
|
||||
static void vring_shutdown(struct virtqueue *_vq)
|
||||
{
|
||||
struct vring_virtqueue *vq = to_vvq(_vq);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < vq->vring.num; i++)
|
||||
detach_buf(vq, i);
|
||||
}
|
||||
|
||||
static inline bool more_used(const struct vring_virtqueue *vq)
|
||||
{
|
||||
return vq->last_used_idx != vq->vring.used->idx;
|
||||
@@ -278,7 +268,6 @@ static struct virtqueue_ops vring_vq_ops = {
|
||||
.kick = vring_kick,
|
||||
.disable_cb = vring_disable_cb,
|
||||
.enable_cb = vring_enable_cb,
|
||||
.shutdown = vring_shutdown,
|
||||
};
|
||||
|
||||
struct virtqueue *vring_new_virtqueue(unsigned int num,
|
||||
|
||||
Reference in New Issue
Block a user