Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753106AbbKIHoe (ORCPT ); Mon, 9 Nov 2015 02:44:34 -0500 Received: from mga11.intel.com ([192.55.52.93]:18986 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751512AbbKIHkN (ORCPT ); Mon, 9 Nov 2015 02:40:13 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,265,1444719600"; d="scan'208";a="845880424" 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 01/12] usb: xhci: add sysfs file for xHCI debug port Date: Mon, 9 Nov 2015 15:38:30 +0800 Message-Id: <1447054721-7390-2-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: 8274 Lines: 248 This patch adds a sysfs file for users to check 1) whether the debug capability is implemented by hardware; 2) if supported, which state does it stay at. With a host that supports debug port, a file named "debug_port_state" will be created under the device sysfs directory. Reading this file will show users the state (disabled, enabled or configured) of the debug port. With a host that does NOT support debug port, "debug_port_state" file won't be created. Signed-off-by: Lu Baolu --- .../ABI/testing/sysfs-bus-pci-drivers-xhci_hcd | 23 +++++ drivers/usb/host/Makefile | 2 +- drivers/usb/host/xhci-ext-caps.h | 14 ++- drivers/usb/host/xhci-sysfs.c | 100 +++++++++++++++++++++ drivers/usb/host/xhci.c | 4 + drivers/usb/host/xhci.h | 4 + 6 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd create mode 100644 drivers/usb/host/xhci-sysfs.c diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd new file mode 100644 index 0000000..dd3e722 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd @@ -0,0 +1,23 @@ +What: /sys/bus/pci/drivers/xhci_hcd/.../debug_port_state +Date: November 2015 +KernelVersion: 4.3.0 +Contact: Lu Baolu +Description: + This file is designed for users to check the state of a + USB3 debug port. On a machine which supports USB3 debug + port, this file will be created. Reading this file will + show the state (disabled, enabled or configured) of the + debug port. On a machine that doesn't support USB3 debug + port, this file doesn't exist. + + The state of a debug port could be: + 1) disabled: The debug port is not enabled and the root + port has been switched to xHCI host as a normal + root port. + 2) enabled: The debug port is enabled. The debug port + has been assigned to debug capability. The debug + capability is able to handle the control requests + defined in USB3 spec. + 3) configured: The debug port has been enumerated by the + debug host as a debug device. The debug port is + in use now. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e7558ab..810c304 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -12,7 +12,7 @@ fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o xhci-hcd-y := xhci.o xhci-mem.o xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o -xhci-hcd-y += xhci-trace.o +xhci-hcd-y += xhci-trace.o xhci-sysfs.o xhci-plat-hcd-y := xhci-plat.o ifneq ($(CONFIG_USB_XHCI_MVEBU), ) diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index 9fe3225..12c87e5 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -49,8 +49,15 @@ #define XHCI_EXT_CAPS_PM 3 #define XHCI_EXT_CAPS_VIRT 4 #define XHCI_EXT_CAPS_ROUTE 5 -/* IDs 6-9 reserved */ +#define XHCI_EXT_CAPS_LOCALMEM 6 +/* IDs 7-9 reserved */ #define XHCI_EXT_CAPS_DEBUG 10 +/* IDs 192-255 vendor specific */ +#define XHCI_EXT_CAPS_VEN_START 192 +#define XHCI_EXT_CAPS_VEN_END 255 +#define XHCI_EXT_CAPS_VENDOR(p) (((p) >= XHCI_EXT_CAPS_VEN_START) && \ + ((p) <= XHCI_EXT_CAPS_VEN_END)) +#define XHCI_EXT_MAX_CAPID XHCI_EXT_CAPS_VEN_END /* USB Legacy Support Capability - section 7.1.1 */ #define XHCI_HC_BIOS_OWNED (1 << 16) #define XHCI_HC_OS_OWNED (1 << 24) @@ -73,6 +80,11 @@ #define XHCI_HLC (1 << 19) #define XHCI_BLC (1 << 20) +/* Debug capability - section 7.6.8 */ +#define XHCI_DBC_DCCTRL 0x20 +#define XHCI_DBC_DCCTRL_DCR (1 << 0) +#define XHCI_DBC_DCCTRL_DCE (1 << 31) + /* command register values to disable interrupts and halt the HC */ /* start/stop HC execution - do not write unless HC is halted*/ #define XHCI_CMD_RUN (1 << 0) diff --git a/drivers/usb/host/xhci-sysfs.c b/drivers/usb/host/xhci-sysfs.c new file mode 100644 index 0000000..0192ac4 --- /dev/null +++ b/drivers/usb/host/xhci-sysfs.c @@ -0,0 +1,100 @@ +/* + * sysfs interface for xHCI host controller driver + * + * Copyright (C) 2015 Intel Corp. + * + * Author: Lu Baolu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include + +#include "xhci.h" + +/* + * Return the register offset of a extended capability specified + * by @cap_id. Return 0 if @cap_id capability is not supported or + * in error cases. + */ +static int get_extended_capability_offset(struct xhci_hcd *xhci, + int cap_id) +{ + u32 cap_reg; + unsigned long flags; + int offset; + void __iomem *base = (void __iomem *) xhci->cap_regs; + struct usb_hcd *hcd = xhci_to_hcd(xhci); + int time_to_leave = XHCI_EXT_MAX_CAPID; + + spin_lock_irqsave(&xhci->lock, flags); + + offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); + if (!HCD_HW_ACCESSIBLE(hcd) || !offset) { + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; + } + + while (time_to_leave--) { + cap_reg = readl(base + offset); + + if (XHCI_EXT_CAPS_ID(cap_reg) == cap_id) + break; + + offset = xhci_find_next_cap_offset(base, offset); + if (!offset) + break; + } + + spin_unlock_irqrestore(&xhci->lock, flags); + + return offset; +} + +static ssize_t debug_port_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count = 0, offset; + char *state; + void __iomem *dbc_base; + u32 dcctrl_reg; + struct xhci_hcd *xhci = hcd_to_xhci(dev_get_drvdata(dev)); + + offset = get_extended_capability_offset(xhci, XHCI_EXT_CAPS_DEBUG); + if (!offset) + return 0; + + dbc_base = (void __iomem *) xhci->cap_regs + offset; + dcctrl_reg = readl(dbc_base + XHCI_DBC_DCCTRL); + + if (!(dcctrl_reg & XHCI_DBC_DCCTRL_DCE)) + state = "disabled"; + else if (dcctrl_reg & XHCI_DBC_DCCTRL_DCR) + state = "configured"; + else + state = "enabled"; + + count = scnprintf(buf, PAGE_SIZE, "%s\n", state); + + return count; +} +static DEVICE_ATTR_RO(debug_port_state); + +int xhci_sysfs_create_files(struct xhci_hcd *xhci) +{ + struct device *dev = xhci_to_hcd(xhci)->self.controller; + + if (get_extended_capability_offset(xhci, XHCI_EXT_CAPS_DEBUG)) + return device_create_file(dev, &dev_attr_debug_port_state); + + return 0; +} + +void xhci_sysfs_remove_files(struct xhci_hcd *xhci) +{ + struct device *dev = xhci_to_hcd(xhci)->self.controller; + + if (get_extended_capability_offset(xhci, XHCI_EXT_CAPS_DEBUG)) + device_remove_file(dev, &dev_attr_debug_port_state); +} diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6e7dc6f..583b59f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -651,6 +651,9 @@ int xhci_run(struct usb_hcd *hcd) } xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_run for USB2 roothub"); + + xhci_sysfs_create_files(xhci); + return 0; } EXPORT_SYMBOL_GPL(xhci_run); @@ -684,6 +687,7 @@ void xhci_stop(struct usb_hcd *hcd) xhci_reset(xhci); spin_unlock_irq(&xhci->lock); + xhci_sysfs_remove_files(xhci); xhci_cleanup_msix(xhci); /* Deleting Compliance Mode Recovery Timer */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index be9048e..6bd2e6a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1950,4 +1950,8 @@ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); +/* xHCI sysfs interfaces */ +int xhci_sysfs_create_files(struct xhci_hcd *xhci); +void xhci_sysfs_remove_files(struct xhci_hcd *xhci); + #endif /* __LINUX_XHCI_HCD_H */ -- 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/