Skip to content
  • Hans Verkuil's avatar
    media: vb2: keep a reference to the request until dqbuf · 6093d300
    Hans Verkuil authored
    When vb2_buffer_done is called the buffer is unbound from the
    request and put. The media_request_object_put also 'put's the
    request reference. If the application has already closed the
    request fd, then that means that the request reference at that
    point goes to 0 and the whole request is released.
    
    This means that the control handler associated with the request is
    also freed and that causes this kernel oops:
    
    [174705.995401] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:908
    [174705.995411] in_atomic(): 1, irqs_disabled(): 1, pid: 28071, name: vivid-000-vid-o
    [174705.995416] 2 locks held by vivid-000-vid-o/28071:
    [174705.995420]  #0: 000000001ea3a232 (&dev->mutex#3){....}, at: vivid_thread_vid_out+0x3f5/0x550 [vivid]
    [174705.995447]  #1: 00000000e30a0d1e (&(&q->done_lock)->rlock){....}, at: vb2_buffer_done+0x92/0x1d0 [videobuf2_common]
    [174705.995460] Preemption disabled at:
    [174705.995461] [<0000000000000000>]           (null)
    [174705.995472] CPU: 11 PID: 28071 Comm: vivid-000-vid-o Tainted: G        W         4.20.0-rc1-test-no #88
    
    
    [174705.995476] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 05/19/2017
    [174705.995481] Call Trace:
    [174705.995500]  dump_stack+0x46/0x60
    [174705.995512]  ___might_sleep.cold.79+0xe1/0xf1
    [174705.995523]  __mutex_lock+0x50/0x8f0
    [174705.995531]  ? find_held_lock+0x2d/0x90
    [174705.995536]  ? find_held_lock+0x2d/0x90
    [174705.995542]  ? find_held_lock+0x2d/0x90
    [174705.995564]  ? v4l2_ctrl_handler_free.part.13+0x44/0x1d0 [videodev]
    [174705.995576]  v4l2_ctrl_handler_free.part.13+0x44/0x1d0 [videodev]
    [174705.995590]  v4l2_ctrl_request_release+0x1c/0x30 [videodev]
    [174705.995600]  media_request_clean+0x64/0xe0 [media]
    [174705.995609]  media_request_release+0x19/0x40 [media]
    [174705.995617]  vb2_buffer_done+0xef/0x1d0 [videobuf2_common]
    [174705.995630]  vivid_thread_vid_out+0x2c1/0x550 [vivid]
    [174705.995645]  ? vivid_stop_generating_vid_cap+0x1c0/0x1c0 [vivid]
    [174705.995653]  kthread+0x113/0x130
    [174705.995659]  ? kthread_park+0x80/0x80
    [174705.995667]  ret_from_fork+0x35/0x40
    
    The vb2_buffer_done function can be called from interrupt context, so
    anything that sleeps is not allowed.
    
    The solution is to increment the request refcount when the buffer is
    queued and decrement it when the buffer is dequeued. Releasing the
    request is fine if that happens from VIDIOC_DQBUF.
    
    Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
    Acked-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
    Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
    Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
    6093d300