From patchwork Tue Sep 18 14:18:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minas Harutyunyan X-Patchwork-Id: 10604413 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 052A613AD for ; Tue, 18 Sep 2018 14:19:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8B472AD74 for ; Tue, 18 Sep 2018 14:19:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DCCBC2AD86; Tue, 18 Sep 2018 14:19:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CFFE12AD74 for ; Tue, 18 Sep 2018 14:19:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729416AbeIRTwC (ORCPT ); Tue, 18 Sep 2018 15:52:02 -0400 Received: from us01smtprelay-2.synopsys.com ([198.182.47.9]:45582 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728065AbeIRTwC (ORCPT ); Tue, 18 Sep 2018 15:52:02 -0400 Received: from mailhost.synopsys.com (mailhost2.synopsys.com [10.13.184.66]) by smtprelay.synopsys.com (Postfix) with ESMTP id 418DB24E118A; Tue, 18 Sep 2018 07:19:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1537280354; bh=wTCI2NYN9NgKXF+4FXGlE4ajadMxSUmxE0QE26z8Ql0=; h=Date:From:Subject:To:CC:From; b=AfVb8HUrWxXCscd5PyWiPv03Pk++mxD8N+2/ZR90NJtXxLTsRgWBPl7mYtoNJxAut ZXw6MG4uyAHVItJd/grFsD1jBzUUn7xOQ0F/JjShPXoQOWaSOoQG6O+KRBZOCYklne VW4nM9wbWu2Y+zYzguRjOP51qCiViwZf9A4lLsr9alB8TuOw34RSj8tVEPDPa3p5S6 YChGR/PlmvAPluxfz248dkbC0H7GR8jxXG5m5CYPkS/80+6DZtUbc7YzpKbXprY31l UqfpHrvwlVp4Z03mPdxlNUSBg4OaKXC5NmuwHq1cl/sN+M3vDQIu67lYBPL7OSrOG9 cKhyBgkwhLO9Q== Received: from US01WEHTC2.internal.synopsys.com (us01wehtc2.internal.synopsys.com [10.12.239.237]) by mailhost.synopsys.com (Postfix) with ESMTP id 13FC63469; Tue, 18 Sep 2018 07:19:14 -0700 (PDT) Received: from US01WEHTC3.internal.synopsys.com (10.15.84.232) by US01WEHTC2.internal.synopsys.com (10.12.239.237) with Microsoft SMTP Server (TLS) id 14.3.361.1; Tue, 18 Sep 2018 07:18:56 -0700 Received: from hminas-z420 (10.13.184.20) by US01WEHTC3.internal.synopsys.com (10.15.84.231) with Microsoft SMTP Server (TLS) id 14.3.361.1; Tue, 18 Sep 2018 07:18:53 -0700 Received: by hminas-z420 (sSMTP sendmail emulation); Tue, 18 Sep 2018 18:18:49 +0400 Date: Tue, 18 Sep 2018 18:18:49 +0400 Message-ID: From: Minas Harutyunyan Subject: [PATCH] usb: dwc2: Disable all EP's on disconnect To: Felipe Balbi , Greg Kroah-Hartman , Minas Harutyunyan , CC: John Youn MIME-Version: 1.0 X-Originating-IP: [10.13.184.20] Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Disabling all EP's allow to reset EP's to initial state. On disconnect disable all EP's instead of just killing all requests. Because of some platform didn't catch disconnect event, same stuff added to dwc2_hsotg_core_init_disconnected() function when USB reset detected on the bus. In dwc2_hsotg_ep_disable() function before locking hsotg->lock, check if it locked by calling functions then unlock. Lock again on exit if it was locked. Same lock checking flow added to dwc2_hsotg_udc_stop() function. Signed-off-by: Minas Harutyunyan --- drivers/usb/dwc2/gadget.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 220c0f9b89b0..30975731812e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3109,6 +3109,8 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); } +static int dwc2_hsotg_ep_disable(struct usb_ep *ep); + /** * dwc2_hsotg_disconnect - disconnect service * @hsotg: The device state. @@ -3127,13 +3129,12 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) hsotg->connected = 0; hsotg->test_mode = 0; + /* all endpoints should be shutdown */ for (ep = 0; ep < hsotg->num_of_eps; ep++) { if (hsotg->eps_in[ep]) - kill_all_requests(hsotg, hsotg->eps_in[ep], - -ESHUTDOWN); + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); if (hsotg->eps_out[ep]) - kill_all_requests(hsotg, hsotg->eps_out[ep], - -ESHUTDOWN); + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); } call_gadget(hsotg, disconnect); @@ -3191,13 +3192,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, u32 val; u32 usbcfg; u32 dcfg = 0; + int ep; /* Kill any ep0 requests as controller will be reinitialized */ kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); - if (!is_usb_reset) + if (!is_usb_reset) { if (dwc2_core_reset(hsotg, true)) return; + } else { + /* all endpoints should be shutdown */ + for (ep = 1; ep < hsotg->num_of_eps; ep++) { + if (hsotg->eps_in[ep]) + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); + if (hsotg->eps_out[ep]) + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); + } + } /* * we must now enable ep0 ready for host detection and then @@ -3993,6 +4004,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) unsigned long flags; u32 epctrl_reg; u32 ctrl; + int locked; dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep); @@ -4008,6 +4020,8 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); + locked = spin_trylock(&hsotg->lock); + spin_unlock(&hsotg->lock); spin_lock_irqsave(&hsotg->lock, flags); ctrl = dwc2_readl(hsotg, epctrl_reg); @@ -4033,6 +4047,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) hs_ep->fifo_size = 0; spin_unlock_irqrestore(&hsotg->lock, flags); + if (!locked) + spin_lock(&hsotg->lock); + return 0; } @@ -4316,6 +4333,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) struct dwc2_hsotg *hsotg = to_hsotg(gadget); unsigned long flags = 0; int ep; + int locked; if (!hsotg) return -ENODEV; @@ -4328,6 +4346,8 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); } + locked = spin_trylock(&hsotg->lock); + spin_unlock(&hsotg->lock); spin_lock_irqsave(&hsotg->lock, flags); hsotg->driver = NULL; @@ -4335,6 +4355,8 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); + if (!locked) + spin_lock(&hsotg->lock); if (!IS_ERR_OR_NULL(hsotg->uphy)) otg_set_peripheral(hsotg->uphy->otg, NULL);