linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] hdpvr: fix locking and a missing msleep
@ 2019-06-20 11:43 Hans Verkuil
  2019-06-21  2:48 ` Keith Pyle
  0 siblings, 1 reply; 2+ messages in thread
From: Hans Verkuil @ 2019-06-20 11:43 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Keith Pyle

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>
---
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 3786ddcc0d18..5b3e67b80627 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -435,7 +435,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;
 	}

@@ -461,10 +461,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;
@@ -1124,9 +1131,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);

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] hdpvr: fix locking and a missing msleep
  2019-06-20 11:43 [PATCH] hdpvr: fix locking and a missing msleep Hans Verkuil
@ 2019-06-21  2:48 ` Keith Pyle
  0 siblings, 0 replies; 2+ messages in thread
From: Keith Pyle @ 2019-06-21  2:48 UTC (permalink / raw)
  To: Hans Verkuil, Linux Media Mailing List

On 06/20/19 06:43, Hans Verkuil wrote:
> 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>
This patch looks good.

I have repeated my tests and all passed (simple captures, capture with 
HD-PVR restart streaming) .   There were no lockdep reports and no 
process deadlocks.  The streaming restart now works and logs the restart 
in kern.log.

Keith
> ---
> diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
> index 3786ddcc0d18..5b3e67b80627 100644
> --- a/drivers/media/usb/hdpvr/hdpvr-video.c
> +++ b/drivers/media/usb/hdpvr/hdpvr-video.c
> @@ -435,7 +435,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;
>   	}
>
> @@ -461,10 +461,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;
> @@ -1124,9 +1131,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);
>


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-06-21  2:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-20 11:43 [PATCH] hdpvr: fix locking and a missing msleep Hans Verkuil
2019-06-21  2:48 ` Keith Pyle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).