Commit 395f5409 authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

xhci: support new USB 3.1 hub request to get extended port status

USB 3.1 adds different types of Get Port Status request.
The Get Extended Port Status request returns 4 additional bytes
after the normal portstatus and portchange words containing
link speed and lane information about a connected enhanced super
speed device
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b50107bb
...@@ -659,6 +659,22 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, ...@@ -659,6 +659,22 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
} }
} }
static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li)
{
u32 ext_stat = 0;
int speed_id;
/* only support rx and tx lane counts of 1 in usb3.1 spec */
speed_id = DEV_PORT_SPEED(raw_port_status);
ext_stat |= speed_id; /* bits 3:0, RX speed id */
ext_stat |= speed_id << 4; /* bits 7:4, TX speed id */
ext_stat |= PORT_RX_LANES(port_li) << 8; /* bits 11:8 Rx lane count */
ext_stat |= PORT_TX_LANES(port_li) << 12; /* bits 15:12 Tx lane count */
return ext_stat;
}
/* /*
* Converts a raw xHCI port status into the format that external USB 2.0 or USB * Converts a raw xHCI port status into the format that external USB 2.0 or USB
* 3.0 hubs use. * 3.0 hubs use.
...@@ -874,6 +890,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -874,6 +890,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_dbg(xhci, "Get port status returned 0x%x\n", status); xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
put_unaligned(cpu_to_le32(status), (__le32 *) buf); put_unaligned(cpu_to_le32(status), (__le32 *) buf);
/* if USB 3.1 extended port status return additional 4 bytes */
if (wValue == 0x02) {
u32 port_li;
if (hcd->speed < HCD_USB31 || wLength != 8) {
xhci_err(xhci, "get ext port status invalid parameter\n");
retval = -EINVAL;
break;
}
port_li = readl(port_array[wIndex] + PORTLI);
status = xhci_get_ext_port_status(temp, port_li);
put_unaligned_le32(cpu_to_le32(status), &buf[4]);
}
break; break;
case SetPortFeature: case SetPortFeature:
if (wValue == USB_PORT_FEAT_LINK_STATE) if (wValue == USB_PORT_FEAT_LINK_STATE)
......
...@@ -335,6 +335,7 @@ struct xhci_op_regs { ...@@ -335,6 +335,7 @@ struct xhci_op_regs {
#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS) #define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS)
#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP) #define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP)
#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS) #define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS)
#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f)
/* Bits 20:23 in the Slot Context are the speed for the device */ /* Bits 20:23 in the Slot Context are the speed for the device */
#define SLOT_SPEED_FS (XDEV_FS << 10) #define SLOT_SPEED_FS (XDEV_FS << 10)
...@@ -419,6 +420,9 @@ struct xhci_op_regs { ...@@ -419,6 +420,9 @@ struct xhci_op_regs {
#define PORT_L1DS(p) (((p) & 0xff) << 8) #define PORT_L1DS(p) (((p) & 0xff) << 8)
#define PORT_HLE (1 << 16) #define PORT_HLE (1 << 16)
/* USB3 Protocol PORTLI Port Link Information */
#define PORT_RX_LANES(p) (((p) >> 16) & 0xf)
#define PORT_TX_LANES(p) (((p) >> 20) & 0xf)
/* USB2 Protocol PORTHLPMC */ /* USB2 Protocol PORTHLPMC */
#define PORT_HIRDM(p)((p) & 3) #define PORT_HIRDM(p)((p) & 3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment