Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752350AbbKIHkX (ORCPT ); Mon, 9 Nov 2015 02:40:23 -0500 Received: from mga11.intel.com ([192.55.52.93]:13780 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752041AbbKIHkT (ORCPT ); Mon, 9 Nov 2015 02:40:19 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,265,1444719600"; d="scan'208";a="845880454" From: Lu Baolu To: Mathias Nyman , Greg Kroah-Hartman , Alan Stern Cc: linux-usb@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH v3 04/12] usb: xhci: dbc: add support for Intel xHCI dbc quirk Date: Mon, 9 Nov 2015 15:38:33 +0800 Message-Id: <1447054721-7390-5-git-send-email-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1447054721-7390-1-git-send-email-baolu.lu@linux.intel.com> References: <1447054721-7390-1-git-send-email-baolu.lu@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3234 Lines: 113 On Intel platform, if the debug target is connected with debug host, enabling DCE bit in command register leads to a hung bus state. In the hung state, the host system will not see a port connected status bit set. Hence debug target fails to be probed. The state could be resolved by performing a port reset to the debug port from the host xHCI. This patch introduces this work around. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/xhci-dbc.h | 2 ++ 2 files changed, 54 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 22a1de9..6b23f09 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -255,6 +255,8 @@ static void __iomem *xdbc_map_pci_mmio(u32 bus, xdbcp->bar = bar; xdbcp->xhci_base = base; xdbcp->xhci_length = sz64; + xdbcp->vendor = read_pci_config_16(bus, dev, func, PCI_VENDOR_ID); + xdbcp->device = read_pci_config_16(bus, dev, func, PCI_DEVICE_ID); if (length) *length = sz64; @@ -651,6 +653,52 @@ static int xdbc_mem_init(void) return 0; } +static void xdbc_reset_debug_port_callback(int cap_offset, void *data) +{ + u8 major; + u32 val, port_offset, port_count; + u32 cap_length; + void __iomem *ops_reg; + void __iomem *portsc; + int i; + + val = readl(xdbcp->xhci_base + cap_offset); + major = (u8) XHCI_EXT_PORT_MAJOR(val); + + /* only reset super-speed port */ + if (major != 0x3) + return; + + val = readl(xdbcp->xhci_base + cap_offset + 8); + port_offset = XHCI_EXT_PORT_OFF(val); + port_count = XHCI_EXT_PORT_COUNT(val); + xdbc_trace("Extcap Port offset %d count %d\n", + port_offset, port_count); + + cap_length = readl(xdbcp->xhci_base) & 0xff; + ops_reg = xdbcp->xhci_base + cap_length; + + port_offset--; + for (i = port_offset; i < (port_offset + port_count); i++) { + portsc = ops_reg + 0x400 + i * 0x10; + val = readl(portsc); + /* reset the port if CCS bit is cleared */ + if (!(val & 0x1)) + writel(val | (1 << 4), portsc); + } +} + +static void xdbc_reset_debug_port(void) +{ + xdbc_walk_excap(xdbcp->bus, + xdbcp->dev, + xdbcp->func, + XHCI_EXT_CAPS_PROTOCOL, + false, + xdbc_reset_debug_port_callback, + NULL); +} + /* * xdbc_start: start DbC * @@ -669,6 +717,10 @@ static int xdbc_start(void) return -ENODEV; } + /* reset port to avoid bus hang */ + if (xdbcp->vendor == PCI_VENDOR_ID_INTEL) + xdbc_reset_debug_port(); + /* wait for port connection */ if (handshake(&xdbcp->xdbc_reg->portsc, PORTSC_CCS, PORTSC_CCS, 5000000, 100) < 0) { diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 153fb87..fc0ef9a 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -128,6 +128,8 @@ struct xdbc_state { u32 dev; u32 func; u8 bar; + u16 vendor; + u16 device; void __iomem *xhci_base; size_t xhci_length; #define XDBC_PCI_MAX_BUSES 256 -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/