diff options
author | Takashi Iwai <tiwai@suse.de> | 2022-08-04 09:58:25 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2022-08-10 10:07:01 +0200 |
commit | e25d5954264d1871ab2792c7ca2298b811462500 (patch) | |
tree | db1088c2ffb6d6491a9bbd94f5f153e5a3f255cf /drivers/gpu/drm/udl/udl_main.c | |
parent | 0f7dc324b2e9e55db9323302f944fd952dbed967 (diff) |
drm/udl: Kill pending URBs at suspend and disconnect
At both suspend and disconnect, we should rather cancel the pending
URBs immediately. For the suspend case, the display will be turned
off, so it makes no sense to process the rendering. And for the
disconnect case, the device may be no longer accessible, hence we
shouldn't do any submission.
Tested-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20220804075826.27036-4-tiwai@suse.de
Diffstat (limited to 'drivers/gpu/drm/udl/udl_main.c')
-rw-r--r-- | drivers/gpu/drm/udl/udl_main.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 93615648414b..47204b7eb10e 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -135,7 +135,7 @@ void udl_urb_completion(struct urb *urb) urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */ spin_lock_irqsave(&udl->urbs.lock, flags); - list_add_tail(&unode->entry, &udl->urbs.list); + list_move(&unode->entry, &udl->urbs.list); udl->urbs.available++; spin_unlock_irqrestore(&udl->urbs.lock, flags); @@ -180,6 +180,7 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); + INIT_LIST_HEAD(&udl->urbs.in_flight); init_waitqueue_head(&udl->urbs.sleep); udl->urbs.count = 0; @@ -246,7 +247,7 @@ struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout) } unode = list_first_entry(&udl->urbs.list, struct urb_node, entry); - list_del_init(&unode->entry); + list_move(&unode->entry, &udl->urbs.in_flight); udl->urbs.available--; unlock: @@ -279,7 +280,7 @@ int udl_sync_pending_urbs(struct drm_device *dev) 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, + list_empty(&udl->urbs.in_flight), udl->urbs.lock, msecs_to_jiffies(2000))) ret = -ETIMEDOUT; @@ -287,6 +288,23 @@ int udl_sync_pending_urbs(struct drm_device *dev) return ret; } +/* kill pending URBs */ +void udl_kill_pending_urbs(struct drm_device *dev) +{ + struct udl_device *udl = to_udl(dev); + struct urb_node *unode; + + spin_lock_irq(&udl->urbs.lock); + while (!list_empty(&udl->urbs.in_flight)) { + unode = list_first_entry(&udl->urbs.in_flight, + struct urb_node, entry); + spin_unlock_irq(&udl->urbs.lock); + usb_kill_urb(unode->urb); + spin_lock_irq(&udl->urbs.lock); + } + spin_unlock_irq(&udl->urbs.lock); +} + int udl_init(struct udl_device *udl) { struct drm_device *dev = &udl->drm; @@ -335,6 +353,7 @@ int udl_drop_usb(struct drm_device *dev) { struct udl_device *udl = to_udl(dev); + udl_kill_pending_urbs(dev); udl_free_urb_list(dev); put_device(udl->dmadev); udl->dmadev = NULL; |