From patchwork Thu Oct 12 00:24:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avichal Rakesh X-Patchwork-Id: 151632 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2908:b0:403:3b70:6f57 with SMTP id ib8csp899161vqb; Wed, 11 Oct 2023 17:25:22 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFOoPdiXSe9esAFgExD+2uG+MJO6/f+HjdeNpzA+Ie7I+E+gadeh/lk7T+2/2vglk8E5zr5 X-Received: by 2002:a17:902:a40e:b0:1c9:bd60:72a6 with SMTP id p14-20020a170902a40e00b001c9bd6072a6mr5799901plq.4.1697070321991; Wed, 11 Oct 2023 17:25:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697070321; cv=none; d=google.com; s=arc-20160816; b=LGAMAEH9xB6lmU5ptbwOvzbTz2G41SEJzenoANaGgFXLacE6W/DPzS6Wm0i7iZCuQ5 QLXATA1S9ANN+eW6j1K1G2X8SxL+AIrx89ZqUC6z4lTmE+qRFWJFo1aKzvbMGZDyQKPq jyQZ8Yj53HJ+22L/fa6I+iRWMAk6zMx3BXiluoF/2mSZZCJ16/BXElCwHIRyz2M5a1bv Lxh68Z5i+MhjfZRnnYiNmIdmQhbg5rxJ5xJotV3r/9zVd7MulMxHiiY+PXWl8Rl6NmBh a0vdXeokjLsE0uK14hOTEQ/ZUpE31k3mCX4jSAZ5+ZYLaiTS3nz9CzpvsuT6ILxeiCeQ Ze8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=TG++fvWfitw/Sd3Hpgv4FLh87i4JPu5cxo2T/O4RJwY=; fh=0wk28KT8ebzzQgtMVSsY3TFcpC6qYdokWdikfW1Lhwk=; b=R9vMzeyUEGLfaMRf8rX0LMTQ0iBFHMG9d56uguM3IXvZEqgSDOSaYma0zWaDsxCsj4 HxUUpG0AaWm9t6hwY71of6hV2AlxB7BIDbJc98tQRVAYfiGJEBfzLq/+n6kyKgdNu1u2 Xp9laMo2tMbhT0MrIFfpNYCjFDBQTfxtRo2g1bVwBbNjbI2FxfijhbGiBKqxMeNoubI/ erHyLS+ACxFnoBZtIKotDXbjieBEkGdyLeYMnArLX1DunrhxGlWLXKvY0WwIydaKU7y9 Fe2A7Mj7fovEp7Pggg8UQj7/LXyNV/MnGwJRqSZDJ3zcoh4LgXtevS/8EWyNwYUB0h8x F5Kg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=IQ7LCc4d; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from pete.vger.email (pete.vger.email. [23.128.96.36]) by mx.google.com with ESMTPS id i14-20020a170902c94e00b001c61bd7cee0si974427pla.211.2023.10.11.17.25.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Oct 2023 17:25:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) client-ip=23.128.96.36; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=IQ7LCc4d; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by pete.vger.email (Postfix) with ESMTP id 9D589818FBD4; Wed, 11 Oct 2023 17:25:14 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233919AbjJLAY5 (ORCPT + 18 others); Wed, 11 Oct 2023 20:24:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40640 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231381AbjJLAY4 (ORCPT ); Wed, 11 Oct 2023 20:24:56 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7F58B94 for ; Wed, 11 Oct 2023 17:24:55 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id d9443c01a7336-1c9d140fb3eso3484595ad.3 for ; Wed, 11 Oct 2023 17:24:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1697070295; x=1697675095; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=TG++fvWfitw/Sd3Hpgv4FLh87i4JPu5cxo2T/O4RJwY=; b=IQ7LCc4dLlKSkhl/k/jDiI6c6qxEapg6q03XfT+vMZt/x6+16yOiUq4zLS8KnCRBEd s3beUpzLqnK3yJ6QavMqqgcsL6GbjizRR6HdI9Af32TX26zaTkAPDi4WeFNOkNxVTkME 2FyvtiLucNPxALbvDGfQSW4cpIIi6cQNXKvbyNOP//qbeDB9LL2BkVGHjuwBwClHXj7U Aa637zUHDVlepYSQH4bfiwxw5CrNnKeImblV621OlWgvJciTJDnfKOBv3Pp2b3IKAm4v NvZYsQTouwY4LkppeCC8nJ1bsOWhaaaZDPJrHw911uBRGrmQN9vJeMQ3ZyR59mYqRuJH 04IQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697070295; x=1697675095; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TG++fvWfitw/Sd3Hpgv4FLh87i4JPu5cxo2T/O4RJwY=; b=SqaerRqrBkUw5ATmVN0fUtkaQEzMfhnQAg6hQBT4ABq9y2LchhcfBdtbsFrR4c6QBa 7LfwKW+LgPNcoRZcHAEWYy2kHX6UqPZSbs0AmSoEjD7QCS7OQjt3F2npcTolA3oqtjB4 MrIaQ6bkjizeNAE+GFSYVJDHHZ+nY1p3EHm4xpfFR8UpT2KZEJXYkdsR+iMye3Xj5bRv hfRO8AVf8eK47dC78IFGVrliqREZE5FRWeBRL0D0BbXJ9I/vGzWK0SVTKJ4h04v9w1oZ mXZfG44yWJvjvmmL3o0X0I1/iNR5PElC2V4feFLXBYvxJYXXyFk12aSKugMyNc8EkkZu lNTA== X-Gm-Message-State: AOJu0YyGj0VH/93ARmPK/5jEm9fkg1T1SHH2Sl91BBWvdWuEln6dm4rH jmuIqPDxr8M/Uz1cl7gbvHSQ0Tiysjws X-Received: from hi-h2o-specialist.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:3cef]) (user=arakesh job=sendgmr) by 2002:a17:90b:2391:b0:27d:1cfb:7185 with SMTP id mr17-20020a17090b239100b0027d1cfb7185mr21475pjb.9.1697070294985; Wed, 11 Oct 2023 17:24:54 -0700 (PDT) Date: Wed, 11 Oct 2023 17:24:49 -0700 In-Reply-To: <20230930184821.310143-1-arakesh@google.com> Mime-Version: 1.0 References: <20230930184821.310143-1-arakesh@google.com> X-Mailer: git-send-email 2.42.0.609.gbb76f46606-goog Message-ID: <20231012002451.254737-1-arakesh@google.com> Subject: [PATCH v4 1/3] usb: gadget: uvc: prevent use of disabled endpoint From: Avichal Rakesh To: arakesh@google.com, dan.scally@ideasonboard.com, laurent.pinchart@ideasonboard.com, m.grzeschik@pengutronix.de Cc: etalvala@google.com, gregkh@linuxfoundation.org, jchowdhary@google.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org X-Spam-Status: No, score=-4.8 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on pete.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (pete.vger.email [0.0.0.0]); Wed, 11 Oct 2023 17:25:14 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778501398075540037 X-GMAIL-MSGID: 1779507210029008949 Currently the set_alt callback immediately disables the endpoint and queues the v4l2 streamoff event. However, as the streamoff event is processed asynchronously, it is possible that the video_pump thread attempts to queue requests to an already disabled endpoint. This change moves disabling usb endpoint to the end of streamoff event callback. As the endpoint's state can no longer be used, video_pump is now guarded by uvc->state as well. To be consistent with the actual streaming state, uvc->state is now toggled between CONNECTED and STREAMING from the v4l2 event callback only. Link: https://lore.kernel.org/20230615171558.GK741@pendragon.ideasonboard.com/ Link: https://lore.kernel.org/20230531085544.253363-1-dan.scally@ideasonboard.com/ Reviewed-by: Michael Grzeschik Signed-off-by: Avichal Rakesh --- v1 -> v2: Rebased to ToT and reworded commit message. v2 -> v3: Fix email threading goof-up v3 -> v4: Address review comments & re-rebase to ToT drivers/usb/gadget/function/f_uvc.c | 11 +++++------ drivers/usb/gadget/function/f_uvc.h | 2 +- drivers/usb/gadget/function/uvc.h | 2 +- drivers/usb/gadget/function/uvc_v4l2.c | 21 ++++++++++++++++++--- drivers/usb/gadget/function/uvc_video.c | 3 ++- 5 files changed, 27 insertions(+), 12 deletions(-) -- 2.42.0.609.gbb76f46606-goog diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index faa398109431..ae08341961eb 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -263,10 +263,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) return 0; } -void uvc_function_setup_continue(struct uvc_device *uvc) +void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep) { struct usb_composite_dev *cdev = uvc->func.config->cdev; + if (disable_ep && uvc->video.ep) + usb_ep_disable(uvc->video.ep); + usb_composite_setup_continue(cdev); } @@ -337,15 +340,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) if (uvc->state != UVC_STATE_STREAMING) return 0; - if (uvc->video.ep) - usb_ep_disable(uvc->video.ep); - memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMOFF; v4l2_event_queue(&uvc->vdev, &v4l2_event); - uvc->state = UVC_STATE_CONNECTED; - return 0; + return USB_GADGET_DELAYED_STATUS; case 1: if (uvc->state != UVC_STATE_CONNECTED) diff --git a/drivers/usb/gadget/function/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h index 1db972d4beeb..e7f9f13f14dc 100644 --- a/drivers/usb/gadget/function/f_uvc.h +++ b/drivers/usb/gadget/function/f_uvc.h @@ -11,7 +11,7 @@ struct uvc_device; -void uvc_function_setup_continue(struct uvc_device *uvc); +void uvc_function_setup_continue(struct uvc_device *uvc, int disale_ep); void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 6751de8b63ad..989bc6b4e93d 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -177,7 +177,7 @@ struct uvc_file_handle { * Functions */ -extern void uvc_function_setup_continue(struct uvc_device *uvc); +extern void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep); extern void uvc_function_connect(struct uvc_device *uvc); extern void uvc_function_disconnect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 3f0a9795c0d4..c0d77564a204 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -451,7 +451,7 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) * Complete the alternate setting selection setup phase now that * userspace is ready to provide video frames. */ - uvc_function_setup_continue(uvc); + uvc_function_setup_continue(uvc, 0); uvc->state = UVC_STATE_STREAMING; return 0; @@ -463,11 +463,19 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) struct video_device *vdev = video_devdata(file); struct uvc_device *uvc = video_get_drvdata(vdev); struct uvc_video *video = &uvc->video; + int ret = 0; if (type != video->queue.queue.type) return -EINVAL; - return uvcg_video_enable(video, 0); + uvc->state = UVC_STATE_CONNECTED; + ret = uvcg_video_enable(video, 0); + if (ret < 0) { + return ret; + } + + uvc_function_setup_continue(uvc, 1); + return 0; } static int @@ -500,6 +508,14 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, static void uvc_v4l2_disable(struct uvc_device *uvc) { uvc_function_disconnect(uvc); + /* + * Drop uvc->state to CONNECTED if it was streaming before. + * This ensures that the usb_requests are no longer queued + * to the controller. + */ + if (uvc->state == UVC_STATE_STREAMING) + uvc->state = UVC_STATE_CONNECTED; + uvcg_video_enable(&uvc->video, 0); uvcg_free_buffers(&uvc->video.queue); uvc->func_connected = false; @@ -647,4 +663,3 @@ const struct v4l2_file_operations uvc_v4l2_fops = { .get_unmapped_area = uvcg_v4l2_get_unmapped_area, #endif }; - diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 91af3b1ef0d4..c334802ac0a4 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -384,13 +384,14 @@ static void uvcg_video_pump(struct work_struct *work) struct uvc_video_queue *queue = &video->queue; /* video->max_payload_size is only set when using bulk transfer */ bool is_bulk = video->max_payload_size; + struct uvc_device *uvc = video->uvc; struct usb_request *req = NULL; struct uvc_buffer *buf; unsigned long flags; bool buf_done; int ret; - while (video->ep->enabled) { + while (uvc->state == UVC_STATE_STREAMING && video->ep->enabled) { /* * Retrieve the first available USB request, protected by the * request lock.