From patchwork Thu May 20 20:21:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Stern X-Patchwork-Id: 443762 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C837C433ED for ; Thu, 20 May 2021 20:21:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5FFCB60FDC for ; Thu, 20 May 2021 20:21:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236069AbhETUXQ (ORCPT ); Thu, 20 May 2021 16:23:16 -0400 Received: from netrider.rowland.org ([192.131.102.5]:54383 "HELO netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S236062AbhETUXP (ORCPT ); Thu, 20 May 2021 16:23:15 -0400 Received: (qmail 1217366 invoked by uid 1000); 20 May 2021 16:21:52 -0400 Date: Thu, 20 May 2021 16:21:52 -0400 From: Alan Stern To: Felipe Balbi Cc: USB mailing list Subject: [PATCH 2/4] USB: UDC: Implement udc_async_callbacks in dummy-hcd Message-ID: <20210520202152.GD1216852@rowland.harvard.edu> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This patch adds a udc_async_callbacks handler to the dummy-hcd UDC driver, which will prevent a theoretical race during gadget unbinding. The implementation is simple, since dummy-hcd already has a flag to keep track of whether emulated IRQs are enabled. All the handler has to do is store the enable value in the flag, and avoid setting the flag prematurely. Signed-off-by: Alan Stern Acked-by: Felipe Balbi --- [as1957] drivers/usb/gadget/udc/dummy_hcd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) Index: usb-devel/drivers/usb/gadget/udc/dummy_hcd.c =================================================================== --- usb-devel.orig/drivers/usb/gadget/udc/dummy_hcd.c +++ usb-devel/drivers/usb/gadget/udc/dummy_hcd.c @@ -919,6 +919,15 @@ static void dummy_udc_set_speed(struct u dummy_udc_update_ep0(dum); } +static void dummy_udc_async_callbacks(struct usb_gadget *_gadget, bool enable) +{ + struct dummy *dum = gadget_dev_to_dummy(&_gadget->dev); + + spin_lock_irq(&dum->lock); + dum->ints_enabled = enable; + spin_unlock_irq(&dum->lock); +} + static int dummy_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int dummy_udc_stop(struct usb_gadget *g); @@ -931,6 +940,7 @@ static const struct usb_gadget_ops dummy .udc_start = dummy_udc_start, .udc_stop = dummy_udc_stop, .udc_set_speed = dummy_udc_set_speed, + .udc_async_callbacks = dummy_udc_async_callbacks, }; /*-------------------------------------------------------------------------*/ @@ -990,7 +1000,6 @@ static int dummy_udc_start(struct usb_ga spin_lock_irq(&dum->lock); dum->devstatus = 0; dum->driver = driver; - dum->ints_enabled = 1; spin_unlock_irq(&dum->lock); return 0; From patchwork Thu May 20 20:22:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Stern X-Patchwork-Id: 443761 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.5 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9348C433B4 for ; Thu, 20 May 2021 20:22:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A9F1B6135B for ; Thu, 20 May 2021 20:22:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236142AbhETUX3 (ORCPT ); Thu, 20 May 2021 16:23:29 -0400 Received: from netrider.rowland.org ([192.131.102.5]:33487 "HELO netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S235955AbhETUX3 (ORCPT ); Thu, 20 May 2021 16:23:29 -0400 Received: (qmail 1217395 invoked by uid 1000); 20 May 2021 16:22:06 -0400 Date: Thu, 20 May 2021 16:22:06 -0400 From: Alan Stern To: Felipe Balbi Cc: USB mailing list Subject: [PATCH 4/4] USB: UDC: Implement udc_async_callbacks in net2272 Message-ID: <20210520202206.GF1216852@rowland.harvard.edu> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This patch adds a udc_async_callbacks handler to the net2272 UDC driver, which will prevent a theoretical race during gadget unbinding. The net2272 driver is sufficiently complicated that I didn't want to mess around with IRQ settings. Instead, the patch simply adds a new flag to control async callbacks, and checks the flag before issuing any of them. Signed-off-by: Alan Stern Acked-by: Felipe Balbi --- [as1959] drivers/usb/gadget/udc/net2272.c | 41 +++++++++++++++++++++++++-------------- drivers/usb/gadget/udc/net2272.h | 1 2 files changed, 28 insertions(+), 14 deletions(-) Index: usb-devel/drivers/usb/gadget/udc/net2272.c =================================================================== --- usb-devel.orig/drivers/usb/gadget/udc/net2272.c +++ usb-devel/drivers/usb/gadget/udc/net2272.c @@ -1149,6 +1149,7 @@ net2272_pullup(struct usb_gadget *_gadge static int net2272_start(struct usb_gadget *_gadget, struct usb_gadget_driver *driver); static int net2272_stop(struct usb_gadget *_gadget); +static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable); static const struct usb_gadget_ops net2272_ops = { .get_frame = net2272_get_frame, @@ -1157,6 +1158,7 @@ static const struct usb_gadget_ops net22 .pullup = net2272_pullup, .udc_start = net2272_start, .udc_stop = net2272_stop, + .udc_async_callbacks = net2272_async_callbacks, }; /*---------------------------------------------------------------------------*/ @@ -1475,7 +1477,7 @@ stop_activity(struct net2272 *dev, struc net2272_dequeue_all(&dev->ep[i]); /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->async_callbacks && driver) { spin_unlock(&dev->lock); driver->disconnect(&dev->gadget); spin_lock(&dev->lock); @@ -1500,6 +1502,15 @@ static int net2272_stop(struct usb_gadge return 0; } +static void net2272_async_callbacks(struct usb_gadget *_gadget, bool enable) +{ + struct net2272 *dev = container_of(_gadget, struct net2272, gadget); + + spin_lock_irq(&dev->lock); + dev->async_callbacks = enable; + spin_unlock_irq(&dev->lock); +} + /*---------------------------------------------------------------------------*/ /* handle ep-a/ep-b dma completions */ static void @@ -1909,9 +1920,11 @@ net2272_handle_stat0_irqs(struct net2272 u.r.bRequestType, u.r.bRequest, u.r.wValue, u.r.wIndex, net2272_ep_read(ep, EP_CFG)); - spin_unlock(&dev->lock); - tmp = dev->driver->setup(&dev->gadget, &u.r); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &u.r); + spin_lock(&dev->lock); + } } /* stall ep0 on error */ @@ -1993,14 +2006,14 @@ net2272_handle_stat1_irqs(struct net2272 if (disconnect || reset) { stop_activity(dev, dev->driver); net2272_ep0_start(dev); - spin_unlock(&dev->lock); - if (reset) - usb_gadget_udc_reset - (&dev->gadget, dev->driver); - else - (dev->driver->disconnect) - (&dev->gadget); - spin_lock(&dev->lock); + if (dev->async_callbacks) { + spin_unlock(&dev->lock); + if (reset) + usb_gadget_udc_reset(&dev->gadget, dev->driver); + else + (dev->driver->disconnect)(&dev->gadget); + spin_lock(&dev->lock); + } return; } } @@ -2014,14 +2027,14 @@ net2272_handle_stat1_irqs(struct net2272 if (stat & tmp) { net2272_write(dev, IRQSTAT1, tmp); if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) { - if (dev->driver->suspend) + if (dev->async_callbacks && dev->driver->suspend) dev->driver->suspend(&dev->gadget); if (!enable_suspend) { stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT); dev_dbg(dev->dev, "Suspend disabled, ignoring\n"); } } else { - if (dev->driver->resume) + if (dev->async_callbacks && dev->driver->resume) dev->driver->resume(&dev->gadget); } stat &= ~tmp; Index: usb-devel/drivers/usb/gadget/udc/net2272.h =================================================================== --- usb-devel.orig/drivers/usb/gadget/udc/net2272.h +++ usb-devel/drivers/usb/gadget/udc/net2272.h @@ -442,6 +442,7 @@ struct net2272 { softconnect:1, wakeup:1, added:1, + async_callbacks:1, dma_eot_polarity:1, dma_dack_polarity:1, dma_dreq_polarity:1,