lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1446538452-23099-2-git-send-email-baolu.lu@linux.intel.com>
Date:	Tue,  3 Nov 2015 16:14:01 +0800
From:	Lu Baolu <baolu.lu@...ux.intel.com>
To:	Mathias Nyman <mathias.nyman@...el.com>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Alan Stern <stern@...land.harvard.edu>
Cc:	linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org,
	Lu Baolu <baolu.lu@...ux.intel.com>
Subject: [PATCH v2 01/12] usb: xhci: add sysfs file for xHCI debug port

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 <baolu.lu@...ux.intel.com>
---
 .../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 <baolu.lu@...ux.intel.com>
+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 <baolu.lu@...ux.intel.com>
+ *
+ * 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 <linux/kernel.h>
+
+#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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ