Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: xhci: Add debugfs support for xHCI Port Link Info (PORTLI) register.

Each xHCI roothub port has a Port Link Info (PORTLI) register that is
used by USB3 and eUSB2V2 ports.

USB3 ports show link error count, rx lane count, and tx lane count.

eUSB2V2 ports show Rx Data Rate (RDR) and Tx Data Rate (TDR).

Rx/Tx Data Rate is a multiple of USB2 2.0 HS 480 Mb/s data rates,
and is only valid if a eUSB2V2 device is connected (CCS=1).

0 = "USB 2.0 HS" normal HS 480 Mb/s, no eUSB2V2 in use
1 = "HS1" Assymetric eUSB2V2 where this direction runs normal 480Mb/s
2 = "HS2" 960Mb/s
...
10 = "HS10" 4.8 Gb/s, max eUSB2V2 rate

PORTLI is Reserved and preserve "RsvdP" for normal USB2 ports

Sample output of USB3 port PORTLI:
cat /sys/kernel/debug/usb/xhci/0000:00:14.0/ports/port14/portli
0x00000000 LEC=0 RLC=0 TLC=0

Signed-off-by: Rai, Amardeep <amardeep.rai@intel.com>
Co-developed-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20251119142417.2820519-24-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Rai, Amardeep and committed by
Greg Kroah-Hartman
384c57ec 757508d6

+42 -1
+3 -1
drivers/usb/host/xhci-caps.h
··· 115 115 /* bit 10 - Rsvd */ 116 116 /* bit 11 - HC support Double BW on a eUSB2 HS ISOC EP */ 117 117 #define HCC2_EUSB2_DIC BIT(11) 118 - /* bits 31:12 - Rsvd */ 118 + /* bit 12 - HC support eUSB2V2 capability */ 119 + #define HCC2_E2V2C BIT(12) 120 + /* bits 31:13 - Rsvd */
+34
drivers/usb/host/xhci-debugfs.c
··· 383 383 .release = single_release, 384 384 }; 385 385 386 + static int xhci_portli_show(struct seq_file *s, void *unused) 387 + { 388 + struct xhci_port *port = s->private; 389 + struct xhci_hcd *xhci = hcd_to_xhci(port->rhub->hcd); 390 + u32 portli; 391 + 392 + portli = readl(&port->port_reg->portli); 393 + 394 + /* PORTLI fields are valid if port is a USB3 or eUSB2V2 port */ 395 + if (port->rhub == &xhci->usb3_rhub) 396 + seq_printf(s, "0x%08x LEC=%u RLC=%u TLC=%u\n", portli, 397 + PORT_LEC(portli), PORT_RX_LANES(portli), PORT_TX_LANES(portli)); 398 + else if (xhci->hcc_params2 & HCC2_E2V2C) 399 + seq_printf(s, "0x%08x RDR=%u TDR=%u\n", portli, 400 + PORTLI_RDR(portli), PORTLI_TDR(portli)); 401 + else 402 + seq_printf(s, "0x%08x RsvdP\n", portli); 403 + 404 + return 0; 405 + } 406 + 407 + static int xhci_portli_open(struct inode *inode, struct file *file) 408 + { 409 + return single_open(file, xhci_portli_show, inode->i_private); 410 + } 411 + 412 + static const struct file_operations portli_fops = { 413 + .open = xhci_portli_open, 414 + .read = seq_read, 415 + .llseek = seq_lseek, 416 + .release = single_release, 417 + }; 418 + 386 419 static void xhci_debugfs_create_files(struct xhci_hcd *xhci, 387 420 struct xhci_file_map *files, 388 421 size_t nentries, void *data, ··· 657 624 dir = debugfs_create_dir(port_name, parent); 658 625 port = &xhci->hw_ports[i]; 659 626 debugfs_create_file("portsc", 0644, dir, port, &port_fops); 627 + debugfs_create_file("portli", 0444, dir, port, &portli_fops); 660 628 } 661 629 } 662 630
+5
drivers/usb/host/xhci-port.h
··· 144 144 #define PORT_TEST_MODE_SHIFT 28 145 145 146 146 /* USB3 Protocol PORTLI Port Link Information */ 147 + #define PORT_LEC(p) ((p) & 0xffff) 147 148 #define PORT_RX_LANES(p) (((p) >> 16) & 0xf) 148 149 #define PORT_TX_LANES(p) (((p) >> 20) & 0xf) 150 + 151 + /* eUSB2v2 protocol PORTLI Port Link information, RsvdP for normal USB2 */ 152 + #define PORTLI_RDR(p) ((p) & 0xf) 153 + #define PORTLI_TDR(p) (((p) >> 4) & 0xf) 149 154 150 155 /* USB2 Protocol PORTHLPMC */ 151 156 #define PORT_HIRDM(p)((p) & 3)