summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/xhci-hub.c13
-rw-r--r--drivers/usb/host/xhci.c7
-rw-r--r--drivers/usb/host/xhci.h4
-rw-r--r--include/linux/usb.h8
4 files changed, 24 insertions, 8 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 4ba910eadd3f..d27c30ac17fd 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -763,9 +763,12 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci)
*
* A USB3 device must be connected to the port to detect the tunnel.
*
- * Return: true if USB3 connection is tunneled over USB4
+ * Return: link tunnel mode enum, USB_LINK_UNKNOWN if host is incapable of
+ * detecting USB3 over USB4 tunnels. USB_LINK_NATIVE or USB_LINK_TUNNELED
+ * otherwise.
*/
-bool xhci_port_is_tunneled(struct xhci_hcd *xhci, struct xhci_port *port)
+enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
+ struct xhci_port *port)
{
void __iomem *base;
u32 offset;
@@ -777,10 +780,12 @@ bool xhci_port_is_tunneled(struct xhci_hcd *xhci, struct xhci_port *port)
offset = XHCI_INTEL_SPR_ESS_PORT_OFFSET + port->hcd_portnum * 0x20;
if (readl(base + offset) & XHCI_INTEL_SPR_TUNEN)
- return true;
+ return USB_LINK_TUNNELED;
+ else
+ return USB_LINK_NATIVE;
}
- return false;
+ return USB_LINK_UNKNOWN;
}
void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1ea2c91106b7..a69245074395 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4529,9 +4529,12 @@ static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
if (hcd->speed >= HCD_USB3 && !udev->parent->parent) {
port = xhci->usb3_rhub.ports[udev->portnum - 1];
- if (xhci_port_is_tunneled(xhci, port))
+ udev->tunnel_mode = xhci_port_is_tunneled(xhci, port);
+ if (udev->tunnel_mode == USB_LINK_UNKNOWN)
+ dev_dbg(&udev->dev, "link tunnel state unknown\n");
+ else if (udev->tunnel_mode == USB_LINK_TUNNELED)
dev_dbg(&udev->dev, "tunneled over USB4 link\n");
- else
+ else if (udev->tunnel_mode == USB_LINK_NATIVE)
dev_dbg(&udev->dev, "native USB 3.x link\n");
return 0;
}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index e87a6b2f139d..40aebdfb37c9 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1929,8 +1929,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
-bool xhci_port_is_tunneled(struct xhci_hcd *xhci, struct xhci_port *port);
-
+enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci,
+ struct xhci_port *port);
void xhci_hc_died(struct xhci_hcd *xhci);
#ifdef CONFIG_PM
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 832997a9da0a..672d8fc2abdb 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -495,6 +495,12 @@ struct usb_dev_state;
struct usb_tt;
+enum usb_link_tunnel_mode {
+ USB_LINK_UNKNOWN = 0,
+ USB_LINK_NATIVE,
+ USB_LINK_TUNNELED,
+};
+
enum usb_port_connect_type {
USB_PORT_CONNECT_TYPE_UNKNOWN = 0,
USB_PORT_CONNECT_TYPE_HOT_PLUG,
@@ -605,6 +611,7 @@ struct usb3_lpm_parameters {
* WUSB devices are not, until we authorize them from user space.
* FIXME -- complete doc
* @authenticated: Crypto authentication passed
+ * @tunnel_mode: Connection native or tunneled over USB4
* @lpm_capable: device supports LPM
* @lpm_devinit_allow: Allow USB3 device initiated LPM, exit latency is in range
* @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
@@ -714,6 +721,7 @@ struct usb_device {
unsigned do_remote_wakeup:1;
unsigned reset_resume:1;
unsigned port_is_suspended:1;
+ enum usb_link_tunnel_mode tunnel_mode;
int slot_id;
struct usb2_lpm_parameters l1_params;