From patchwork Mon Nov 17 08:59:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 5316371 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BD2F59F1E1 for ; Mon, 17 Nov 2014 08:59:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DFBC220125 for ; Mon, 17 Nov 2014 08:59:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D73AB2010B for ; Mon, 17 Nov 2014 08:59:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751607AbaKQI7o (ORCPT ); Mon, 17 Nov 2014 03:59:44 -0500 Received: from mailout3.w1.samsung.com ([210.118.77.13]:34397 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751464AbaKQI7n (ORCPT ); Mon, 17 Nov 2014 03:59:43 -0500 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NF600BU1EGAWD40@mailout3.w1.samsung.com>; Mon, 17 Nov 2014 09:02:34 +0000 (GMT) X-AuditID: cbfec7f4-b7f6c6d00000120b-53-5469b8fd7e88 Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id FB.CC.04619.DF8B9645; Mon, 17 Nov 2014 08:59:41 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0NF600IEJEBC0A50@eusync4.samsung.com>; Mon, 17 Nov 2014 08:59:41 +0000 (GMT) From: Marek Szyprowski To: linux-usb@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Kyungmin Park , Robert Baldyga , Paul Zimmerman , Krzysztof Kozlowski , Felipe Balbi Subject: [PATCH v5] usb: dwc2/gadget: rework disconnect event handling Date: Mon, 17 Nov 2014 09:59:42 +0100 Message-id: <1416214782-13911-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <54699561.5040303@samsung.com> References: <54699561.5040303@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrEJMWRmVeSWpSXmKPExsVy+t/xa7p/d2SGGLTfV7Q4eL/e4vULQ4uz TW/YLWac38dksWhZK7PF2iN32S22T5nOZPHg8E52Bw6Pvi2rGD227P/M6HH8xnYmj8+b5AJY orhsUlJzMstSi/TtErgyGi6vZi+4JFHROzmsgfGTcBcjJ4eEgInEnSNPWSBsMYkL99azdTFy cQgJLGWU2LdyBjuE08ck8fbZNmaQKjYBQ4mut11sILaIgIPEkqV3wGxmgZ+MEpd+8HUxcnAI C7hJXLoSCRJmEVCVuL3xPiuIzSvgIbF26SNWiGVyEv9frmACsTkFtCWmHT4MNkZIQEvi64E1 bBMYeRcwMqxiFE0tTS4oTkrPNdQrTswtLs1L10vOz93ECAmnLzsYFx+zOsQowMGoxMP7oC8z RIg1say4MvcQowQHs5IIr/I2oBBvSmJlVWpRfnxRaU5q8SFGJg5OqQbGlaFH5GtnZrxkMTHP OnCBbbrl98CmC4FVyTsOr9f7Nf/OSyvJ1yrmE1pyGeSXtrFr6xS2zXD++FVnxqLas9wlW1dE nOYumCYxMy4tVye59FpxU1NvkeLyU7WyHGtT1ixL+zK36eyBRxlqAZHzaje/atvyJqjnrq6q PJtwe4mO9O/oTcVr/95TYinOSDTUYi4qTgQAqUBjjAUCAAA= Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a call to s3c_hsotg_disconnect() from 'end session' interrupt (GOTGINT_SES_END_DET) to correctly notify gadget subsystem about unplugged usb cable. DISCONNINT interrupt cannot be used for this purpose, because it is asserted only in host mode. To avoid reporting disconnect event more than once, a disconnect call has been moved from USB_REQ_SET_ADDRESS handling function to SESSREQINT interrupt. This way driver ensures that disconnect event is reported either when usb cable is unplugged or every time the host starts a new session. To handle devices which has been synthesized without SRP support, connected state is set in ENUMDONE interrupt. Signed-off-by: Marek Szyprowski Acked-by: Paul Zimmerman --- drivers/usb/dwc2/core.h | 1 + drivers/usb/dwc2/gadget.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 55c90c53f2d6..e54c3c50cd48 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -210,6 +210,7 @@ struct s3c_hsotg { u8 ctrl_buff[8]; struct usb_gadget gadget; + unsigned int connected:1; unsigned int setup; unsigned long last_rst; struct s3c_hsotg_ep *eps; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index fcd2bb55ccca..89b1bea50ee3 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1029,7 +1029,6 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, } static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); -static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); /** * s3c_hsotg_stall_ep0 - stall ep0 @@ -1107,7 +1106,6 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: - s3c_hsotg_disconnect(hsotg); dcfg = readl(hsotg->regs + DCFG); dcfg &= ~DCFG_DEVADDR_MASK; dcfg |= (le16_to_cpu(ctrl->wValue) << @@ -2031,6 +2029,10 @@ static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg) { unsigned ep; + if (!hsotg->connected) + return; + + hsotg->connected = 0; for (ep = 0; ep < hsotg->num_of_eps; ep++) kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true); @@ -2290,17 +2292,27 @@ irq_retry: dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); writel(otgint, hsotg->regs + GOTGINT); + + if (otgint & GOTGINT_SES_END_DET) { + s3c_hsotg_disconnect(hsotg); + hsotg->gadget.speed = USB_SPEED_UNKNOWN; + } } if (gintsts & GINTSTS_SESSREQINT) { dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__); writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS); + /* + * Report disconnect if there is any previous session established + */ + s3c_hsotg_disconnect(hsotg); } if (gintsts & GINTSTS_ENUMDONE) { writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS); s3c_hsotg_irq_enumdone(hsotg); + hsotg->connected = 1; } if (gintsts & GINTSTS_CONIDSTSCHNG) {