virtio: add virtio_device_shutdown() helper

The generic virtio bus .shutdown handler, virtio_dev_shutdown(), breaks
and resets a device once it has established that the driver has no
.shutdown of its own. A driver that does implement .shutdown, to quiesce
its own activity first, still needs the same break and reset afterwards
and would otherwise have to open code it.

Factor the break + synchronize_cbs + reset sequence out of
virtio_dev_shutdown() into an exported virtio_device_shutdown() helper so
such drivers can reuse it instead of duplicating the core logic.

No functional change.

Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260624140846.2616797-2-den@openvz.org>
This commit is contained in:
Denis V. Lunev
2026-06-24 16:08:43 +02:00
committed by Michael S. Tsirkin
parent 2187be2121
commit 0d8aebe089
2 changed files with 28 additions and 14 deletions

View File

@@ -401,6 +401,32 @@ static const struct cpumask *virtio_irq_get_affinity(struct device *_d,
return dev->config->get_vq_affinity(dev, irq_vec);
}
/**
* virtio_device_shutdown - break and reset a device on shutdown
* @dev: the device
*
* Drivers with their own .shutdown method should quiesce their activity and
* then call this to stop the device the way the generic shutdown path does.
*/
void virtio_device_shutdown(struct virtio_device *dev)
{
/*
* Some devices get wedged if you kick them after they are
* reset. Mark all vqs as broken to make sure we don't.
*/
virtio_break_device(dev);
/*
* Guarantee that any callback will see vq->broken as true.
*/
virtio_synchronize_cbs(dev);
/*
* As IOMMUs are reset on shutdown, this will block device access to memory.
* Some devices get wedged if this happens, so reset to make sure it does not.
*/
dev->config->reset(dev);
}
EXPORT_SYMBOL_GPL(virtio_device_shutdown);
static void virtio_dev_shutdown(struct device *_d)
{
struct virtio_device *dev = dev_to_virtio(_d);
@@ -419,20 +445,7 @@ static void virtio_dev_shutdown(struct device *_d)
return;
}
/*
* Some devices get wedged if you kick them after they are
* reset. Mark all vqs as broken to make sure we don't.
*/
virtio_break_device(dev);
/*
* Guarantee that any callback will see vq->broken as true.
*/
virtio_synchronize_cbs(dev);
/*
* As IOMMUs are reset on shutdown, this will block device access to memory.
* Some devices get wedged if this happens, so reset to make sure it does not.
*/
dev->config->reset(dev);
virtio_device_shutdown(dev);
}
static int virtio_dev_num_vf(struct device *dev)

View File

@@ -213,6 +213,7 @@ int virtio_device_freeze(struct virtio_device *dev);
int virtio_device_restore(struct virtio_device *dev);
#endif
void virtio_reset_device(struct virtio_device *dev);
void virtio_device_shutdown(struct virtio_device *dev);
int virtio_device_reset_prepare(struct virtio_device *dev);
int virtio_device_reset_done(struct virtio_device *dev);