From patchwork Sat Apr 10 00:46:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 419119 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCC98C433ED for ; Sat, 10 Apr 2021 00:46:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ACD6C610A6 for ; Sat, 10 Apr 2021 00:46:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235311AbhDJArK (ORCPT ); Fri, 9 Apr 2021 20:47:10 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.73.133]:39308 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235215AbhDJArJ (ORCPT ); Fri, 9 Apr 2021 20:47:09 -0400 Received: from mailhost.synopsys.com (sv1-mailhost1.synopsys.com [10.205.2.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id D2138401F1; Sat, 10 Apr 2021 00:46:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1618015616; bh=RdQLhzKTixlRLwaPIZsQGBw3e8nw+wSYiVqpTUvN2zQ=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=Qvc22IvYK6rbewN4NHgnsh3e2HHybIJSWkXjMgKIfAKc8+ph9riWt/4WpmtZO5UKM enyWpFQ6xPikMcXB/Jxlih4guiaJdNY/ijOQfl11KWX4BOSXBRa9E5o+6d3hWkIM8/ cYWh56ofvTY6ppNu1wNS4Ke8Vmc1lXzcijt7MUJ1pEyN9OUeNc6pZ8vUf6QoqKIPD6 DYkvLFgRiu7eg1625Oj7Zzk53839A4h4uc6ePnnt0TmCgoiRWmIjWXApK6LQfui8or tZxGsVhJpmKE9chrvHefEJ3c78CCb/TxxX0TRYAkhOX5bhiSPESfT4a/5wvl6SJSsv 6U2UgHtyMD4tw== Received: from lab-vbox (unknown [10.205.130.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id A0056A006A; Sat, 10 Apr 2021 00:46:53 +0000 (UTC) Received: by lab-vbox (sSMTP sendmail emulation); Fri, 09 Apr 2021 17:46:53 -0700 Date: Fri, 09 Apr 2021 17:46:53 -0700 Message-Id: <29484f4633a2b0e19b37fe407aebe415e9214390.1618014279.git.Thinh.Nguyen@synopsys.com> In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH v2 2/7] usb: xhci: Move xhci-plat header to common usb header To: Felipe Balbi , Greg Kroah-Hartman , Thinh.Nguyen@synopsys.com, linux-usb@vger.kernel.org, Pawel Laszczak , Aswath Govindraju , Mathias Nyman , Roger Quadros , Peter Chen Cc: John Youn Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org DWC3 and CDNS3 need to access the private platform structure to pass quirks to the xhci-plat glue layer. Move xhci-plat.h to a common header location under include/linux/usb so DWC3 and CDNS3 can properly access them. Signed-off-by: Thinh Nguyen --- Changes in v2: - New patch for this series drivers/usb/cdns3/host.c | 2 +- drivers/usb/host/xhci-plat.c | 2 +- drivers/usb/host/xhci-rcar.c | 2 +- .../usb/host => include/linux/usb}/xhci-plat.h | 18 +++++++++--------- 4 files changed, 12 insertions(+), 12 deletions(-) rename {drivers/usb/host => include/linux/usb}/xhci-plat.h (54%) diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index 84dadfa726aa..02634d9762a4 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -14,8 +14,8 @@ #include "drd.h" #include "host-export.h" #include +#include #include "../host/xhci.h" -#include "../host/xhci-plat.h" #define XECP_PORT_CAP_REG 0x8000 #define XECP_AUX_CTRL_REG1 0x8120 diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index c1edcc9b13ce..3003fde3b430 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -19,9 +19,9 @@ #include #include #include +#include #include "xhci.h" -#include "xhci-plat.h" #include "xhci-mvebu.h" #include "xhci-rcar.h" diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index 1bc4fe7b8c75..8d779df7b1e1 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -12,9 +12,9 @@ #include #include #include +#include #include "xhci.h" -#include "xhci-plat.h" #include "xhci-rcar.h" /* diff --git a/drivers/usb/host/xhci-plat.h b/include/linux/usb/xhci-plat.h similarity index 54% rename from drivers/usb/host/xhci-plat.h rename to include/linux/usb/xhci-plat.h index 561d0b7bce09..a58f1d44306d 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/include/linux/usb/xhci-plat.h @@ -5,21 +5,21 @@ * Copyright (C) 2015 Renesas Electronics Corporation */ -#ifndef _XHCI_PLAT_H -#define _XHCI_PLAT_H +#ifndef __LINUX_USB_XHCI_PLAT_H +#define __LINUX_USB_XHCI_PLAT_H -#include "xhci.h" /* for hcd_to_xhci() */ +struct usb_hcd; struct xhci_plat_priv { const char *firmware_name; unsigned long long quirks; - int (*plat_setup)(struct usb_hcd *); - void (*plat_start)(struct usb_hcd *); - int (*init_quirk)(struct usb_hcd *); - int (*suspend_quirk)(struct usb_hcd *); - int (*resume_quirk)(struct usb_hcd *); + int (*plat_setup)(struct usb_hcd *hcd); + void (*plat_start)(struct usb_hcd *hcd); + int (*init_quirk)(struct usb_hcd *hcd); + int (*suspend_quirk)(struct usb_hcd *hcd); + int (*resume_quirk)(struct usb_hcd *hcd); }; #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) #define xhci_to_priv(x) ((struct xhci_plat_priv *)(x)->priv) -#endif /* _XHCI_PLAT_H */ +#endif /* __LINUX_USB_XHCI_PLAT_H */ From patchwork Sat Apr 10 00:47:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 419118 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99E47C433B4 for ; Sat, 10 Apr 2021 00:47:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D66B6113A for ; Sat, 10 Apr 2021 00:47:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235319AbhDJArX (ORCPT ); Fri, 9 Apr 2021 20:47:23 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.73.133]:39328 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235312AbhDJArW (ORCPT ); Fri, 9 Apr 2021 20:47:22 -0400 Received: from mailhost.synopsys.com (sv2-mailhost2.synopsys.com [10.205.2.134]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 02EA3401F1; Sat, 10 Apr 2021 00:47:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1618015629; bh=boOwoNo4+Zfzi026H2CCOo49+BR7HecMuFsdKCIS/WI=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=b1gr4tGTZjvX6QsbhcAjZUZ6hGowogUl593zw5fSk5Y1JLmd3eDfyN9RJGKsMwv6D CEPbMu1zAjW3klBER8GGoaioRI83R/Fi+0aKxDLXLQ7n2QrFE5OH7JIgtpcgq0VLhX A7GXdyvh8cr4HT2WK3JxYn5i4letqMLBreG/BuR451NExkginAOCHIkT7PcfiMPRwn k1IZdkZgVFhySbpg7k8luCHd8Lm3NSH4VSW086Y3Kau+DTNjEpoXbNWXC4abtpY7+i bWHV6pfVARPRlsJYv/cSu/f3EUhG9w3DxZmRTjE+HKqqkHIcViPyL3UQpkEPJ/9kp5 oD3SvxsX2ZL9Q== Received: from lab-vbox (unknown [10.205.130.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id CD5C9A0096; Sat, 10 Apr 2021 00:47:07 +0000 (UTC) Received: by lab-vbox (sSMTP sendmail emulation); Fri, 09 Apr 2021 17:47:07 -0700 Date: Fri, 09 Apr 2021 17:47:07 -0700 Message-Id: In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH v2 4/7] usb: xhci: Workaround undercalculated BW for fullspeed BI To: Felipe Balbi , Greg Kroah-Hartman , Thinh.Nguyen@synopsys.com, linux-usb@vger.kernel.org, Mathias Nyman Cc: John Youn Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org DWC_usb31 host version 1.90a and prior undercalculates the bandwidth available for interrupt endpoints. The controller will return bandwidth error on config endpoint commands if there are already 6 or more fullspeed interrupt endpoints with bInterval of 4 (or 4ms) associated with a single fullspeed bus instance (BI). To workaround this, configure and use the endpoint at a shorter interrupt interval. Lower the ep_ctx interval from 5 to 4 (or 2ms) for interrupt endpoints of the fullspeed BI. Note: we have not observed functional impact to the fullspeed devices by lowering the interrupt service interval (at least for a few devices that we tested). To simplify the workaround, let's just check and apply the workaround if the endpoint is a fullspeed interrupt endpoint with interval of 4ms and if the top parent device is also operating in fullspeed (i.e. associated with fullspeed BI). Signed-off-by: Thinh Nguyen --- Changes in v2: - None Note: Checkpatch will give a warning below for getting top_dev: WARNING: suspect code indent for conditional statements Since this logic is done everywhere else in the driver, I'm keeping it consistent here. drivers/usb/host/xhci-mem.c | 23 +++++++++++++++++++++++ include/linux/usb/xhci-quirks.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 1053b43008e4..e01d0ddb012a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1463,6 +1463,29 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, } } + /* + * Check for undercalculated bandwidth quirk for interrupt endpoints + * associated with fullspeed BI. + */ + if ((xhci->quirks & XHCI_LIMIT_FS_BI_INTR_EP) && + usb_endpoint_xfer_int(&ep->desc) && + udev->speed == USB_SPEED_FULL && + interval == 5) { + struct usb_device *top_dev; + + for (top_dev = udev; + top_dev->parent && top_dev->parent->parent; + top_dev = top_dev->parent) + /* Found device below root hub */; + + /* + * If the top device is operating at fullspeed, then the + * controller is using fullspeed BI for this device. + */ + if (top_dev->speed == USB_SPEED_FULL) + interval = 4; + } + mult = xhci_get_endpoint_mult(udev, ep); max_packet = usb_endpoint_maxp(&ep->desc); max_burst = xhci_get_endpoint_max_burst(udev, ep); diff --git a/include/linux/usb/xhci-quirks.h b/include/linux/usb/xhci-quirks.h index 65bb62d3d31d..5bedf5a25f7a 100644 --- a/include/linux/usb/xhci-quirks.h +++ b/include/linux/usb/xhci-quirks.h @@ -59,5 +59,6 @@ #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_ISOC_BLOCKED_DISCONNECT BIT_ULL(41) +#define XHCI_LIMIT_FS_BI_INTR_EP BIT_ULL(42) #endif /* __LINUX_USB_XHCI_QUIRKS_H */ From patchwork Sat Apr 10 00:47:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 419117 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF2F9C433B4 for ; Sat, 10 Apr 2021 00:47:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B2DBD6115A for ; Sat, 10 Apr 2021 00:47:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235323AbhDJArf (ORCPT ); Fri, 9 Apr 2021 20:47:35 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.73.133]:39340 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235312AbhDJArf (ORCPT ); Fri, 9 Apr 2021 20:47:35 -0400 Received: from mailhost.synopsys.com (sv1-mailhost2.synopsys.com [10.205.2.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id C813940344; Sat, 10 Apr 2021 00:47:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1618015641; bh=Ity4RAQpCC9LKIRutd5Q6SyJNY07n8Go4Fm1XgNf0jo=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=iJpYeiBjg6WXOFW6p131CN0KXAqJSC7Z+PpDwqjz5R8XxVzX9wZ2tOVDITz01SPkG qMTYal+m05+AktQPM4FbjQLtlOongW/Bwbawgr42IEuSnrN+kavApaBvSf+zSOmpKG oSQvHVjdxUWYc9C/MCHw6bzAmQW7/7AE/p0FAWy72wdSb810kf33NMnCBMqFp1rNJj HXwYH46S6aERVx6mumVoAqxAL7KNeZEIqiSdzvKdBB2OqBMoRlRP5tvQUcKjCJGQ90 WNjTbpi8xhQ2Uuri99xl8dJwmF2+xdOTdGPHd5AOYI356nuTjgcWY7xoJ7XDct9LBe v29pntzG9KFvg== Received: from lab-vbox (unknown [10.205.130.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 7F81AA007C; Sat, 10 Apr 2021 00:47:20 +0000 (UTC) Received: by lab-vbox (sSMTP sendmail emulation); Fri, 09 Apr 2021 17:47:20 -0700 Date: Fri, 09 Apr 2021 17:47:20 -0700 Message-Id: In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH v2 6/7] usb: xhci: Workaround lost disconnect port status To: Felipe Balbi , Greg Kroah-Hartman , Thinh.Nguyen@synopsys.com, linux-usb@vger.kernel.org, Mathias Nyman Cc: John Youn Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org If an eSS device with active periodic transfers is disconnected from the DWC_usb31 (v1.90a and prior) host controller at root port, the host controller may not detect a disconnection. By active transfers, it means that the endpoint is not in flow control, and there are active Transfer Descriptors available for the host to initiate transfers to the endpoint. This issue can occur if the endpoint periodic interval is in 2ms, 4ms, or 8ms. In addition, the host controller will not be able to detect a new device connection while the disconnection is not processed. The controller will set the link state of the affected port to eSS_INACTIVE. To workaround this, have the xHCI driver polls for the eSS root port status every 2 seconds. If eSS_INACTIVE state is detected, initiate a fake connection change to stop all the active endpoints and start polling for new connection change. Since XHCI_COMP_MODE_QUIRK is basically doing the same thing except for polling for a different link state, we will use the same timer and polling rate for this new workaround. Introduce a new quirk XHCI_LOST_DISCONNECT_QUIRK to poll for eSS_INACTIVE port link state and fake a connection change. Signed-off-by: Thinh Nguyen --- Changes in v2: - None drivers/usb/host/xhci-hub.c | 10 +++++++- drivers/usb/host/xhci.c | 44 ++++++++++++++++++++++++--------- include/linux/usb/xhci-quirks.h | 1 + 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 8bfafbd680ab..32fbf95f021b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -868,6 +868,11 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && (pls == USB_SS_PORT_LS_COMP_MOD)) pls |= USB_PORT_STAT_CONNECTION; + + /* Fake a connection change */ + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) && + pls == XDEV_INACTIVE) + pls |= USB_PORT_STAT_CONNECTION; } /* update status field */ @@ -887,7 +892,8 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u32 all_ports_seen_u0 = ((1 << xhci->usb3_rhub.num_ports) - 1); bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); - if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) + if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK) || + (xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK)) return; if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { @@ -1654,6 +1660,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) trace_xhci_hub_status_data(i, temp); if ((temp & mask) != 0 || + ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) && + (temp & PORT_PLS_MASK) == XDEV_INACTIVE) || (bus_state->port_c_suspend & 1 << i) || (bus_state->resume_done[i] && time_after_eq( jiffies, bus_state->resume_done[i]))) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e1b3d1063f6b..62275ee88849 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -485,10 +485,14 @@ static void port_check(struct timer_list *t) xhci = from_timer(xhci, t, port_check_timer); rhub = &xhci->usb3_rhub; + hcd = xhci->shared_hcd; for (i = 0; i < rhub->num_ports; i++) { + bool poll_rhub = false; + temp = readl(rhub->ports[i]->addr); - if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD)) { /* * Compliance Mode Detected. Letting USB Core * handle the Warm Reset @@ -498,8 +502,15 @@ static void port_check(struct timer_list *t) i + 1); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Attempting compliance mode recovery"); - hcd = xhci->shared_hcd; + poll_rhub = true; + } + + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) && + ((temp & PORT_PLS_MASK) == XDEV_INACTIVE)) + poll_rhub = true; + + if (poll_rhub) { if (hcd->state == HC_STATE_SUSPENDED) usb_hcd_resume_root_hub(hcd); @@ -507,7 +518,9 @@ static void port_check(struct timer_list *t) } } - if (xhci->port_status_u0 != ((1 << rhub->num_ports) - 1)) + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) || + ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + xhci->port_status_u0 != ((1 << rhub->num_ports) - 1))) mod_timer(&xhci->port_check_timer, jiffies + msecs_to_jiffies(PORT_CHECK_MSECS)); } @@ -593,10 +606,12 @@ static int xhci_init(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init"); /* Initializing Compliance Mode Recovery Data If Needed */ - if (xhci_compliance_mode_recovery_timer_quirk_check()) { + if (xhci_compliance_mode_recovery_timer_quirk_check()) xhci->quirks |= XHCI_COMP_MODE_QUIRK; + + if (xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK || + xhci->quirks & XHCI_COMP_MODE_QUIRK) port_check_timer_init(xhci); - } return retval; } @@ -736,8 +751,9 @@ static void xhci_stop(struct usb_hcd *hcd) xhci_cleanup_msix(xhci); /* Deleting Compliance Mode Recovery Timer */ - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && - (!(xhci_all_ports_seen_u0(xhci)))) { + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) || + ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci)))) { del_timer_sync(&xhci->port_check_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "%s: port check timer deleted", __func__); @@ -1058,8 +1074,9 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) * Deleting Port Check Timer because the xHCI Host * is about to be suspended. */ - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && - (!(xhci_all_ports_seen_u0(xhci)))) { + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) || + ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci)))) { del_timer_sync(&xhci->port_check_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "%s: port check timer deleted", __func__); @@ -1145,8 +1162,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* If restore operation fails, re-initialize the HC during resume */ if ((temp & STS_SRE) || hibernated) { - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && - !(xhci_all_ports_seen_u0(xhci))) { + if ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) || + ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci)))) { del_timer_sync(&xhci->port_check_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Port Check Timer deleted!"); @@ -1247,7 +1265,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) * to suffer the Compliance Mode issue again. It doesn't matter if * ports have entered previously to U0 before system's suspension. */ - if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running) + if (!comp_timer_running && + ((xhci->quirks & XHCI_LOST_DISCONNECT_QUIRK) || + (xhci->quirks & XHCI_COMP_MODE_QUIRK))) port_check_timer_init(xhci); if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL) diff --git a/include/linux/usb/xhci-quirks.h b/include/linux/usb/xhci-quirks.h index 5bedf5a25f7a..df92e78b8083 100644 --- a/include/linux/usb/xhci-quirks.h +++ b/include/linux/usb/xhci-quirks.h @@ -60,5 +60,6 @@ #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_ISOC_BLOCKED_DISCONNECT BIT_ULL(41) #define XHCI_LIMIT_FS_BI_INTR_EP BIT_ULL(42) +#define XHCI_LOST_DISCONNECT_QUIRK BIT_ULL(43) #endif /* __LINUX_USB_XHCI_QUIRKS_H */