Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp2267932ybl; Thu, 19 Dec 2019 10:43:19 -0800 (PST) X-Google-Smtp-Source: APXvYqz+3n7IjaXdmUf7WmEFLr0/QlrL9GCBPewYqWtjOrcoqltjF+INjxjvysEIUYRMYm0Ms6kz X-Received: by 2002:a9d:1e4:: with SMTP id e91mr4786881ote.324.1576780998547; Thu, 19 Dec 2019 10:43:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1576780998; cv=none; d=google.com; s=arc-20160816; b=QDhEeXEwVsAfWGtYg3WWpX55W8o24ZL0eBNUO4io8h0C6JvivLQrzr2h3HO3hHp+Re 1/HT/dOrSwbmZ2nTjTAFInkpPpWJGzeanS+Gn0F2cVJb0epWYvLu5M5KNWCwWvBNpLAm 1IAJq5G+bIphR2uMYVOhxtY4cIic4CQcifMyAVwk55HVWzKT9w/DA7vj+bEQWYUYCbK/ g0vEwLiiLEAThJAwGBWkYWyrCkjtqkp4jtBNBEL48ctucJ/z7t6oNvdbIYxtDZu2i+OY yX2o5dysOiPMMI7boTehUlHeTs9Fat6FqXusM6yPeeE1g1i+2CDVQlMRvwrYKpXHhMRO Igog== 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=X9CojSW08lhFQKxL1KJk3o1CLKsWGNwLwArnSb9ZkNU=; b=FsSffRT/CdOUvNMHS+Jk4KminTyLZFbaa2f8lCNT4wXQ1TD1gck3nNsDM2tjIpCppy 4rfq977LBQSLnLJgvswX1Lrt+b7PFKF1j2FVi3Rd42Is3GaS+m7F6I5SIk5utLLDBUtp GbRAGSeow2GrNt1Ywy1tbZsV49SVZ56DhCFqYg0UlN92J+CQHNNp6sCTINxvw8vIG0q4 o4nhbH41umHwQexE+tm4Lh8GL9/2P56y8in+0FAb3SItRKEHzUPddGqszcDVu3IXqbCa pg3yuvyq9F5kRMOS6ZtcDuRYJRfl84I9P2amZcWJnK3TqcuUHx9HNs0mgcHbXgVVmqOu 1bLg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@kernel.org header.s=default header.b=qkQQFpwF; 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 m20si3674185otq.35.2019.12.19.10.43.06; Thu, 19 Dec 2019 10:43:18 -0800 (PST) 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=fail header.i=@kernel.org header.s=default header.b=qkQQFpwF; 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 S1728605AbfLSSl6 (ORCPT + 99 others); Thu, 19 Dec 2019 13:41:58 -0500 Received: from mail.kernel.org ([198.145.29.99]:32920 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727711AbfLSSlz (ORCPT ); Thu, 19 Dec 2019 13:41:55 -0500 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 F003324672; Thu, 19 Dec 2019 18:41:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576780914; bh=YAaiHFebq0MAtlX9h1+d1UMOmTcd0OM9rUvU91wapyU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qkQQFpwFMQ8ie93kY+kNjIqrc2tPSoB3bdhQrJrJeERECHmmS4O0f9uKIQs3s7mvf ZzfxXcvrZJrEj5U6IFHJ44KXalFxTYjt6RIadoS5vIA1hvq7wEqU2GU395aJiC4r80 wu2ny9wUvsXity/Ewy1XaIa0fMK8gIjztqg/Ff9w= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Lee, Hou-hsun" , "Lee, Chiasheng" , Mathias Nyman , Lee@vger.kernel.org Subject: [PATCH 4.4 160/162] xhci: fix USB3 device initiated resume race with roothub autosuspend Date: Thu, 19 Dec 2019 19:34:28 +0100 Message-Id: <20191219183217.505075467@linuxfoundation.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20191219183150.477687052@linuxfoundation.org> References: <20191219183150.477687052@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: Mathias Nyman commit 057d476fff778f1d3b9f861fdb5437ea1a3cfc99 upstream. A race in xhci USB3 remote wake handling may force device back to suspend after it initiated resume siganaling, causing a missed resume event or warm reset of device. When a USB3 link completes resume signaling and goes to enabled (UO) state a interrupt is issued and the interrupt handler will clear the bus_state->port_remote_wakeup resume flag, allowing bus suspend. If the USB3 roothub thread just finished reading port status before the interrupt, finding ports still in suspended (U3) state, but hasn't yet started suspending the hub, then the xhci interrupt handler will clear the flag that prevented roothub suspend and allow bus to suspend, forcing all port links back to suspended (U3) state. Example case: usb_runtime_suspend() # because all ports still show suspended U3 usb_suspend_both() hub_suspend(); # successful as hub->wakeup_bits not set yet ==> INTERRUPT xhci_irq() handle_port_status() clear bus_state->port_remote_wakeup usb_wakeup_notification() sets hub->wakeup_bits; kick_hub_wq() <== END INTERRUPT hcd_bus_suspend() xhci_bus_suspend() # success as port_remote_wakeup bits cleared Fix this by increasing roothub usage count during port resume to prevent roothub autosuspend, and by making sure bus_state->port_remote_wakeup flag is only cleared after resume completion is visible, i.e. after xhci roothub returned U0 or other non-U3 link state link on a get port status request. Issue rootcaused by Chiasheng Lee Cc: Cc: Lee, Hou-hsun Reported-by: Lee, Chiasheng Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20191211142007.8847-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 8 ++++++++ drivers/usb/host/xhci-ring.c | 6 +----- drivers/usb/host/xhci.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -736,6 +736,14 @@ static u32 xhci_get_port_status(struct u status |= USB_PORT_STAT_C_BH_RESET << 16; if ((raw_port_status & PORT_CEC)) status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + + /* USB3 remote wake resume signaling completed */ + if (bus_state->port_remote_wakeup & (1 << wIndex) && + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME && + (raw_port_status & PORT_PLS_MASK) != XDEV_RECOVERY) { + bus_state->port_remote_wakeup &= ~(1 << wIndex); + usb_hcd_end_port_resume(&hcd->self, wIndex); + } } if (hcd->speed < HCD_USB3) { --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1602,9 +1602,6 @@ static void handle_port_status(struct xh usb_hcd_resume_root_hub(hcd); } - if (hcd->speed >= HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) - bus_state->port_remote_wakeup &= ~(1 << faked_port_index); - if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); @@ -1623,6 +1620,7 @@ static void handle_port_status(struct xh bus_state->port_remote_wakeup |= 1 << faked_port_index; xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); + usb_hcd_start_port_resume(&hcd->self, faked_port_index); xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); /* Need to wait until the next link state change @@ -1660,8 +1658,6 @@ static void handle_port_status(struct xh if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { - bus_state->port_remote_wakeup &= - ~(1 << faked_port_index); xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); usb_wakeup_notification(hcd->self.root_hub, --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -314,6 +314,7 @@ struct xhci_op_regs { #define XDEV_U3 (0x3 << 5) #define XDEV_INACTIVE (0x6 << 5) #define XDEV_POLLING (0x7 << 5) +#define XDEV_RECOVERY (0x8 << 5) #define XDEV_COMP_MODE (0xa << 5) #define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */