Skip to content

Commit 560f961

Browse files
committed
Merge: virtio: break and reset virtio devices on device_shutdown()
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/670 JIRA: https://issues.redhat.com/browse/RHEL-85779 UPSTREAM: yes When vIOMMU is reset before devices, if devices are not reset on shutdown they continue to poke at guest memory and get errors from the IOMMU. Some devices get wedged then. The problem can be solved by breaking all virtio devices on virtio bus shutdown, then resetting them. Signed-off-by: Eric Auger <eric.auger@redhat.com> v1 -> v2: * added "virtgpu: don't reset on shutdown" fixing the regression observed with virtio-gpu Approved-by: José Expósito <jexposit@redhat.com> Approved-by: Jocelyn Falempe <jfalempe@redhat.com> Approved-by: Laurent Vivier <lvivier@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents e9ce04b + 55a791e commit 560f961

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

drivers/gpu/drm/virtio/virtgpu_drv.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ static void virtio_gpu_remove(struct virtio_device *vdev)
123123
drm_dev_put(dev);
124124
}
125125

126+
static void virtio_gpu_shutdown(struct virtio_device *vdev)
127+
{
128+
/*
129+
* drm does its own synchronization on shutdown.
130+
* Do nothing here, opt out of device reset.
131+
*/
132+
}
133+
126134
static void virtio_gpu_config_changed(struct virtio_device *vdev)
127135
{
128136
struct drm_device *dev = vdev->priv;
@@ -157,6 +165,7 @@ static struct virtio_driver virtio_gpu_driver = {
157165
.id_table = id_table,
158166
.probe = virtio_gpu_probe,
159167
.remove = virtio_gpu_remove,
168+
.shutdown = virtio_gpu_shutdown,
160169
.config_changed = virtio_gpu_config_changed
161170
};
162171

drivers/virtio/virtio.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,40 @@ static const struct cpumask *virtio_irq_get_affinity(struct device *_d,
395395
return dev->config->get_vq_affinity(dev, irq_vec);
396396
}
397397

398+
static void virtio_dev_shutdown(struct device *_d)
399+
{
400+
struct virtio_device *dev = dev_to_virtio(_d);
401+
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
402+
403+
/*
404+
* Stop accesses to or from the device.
405+
* We only need to do it if there's a driver - no accesses otherwise.
406+
*/
407+
if (!drv)
408+
return;
409+
410+
/* If the driver has its own shutdown method, use that. */
411+
if (drv->shutdown) {
412+
drv->shutdown(dev);
413+
return;
414+
}
415+
416+
/*
417+
* Some devices get wedged if you kick them after they are
418+
* reset. Mark all vqs as broken to make sure we don't.
419+
*/
420+
virtio_break_device(dev);
421+
/*
422+
* Guarantee that any callback will see vq->broken as true.
423+
*/
424+
virtio_synchronize_cbs(dev);
425+
/*
426+
* As IOMMUs are reset on shutdown, this will block device access to memory.
427+
* Some devices get wedged if this happens, so reset to make sure it does not.
428+
*/
429+
dev->config->reset(dev);
430+
}
431+
398432
static const struct bus_type virtio_bus = {
399433
.name = "virtio",
400434
.match = virtio_dev_match,
@@ -403,6 +437,7 @@ static const struct bus_type virtio_bus = {
403437
.probe = virtio_dev_probe,
404438
.remove = virtio_dev_remove,
405439
.irq_get_affinity = virtio_irq_get_affinity,
440+
.shutdown = virtio_dev_shutdown,
406441
};
407442

408443
int __register_virtio_driver(struct virtio_driver *driver, struct module *owner)

include/linux/virtio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ size_t virtio_max_dma_size(const struct virtio_device *vdev);
205205
* changes; may be called in interrupt context.
206206
* @freeze: optional function to call during suspend/hibernation.
207207
* @restore: optional function to call on resume.
208+
* @shutdown: synchronize with the device on shutdown. If provided, replaces
209+
* the virtio core implementation.
208210
*/
209211
struct virtio_driver {
210212
struct device_driver driver;
@@ -220,6 +222,7 @@ struct virtio_driver {
220222
void (*config_changed)(struct virtio_device *dev);
221223
int (*freeze)(struct virtio_device *dev);
222224
int (*restore)(struct virtio_device *dev);
225+
void (*shutdown)(struct virtio_device *dev);
223226
};
224227

225228
#define drv_to_virtio(__drv) container_of_const(__drv, struct virtio_driver, driver)

0 commit comments

Comments
 (0)