[PATCH v4 1/4] [media] davinci: vpif_capture: don't lock over s_stream
From: khilman@baylibre.com (Kevin Hilman)
Date: 2016-12-07 16:06:36
Also in:
linux-devicetree, linux-media
Laurent Pinchart [off-list ref] writes: > Hi Kevin,
On Tuesday 06 Dec 2016 08:49:38 Kevin Hilman wrote:quoted
Laurent Pinchart writes:quoted
On Tuesday 29 Nov 2016 15:57:09 Kevin Hilman wrote:quoted
Video capture subdevs may be over I2C and may sleep during xfer, so we cannot do IRQ-disabled locking when calling the subdev. Signed-off-by: Kevin Hilman <khilman@baylibre.com> --- drivers/media/platform/davinci/vpif_capture.c | 3 +++ 1 file changed, 3 insertions(+)diff --git a/drivers/media/platform/davinci/vpif_capture.cb/drivers/media/platform/davinci/vpif_capture.c index 5104cc0ee40e..9f8f41c0f251 100644--- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c@@ -193,7 +193,10 @@ static int vpif_start_streaming(struct vb2_queue*vq, unsigned int count) } } + spin_unlock_irqrestore(&common->irqlock, flags); ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); + spin_lock_irqsave(&common->irqlock, flags);I always get anxious when I see a spinlock being released randomly with an operation in the middle of a protected section. Looking at the code it looks like the spinlock is abused here. irqlock should only protect the dma_queue and should thus only be taken around the following code: spin_lock_irqsave(&common->irqlock, flags); /* Get the next frame from the buffer queue */ common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, struct vpif_cap_buffer, list); /* Remove buffer from the buffer queue */ list_del(&common->cur_frm->list); spin_unlock_irqrestore(&common->irqlock, flags);Yes, that looks correct. Will update.quoted
The code that is currently protected by the lock in the start and stop streaming functions should be protected by a mutex instead.I tried taking the mutex here, but lockdep pointed out a deadlock. I may not be fully understanding the V4L2 internals here, but it seems that the ioctl is already taking a mutex, so taking it again in start/stop streaming is a deadlock. Unless you think the locking should be nested here, it seems to me that the mutex isn't needed.The V4L2 core can lock all ioctls using struct video_device::lock. For buffer- related ioctls, it can optionally use a separate lock from struct vb2_queue::lock. See v4l2_ioctl_get_lock() in drivers/media/v4l2-core/v4l2- ioctl.c. The vpif-capture driver sets both the video_device and vb2_queue locks to the same lock (which would have the same effect as leaving the vb2_queue lock NULL). All ioctls are thus serialized. You would only need to handle locking in start_streaming and stop_streaming manually if you didn't rely on the core serializing the ioctls.
OK, thanks for clarifying how that works. Kevin