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 <[email protected]> --- drivers/virtio/virtio.c | 41 +++++++++++++++++++++++++++-------------- include/linux/virtio.h | 1 + 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 299fa83be1d5..75bb4ffe3b87 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -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) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index bf089e51970e..66184828fdd0 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -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); -- 2.53.0

