From: Kieran Bingham <kieran.bingham@ideasonboard.com>
To: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Olivier BRAUN <olivier.braun@stereolabs.com>,
Troy Kisky <troy.kisky@boundarydevices.com>
Subject: Re: [RFT PATCH v3 6/6] uvcvideo: Move decode processing to process context
Date: Sat, 13 Jan 2018 07:32:57 +0000 [thread overview]
Message-ID: <d88ac9c7-bc9d-b656-fd0f-9f8a445276f8@ideasonboard.com> (raw)
In-Reply-To: <alpine.DEB.2.20.1801121025210.4338@axis700.grange>
Hi Guennadi,
Thanks for your review and time on this.
I certainly appreciate the extra eyes here!
On 12/01/18 09:37, Guennadi Liakhovetski wrote:
> Hi Kieran,
>
> On Fri, 12 Jan 2018, Kieran Bingham wrote:
>
>> Newer high definition cameras, and cameras with multiple lenses such as
>> the range of stereo-vision cameras now available have ever increasing
>> data rates.
>>
>> The inclusion of a variable length packet header in URB packets mean
>> that we must memcpy the frame data out to our destination 'manually'.
>> This can result in data rates of up to 2 gigabits per second being
>> processed.
>>
>> To improve efficiency, and maximise throughput, handle the URB decode
>> processing through a work queue to move it from interrupt context, and
>> allow multiple processors to work on URBs in parallel.
>>
>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>
>> ---
>> v2:
>> - Lock full critical section of usb_submit_urb()
>>
>> v3:
>> - Fix race on submitting uvc_video_decode_data_work() to work queue.
>> - Rename uvc_decode_op -> uvc_copy_op (Generic to encode/decode)
>> - Rename decodes -> copy_operations
>> - Don't queue work if there is no async task
>> - obtain copy op structure directly in uvc_video_decode_data()
>> - uvc_video_decode_data_work() -> uvc_video_copy_data_work()
>> ---
>> drivers/media/usb/uvc/uvc_queue.c | 12 +++-
>> drivers/media/usb/uvc/uvc_video.c | 116 +++++++++++++++++++++++++++----
>> drivers/media/usb/uvc/uvcvideo.h | 24 ++++++-
>> 3 files changed, 138 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
>> index 5a9987e547d3..598087eeb5c2 100644
>> --- a/drivers/media/usb/uvc/uvc_queue.c
>> +++ b/drivers/media/usb/uvc/uvc_queue.c
>> @@ -179,10 +179,22 @@ static void uvc_stop_streaming(struct vb2_queue *vq)
>> struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
>> struct uvc_streaming *stream = uvc_queue_to_stream(queue);
>>
>> + /* Prevent new buffers coming in. */
>> + spin_lock_irq(&queue->irqlock);
>> + queue->flags |= UVC_QUEUE_STOPPING;
>> + spin_unlock_irq(&queue->irqlock);
Q_A: <label for below>
>> +
>> + /*
>> + * All pending work should be completed before disabling the stream, as
>> + * all URBs will be free'd during uvc_video_enable(s, 0).
>> + */
>> + flush_workqueue(stream->async_wq);
>
> What if we manage to get one last URB here, then...
That will be fine. queue->flags = UVC_QUEUE_STOPPING, and thus no more items can
be added to the workqueue.
>> +
>> uvc_video_enable(stream, 0);
>>
Q_B: <label for below>
>> spin_lock_irq(&queue->irqlock);
>> uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
>> + queue->flags &= ~UVC_QUEUE_STOPPING;
>> spin_unlock_irq(&queue->irqlock);
>> }
>>
>> diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
>> index 3878bec3276e..fb6b5af17380 100644
>> --- a/drivers/media/usb/uvc/uvc_video.c
>> +++ b/drivers/media/usb/uvc/uvc_video.c
>
> [snip]
>
>> + /*
>> + * When the stream is stopped, all URBs are freed as part of the call to
>> + * uvc_stop_streaming() and must not be handled asynchronously. In that
>> + * event we can safely complete the packet work directly in this
>> + * context, without resubmitting the URB.
>> + */
>> + spin_lock_irqsave(&queue->irqlock, flags);
>> + if (!(queue->flags & UVC_QUEUE_STOPPING)) {
>> + INIT_WORK(&uvc_urb->work, uvc_video_copy_data_work);
>> + queue_work(stream->async_wq, &uvc_urb->work);
>> + } else {
>> + uvc_video_copy_packets(uvc_urb);
>
> Can it not happen, that if the stream is currently being stopped, the
> queue has been flushed, possibly the previous URB or a couple of them
> don't get decoded, but you do decode this one, creating a corrupted frame?
> Wouldn't it be better to just drop this URB too?
I don't think so.
The only time that this uvc_video_copy_packets() can be called directly in this
context is if UVC_QUEUE_STOPPING is set, *AND* we have the lock...
Therefore we must be executing between points Q_A and Q_B above.
The flush_workqueue() will ensure that all queued work is completed.
By calling uvc_video_copy_packets() directly we are ensuring that this last
packet is also completed. The headers have already been processed at this stage
during the call to ->decode() - so all we are actually doing here is the async
memcpy work which has already been promised by the header processing, and
releasing the references on the vb2 buffers if applicable.
Any buffers not fully completed will be returned marked and returned by the call
to :
uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
which happens *after* label Q_B:
--
Regards
Kieran
>
>> }
>> + spin_unlock_irqrestore(&queue->irqlock, flags);
>> }
>>
>> /*
>
> Thanks
> Guennadi
>
next prev parent reply other threads:[~2018-01-13 7:33 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-12 9:19 [RFT PATCH v3 0/6] Asynchronous UVC Kieran Bingham
2018-01-12 9:19 ` [RFT PATCH v3 1/6] uvcvideo: Refactor URB descriptors Kieran Bingham
2018-01-12 9:19 ` [RFT PATCH v3 5/6] uvcvideo: queue: Support asynchronous buffer handling Kieran Bingham
2018-01-16 23:45 ` Laurent Pinchart
2018-07-30 20:39 ` Laurent Pinchart
2018-11-06 15:07 ` Kieran Bingham
2018-01-12 9:19 ` [RFT PATCH v3 2/6] uvcvideo: Convert decode functions to use new context structure Kieran Bingham
2018-01-12 9:19 ` [RFT PATCH v3 4/6] uvcvideo: queue: Simplify spin-lock usage Kieran Bingham
2018-01-16 17:23 ` Laurent Pinchart
2018-01-17 9:44 ` Philipp Zabel
2018-01-12 9:19 ` [RFT PATCH v3 3/6] uvcvideo: Protect queue internals with helper Kieran Bingham
2018-01-12 9:19 ` [RFT PATCH v3 6/6] uvcvideo: Move decode processing to process context Kieran Bingham
2018-01-12 9:37 ` Guennadi Liakhovetski
2018-01-13 7:32 ` Kieran Bingham [this message]
2018-01-16 23:57 ` Laurent Pinchart
2018-01-15 19:35 ` [RFT PATCH v3 0/6] Asynchronous UVC Philipp Zabel
2018-01-16 14:55 ` Kieran Bingham
2018-01-18 4:59 ` Randy Dunlap
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d88ac9c7-bc9d-b656-fd0f-9f8a445276f8@ideasonboard.com \
--to=kieran.bingham@ideasonboard.com \
--cc=g.liakhovetski@gmx.de \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=olivier.braun@stereolabs.com \
--cc=troy.kisky@boundarydevices.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®