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-next>] [day] [month] [year] [list]
Message-Id: <20170208134444.18369-1-alexander.stein@systec-electronic.com>
Date:   Wed,  8 Feb 2017 14:44:44 +0100
From:   Alexander Stein <alexander.stein@...tec-electronic.com>
To:     Mathias Nyman <mathias.nyman@...el.com>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc:     Alexander Stein <alexander.stein@...tec-electronic.com>,
        linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org,
        "Wang, Yu" <yu.y.wang@...el.com>,
        "Li, Guanglei" <guangleix.li@...el.com>,
        "Wu, Hao" <hao.wu@...el.com>
Subject: [PATCH v2 1/1] xhci: add USB2 test mode support

This patch adds support for USB2 test mode (Test_J, Test_K,
Test_SE0_NAK and Test_Packet) per XHCI spec 4.19.6.

USB2 test mode is a required hardware feature for system integrators
validating their hardware according to USB spec, regarding signal
strength and stuff. It is purely a hardware test feature.

Usually you need an oscilloscope and have to enable those test modes on
the hardware. This will send some specific test patterns on D+/D-. There
is no report available (in Linux itself) as it is purely externally
visible. Regular USB usage is not possible at that time.
Anyone (well access to e.g. /dev/bus/usb/001/001 provided) can use it by
sending appropriate USB_PORT_FEAT_TEST requests to the hub.
The same feature for ehci based hosts is already available at
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/host/ehci-hub.c#n1267

Signed-off-by: "Wang, Yu" <yu.y.wang@...el.com>
Signed-off-by: "Li, Guanglei" <guangleix.li@...el.com>
Signed-off-by: "Wu, Hao" <hao.wu@...el.com>
Signed-off-by: Alexander Stein <alexander.stein@...tec-electronic.com>
---
Changes in v2:
* Added additional info about USB2 test modes itself into commit message
* Add URL for same test mode feature on ehci hosts.

 drivers/usb/host/xhci-hub.c | 63 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0ef1690..cd561f1 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -879,13 +879,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 	int max_ports;
 	unsigned long flags;
 	u32 temp, status;
-	int retval = 0;
+	int i, retval = 0;
 	__le32 __iomem **port_array;
 	int slot_id;
 	struct xhci_bus_state *bus_state;
 	u16 link_state = 0;
 	u16 wake_mask = 0;
 	u16 timeout = 0;
+	u16 selector = 0;
 
 	max_ports = xhci_get_ports(hcd, &port_array);
 	bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -959,6 +960,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			link_state = (wIndex & 0xff00) >> 3;
 		if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
 			wake_mask = wIndex & 0xff00;
+		if (wValue == USB_PORT_FEAT_TEST)
+			selector = (wIndex & 0xff00) >> 8;
 		/* The MSB of wIndex is the U1/U2 timeout */
 		timeout = (wIndex & 0xff00) >> 8;
 		wIndex &= 0xff;
@@ -1134,6 +1137,64 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			temp |= PORT_U2_TIMEOUT(timeout);
 			writel(temp, port_array[wIndex] + PORTPMSC);
 			break;
+		case USB_PORT_FEAT_TEST:
+			/* 4.19.6 Port Test Modes (USB2 Test Mode) */
+			if (hcd->speed != HCD_USB2)
+				goto error;
+
+			/* FIXME: Test_Force_Enable case to be implemented */
+			if (selector < TEST_J || selector > TEST_PACKET)
+				goto error;
+
+			/* Disable all Device Slots */
+			for (i = 0; i < MAX_HC_SLOTS; i++) {
+				struct xhci_command *command;
+
+				if (!xhci->dcbaa->dev_context_ptrs[i])
+					continue;
+				command = xhci_alloc_command(xhci, false,
+						false, GFP_ATOMIC);
+				if (!command)
+					return -ENOMEM;
+				if (xhci_queue_slot_control(xhci, command,
+						TRB_DISABLE_SLOT, i)) {
+					xhci_err(xhci,
+						"Disable slot[%d] fail!\n", i);
+						goto error;
+					}
+				xhci_dbg(xhci, "Disable Slot[%d].\n", i);
+			}
+
+			/* Put all ports to the Disable state by clear PP */
+			xhci_dbg(xhci, "Disable all port (PP = 0)\n");
+			for (i = 0; i < max_ports; i++) {
+				temp = readl(port_array[i]);
+				temp &= ~PORT_POWER;
+				writel(temp, port_array[i]);
+			}
+
+			/* Stop the controller */
+			xhci_dbg(xhci, "Stop controller\n");
+			temp = readl(&xhci->op_regs->command);
+			temp &= ~CMD_RUN;
+			writel(temp, &xhci->op_regs->command);
+
+			if (xhci_handshake(&xhci->op_regs->status,
+				STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
+				xhci_warn(xhci, "Stop controller timeout\n");
+				return -ETIMEDOUT;
+			}
+
+			/* Disable runtime PM for test mode */
+			pm_runtime_forbid(hcd->self.controller);
+
+			/* Set PORTPMSC.PTC field for selected test mode */
+			xhci_dbg(xhci, "Enter Test Mode: %d\n", selector);
+			temp = readl(port_array[wIndex] + PORTPMSC);
+			temp |= selector << 28;
+			writel(temp, port_array[wIndex] + PORTPMSC);
+
+			break;
 		default:
 			goto error;
 		}
-- 
2.10.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ