lkml.org 
[lkml]   [2019]   [Jul]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 070/105] media: hdpvr: fix locking and a missing msleep
    Date
    From: Hans Verkuil <hverkuil@xs4all.nl>

    [ Upstream commit 6bc5a4a1927556ff9adce1aa95ea408c95453225 ]

    This driver has three locking issues:

    - The wait_event_interruptible() condition calls hdpvr_get_next_buffer(dev)
    which uses a mutex, which is not allowed. Rewrite with list_empty_careful()
    that doesn't need locking.

    - In hdpvr_read() the call to hdpvr_stop_streaming() didn't lock io_mutex,
    but it should have since stop_streaming expects that.

    - In hdpvr_device_release() io_mutex was locked when calling flush_work(),
    but there it shouldn't take that mutex since the work done by flush_work()
    also wants to lock that mutex.

    There are also two other changes (suggested by Keith):

    - msecs_to_jiffies(4000); (a NOP) should have been msleep(4000).
    - Change v4l2_dbg to v4l2_info to always log if streaming had to be restarted.

    Reported-by: Keith Pyle <kpyle@austin.rr.com>
    Suggested-by: Keith Pyle <kpyle@austin.rr.com>
    Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
    Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/media/usb/hdpvr/hdpvr-video.c | 17 +++++++++++------
    1 file changed, 11 insertions(+), 6 deletions(-)

    diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
    index 7fb036d6a86e..991f820a4530 100644
    --- a/drivers/media/usb/hdpvr/hdpvr-video.c
    +++ b/drivers/media/usb/hdpvr/hdpvr-video.c
    @@ -439,7 +439,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
    /* wait for the first buffer */
    if (!(file->f_flags & O_NONBLOCK)) {
    if (wait_event_interruptible(dev->wait_data,
    - hdpvr_get_next_buffer(dev)))
    + !list_empty_careful(&dev->rec_buff_list)))
    return -ERESTARTSYS;
    }

    @@ -465,10 +465,17 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
    goto err;
    }
    if (!err) {
    - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
    - "timeout: restart streaming\n");
    + v4l2_info(&dev->v4l2_dev,
    + "timeout: restart streaming\n");
    + mutex_lock(&dev->io_mutex);
    hdpvr_stop_streaming(dev);
    - msecs_to_jiffies(4000);
    + mutex_unlock(&dev->io_mutex);
    + /*
    + * The FW needs about 4 seconds after streaming
    + * stopped before it is ready to restart
    + * streaming.
    + */
    + msleep(4000);
    err = hdpvr_start_streaming(dev);
    if (err) {
    ret = err;
    @@ -1133,9 +1140,7 @@ static void hdpvr_device_release(struct video_device *vdev)
    struct hdpvr_device *dev = video_get_drvdata(vdev);

    hdpvr_delete(dev);
    - mutex_lock(&dev->io_mutex);
    flush_work(&dev->worker);
    - mutex_unlock(&dev->io_mutex);

    v4l2_device_unregister(&dev->v4l2_dev);
    v4l2_ctrl_handler_free(&dev->hdl);
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-07-15 17:46    [W:2.626 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site