Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp5761758imm; Mon, 23 Jul 2018 05:45:22 -0700 (PDT) X-Google-Smtp-Source: AAOMgpenWHrUZDDgtCkBYnzuo2XIDTtsSFW50GoAZQKvZV4qiMr2fvkRRmAnlXR6cF6RH/griPth X-Received: by 2002:a17:902:a60b:: with SMTP id u11-v6mr12735707plq.158.1532349922862; Mon, 23 Jul 2018 05:45:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1532349922; cv=none; d=google.com; s=arc-20160816; b=LQBh+JlBx/obR0nx69B0A1B9oFqTORfnFga/y6bFFvCL1oFk9rXRvPCsbA+7IMFmsK Jfs+6/q93T9Ys0b+anWxF8igoo+FnZy5tuMSuTQJ0KK7GWQO2I4MIadUrIeXQiCke3fr U44rlNDB60buIq148+yo69U0frsDya8TyLRulEk9eKXYaOUZx8BZRi/p57fBq3Y8knpk PBKodM+Pw0NlDUV/SSwvdu6Th9AAPjG6Ia7o2GBpxmDZsBnbom/V/KeONzUXbTFKae6R Mmtv5dXNs7gNSB1r2ldWlLnf5WBWIsCSD2TFTWBr5BoIHAD4Dz5SqWmIBxJjrqmXYlYl ogRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=5KKGKMY9aWPmSpkmR7kOQ28BqEELAEMCsxNafkC2+TQ=; b=g/RftZ5hSPhOUKKIt6m8g5xQZtvdR8sPjD/8H1cr4zF+tO6AeNtRrSDxRdAFxRnXCk ePBb6GTs+A7X96wFYQCy5PNAUsVIiPkpUd5ZugI8eyBEw41bIUAxZuYnnCEplI+2gM1I ZTl2fTJRudv5P2t5W61hJqCKF1NC2VCKidJl0/6gALbNy0WPYADPFwdZbokzlOxlNQij x0Cv/Jc7l3K+jBCGCZ9uIXUFLrA5vrOWTdVNVHW6jNpsbHdfbzixIrELAg2lW8diEBQl q5evg7SNzRzcHfhVLOtX4A4yhAb46Sgmeu3moIfPJ3yitEn0arh0ZoY4LESUrLmY2cjl bNPg== ARC-Authentication-Results: i=1; mx.google.com; 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 o8-v6si8697301pgo.175.2018.07.23.05.45.08; Mon, 23 Jul 2018 05:45:22 -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; 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 S2388863AbeGWNoO (ORCPT + 99 others); Mon, 23 Jul 2018 09:44:14 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:47676 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388743AbeGWNoO (ORCPT ); Mon, 23 Jul 2018 09:44:14 -0400 Received: from localhost (LFbn-1-12238-233.w90-92.abo.wanadoo.fr [90.92.53.233]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id B2684A95; Mon, 23 Jul 2018 12:43:10 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mathias Nyman , Kai-Heng Feng Subject: [PATCH 4.4 017/107] xhci: Fix perceived dead host due to runtime suspend race with event handler Date: Mon, 23 Jul 2018 14:41:11 +0200 Message-Id: <20180723122413.756202517@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180723122413.003644357@linuxfoundation.org> References: <20180723122413.003644357@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Mathias Nyman commit 229bc19fd7aca4f37964af06e3583c1c8f36b5d6 upstream. Don't rely on event interrupt (EINT) bit alone to detect pending port change in resume. If no change event is detected the host may be suspended again, oterwise roothubs are resumed. There is a lag in xHC setting EINT. If we don't notice the pending change in resume, and the controller is runtime suspeded again, it causes the event handler to assume host is dead as it will fail to read xHC registers once PCI puts the controller to D3 state. [ 268.520969] xhci_hcd: xhci_resume: starting port polling. [ 268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling. [ 268.521030] xhci_hcd: xhci_suspend: stopping port polling. [ 268.521040] xhci_hcd: // Setting command ring address to 0x349bd001 [ 268.521139] xhci_hcd: Port Status Change Event for port 3 [ 268.521149] xhci_hcd: resume root hub [ 268.521163] xhci_hcd: port resume event for port 3 [ 268.521168] xhci_hcd: xHC is not running. [ 268.521174] xhci_hcd: handle_port_status: starting port polling. [ 268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, assume dead The EINT lag is described in a additional note in xhci specs 4.19.2: "Due to internal xHC scheduling and system delays, there will be a lag between a change bit being set and the Port Status Change Event that it generated being written to the Event Ring. If SW reads the PORTSC and sees a change bit set, there is no guarantee that the corresponding Port Status Change Event has already been written into the Event Ring." Cc: Signed-off-by: Mathias Nyman Signed-off-by: Kai-Heng Feng Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++++++++++++++++--- drivers/usb/host/xhci.h | 4 ++++ 2 files changed, 41 insertions(+), 3 deletions(-) --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -887,6 +887,41 @@ static void xhci_disable_port_wake_on_bi spin_unlock_irqrestore(&xhci->lock, flags); } +static bool xhci_pending_portevent(struct xhci_hcd *xhci) +{ + __le32 __iomem **port_array; + int port_index; + u32 status; + u32 portsc; + + status = readl(&xhci->op_regs->status); + if (status & STS_EINT) + return true; + /* + * Checking STS_EINT is not enough as there is a lag between a change + * bit being set and the Port Status Change Event that it generated + * being written to the Event Ring. See note in xhci 1.1 section 4.19.2. + */ + + port_index = xhci->num_usb2_ports; + port_array = xhci->usb2_ports; + while (port_index--) { + portsc = readl(port_array[port_index]); + if (portsc & PORT_CHANGE_MASK || + (portsc & PORT_PLS_MASK) == XDEV_RESUME) + return true; + } + port_index = xhci->num_usb3_ports; + port_array = xhci->usb3_ports; + while (port_index--) { + portsc = readl(port_array[port_index]); + if (portsc & PORT_CHANGE_MASK || + (portsc & PORT_PLS_MASK) == XDEV_RESUME) + return true; + } + return false; +} + /* * Stop HC (not bus-specific) * @@ -983,7 +1018,7 @@ EXPORT_SYMBOL_GPL(xhci_suspend); */ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) { - u32 command, temp = 0, status; + u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); struct usb_hcd *secondary_hcd; int retval = 0; @@ -1105,8 +1140,7 @@ int xhci_resume(struct xhci_hcd *xhci, b done: if (retval == 0) { /* Resume root hubs only when have pending events. */ - status = readl(&xhci->op_regs->status); - if (status & STS_EINT) { + if (xhci_pending_portevent(xhci)) { usb_hcd_resume_root_hub(xhci->shared_hcd); usb_hcd_resume_root_hub(hcd); } --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -382,6 +382,10 @@ struct xhci_op_regs { #define PORT_PLC (1 << 22) /* port configure error change - port failed to configure its link partner */ #define PORT_CEC (1 << 23) +#define PORT_CHANGE_MASK (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ + PORT_RC | PORT_PLC | PORT_CEC) + + /* Cold Attach Status - xHC can set this bit to report device attached during * Sx state. Warm port reset should be perfomed to clear this bit and move port * to connected state.