Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752744AbeADSza (ORCPT + 1 other); Thu, 4 Jan 2018 13:55:30 -0500 Received: from mout.gmx.net ([212.227.15.18]:60182 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752348AbeADSz2 (ORCPT ); Thu, 4 Jan 2018 13:55:28 -0500 Date: Thu, 4 Jan 2018 19:54:28 +0100 (CET) From: Guennadi Liakhovetski X-X-Sender: lyakh@axis700.grange To: Kieran Bingham cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, laurent.pinchart@ideasonboard.com, Olivier BRAUN , kieran.bingham@ideasonboard.com, Mauro Carvalho Chehab , Hans Verkuil , Baoyou Xie , Jaejoong Kim , Kate Stewart , Nicolas Dufresne , Greg Kroah-Hartman , Daniel Patrick Johnson , Jim Lin Subject: Re: [RFC/RFT PATCH 6/6] uvcvideo: Move decode processing to process context In-Reply-To: <48e2716d3902214a89aa30f3d1672512f8ea8773.1515010476.git-series.kieran.bingham@ideasonboard.com> Message-ID: References: <48e2716d3902214a89aa30f3d1672512f8ea8773.1515010476.git-series.kieran.bingham@ideasonboard.com> User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Provags-ID: V03:K0:re2AUEGH0wnjn0e/Z/xLGPIbmuMKTXTkIFwbf2cGP8mEU2uwcPy TBSgkIs9+UITdBREC8e53fjzKHaxTcuvZJz/FG+TDRjSYOruBhsAwvjkziyo5215g064TS1 PWNOG5up1iedHYD0hghYCVZP0tZVR5bQBLQTXmsicfo4lF91K2Oi7Mwy6OM0TZARxeZzPLL nrJ29S15wH8eyjUhNY1cg== X-UI-Out-Filterresults: notjunk:1;V01:K0:Hb/zCdmQDRY=:WB9G7amehVOr/N9wN3loK/ 2BdRmSPBlIO0XpTOnsJsOhhHyyUo6VCZMew9tSJeazowgeJnTqRMNiduBfRPouIf1zBBccBJk gkVwg9Racpms7DrGTKZDlX5DP//GAx8BtVKkF4Hc2TxuxR395Z6P8CKAbh7sng//N4ibHFnzO JFiobHlaCaT9KiE9+6ta3doQTf8uygd/Hdko1IS6vyt2pW8GlB6B1wNCtjDOvBmwCJ7vaA5Bu ddjbJXED+7MwzOvMQyCyJ3y5ji9wk/Jdbhi4zz44BezhRPYLrGshyr4AA+0FQa+0mXByxskYb SGXEcHt5sUk6kZWJWab0wdKDejWiPllHg77ZeJr08dbrQWuNLfgJW1Xp+F0xHsJflAgfUc6Im vYfnW4JkPXqH2zcV39y0BKkwXdZWheM9bv3U+PyrnLmoVMx7LefFWOLqnOtF/l7LRa39iAioQ VNM16DyneZe3tK2O1XND7Yzxt1dimqS6jCk1HOdEV0YEv2psy4krJRplg0mDzNkmp4KtM9K+8 P9skFAj4bbNx8NlOFqA5SKW78PcsSimVIWtLwhOM3K4MsYPu/eP7tjhfAvmk6ln8v/kt6fogv 9MEvZVGyU60cj/1zq7Qf1QnJ9virDlfOn9VSNiBKRSRVEx5oSYFtQSjSTQCDKTQ+iPYmZCGLT 6PWhl5ZMA6JUH5YBSAswpQAkOgC7riRqwboAFQpSqA55JQpI8hUBN/rZaRbBqBMrBobHZFkm9 NBeSl/Yg/R343xw6T/PKf+gGUVXC+5AvCzQoQFOGmxQ2Bl0aIoFIFx+z3S+HAmUR2d5bJsKiP hUGE4oUratr2LWrlhCxHswga5CA3uz6rmo8R+7+f/fKtZZt1E8= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: On Wed, 3 Jan 2018, Kieran Bingham wrote: > From: Kieran Bingham > > Newer high definition cameras, and cameras with multiple lenses such as > the range of stereovision 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 > --- > drivers/media/usb/uvc/uvc_queue.c | 12 +++- > drivers/media/usb/uvc/uvc_video.c | 114 ++++++++++++++++++++++++++----- > drivers/media/usb/uvc/uvcvideo.h | 24 +++++++- > 3 files changed, 132 insertions(+), 18 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c > index 204dd91a8526..07fcbfc132c9 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); > + > + /* > + * 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); > + > uvc_video_enable(stream, 0); > > 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 045ac655313c..b7b32a6bc2dc 100644 > --- a/drivers/media/usb/uvc/uvc_video.c > +++ b/drivers/media/usb/uvc/uvc_video.c > @@ -1058,21 +1058,70 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, > return data[0]; > } > > -static void uvc_video_decode_data(struct uvc_streaming *stream, > - struct uvc_buffer *buf, const __u8 *data, int len) > +/* > + * uvc_video_decode_data_work: Asynchronous memcpy processing > + * > + * Perform memcpy tasks in process context, with completion handlers > + * to return the URB, and buffer handles. > + * > + * The work submitter must pre-determine that the work is safe > + */ > +static void uvc_video_decode_data_work(struct work_struct *work) > { > - unsigned int maxlen, nbytes; > - void *mem; > + struct uvc_urb *uvc_urb = container_of(work, struct uvc_urb, work); > + struct uvc_streaming *stream = uvc_urb->stream; > + struct uvc_video_queue *queue = &stream->queue; > + unsigned int i; > + bool stopping; > + int ret; > + > + for (i = 0; i < uvc_urb->packets; i++) { > + struct uvc_decode_op *op = &uvc_urb->decodes[i]; > + > + memcpy(op->dst, op->src, op->len); > + > + /* Release reference taken on this buffer */ > + uvc_queue_buffer_release(op->buf); > + } > + > + /* > + * Prevent resubmitting URBs when shutting down to ensure that no new > + * work item will be scheduled after uvc_stop_streaming() flushes the > + * work queue. > + */ > + spin_lock_irq(&queue->irqlock); > + stopping = queue->flags & UVC_QUEUE_STOPPING; > + spin_unlock_irq(&queue->irqlock); Are you sure this locking really helps? What if uvc_stop_streaming() runs here? Thanks Guennadi > + > + if (stopping) > + return; > + > + ret = usb_submit_urb(uvc_urb->urb, GFP_ATOMIC); > + if (ret < 0) > + uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", > + ret); > +}