xhci: save slot ID in struct 'xhci_port'
authorNiklas Neronin <niklas.neronin@intel.com>
Thu, 29 Feb 2024 14:14:32 +0000 (16:14 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 Mar 2024 19:25:27 +0000 (20:25 +0100)
Slot ID is a index of a virtual device in struct 'xhci_hcd->devs[]'.
Previously, to get the slot ID associated with a port, we had to loop
through all devices and compare ports, which is very inefficient.
Instead, the slot ID (of the device which is directly connected to the
port), is added to the its corresponding 'xhci_port' struct. As a result,
finding the port's device is quick and easy.

Function 'xhci_find_slot_id_by_port()' is removed, as it is no longer
needed.

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-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h

index 37128a777a58ed92d2319043765efa85be42be49..61f083de6e196744ea3e6655a86c83581ce34d10 100644 (file)
@@ -448,40 +448,6 @@ u32 xhci_port_state_to_neutral(u32 state)
 }
 EXPORT_SYMBOL_GPL(xhci_port_state_to_neutral);
 
-/**
- * xhci_find_slot_id_by_port() - Find slot id of a usb device on a roothub port
- * @hcd: pointer to hcd of the roothub
- * @xhci: pointer to xhci structure
- * @port: one-based port number of the port in this roothub.
- *
- * Return: Slot id of the usb device connected to the root port, 0 if not found
- */
-
-int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
-               u16 port)
-{
-       int slot_id;
-       int i;
-       enum usb_device_speed speed;
-
-       /* 'hcd_portnum' is zero-based, thus convert one-based 'port' to zero-based */
-       port -= 1;
-       slot_id = 0;
-       for (i = 0; i < MAX_HC_SLOTS; i++) {
-               if (!xhci->devs[i] || !xhci->devs[i]->udev)
-                       continue;
-               speed = xhci->devs[i]->udev->speed;
-               if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
-                               && xhci->devs[i]->rhub_port->hcd_portnum == port) {
-                       slot_id = i;
-                       break;
-               }
-       }
-
-       return slot_id;
-}
-EXPORT_SYMBOL_GPL(xhci_find_slot_id_by_port);
-
 /*
  * Stop device
  * It issues stop endpoint command for EP 0 to 30. And wait the last command
@@ -932,7 +898,6 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
        struct xhci_bus_state *bus_state;
        struct xhci_hcd *xhci;
        struct usb_hcd *hcd;
-       int slot_id;
        u32 wIndex;
 
        hcd = port->rhub->hcd;
@@ -988,13 +953,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
                spin_lock_irqsave(&xhci->lock, *flags);
 
                if (time_left) {
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                                           wIndex + 1);
-                       if (!slot_id) {
+                       if (!port->slot_id) {
                                xhci_dbg(xhci, "slot_id is zero\n");
                                return -ENODEV;
                        }
-                       xhci_ring_device(xhci, slot_id);
+                       xhci_ring_device(xhci, port->slot_id);
                } else {
                        int port_status = readl(port->addr);
 
@@ -1204,7 +1167,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
        unsigned long flags;
        u32 temp, status;
        int retval = 0;
-       int slot_id;
        struct xhci_bus_state *bus_state;
        u16 link_state = 0;
        u16 wake_mask = 0;
@@ -1334,15 +1296,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                goto error;
                        }
 
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                                           portnum1);
-                       if (!slot_id) {
+                       if (!port->slot_id) {
                                xhci_warn(xhci, "slot_id is zero\n");
                                goto error;
                        }
                        /* unlock to execute stop endpoint commands */
                        spin_unlock_irqrestore(&xhci->lock, flags);
-                       xhci_stop_device(xhci, slot_id, 1);
+                       xhci_stop_device(xhci, port->slot_id, 1);
                        spin_lock_irqsave(&xhci->lock, flags);
 
                        xhci_set_link_state(xhci, port, XDEV_U3);
@@ -1465,14 +1425,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
                        if (link_state == USB_SS_PORT_LS_U3) {
                                int retries = 16;
-                               slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                                                   portnum1);
-                               if (slot_id) {
+                               if (port->slot_id) {
                                        /* unlock to execute stop endpoint
                                         * commands */
                                        spin_unlock_irqrestore(&xhci->lock,
                                                                flags);
-                                       xhci_stop_device(xhci, slot_id, 1);
+                                       xhci_stop_device(xhci, port->slot_id, 1);
                                        spin_lock_irqsave(&xhci->lock, flags);
                                }
                                xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U3);
@@ -1586,13 +1544,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        }
                        bus_state->port_c_suspend |= 1 << wIndex;
 
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                       portnum1);
-                       if (!slot_id) {
+                       if (!port->slot_id) {
                                xhci_dbg(xhci, "slot_id is zero\n");
                                goto error;
                        }
-                       xhci_ring_device(xhci, slot_id);
+                       xhci_ring_device(xhci, port->slot_id);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        bus_state->port_c_suspend &= ~(1 << wIndex);
@@ -1823,10 +1779,7 @@ retry:
                if (!portsc_buf[port_index])
                        continue;
                if (test_bit(port_index, &bus_state->bus_suspended)) {
-                       int slot_id;
-
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                                           port_index + 1);
+                       int slot_id = ports[port_index]->slot_id;
                        if (slot_id) {
                                spin_unlock_irqrestore(&xhci->lock, flags);
                                xhci_stop_device(xhci, slot_id, 1);
@@ -1879,7 +1832,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
        struct xhci_bus_state *bus_state;
        unsigned long flags;
        int max_ports, port_index;
-       int slot_id;
        int sret;
        u32 next_state;
        u32 temp, portsc;
@@ -1972,9 +1924,8 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                        continue;
                }
                xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC);
-               slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1);
-               if (slot_id)
-                       xhci_ring_device(xhci, slot_id);
+               if (ports[port_index]->slot_id)
+                       xhci_ring_device(xhci, ports[port_index]->slot_id);
        }
        (void) readl(&xhci->op_regs->command);
 
index 9fa68fa17ac77735fef3902b97502fe079f06d96..c4b3e425bd1914eb2c20d1d7cd896f7794898935 100644 (file)
@@ -907,6 +907,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 
        if (dev->udev && dev->udev->slot_id)
                dev->udev->slot_id = 0;
+       if (dev->rhub_port && dev->rhub_port->slot_id == slot_id)
+               dev->rhub_port->slot_id = 0;
        kfree(xhci->devs[slot_id]);
        xhci->devs[slot_id] = NULL;
 }
@@ -1124,6 +1126,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        dev->rhub_port = xhci_find_rhub_port(xhci, udev);
        if (!dev->rhub_port)
                return -EINVAL;
+       /* Slot ID is set to the device directly below the root hub */
+       if (!udev->parent->parent)
+               dev->rhub_port->slot_id = udev->slot_id;
        slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->rhub_port->hw_portnum + 1));
        xhci_dbg(xhci, "Slot ID %d: HW portnum %d, hcd portnum %d\n",
                 udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum);
index b534ca9752be43cb304f69c94b70b1fef5bc75c8..1843f3d5b1e6055c19f603c338f3f16d3484d076 100644 (file)
@@ -820,7 +820,6 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
        struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
        struct xhci_port        *port;
        struct usb_device       *udev;
-       unsigned int            slot_id;
        u32                     portsc;
        int                     i;
 
@@ -843,15 +842,14 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
                if ((portsc & PORT_PLS_MASK) != XDEV_U3)
                        continue;
 
-               slot_id = xhci_find_slot_id_by_port(port->rhub->hcd, xhci,
-                                                   port->hcd_portnum + 1);
-               if (!slot_id || !xhci->devs[slot_id]) {
+               if (!port->slot_id || !xhci->devs[port->slot_id]) {
                        xhci_err(xhci, "No dev for slot_id %d for port %d-%d in U3\n",
-                                slot_id, port->rhub->hcd->self.busnum, port->hcd_portnum + 1);
+                                port->slot_id, port->rhub->hcd->self.busnum,
+                                port->hcd_portnum + 1);
                        continue;
                }
 
-               udev = xhci->devs[slot_id]->udev;
+               udev = xhci->devs[port->slot_id]->udev;
 
                /* if wakeup is enabled then don't disable the port */
                if (udev->do_remote_wakeup && do_wakeup)
index d4a28ac4967fb6eba78fe0f31ac0d637e383de30..95ed26114ee8b8060e5ac943656740878705e8a2 100644 (file)
@@ -1870,7 +1870,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
        u32 port_id;
        u32 portsc, cmd_reg;
        int max_ports;
-       int slot_id;
        unsigned int hcd_portnum;
        struct xhci_bus_state *bus_state;
        bool bogus_port_status = false;
@@ -1922,9 +1921,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
 
        if (hcd->speed >= HCD_USB3 &&
            (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
-               slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
-               if (slot_id && xhci->devs[slot_id])
-                       xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
+               if (port->slot_id && xhci->devs[port->slot_id])
+                       xhci->devs[port->slot_id]->flags |= VDEV_PORT_ERROR;
        }
 
        if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1982,9 +1980,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
                 * so the roothub behavior is consistent with external
                 * USB 3.0 hub behavior.
                 */
-               slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
-               if (slot_id && xhci->devs[slot_id])
-                       xhci_ring_device(xhci, slot_id);
+               if (port->slot_id && xhci->devs[port->slot_id])
+                       xhci_ring_device(xhci, port->slot_id);
                if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                        usb_wakeup_notification(hcd->self.root_hub,
index 634ab517a7769dea31efc763d02add3a4fde0c32..6f4bf98a628245818c11e32ae355e596efb4c23c 100644 (file)
@@ -1462,6 +1462,8 @@ struct xhci_port {
        unsigned int            lpm_incapable:1;
        unsigned long           resume_timestamp;
        bool                    rexit_active;
+       /* Slot ID is the index of the device directly connected to the port */
+       int                     slot_id;
        struct completion       rexit_done;
        struct completion       u3exit_done;
 };
@@ -1944,8 +1946,6 @@ unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd);
 #endif /* CONFIG_PM */
 
 u32 xhci_port_state_to_neutral(u32 state);
-int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
-               u16 port);
 void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
 
 /* xHCI contexts */