From 0f7dc324b2e9e55db9323302f944fd952dbed967 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 Aug 2022 09:58:24 +0200 Subject: [PATCH] drm/udl: Sync pending URBs at suspend / disconnect We need to wait for finishing to process the all URBs after disabling the pipe; otherwise pending URBs may stray at suspend/resume, leading to a possible memory corruption in a worst case. Tested-by: Thomas Zimmermann Signed-off-by: Takashi Iwai Signed-off-by: Thomas Zimmermann Reviewed-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-3-tiwai@suse.de --- drivers/gpu/drm/udl/udl_drv.h | 1 + drivers/gpu/drm/udl/udl_main.c | 17 +++++++++++++++++ drivers/gpu/drm/udl/udl_modeset.c | 2 ++ 3 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index e008686ec738..f01e50c5b7b7 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -83,6 +83,7 @@ static inline struct urb *udl_get_urb(struct drm_device *dev) } int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); +int udl_sync_pending_urbs(struct drm_device *dev); void udl_urb_completion(struct urb *urb); int udl_init(struct udl_device *udl); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 67fd41e59b80..93615648414b 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -270,6 +270,23 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) return ret; } +/* wait until all pending URBs have been processed */ +int udl_sync_pending_urbs(struct drm_device *dev) +{ + struct udl_device *udl = to_udl(dev); + int ret = 0; + + spin_lock_irq(&udl->urbs.lock); + /* 2 seconds as a sane timeout */ + if (!wait_event_lock_irq_timeout(udl->urbs.sleep, + udl->urbs.available == udl->urbs.count, + udl->urbs.lock, + msecs_to_jiffies(2000))) + ret = -ETIMEDOUT; + spin_unlock_irq(&udl->urbs.lock); + return ret; +} + int udl_init(struct udl_device *udl) { struct drm_device *dev = &udl->drm; diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index e67c40a48fb4..50025606b6ad 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -408,6 +408,8 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) buf = udl_dummy_render(buf); udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); + + udl_sync_pending_urbs(dev); } static void -- 2.34.1