summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuj Bolewar <bolewara@gmail.com>2026-08-02 22:05:17 +0530
committerDmitry Osipenko <dmitry.osipenko@collabora.com>2026-08-14 16:38:21 +0300
commit61d85f99b5a55d4f717c4bb2f4c4acabf22ee3fc (patch)
tree06e60f7681c761483acff6c1d643b543041b265e
parentd96504ea631874220d89c455d735da51a796ead0 (diff)
drm/virtio: reclaim pending vbufs before tearing down vqs
virtio_gpu_free_vbufs() destroys the vbufs kmem_cache after the virtqueues have already been released. Commands that were queued but never completed by the device leave their vbuffers stranded in the virtqueue, so the cache still holds live objects when virtio_gpu_deinit() tears everything down. This triggers a WARNING in virtio_gpu_free_vbufs: BUG virtio-gpu-vbufs (Not tainted): Objects remaining in cache on __kmem_cache_shutdown() Drain any buffers still sitting in the control and cursor virtqueues in virtio_gpu_deinit() after the device has been reset and before the virtqueues are deleted, following the same pattern used by virtio_console's remove_vqs(). Each reclaimed buffer is released with free_vbuf(), dropping the reference on any GEM objects it holds. Pending RESOURCE_UNREF commands are handled as well: their resp_cb_data still references a GEM object, so it is cleaned up with virtio_gpu_cleanup_object() to avoid leaking it on teardown. Reported-by: syzbot+06f9b2a53ba4a5a47644@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=06f9b2a53ba4a5a47644 Signed-off-by: Anuj Bolewar <bolewara@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Link: https://patch.msgid.link/20260802-virtio-gpu-reclaim-vbufs-v2-1-5767fb860691@gmail.com
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c15
3 files changed, 17 insertions, 0 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 7449907754a4..3e491c808734 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -332,6 +332,7 @@ void virtio_gpu_array_put_free_work(struct work_struct *work);
/* virtgpu_vq.c */
int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev);
void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev);
+void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev);
void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
struct virtio_gpu_object *bo,
struct virtio_gpu_object_params *params,
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index b4329f28e976..e5a6ae679f36 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -298,6 +298,7 @@ void virtio_gpu_deinit(struct drm_device *dev)
flush_work(&vgdev->cursorq.dequeue_work);
flush_work(&vgdev->config_changed_work);
virtio_reset_device(vgdev->vdev);
+ virtio_gpu_reclaim_vbufs(vgdev);
vgdev->vdev->config->del_vqs(vgdev->vdev);
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index e5e1af8b8e8a..ab6106f4bdfc 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -208,6 +208,21 @@ static void free_vbuf(struct virtio_gpu_device *vgdev,
kmem_cache_free(vgdev->vbufs, vbuf);
}
+void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev)
+{
+ struct virtio_gpu_vbuffer *vbuf;
+
+ while ((vbuf = virtqueue_detach_unused_buf(vgdev->ctrlq.vq))) {
+ if (vbuf->objs)
+ virtio_gpu_array_put_free(vbuf->objs);
+ if (vbuf->resp_cb_data)
+ virtio_gpu_cleanup_object(vbuf->resp_cb_data);
+ free_vbuf(vgdev, vbuf);
+ }
+ while ((vbuf = virtqueue_detach_unused_buf(vgdev->cursorq.vq)))
+ free_vbuf(vgdev, vbuf);
+}
+
static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list)
{
struct virtio_gpu_vbuffer *vbuf;