Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp1011070ybe; Wed, 4 Sep 2019 11:06:50 -0700 (PDT) X-Google-Smtp-Source: APXvYqwZqvincREpjKsgY8MqS2PPDq58adVPrdiQtZllxSy8q3ZC0AH+sSNVoDaW3faOtM+sCQbf X-Received: by 2002:a63:9e56:: with SMTP id r22mr36215658pgo.221.1567620410675; Wed, 04 Sep 2019 11:06:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1567620410; cv=none; d=google.com; s=arc-20160816; b=SUlf5ZGb7c1fXgwp8e+ETmBq07MV+kKP3Nyg1PVA6ft6/gxkxT20BzVN5DZlmPugY4 54/8bNIUhR1C0Nxmv3WTB4HfbJU+XMavIdP7QRo7mlSBhcxYwP1EYwvlvwlDi9aoWNEt yfu/8Wlor/thPNdR/M8ulz/bbGEfwzlbs3BnrvyTQiINF0e4A38TCKGbodEITZcaTwPx 8sRF4WcXSV4IhcUa91/TGFfSwtpK9yn29/mJwMDd4fE8MKT2K1xY96cEPzS9Ikb6XCTk q8fon4p9U6ZFJXNraUiIU92P1t+14jAiuTzsncpWY6bNJAT/2IC/9VWHLOU3jCBtXYSK /CCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=8qK3y8f/Vp1wk0tDrh8ru0N5nQH0s5awHgobgHl2EFs=; b=GRTE6HBlvKTSv5T1Ncy5YyaYSlisk9PqBRAqPD5ujcj5BtcJd25BydMVX8whM8eDsX je3vuqtKRmvLvmk1uGe9iwg6x++Hx0tAMr2l3w1782L2njWIhL92WG6oflb2zaReZKnY awO4XuAL6F38nV2fwRvXiIN2mpGbt+gRnl8c5ABcwBEhbHWkHjcNXhPpXXcJ64q8cED3 SEmoCpf0mUebqe6lVRPQBlkJh40JGbvVc4PMd6zf4NW8UkkV+KqvkQSq+9Y+w5mnyK6q xg/Kax/bPRCUC4u2pZNquq/OTU7jFy/xWLy10fea7yJr5hYBAJokNvMEOuE7RnMH0ovi y5lQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=UVBRu01R; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d13si21225387pfo.33.2019.09.04.11.06.26; Wed, 04 Sep 2019 11:06:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=UVBRu01R; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388984AbfIDSDm (ORCPT + 99 others); Wed, 4 Sep 2019 14:03:42 -0400 Received: from mail.kernel.org ([198.145.29.99]:44344 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388190AbfIDSDl (ORCPT ); Wed, 4 Sep 2019 14:03:41 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4772322CEA; Wed, 4 Sep 2019 18:03:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1567620219; bh=Jqa7KwWv6RvHZOOVUnA2CoiUjZyNBa6w4CmiEFx6m84=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UVBRu01R2eDQSXxrBobg6SCJ7ou8eJlIMtfSqM5vCEjO3ZpB9wRumy+sAvub4bIaq oneFjK5o19Q8qjnr84EYBM2yttub627PIR2Y39KiRHnZmkrpAWLHbhWek/ZzvqNpRi 67lQKKjNbwXqbF+ncwava0EhQQwr+zGMxyEsYRos= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Peter Chen Subject: [PATCH 4.14 33/57] usb: chipidea: udc: dont do hardware access if gadget has stopped Date: Wed, 4 Sep 2019 19:54:01 +0200 Message-Id: <20190904175305.227271525@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190904175301.777414715@linuxfoundation.org> References: <20190904175301.777414715@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Peter Chen commit cbe85c88ce80fb92956a0793518d415864dcead8 upstream. After _gadget_stop_activity is executed, we can consider the hardware operation for gadget has finished, and the udc can be stopped and enter low power mode. So, any later hardware operations (from usb_ep_ops APIs or usb_gadget_ops APIs) should be considered invalid, any deinitializatons has been covered at _gadget_stop_activity. I meet this problem when I plug out usb cable from PC using mass_storage gadget, my callstack like: vbus interrupt->.vbus_session-> composite_disconnect ->pm_runtime_put_sync(&_gadget->dev), the composite_disconnect will call fsg_disable, but fsg_disable calls usb_ep_disable using async way, there are register accesses for usb_ep_disable. So sometimes, I get system hang due to visit register without clock, sometimes not. The Linux Kernel USB maintainer Alan Stern suggests this kinds of solution. See: http://marc.info/?l=linux-usb&m=138541769810983&w=2. Cc: #v4.9+ Signed-off-by: Peter Chen Link: https://lore.kernel.org/r/20190820020503.27080-2-peter.chen@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/udc.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -711,12 +711,6 @@ static int _gadget_stop_activity(struct struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); unsigned long flags; - spin_lock_irqsave(&ci->lock, flags); - ci->gadget.speed = USB_SPEED_UNKNOWN; - ci->remote_wakeup = 0; - ci->suspended = 0; - spin_unlock_irqrestore(&ci->lock, flags); - /* flush all endpoints */ gadget_for_each_ep(ep, gadget) { usb_ep_fifo_flush(ep); @@ -734,6 +728,12 @@ static int _gadget_stop_activity(struct ci->status = NULL; } + spin_lock_irqsave(&ci->lock, flags); + ci->gadget.speed = USB_SPEED_UNKNOWN; + ci->remote_wakeup = 0; + ci->suspended = 0; + spin_unlock_irqrestore(&ci->lock, flags); + return 0; } @@ -1305,6 +1305,10 @@ static int ep_disable(struct usb_ep *ep) return -EBUSY; spin_lock_irqsave(hwep->lock, flags); + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) { + spin_unlock_irqrestore(hwep->lock, flags); + return 0; + } /* only internal SW should disable ctrl endpts */ @@ -1394,6 +1398,10 @@ static int ep_queue(struct usb_ep *ep, s return -EINVAL; spin_lock_irqsave(hwep->lock, flags); + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) { + spin_unlock_irqrestore(hwep->lock, flags); + return 0; + } retval = _ep_queue(ep, req, gfp_flags); spin_unlock_irqrestore(hwep->lock, flags); return retval; @@ -1417,8 +1425,8 @@ static int ep_dequeue(struct usb_ep *ep, return -EINVAL; spin_lock_irqsave(hwep->lock, flags); - - hw_ep_flush(hwep->ci, hwep->num, hwep->dir); + if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN) + hw_ep_flush(hwep->ci, hwep->num, hwep->dir); list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { dma_pool_free(hwep->td_pool, node->ptr, node->dma); @@ -1489,6 +1497,10 @@ static void ep_fifo_flush(struct usb_ep } spin_lock_irqsave(hwep->lock, flags); + if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) { + spin_unlock_irqrestore(hwep->lock, flags); + return; + } hw_ep_flush(hwep->ci, hwep->num, hwep->dir); @@ -1557,6 +1569,10 @@ static int ci_udc_wakeup(struct usb_gadg int ret = 0; spin_lock_irqsave(&ci->lock, flags); + if (ci->gadget.speed == USB_SPEED_UNKNOWN) { + spin_unlock_irqrestore(&ci->lock, flags); + return 0; + } if (!ci->remote_wakeup) { ret = -EOPNOTSUPP; goto out;