Message ID | 20230531040203.19295-3-badhri@google.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp2630328vqr; Tue, 30 May 2023 21:26:41 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4G7snHInrlpUVZYY7ArXWRxMUPge0p2PeMlaQq2fefvHwRHG3ovtIFWtN+w6JBjhz4+DrJ X-Received: by 2002:a05:6a00:1502:b0:63e:6b8a:7975 with SMTP id q2-20020a056a00150200b0063e6b8a7975mr5531004pfu.9.1685507201019; Tue, 30 May 2023 21:26:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685507201; cv=none; d=google.com; s=arc-20160816; b=eq1TczjtnfRyc+YM5Cf53r5ymTv21s24vnFm/RlsrrT5RhsKTipFzlSDzz2zwlB9ky pDuLWi1wl6c/fZcLP+zVtjuKkWG3Fmr3f3wLYcrgmRl4BR8Icli1glfgTi+Uw23McmIh f/hxeFbQ5YuYUhz6eNtuedOdP/rL7uXI3efQxS13aQVYVTrka1uqnE0NXf5QmDLUQD9g iXl6ocGHh5F7AwXgCHEeNS9oTaDi73a0Bs7UvJpmOIdWJXNuG1ha2u043d+wAms3b66d MZ2GSduBjkdMf0zRo6Y3ddVmp/JTbJV7JXkbmv0hJtMDfO07+3hTP2Eu/McfH+hvrxew eQ/Q== 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=pTATTkgvxztq9cna9gYn1cQG7KZBsx+3nMydlu+2mlE=; b=YNG5q03aP8STPJGm6+54HNxETgDZcyQJpPlLPC55aP6P2oG3RPRNkit6T2KR+IUW5v dRaI7I4xIfnCPM5lwJTw2GX0jwmP8pnGn2LgNsKHQ3l2OJUTG7TqlMebNei2rLG8T16I w5Y32HGP58oy8qJPuvN+l4p5569yEsj0qrZZKQ3bTEqxLAG1U5M7Rut+bvvozdkGzv4K 4oVMBaPuwbwcQxsN330XFoKeiQuZ3uAS3f5e248YJlzIL/yq5ZA/YlDJKW1JfBsZbCt3 tHyllGfEY33PXVk0yakZn8jPLds20abx/8v06AGAaMjXkBbdSsM70PdMShwbe0zqSygI V1yA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=al+sJCyO; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b5-20020a63eb45000000b0053f3d04e66csi279094pgk.699.2023.05.30.21.26.29; Tue, 30 May 2023 21:26:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=al+sJCyO; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234173AbjEaEC0 (ORCPT <rfc822;callmefire3@gmail.com> + 99 others); Wed, 31 May 2023 00:02:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234064AbjEaECN (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 31 May 2023 00:02:13 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7CEB8107 for <linux-kernel@vger.kernel.org>; Tue, 30 May 2023 21:02:11 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-568c8fa027fso23385457b3.1 for <linux-kernel@vger.kernel.org>; Tue, 30 May 2023 21:02:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685505730; x=1688097730; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=pTATTkgvxztq9cna9gYn1cQG7KZBsx+3nMydlu+2mlE=; b=al+sJCyOmkaF/6ULIYjfy2VcVPz2C1bJQqcCbgFH/qdd7Y3x3ihhhi+6+rzdnEiUv8 lWpn7yW5seO+rgx/NlgTtfMTIYxkGcVq+TSRBWky9mfQUVCpRWY93+2uS5MuaL75iEDA JQ10HgpgPVDpe+CX3mqaEzbLU4+OSdpKbgU8DULnbEDbNMZ98Xg5KZYbWZrFG/RMGaGR jTnl1guy/5DX8hhiygVrhV049zJ1vcM2cd3XqRd4+0afw78MpemU5/cde1on4KzSuR9e ipRGINz/G0pNg9bKudvd2xs9iSVvrJ7sMHbVynO6oRjOrqbl9maLQHug6QJH1nM5+8b2 OqGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685505730; x=1688097730; 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=pTATTkgvxztq9cna9gYn1cQG7KZBsx+3nMydlu+2mlE=; b=gpNjUX79sOxuzC8xgQYUb7hCBmjFlM0GKLJc5wV3MH/WEmOvA84QdDdECjbaBP9wQy kRbEoq7ksNWz1kO4FBXQi4j5yrZ+l5fc2NXTMbwcRlHEiBzDCqvvN2WYYz7y0mvY+ElU So8A12DimtVLZ2Zn3qkens0BGwUvqWON1SHwT78Xkuul4oMMG6OGPU3iiKebePGVbfsf SKR8RUXF+JSz2CZq3S62yIVBL1YNoBOPtrSjIcqhIsuS4cS3PdsHRqO01tE34lfinkGE iS6wfCDA3zd32IqGykAy4oSpq2JDZs9FVvyuLjij1+6qUDJKOK5OHcElomFB8qyTsLhf MfRw== X-Gm-Message-State: AC+VfDy8HubpjWYNqfZZ65EiyXspj//PkfmorTglIpexRFqj1FMT7Jpw XNuPTiTGX5zE91Icisssf3ZOu+U4JIU= X-Received: from badhri.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:6442]) (user=badhri job=sendgmr) by 2002:a81:b661:0:b0:565:ce25:2693 with SMTP id h33-20020a81b661000000b00565ce252693mr2529499ywk.3.1685505730774; Tue, 30 May 2023 21:02:10 -0700 (PDT) Date: Wed, 31 May 2023 04:02:03 +0000 In-Reply-To: <20230531040203.19295-1-badhri@google.com> Mime-Version: 1.0 References: <20230531040203.19295-1-badhri@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230531040203.19295-3-badhri@google.com> Subject: [PATCH v5 3/3] usb: gadget: udc: core: Prevent UDC from starting when unbound From: Badhri Jagan Sridharan <badhri@google.com> To: gregkh@linuxfoundation.org, stern@rowland.harvard.edu, colin.i.king@gmail.com, xuetao09@huawei.com, quic_eserrao@quicinc.com, water.zhangjiantao@huawei.com, peter.chen@freescale.com, balbi@ti.com, francesco@dolcini.it, alistair@alistair23.me, stephan@gerhold.net, bagasdotme@gmail.com, luca@z3ntu.xyz Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Badhri Jagan Sridharan <badhri@google.com>, stable <stable@kernel.org> Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767382398514890342?= X-GMAIL-MSGID: =?utf-8?q?1767382398514890342?= |
Series |
[v5,1/3] usb: gadget: udc: core: Offload usb_udc_vbus_handler processing
|
|
Commit Message
Badhri Jagan Sridharan
May 31, 2023, 4:02 a.m. UTC
UDC should neither be started nor pulled up unless the gadget driver is
bound. The new flag "allow_start" is now set by gadget_bind_driver()
and cleared by gadget_unbind_driver(). usb_gadget_udc_start_locked()
now checks whether allow_start is set before starting the UDC by
invoking the ->udc_start() callback.
Fixes: fc274c1e9973 ("USB: gadget: Add a new bus for gadgets")
Cc: stable <stable@kernel.org>
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
---
v5 is the first version in this series.
---
drivers/usb/gadget/udc/core.c | 8 ++++++++
1 file changed, 8 insertions(+)
Comments
On Wed, May 31, 2023 at 04:02:03AM +0000, Badhri Jagan Sridharan wrote: > UDC should neither be started nor pulled up unless the gadget driver is > bound. The new flag "allow_start" is now set by gadget_bind_driver() > and cleared by gadget_unbind_driver(). usb_gadget_udc_start_locked() > now checks whether allow_start is set before starting the UDC by > invoking the ->udc_start() callback. "allow_start" isn't quite the right name either, because there is a short time interval during which the UDC is started but we don't want to allow it to connect to the host (this occurs in gadget_unbind_driver() between the disconnect call and the usb_gadge_udc_stop call). A more accurate name would be "allow_connect" or "allow_pullup". > Fixes: fc274c1e9973 ("USB: gadget: Add a new bus for gadgets") > Cc: stable <stable@kernel.org> > Signed-off-by: Badhri Jagan Sridharan <badhri@google.com> > --- > v5 is the first version in this series. > --- > drivers/usb/gadget/udc/core.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c > index 6ffe5fda8bb7..ac9d6186815d 100644 > --- a/drivers/usb/gadget/udc/core.c > +++ b/drivers/usb/gadget/udc/core.c > @@ -37,6 +37,8 @@ static const struct bus_type gadget_bus_type; > * @vbus: for udcs who care about vbus status, this value is real vbus status; > * for udcs who do not care about vbus status, this value is always true > * @started: the UDC's started state. True if the UDC had started. > + * @allow_start: Indicates whether UDC is allowed to start. Set/cleared by gadget_(un)bind_driver() > + * after gadget driver is bound or unbound. > * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related > * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked, > * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are As before, wrap the comments around column 76. > @@ -52,6 +54,7 @@ struct usb_udc { > struct list_head list; > bool vbus; > bool started; > + bool allow_start; > struct work_struct vbus_work; > struct mutex connect_lock; > }; > @@ -1204,6 +1207,9 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) > if (udc->started) { > dev_err(&udc->dev, "UDC had already started\n"); > return -EBUSY; > + } else if (!udc->allow_start) { > + dev_err(&udc->dev, "UDC not allowed to start. Is gadget driver bound ?\n"); > + return -EIO; > } This isn't the right test or the right place. We want to prevent the UDC from connecting to the host, not prevent it from starting. > > ret = udc->gadget->ops->udc_start(udc->gadget, udc->driver); > @@ -1590,6 +1596,7 @@ static int gadget_bind_driver(struct device *dev) > goto err_bind; > > mutex_lock(&udc->connect_lock); > + udc->allow_start = true; > ret = usb_gadget_udc_start_locked(udc); > if (ret) { > mutex_unlock(&udc->connect_lock); > @@ -1630,6 +1637,7 @@ static void gadget_unbind_driver(struct device *dev) > > cancel_work_sync(&udc->vbus_work); > mutex_lock(&udc->connect_lock); > + udc->allow_start = false; > usb_gadget_disconnect_locked(gadget); > usb_gadget_disable_async_callbacks(udc); > if (gadget->irq) Here is where the problem about the vbus work item getting requeued can be fixed. Clear the allow_connect flag before the call to cancel_work_sync(). That way, even if the vbus work item gets queued again after it is cancelled, when it does run it won't do anything. Although, come to think of it, there is still the problem of making sure that the work item doesn't run after the udc has been deallocated. It looks like you will also need to cancel the work item at the end of usb_del_gadget(). At that point the UDC has already been stopped, so it won't call usb_hcd_vbus_handler() again. Alan Stern
On Wed, May 31, 2023 at 10:40 AM Alan Stern <stern@rowland.harvard.edu> wrote: > > On Wed, May 31, 2023 at 04:02:03AM +0000, Badhri Jagan Sridharan wrote: > > UDC should neither be started nor pulled up unless the gadget driver is > > bound. The new flag "allow_start" is now set by gadget_bind_driver() > > and cleared by gadget_unbind_driver(). usb_gadget_udc_start_locked() > > now checks whether allow_start is set before starting the UDC by > > invoking the ->udc_start() callback. > > "allow_start" isn't quite the right name either, because there is a > short time interval during which the UDC is started but we don't want > to allow it to connect to the host (this occurs in > gadget_unbind_driver() between the disconnect call and the > usb_gadge_udc_stop call). A more accurate name would be "allow_connect" > or "allow_pullup". Sure, Have renamed the flag to "allow_connect". > > > Fixes: fc274c1e9973 ("USB: gadget: Add a new bus for gadgets") > > Cc: stable <stable@kernel.org> > > Signed-off-by: Badhri Jagan Sridharan <badhri@google.com> > > --- > > v5 is the first version in this series. > > --- > > drivers/usb/gadget/udc/core.c | 8 ++++++++ > > 1 file changed, 8 insertions(+) > > > > diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c > > index 6ffe5fda8bb7..ac9d6186815d 100644 > > --- a/drivers/usb/gadget/udc/core.c > > +++ b/drivers/usb/gadget/udc/core.c > > @@ -37,6 +37,8 @@ static const struct bus_type gadget_bus_type; > > * @vbus: for udcs who care about vbus status, this value is real vbus status; > > * for udcs who do not care about vbus status, this value is always true > > * @started: the UDC's started state. True if the UDC had started. > > + * @allow_start: Indicates whether UDC is allowed to start. Set/cleared by gadget_(un)bind_driver() > > + * after gadget driver is bound or unbound. > > * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related > > * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked, > > * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are > > As before, wrap the comments around column 76. Sounds good ! Have addressed this in v6. Wrapping comments at 76. > > > @@ -52,6 +54,7 @@ struct usb_udc { > > struct list_head list; > > bool vbus; > > bool started; > > + bool allow_start; > > struct work_struct vbus_work; > > struct mutex connect_lock; > > }; > > @@ -1204,6 +1207,9 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) > > if (udc->started) { > > dev_err(&udc->dev, "UDC had already started\n"); > > return -EBUSY; > > + } else if (!udc->allow_start) { > > + dev_err(&udc->dev, "UDC not allowed to start. Is gadget driver bound ?\n"); > > + return -EIO; > > } > > This isn't the right test or the right place. We want to prevent the > UDC from connecting to the host, not prevent it from starting. > > > > > ret = udc->gadget->ops->udc_start(udc->gadget, udc->driver); > > @@ -1590,6 +1596,7 @@ static int gadget_bind_driver(struct device *dev) > > goto err_bind; > > > > mutex_lock(&udc->connect_lock); > > + udc->allow_start = true; > > ret = usb_gadget_udc_start_locked(udc); > > if (ret) { > > mutex_unlock(&udc->connect_lock); > > @@ -1630,6 +1637,7 @@ static void gadget_unbind_driver(struct device *dev) > > > > cancel_work_sync(&udc->vbus_work); > > mutex_lock(&udc->connect_lock); > > + udc->allow_start = false; > > usb_gadget_disconnect_locked(gadget); > > usb_gadget_disable_async_callbacks(udc); > > if (gadget->irq) > > Here is where the problem about the vbus work item getting requeued can > be fixed. Clear the allow_connect flag before the call to > cancel_work_sync(). That way, even if the vbus work item gets queued > again after it is cancelled, when it does run it won't do anything. > > Although, come to think of it, there is still the problem of making sure > that the work item doesn't run after the udc has been deallocated. It > looks like you will also need to cancel the work item at the end of > usb_del_gadget(). At that point the UDC has already been stopped, so it > won't call usb_hcd_vbus_handler() again. Sure, Have made these changes in V6. Thanks a lot, Badhri > > Alan Stern
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 6ffe5fda8bb7..ac9d6186815d 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -37,6 +37,8 @@ static const struct bus_type gadget_bus_type; * @vbus: for udcs who care about vbus status, this value is real vbus status; * for udcs who do not care about vbus status, this value is always true * @started: the UDC's started state. True if the UDC had started. + * @allow_start: Indicates whether UDC is allowed to start. Set/cleared by gadget_(un)bind_driver() + * after gadget driver is bound or unbound. * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked, * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are @@ -52,6 +54,7 @@ struct usb_udc { struct list_head list; bool vbus; bool started; + bool allow_start; struct work_struct vbus_work; struct mutex connect_lock; }; @@ -1204,6 +1207,9 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) if (udc->started) { dev_err(&udc->dev, "UDC had already started\n"); return -EBUSY; + } else if (!udc->allow_start) { + dev_err(&udc->dev, "UDC not allowed to start. Is gadget driver bound ?\n"); + return -EIO; } ret = udc->gadget->ops->udc_start(udc->gadget, udc->driver); @@ -1590,6 +1596,7 @@ static int gadget_bind_driver(struct device *dev) goto err_bind; mutex_lock(&udc->connect_lock); + udc->allow_start = true; ret = usb_gadget_udc_start_locked(udc); if (ret) { mutex_unlock(&udc->connect_lock); @@ -1630,6 +1637,7 @@ static void gadget_unbind_driver(struct device *dev) cancel_work_sync(&udc->vbus_work); mutex_lock(&udc->connect_lock); + udc->allow_start = false; usb_gadget_disconnect_locked(gadget); usb_gadget_disable_async_callbacks(udc); if (gadget->irq)