media: hdpvr: fix locking and a missing msleep
[ 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>
This commit is contained in:
parent
43b9fdc483
commit
bce037abc2
1 changed files with 11 additions and 6 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue