From patchwork Sun Sep 29 18:59:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Grzeschik X-Patchwork-Id: 831500 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EC2164A8F for ; Sun, 29 Sep 2024 18:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636381; cv=none; b=fs/rrxWFIBW+0wjjLuslqZUA3WN3MDijoEro3mRXvL4631DFrfVQjykjyN37ixK9iJMx+ryoFkB/7d0Ue1MZcUPMbDGFNjqijLnruPtMqZrx6cpoDPxGEp0T6r2mF4iwgw5/rU9irNQR6P2/HxYOpziarGBWJpMSdazKno1KTNo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636381; c=relaxed/simple; bh=tqEAc4G4g5DANBIiYnngjMwLHhsQQN7FAdkIiAeqdto=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=s4nOVnKoDRMze5zmmN5jgoOdo7BikvgQx3Po911Z2qCcOJLANT7V2ja0WBMG9oPIGsnyvxABv1ekaCSJBZtD7RnWCm7Sm2IJC/XS6vJJB7SQQRgpq5ZkAI7Mi4paJU4MlFUb/tjQ5RybqCqxDkXnGSbNrRL3YFWo4rNiZNJ52nc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1suz8l-00053u-KM; Sun, 29 Sep 2024 20:59:31 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1suz8l-002Ro5-0m; Sun, 29 Sep 2024 20:59:31 +0200 Received: from localhost ([::1] helo=dude04.red.stw.pengutronix.de) by dude04.red.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1suz8k-0029Vj-2x; Sun, 29 Sep 2024 20:59:30 +0200 From: Michael Grzeschik Date: Sun, 29 Sep 2024 20:59:23 +0200 Subject: [PATCH v6 3/9] usb: gadget: uvc: rework to enqueue in pump worker from encoded queue Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240403-uvc_request_length_by_interval-v6-3-08c05522e1f5@pengutronix.de> References: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> In-Reply-To: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> To: Laurent Pinchart , Daniel Scally , Greg Kroah-Hartman , Avichal Rakesh , Jayant Chowdhary Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@pengutronix.de, Michael Grzeschik X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=10792; i=m.grzeschik@pengutronix.de; h=from:subject:message-id; bh=tqEAc4G4g5DANBIiYnngjMwLHhsQQN7FAdkIiAeqdto=; b=owEBbQKS/ZANAwAKAb9pWET5cfSrAcsmYgBm+aOQN/n0sMwL6+6ej/Bdp2EhaSyh8Kmbxterp AgboMcxWoSJAjMEAAEKAB0WIQQV2+2Fpbqd6fvv0Gi/aVhE+XH0qwUCZvmjkAAKCRC/aVhE+XH0 q4S1D/9/GTbNFgXjvAaRMd31R03/Xj1KhLIFy6T4XlPlKldjD1oTEbbldNgQv0RXEHTwaEGibHh HtflYw3OPbjt/E8axdXhRbv0pDg8k0Hriw/odtnHRBgjM0alKhuUmLWkyQ58pFMvOinMwDzH4YJ 2IqfUWF+YwSkS+OogtCCzEiB5m/nJnBzGtQzCSD+MiyhVOkNGvKQ5KCxcbMn2ocj5LRqsyLMtlg xxFFMhnRbvNX/jLaNsA4zf+VJnLKy4CkMW58Vz2+ze01Rdb84kHg06Gbup59APHgC/bqKEySaNw s6yUQzsscDj3EZoSD8pX/TEUZplrUYwVB7TjlGqr2TNCvS7G0laXPoAjtctq2UkBck2Lxy0RTGG HpTRH6bbKyxcK/EHYgUMqTHtnPxyk/F7EztzzD1VMDxbtY4hOO0vwGMw98LxJ0RAfcDqm1qEhX2 xi5rtz1KbES/byWUpNBdPsUgmYaFwD5/oN2bVLX8q50/sHoBWDYMZ14iGgmGCjQMXzNi2u158zH TJ6eLHBg+RkcnICE1sefWYhgqV7qWCDu3WPdSPxtlRYAbXh3FAcQuw1TG6S+RMqME6FgZuzJhMY 3Vx46L2AEXw9bz4jMoSoHCRE1GKcnAjEKDHa6ZDG2qkxzp5swi1HyM/P49qlvmWdF2kDcDJjARq eQMUnXyZwkaMGvQ== X-Developer-Key: i=m.grzeschik@pengutronix.de; a=openpgp; fpr=957BC452CE953D7EA60CF4FC0BE9E3157A1E2C64 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: m.grzeschik@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-usb@vger.kernel.org We install an kthread with pfifo priority that is iterating over all prepared requests and keeps the isoc queue busy. This way it will be scheduled with the same priority as the interrupt handler. As the kthread is triggered with video_enable it will immediately queue some zero length requests into the hw if there is no buffer data available. It also watches the level of needed zero length requests in the hardware not to fall under the UVCG_REQ_MAX_ZERO_COUNT threshold. This way we can drop the function uvc_video_ep_queue_initial_requests entirely. By using the kthread to do the actual request handling the interrupt handler will not be running into the time consuming and eventually locking work of actually enqueueing the requests back into its own pipeline. This work can now even be scheduled on another cpu. Signed-off-by: Michael Grzeschik --- v5 -> v6: - v4 -> v5: - merging patch '(drivers/usb/gadget/function/uvc_queue.h') into this one - added initial kthread_queue_work(video->kworker, &video->hw_submit); to uvcg_video_enable - fixed error message in uvcg_video_init - reordered this patch in the series - renamed the kworker to hw_submit since the pump thread is used again with the work_queue v1 -> v4: - --- drivers/usb/gadget/function/f_uvc.c | 2 + drivers/usb/gadget/function/uvc.h | 3 + drivers/usb/gadget/function/uvc_video.c | 180 +++++++++++++++----------------- 3 files changed, 87 insertions(+), 98 deletions(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 40187b7112e79..f04376768bc10 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -991,6 +991,8 @@ static void uvc_function_unbind(struct usb_configuration *c, uvcg_info(f, "%s()\n", __func__); + kthread_cancel_work_sync(&video->hw_submit); + if (video->async_wq) destroy_workqueue(video->async_wq); diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 55d796f5f5e8d..4f44a607d9f5c 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -94,6 +94,9 @@ struct uvc_video { struct work_struct pump; struct workqueue_struct *async_wq; + struct kthread_worker *kworker; + struct kthread_work hw_submit; + atomic_t queued; /* Frame parameters */ diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index eb82aaed6ba13..f43bf19218963 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -324,50 +324,6 @@ static int uvcg_video_usb_req_queue(struct uvc_video *video, return 0; } -/* - * Must only be called from uvcg_video_enable - since after that we only want to - * queue requests to the endpoint from the uvc_video_complete complete handler. - * This function is needed in order to 'kick start' the flow of requests from - * gadget driver to the usb controller. - */ -static void uvc_video_ep_queue_initial_requests(struct uvc_video *video) -{ - struct usb_request *req = NULL; - unsigned long flags = 0; - unsigned int count = 0; - int ret = 0; - - /* - * We only queue half of the free list since we still want to have - * some free usb_requests in the free list for the video_pump async_wq - * thread to encode uvc buffers into. Otherwise we could get into a - * situation where the free list does not have any usb requests to - * encode into - we always end up queueing 0 length requests to the - * end point. - */ - unsigned int half_list_size = video->uvc_num_requests / 2; - - spin_lock_irqsave(&video->req_lock, flags); - /* - * Take these requests off the free list and queue them all to the - * endpoint. Since we queue 0 length requests with the req_lock held, - * there isn't any 'data' race involved here with the complete handler. - */ - while (count < half_list_size) { - req = list_first_entry(&video->req_free, struct usb_request, - list); - list_del(&req->list); - req->length = 0; - ret = uvcg_video_ep_queue(video, req); - if (ret < 0) { - uvcg_queue_cancel(&video->queue, 0); - break; - } - count++; - } - spin_unlock_irqrestore(&video->req_lock, flags); -} - static void uvc_video_complete(struct usb_ep *ep, struct usb_request *req) { @@ -375,10 +331,7 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) struct uvc_video *video = ureq->video; struct uvc_video_queue *queue = &video->queue; struct uvc_buffer *last_buf; - struct usb_request *to_queue = req; unsigned long flags; - bool is_bulk = video->max_payload_size; - int ret = 0; spin_lock_irqsave(&video->req_lock, flags); atomic_dec(&video->queued); @@ -441,65 +394,85 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) return; } + list_add_tail(&req->list, &video->req_free); /* - * Here we check whether any request is available in the ready - * list. If it is, queue it to the ep and add the current - * usb_request to the req_free list - for video_pump to fill in. - * Otherwise, just use the current usb_request to queue a 0 - * length request to the ep. Since we always add to the req_free - * list if we dequeue from the ready list, there will never - * be a situation where the req_free list is completely out of - * requests and cannot recover. + * Queue work to the wq as well since it is possible that a + * buffer may not have been completely encoded with the set of + * in-flight usb requests for whih the complete callbacks are + * firing. + * In that case, if we do not queue work to the worker thread, + * the buffer will never be marked as complete - and therefore + * not be returned to userpsace. As a result, + * dequeue -> queue -> dequeue flow of uvc buffers will not + * happen. Since there are is a new free request wake up the pump. */ - to_queue->length = 0; - if (!list_empty(&video->req_ready)) { - to_queue = list_first_entry(&video->req_ready, - struct usb_request, list); - list_del(&to_queue->list); - list_add_tail(&req->list, &video->req_free); - /* - * Queue work to the wq as well since it is possible that a - * buffer may not have been completely encoded with the set of - * in-flight usb requests for whih the complete callbacks are - * firing. - * In that case, if we do not queue work to the worker thread, - * the buffer will never be marked as complete - and therefore - * not be returned to userpsace. As a result, - * dequeue -> queue -> dequeue flow of uvc buffers will not - * happen. - */ - queue_work(video->async_wq, &video->pump); - } else if (atomic_read(&video->queued) > UVCG_REQ_MAX_ZERO_COUNT) { - list_add_tail(&to_queue->list, &video->req_free); - /* - * There is a new free request - wake up the pump. - */ - queue_work(video->async_wq, &video->pump); + queue_work(video->async_wq, &video->pump); - spin_unlock_irqrestore(&video->req_lock, flags); + spin_unlock_irqrestore(&video->req_lock, flags); - return; - } - /* - * Queue to the endpoint. The actual queueing to ep will - * only happen on one thread - the async_wq for bulk endpoints - * and this thread for isoc endpoints. - */ - ret = uvcg_video_usb_req_queue(video, to_queue, !is_bulk); - if (ret < 0) { + kthread_queue_work(video->kworker, &video->hw_submit); +} + +static void uvcg_video_hw_submit(struct kthread_work *work) +{ + struct uvc_video *video = container_of(work, struct uvc_video, hw_submit); + bool is_bulk = video->max_payload_size; + unsigned long flags; + struct usb_request *req; + int ret = 0; + + while (true) { + if (!video->ep->enabled) + return; + spin_lock_irqsave(&video->req_lock, flags); /* - * Endpoint error, but the stream is still enabled. - * Put request back in req_free for it to be cleaned - * up later. + * Here we check whether any request is available in the ready + * list. If it is, queue it to the ep and add the current + * usb_request to the req_free list - for video_pump to fill in. + * Otherwise, just use the current usb_request to queue a 0 + * length request to the ep. Since we always add to the req_free + * list if we dequeue from the ready list, there will never + * be a situation where the req_free list is completely out of + * requests and cannot recover. */ - list_add_tail(&to_queue->list, &video->req_free); + if (!list_empty(&video->req_ready)) { + req = list_first_entry(&video->req_ready, + struct usb_request, list); + } else { + if (list_empty(&video->req_free) || + (atomic_read(&video->queued) > UVCG_REQ_MAX_ZERO_COUNT)) { + spin_unlock_irqrestore(&video->req_lock, flags); + + return; + } + req = list_first_entry(&video->req_free, struct usb_request, + list); + req->length = 0; + } + list_del(&req->list); + /* - * There is a new free request - wake up the pump. + * Queue to the endpoint. The actual queueing to ep will + * only happen on one thread - the async_wq for bulk endpoints + * and this thread for isoc endpoints. */ - queue_work(video->async_wq, &video->pump); - } + ret = uvcg_video_usb_req_queue(video, req, !is_bulk); + if (ret < 0) { + /* + * Endpoint error, but the stream is still enabled. + * Put request back in req_free for it to be cleaned + * up later. + */ + list_add_tail(&req->list, &video->req_free); + /* + * There is a new free request - wake up the pump. + */ + queue_work(video->async_wq, &video->pump); - spin_unlock_irqrestore(&video->req_lock, flags); + } + + spin_unlock_irqrestore(&video->req_lock, flags); + } } static int @@ -771,7 +744,7 @@ int uvcg_video_enable(struct uvc_video *video) atomic_set(&video->queued, 0); - uvc_video_ep_queue_initial_requests(video); + kthread_queue_work(video->kworker, &video->hw_submit); queue_work(video->async_wq, &video->pump); return ret; @@ -794,6 +767,17 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) if (!video->async_wq) return -EINVAL; + /* Allocate a kthread for asynchronous hw submit handler. */ + video->kworker = kthread_create_worker(0, "UVCG"); + if (IS_ERR(video->kworker)) { + uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n"); + return PTR_ERR(video->kworker); + } + + kthread_init_work(&video->hw_submit, uvcg_video_hw_submit); + + sched_set_fifo(video->kworker->task); + video->uvc = uvc; video->fcc = V4L2_PIX_FMT_YUYV; video->bpp = 16; From patchwork Sun Sep 29 18:59:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Grzeschik X-Patchwork-Id: 831498 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B16B57346F for ; Sun, 29 Sep 2024 18:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636382; cv=none; b=f2COSyGOMQsGt0eSxEPh4Ya0sWT0SyAYOgi4Ua1KNVjamwrWpvOVCOnAfh3dWVJwnrByw5Hxml0g6WGXu2+UVA+MvSI1a+Bo2NfVKSXbIktmEq25lynD3bXnlLVXxm/0tqf+kOUVkmmyz6HeBgyPsXSp9feBxYxHCLgyVFFx3/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636382; c=relaxed/simple; bh=Hk7tbELgzh9caEJKk1jfev7yNN44yhrC8FT6TaKYFeM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lvkqMkKeKGRRYy9ek972zzSXnvwYIBQqAYjkm1PU7rMedinm0Od6HXDqPUdZSrWc/pm56v7zb6K7pbuZIN0fhCeLS1RuQRzqAn2Ne1rSVfEwPHhfC/ttb25A/DP2wb2IDJNhm3IlZFsnXfz5owIkA0OlSOAXDXurrMHyPUhuU+Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1suz8l-00053v-KL; Sun, 29 Sep 2024 20:59:31 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1suz8l-002Ro8-1m; Sun, 29 Sep 2024 20:59:31 +0200 Received: from localhost ([::1] helo=dude04.red.stw.pengutronix.de) by dude04.red.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1suz8k-0029Vj-30; Sun, 29 Sep 2024 20:59:30 +0200 From: Michael Grzeschik Date: Sun, 29 Sep 2024 20:59:26 +0200 Subject: [PATCH v6 6/9] usb: gadget: uvc: set req_length based on payload by nreqs instead of req_size Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240403-uvc_request_length_by_interval-v6-6-08c05522e1f5@pengutronix.de> References: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> In-Reply-To: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> To: Laurent Pinchart , Daniel Scally , Greg Kroah-Hartman , Avichal Rakesh , Jayant Chowdhary Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@pengutronix.de, Michael Grzeschik X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5699; i=m.grzeschik@pengutronix.de; h=from:subject:message-id; bh=Hk7tbELgzh9caEJKk1jfev7yNN44yhrC8FT6TaKYFeM=; b=owEBbQKS/ZANAwAKAb9pWET5cfSrAcsmYgBm+aORAkNKtcBauirFrPlVipbScaYLRKdKm78F1 9Lk/vP9PpqJAjMEAAEKAB0WIQQV2+2Fpbqd6fvv0Gi/aVhE+XH0qwUCZvmjkQAKCRC/aVhE+XH0 q13BEACgLwGxeIHzggCVcaJyQjOC7hKf+24RxmNZpdNCMLNIHgLC5NRKbLG4H2pwTjUDx8nnsLT tyi+E8awD9Ma+XZn7wbDpGn/Nmuimo476VJjycM38u/0UMOwCGxtQvMAgOygGSp9rHIrCaH6h0M WAaFFNS22dUjqfZ9tRxCjd6xtlAAgAJFcTxXCOxm4b4aQUlvmHS+MDAlt3NqqOfdIgJVCfsDx1H v4ZGOosmFIOdm0FbyWk+AFWUg3BlfaHitkApnLPR9mMyJowTs9wOE/OXYUUf7V6VDOah449cs/W pFO0BjipqsFGV+kInWsLd/2dkflIc+Ln+un5P2UBk6YPLh66r+i7QARhdhb0Us/rLJ6b6lqX/xa t8VToIryuSaOxwQfFA9h1IsG+c3JcKAwNHQtlwSW+XWfdG48X5IIdkmnQB4KrMshg/XOildWpCU 9rT/OBxmnQxbtKNoU7XmcjPAOj1//ZKRKsN5h/PL+FZ1GVxwVgB6BGzSKFS3j+Lyg6C9+kbBnaa fGQ7zoGYpHIIiKjBRSMqzbiCbA4OElandGTRQk/JNqduTxpapdTUTnL4LWlzOQUaMmCLb5RF/zb lkvfi6erAiA9bVAsiQeB/9NqQR6FtaEa+hsgz8gblHykTD6uoHg/psFBCBjnswtUTT2gOqfKgCZ cpJA7nq/cmiGRTw== X-Developer-Key: i=m.grzeschik@pengutronix.de; a=openpgp; fpr=957BC452CE953D7EA60CF4FC0BE9E3157A1E2C64 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: m.grzeschik@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-usb@vger.kernel.org Compressed formats generate content depending amount of data that is set in the vb2 buffer by the payload_size. When streaming those formats it is better to scatter that smaller data over all requests. This patch is doing that by introducing the calculated req_payload_size which is updated by each frame. It the uses this amount of data to fill the isoc requests instead of the video->req_size. For uncompressed formats it will not make a difference since the payload size will be equal to the imagesize. Therefore the code will have no effecta as req_payload_size will be equal to req_size. Signed-off-by: Michael Grzeschik --- v5 -> v6: - v4 -> v5: - keep using req_size instead of len in encode_isoc_sg to be more explicit - using new initialized variable reqs_per_frame instead of two calculations - reordered this patch in the series v1 -> v4: - --- drivers/usb/gadget/function/uvc.h | 2 ++ drivers/usb/gadget/function/uvc_queue.c | 10 ++++++++-- drivers/usb/gadget/function/uvc_queue.h | 2 ++ drivers/usb/gadget/function/uvc_video.c | 15 ++++++++------- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 099038f1088ef..bedb4ef42864f 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -110,6 +110,8 @@ struct uvc_video { unsigned int uvc_num_requests; + unsigned int reqs_per_frame; + /* Requests */ bool is_enabled; /* tracks whether video stream is enabled */ unsigned int req_size; diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 731e3b9d21acc..6757a4e25a743 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -58,6 +58,7 @@ static int uvc_queue_setup(struct vb2_queue *vq, static int uvc_buffer_prepare(struct vb2_buffer *vb) { struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); + struct uvc_video *video = container_of(queue, struct uvc_video, queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); @@ -78,10 +79,15 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb) buf->mem = vb2_plane_vaddr(vb, 0); } buf->length = vb2_plane_size(vb, 0); - if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { buf->bytesused = 0; - else + } else { buf->bytesused = vb2_get_plane_payload(vb, 0); + buf->req_payload_size = + DIV_ROUND_UP(buf->bytesused + + (video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN), + video->reqs_per_frame); + } return 0; } diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 41f87b917f6bc..b54becc570a38 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h @@ -39,6 +39,8 @@ struct uvc_buffer { unsigned int offset; unsigned int length; unsigned int bytesused; + /* req_payload_size: only used with isoc */ + unsigned int req_payload_size; }; #define UVC_QUEUE_DISCONNECTED (1 << 0) diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 4efd7585d7541..0287a56fa50ad 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -136,7 +136,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, unsigned int pending = buf->bytesused - video->queue.buf_used; struct uvc_request *ureq = req->context; struct scatterlist *sg, *iter; - unsigned int len = video->req_size; + unsigned int len = buf->req_payload_size; unsigned int sg_left, part = 0; unsigned int i; int header_len; @@ -146,15 +146,15 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, /* Init the header. */ header_len = uvc_video_encode_header(video, buf, ureq->header, - video->req_size); + buf->req_payload_size); sg_set_buf(sg, ureq->header, header_len); len -= header_len; if (pending <= len) len = pending; - req->length = (len == pending) ? - len + header_len : video->req_size; + req->length = (len == pending) ? len + header_len : + buf->req_payload_size; /* Init the pending sgs with payload */ sg = sg_next(sg); @@ -202,7 +202,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, { void *mem = req->buf; struct uvc_request *ureq = req->context; - int len = video->req_size; + int len = buf->req_payload_size; int ret; /* Add the header. */ @@ -214,7 +214,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, ret = uvc_video_encode_data(video, buf, mem, len); len -= ret; - req->length = video->req_size - len; + req->length = buf->req_payload_size - len; if (buf->bytesused == video->queue.buf_used || video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { @@ -504,7 +504,7 @@ uvc_video_prep_requests(struct uvc_video *video) if (!usb_endpoint_xfer_isoc(video->ep->desc)) { video->req_size = max_req_size; - video->uvc_num_requests = + video->reqs_per_frame = video->uvc_num_requests = DIV_ROUND_UP(video->imagesize, max_req_size); return; @@ -535,6 +535,7 @@ uvc_video_prep_requests(struct uvc_video *video) * able to fully encode one frame. */ video->uvc_num_requests = nreq + UVCG_REQ_MAX_ZERO_COUNT; + video->reqs_per_frame = nreq; } static int From patchwork Sun Sep 29 18:59:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Grzeschik X-Patchwork-Id: 831499 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A18816BFC0 for ; Sun, 29 Sep 2024 18:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636381; cv=none; b=iFc7Bxek1QuDWALMCRo8wl7pe7Z2lDInWMjbDvwZwaYN6+0Pl4r4ffMi/YoNhoXVvlGqycB29H+K9/7KI++tH1c2OUJqhcukSSgkkocRKLXK6GzZebE0iHvChN/fmsuiXVDwWb7pao5JywBgzWOAzq7zP0FLNPcefFCR3nVIR3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636381; c=relaxed/simple; bh=/U43Y8aGcmzcxzXv+PaUGk5zmq/qPekProSrrAIpWOw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VR/0TYj0BNsD2RIkHt0udamup63PF4FCfs3/kISpm+NuFTNbzjswvIy934/bLwMNjm0vcLEBnYU8QUqqsvm/In+JHeTeruM8Okzvo4ONDRcQn2OAM9s+Lf39e4BTOeHmZoxyOEAYCeW8lNGgXv7aNi4Um7xGqyCMJRbAGEEj5pI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1suz8l-00053r-KL; Sun, 29 Sep 2024 20:59:31 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1suz8l-002RoA-1X; Sun, 29 Sep 2024 20:59:31 +0200 Received: from localhost ([::1] helo=dude04.red.stw.pengutronix.de) by dude04.red.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1suz8k-0029Vj-32; Sun, 29 Sep 2024 20:59:30 +0200 From: Michael Grzeschik Date: Sun, 29 Sep 2024 20:59:28 +0200 Subject: [PATCH v6 8/9] usb: gadget: uvc: add trace of enqueued and completed requests Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240403-uvc_request_length_by_interval-v6-8-08c05522e1f5@pengutronix.de> References: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> In-Reply-To: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> To: Laurent Pinchart , Daniel Scally , Greg Kroah-Hartman , Avichal Rakesh , Jayant Chowdhary Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@pengutronix.de, Michael Grzeschik X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4461; i=m.grzeschik@pengutronix.de; h=from:subject:message-id; bh=/U43Y8aGcmzcxzXv+PaUGk5zmq/qPekProSrrAIpWOw=; b=owEBbQKS/ZANAwAKAb9pWET5cfSrAcsmYgBm+aOSf/qznxVRZC+vvW01WhvqdVTildn7mQpTs pGKbVHs1miJAjMEAAEKAB0WIQQV2+2Fpbqd6fvv0Gi/aVhE+XH0qwUCZvmjkgAKCRC/aVhE+XH0 q1YgD/0WCyun+tWR3YvArZw9ZEVPGEjuRpwapw09R4ugwHgO8ymO8tCeSLwV+N1cHt/+iF9ozpQ m6OnXkmjgTbaNXocL8UcqiO+ThBVXOuFDMHMq99EFQu7AIFbfnYDP6fH5pSllv3B2DoWW/T7na8 uZni47qwusES/FiYSq7YBpmHZaWSe2nu18afMHKc9ugDOWjeK2El0cnmnIB91Y3ZJYiRZ2G99QC 2WQSF5pjL4pBXVAhh8GWjnAVGPU8U4e8ZJ3sDc7sbFw9/lFRf48pZHISSynKXG0vsdJOrwopv+V 4dod0gF9BhtNsVZwshnnOHzTkQZVu0YYjlKU6sSAMM8L1gWElfo12XbxObFLt1ZJLJdIE6vo/Tl jJtN6VfwRgHnkYmWJS64w0/NLc0XaBWmPBMT2evoKQJ8rXn7CIOx1LilKOGiHCGHVUbydpyy0kn HKXEu5KNcdQqtTOvhAlUY6vYowJ7XaRtolgfGpZJiScAg/DzzxugU4NstVvwlByGgo7/Z4+5xhe swhgRwYjWZh/uGSAZosscBkHrsPVkuBOHrScs1jdme+ubagGc20zdtJCippbj1KuydoLqGMpm3w khRTIP5/4gVhQRgmKAMk2TX5+kZ2/Fw3cg8UVQnqUJJxLuYkXrg9OSNvM01DaJZ4czFR26YD7B/ M39JLGMrQvEeLEA== X-Developer-Key: i=m.grzeschik@pengutronix.de; a=openpgp; fpr=957BC452CE953D7EA60CF4FC0BE9E3157A1E2C64 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: m.grzeschik@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-usb@vger.kernel.org This patch is adding trace events for each request that is being enqueued into the hw and will be completed. This way it is possible to track the fill status of the gadget hardware and find potential issues. Signed-off-by: Michael Grzeschik --- v5 -> v6: - fixed compile rule as module - reordered header files v1 -> v5: - new patch --- drivers/usb/gadget/function/Makefile | 3 ++ drivers/usb/gadget/function/uvc_trace.c | 11 ++++++ drivers/usb/gadget/function/uvc_trace.h | 60 +++++++++++++++++++++++++++++++++ drivers/usb/gadget/function/uvc_video.c | 5 +++ 4 files changed, 79 insertions(+) diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index 87917a7d4a9be..92b695388611b 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile @@ -41,6 +41,9 @@ obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o usb_f_uac2-y := f_uac2.o obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o +ifneq ($(CONFIG_TRACING),) + usb_f_uvc-y += uvc_trace.o +endif obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o usb_f_midi-y := f_midi.o obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o diff --git a/drivers/usb/gadget/function/uvc_trace.c b/drivers/usb/gadget/function/uvc_trace.c new file mode 100644 index 0000000000000..d384f6d8221a5 --- /dev/null +++ b/drivers/usb/gadget/function/uvc_trace.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * trace.c - USB UVC Gadget Trace Support + * + * Copyright (C) 2024 Pengutronix e.K. + * + * Author: Michael Grzeschik + */ + +#define CREATE_TRACE_POINTS +#include "uvc_trace.h" diff --git a/drivers/usb/gadget/function/uvc_trace.h b/drivers/usb/gadget/function/uvc_trace.h new file mode 100644 index 0000000000000..04c33cf43cc2d --- /dev/null +++ b/drivers/usb/gadget/function/uvc_trace.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * trace.h - USB UVC Gadget Trace Support + * + * Copyright (C) 2024 Pengutronix e.K. + * + * Author: Michael Grzeschik + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM uvcg + +#if !defined(__UVCG_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __UVCG_TRACE_H + +#include +#include +#include +#include + +DECLARE_EVENT_CLASS(uvcg_video_req, + TP_PROTO(struct usb_request *req, u32 queued), + TP_ARGS(req, queued), + TP_STRUCT__entry( + __field(struct usb_request *, req) + __field(u32, length) + __field(u32, queued) + ), + TP_fast_assign( + __entry->req = req; + __entry->length = req->length; + __entry->queued = queued; + ), + TP_printk("req %p length %u queued %u", + __entry->req, + __entry->length, + __entry->queued) +); + +DEFINE_EVENT(uvcg_video_req, uvcg_video_complete, + TP_PROTO(struct usb_request *req, u32 queued), + TP_ARGS(req, queued) +); + +DEFINE_EVENT(uvcg_video_req, uvcg_video_queue, + TP_PROTO(struct usb_request *req, u32 queued), + TP_ARGS(req, queued) +); + +#endif /* __UVCG_TRACE_H */ + +/* this part has to be here */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE uvc_trace + +#include diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 0287a56fa50ad..115524b79ebd7 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -19,6 +19,7 @@ #include "uvc.h" #include "uvc_queue.h" #include "uvc_video.h" +#include "uvc_trace.h" /* -------------------------------------------------------------------------- * Video codecs @@ -271,6 +272,8 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req) atomic_inc(&video->queued); + trace_uvcg_video_queue(req, atomic_read(&video->queued)); + return ret; } @@ -408,6 +411,8 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) */ queue_work(video->async_wq, &video->pump); + trace_uvcg_video_complete(req, atomic_read(&video->queued)); + spin_unlock_irqrestore(&video->req_lock, flags); kthread_queue_work(video->kworker, &video->hw_submit); From patchwork Sun Sep 29 18:59:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Grzeschik X-Patchwork-Id: 831502 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6D916F073 for ; Sun, 29 Sep 2024 18:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636380; cv=none; b=uhtt9jlXlEzwFbkulCSUVmPRuHTd9Xeomt/IqzseESc7xvoXT84Gm94vKSCh4FIY9IZDh3Y1pB/YuLiUyH31byRONzRNqO9953L36h2iZ7dh8rDhfEgWUZlUK4Hi1vDCXuydb3AHFjoUD6JY+02lZ6F2GQJc4O3XBOwHTRaAkdk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727636380; c=relaxed/simple; bh=7S+aPuRPGUbYnkcvuKpuMWRYvF73uV3ggRsPg/mMG5o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UkTs1hHKo3rnDYGEZI0ZgHRtci2zO2z4U67gQ3EdpWA7fjV2YpSZBTylNwczcYTmrbH9lVSKBJ7Tk04REp3gYJMBeXRa4xe2Di5xbcYsSSXrJVa9ez95tzkpM2KvGvUBN3mZr2Bn4m7HgPY6fSusg8osA4/t1BPnAhMtlFI1Gd0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1suz8l-00053t-KL; Sun, 29 Sep 2024 20:59:31 +0200 Received: from [2a0a:edc0:0:1101:1d::ac] (helo=dude04.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1suz8l-002RoB-1D; Sun, 29 Sep 2024 20:59:31 +0200 Received: from localhost ([::1] helo=dude04.red.stw.pengutronix.de) by dude04.red.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1suz8k-0029Vj-33; Sun, 29 Sep 2024 20:59:30 +0200 From: Michael Grzeschik Date: Sun, 29 Sep 2024 20:59:29 +0200 Subject: [PATCH v6 9/9] usb: gadget: uvc: dont call usb_composite_setup_continue when not streaming Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240403-uvc_request_length_by_interval-v6-9-08c05522e1f5@pengutronix.de> References: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> In-Reply-To: <20240403-uvc_request_length_by_interval-v6-0-08c05522e1f5@pengutronix.de> To: Laurent Pinchart , Daniel Scally , Greg Kroah-Hartman , Avichal Rakesh , Jayant Chowdhary Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@pengutronix.de, Michael Grzeschik X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1116; i=m.grzeschik@pengutronix.de; h=from:subject:message-id; bh=7S+aPuRPGUbYnkcvuKpuMWRYvF73uV3ggRsPg/mMG5o=; b=owEBbQKS/ZANAwAKAb9pWET5cfSrAcsmYgBm+aOSKRNJf2gHyr9LAFLASPoX8Ve4fvtg2MTYI kxp29wUvUyJAjMEAAEKAB0WIQQV2+2Fpbqd6fvv0Gi/aVhE+XH0qwUCZvmjkgAKCRC/aVhE+XH0 q1hyEAC9Ir5VllmE3JkSMXYslr0pvNe7lSHQR4q6gEsFYaviIKdKz/ufdT9Cqnv16+GgzpVRT0F TL3M17aKRLreii0Jnc3CvpcBd+YD4htM2s+m5muwx6PrQH1Hi7HsfzEgJcpruWVFsRxxGEobNWg l8huJfX7l4aQeg3gq7vcwiGoFfSSN9HxbFAfRAX08TQem77kavX4wzzT72BRvb7UtoiAckRb3TM q4jFllw9FJtkfytNOF7W7Y7B9y+q3ZSo5YdHvJ2k2KQ9MsJsQtyqMazrCdY9Wl+Pj2hJkKRTvV6 v22uXItUzb3GiL0PEX/8XvLO/JA+xYXsoyXUW+2MeVigBRdTQdat2p7+uIDvKIHuprNZv8HX/er 8EkJKkGJgFghvVXdAhHH54mefZ7+GD+16A0gSsIQVjnSwZFPFwMqb1x7yaSkcZV34RSXkSn9ErU 55svaoCTXsu2nVXTtMNyKUdJAzGeG7j+8d4Jt3WVcELDkgBkLW1Jo2kZaq2dYNo3N5ZYT0tT7LE h5D3P4W03/vv8onzx/9Nb0NYktsb06VpEl13JjBY8oFBK/FRTnKbFtv5XSLruEviufe4XXhlsnP v3U32J8eqhl0neIRJKkLPIp+Hj58gxoUuMSHfZJB/lzgXzmlVV6sFXq2gc8oV6OzveYqmvDsngn 7puAuykchMJ/Exw== X-Developer-Key: i=m.grzeschik@pengutronix.de; a=openpgp; fpr=957BC452CE953D7EA60CF4FC0BE9E3157A1E2C64 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: m.grzeschik@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-usb@vger.kernel.org If the streamoff call was triggered by some previous disconnect or userspace application shutdown the uvc_function_setup_continue should not be called and the state should not be overwritten. For this situation the set_alt(0) was never called and the streaming ep has no USB_GADGET_DELAYED_STATUS pending. Since the state then was already updated before we also omit the state update. Signed-off-by: Michael Grzeschik --- v5 -> v6: - v1 -> v5: - new patch --- drivers/usb/gadget/function/uvc_v4l2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index ab89f1630acb0..3492855f0fb29 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -546,6 +546,9 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) return ret; + if (uvc->state != UVC_STATE_STREAMING) + return 0; + uvc->state = UVC_STATE_CONNECTED; uvc_function_setup_continue(uvc, 1); return 0;