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

xhci: rework how real & fake ports are found

xHC hardware needs to know which roothub port a USB device is attached to
when controlling the device, so the xHCI driver stores in each device the
roothub port which it's connected behind. This is done with two different
port index values, the 'real_port' which is an index to the xHC hardware
port register array, and the 'fake_port' which is the per hub port index
used by the hub driver.

Instead of finding real & fake port separately, find the root hub port
'xhci_port' structure which contains both real & fake port values:
- 'real_port' is ('hw_portnum' + 1)
- 'fake_port' is ('hcd_portnum' + 1)
i.e. real & fake port are 'hw_portnum' & 'hcd_portnum' in one-based
format.

The 'xhci_port' structure is a better way to refer to roothub ports than
the 'real_port' & 'fake_port'. As a result, these port indexes are slated
to be replaced with a direct pointer to the root hub port. This patch
setups the ground work for the future changes.

Signed-off-by: Niklas Neronin <niklas.neronin@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240229141438.619372-2-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Niklas Neronin and committed by
Greg Kroah-Hartman
c9a63ec5 c40b51b3

+15 -19
+15 -19
drivers/usb/host/xhci-mem.c
··· 1051 1051 * The xHCI roothub may have ports of differing speeds in any order in the port 1052 1052 * status registers. 1053 1053 * 1054 - * The xHCI hardware wants to know the roothub port number that the USB device 1054 + * The xHCI hardware wants to know the roothub port that the USB device 1055 1055 * is attached to (or the roothub port its ancestor hub is attached to). All we 1056 1056 * know is the index of that port under either the USB 2.0 or the USB 3.0 1057 1057 * roothub, but that doesn't give us the real index into the HW port status 1058 - * registers. Call xhci_find_raw_port_number() to get real index. 1058 + * registers. 1059 1059 */ 1060 - static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, 1061 - struct usb_device *udev) 1060 + static struct xhci_port *xhci_find_rhub_port(struct xhci_hcd *xhci, struct usb_device *udev) 1062 1061 { 1063 1062 struct usb_device *top_dev; 1063 + struct xhci_hub *rhub; 1064 1064 struct usb_hcd *hcd; 1065 1065 1066 1066 if (udev->speed >= USB_SPEED_SUPER) ··· 1072 1072 top_dev = top_dev->parent) 1073 1073 /* Found device below root hub */; 1074 1074 1075 - return xhci_find_raw_port_number(hcd, top_dev->portnum); 1075 + rhub = xhci_get_rhub(hcd); 1076 + return rhub->ports[top_dev->portnum - 1]; 1076 1077 } 1077 1078 1078 1079 /* Setup an xHCI virtual device for a Set Address command */ ··· 1082 1081 struct xhci_virt_device *dev; 1083 1082 struct xhci_ep_ctx *ep0_ctx; 1084 1083 struct xhci_slot_ctx *slot_ctx; 1085 - u32 port_num; 1084 + struct xhci_port *rhub_port; 1086 1085 u32 max_packets; 1087 - struct usb_device *top_dev; 1088 1086 1089 1087 dev = xhci->devs[udev->slot_id]; 1090 1088 /* Slot ID 0 is reserved */ ··· 1124 1124 return -EINVAL; 1125 1125 } 1126 1126 /* Find the root hub port this device is under */ 1127 - port_num = xhci_find_real_port_number(xhci, udev); 1128 - if (!port_num) 1127 + rhub_port = xhci_find_rhub_port(xhci, udev); 1128 + if (!rhub_port) 1129 1129 return -EINVAL; 1130 - slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(port_num)); 1131 - /* Set the port number in the virtual_device to the faked port number */ 1132 - for (top_dev = udev; top_dev->parent && top_dev->parent->parent; 1133 - top_dev = top_dev->parent) 1134 - /* Found device below root hub */; 1135 - dev->fake_port = top_dev->portnum; 1136 - dev->real_port = port_num; 1137 - xhci_dbg(xhci, "Set root hub portnum to %d\n", port_num); 1130 + dev->real_port = rhub_port->hw_portnum + 1; 1131 + dev->fake_port = rhub_port->hcd_portnum + 1; 1132 + slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->real_port)); 1133 + xhci_dbg(xhci, "Set root hub portnum to %d\n", dev->real_port); 1138 1134 xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->fake_port); 1139 1135 1140 1136 /* Find the right bandwidth table that this device will be a part of. ··· 1140 1144 * will never be created for the HS root hub. 1141 1145 */ 1142 1146 if (!udev->tt || !udev->tt->hub->parent) { 1143 - dev->bw_table = &xhci->rh_bw[port_num - 1].bw_table; 1147 + dev->bw_table = &xhci->rh_bw[dev->real_port - 1].bw_table; 1144 1148 } else { 1145 1149 struct xhci_root_port_bw_info *rh_bw; 1146 1150 struct xhci_tt_bw_info *tt_bw; 1147 1151 1148 - rh_bw = &xhci->rh_bw[port_num - 1]; 1152 + rh_bw = &xhci->rh_bw[dev->real_port - 1]; 1149 1153 /* Find the right TT. */ 1150 1154 list_for_each_entry(tt_bw, &rh_bw->tts, tt_list) { 1151 1155 if (tt_bw->slot_id != udev->tt->hub->slot_id)