Commit 74151b53 authored by Niklas Neronin's avatar Niklas Neronin Committed by Greg Kroah-Hartman

xhci: save slot ID in struct 'xhci_port'

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: default avatarNiklas Neronin <niklas.neronin@intel.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240229141438.619372-4-mathias.nyman@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 06790c19
...@@ -448,40 +448,6 @@ u32 xhci_port_state_to_neutral(u32 state) ...@@ -448,40 +448,6 @@ u32 xhci_port_state_to_neutral(u32 state)
} }
EXPORT_SYMBOL_GPL(xhci_port_state_to_neutral); 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 * Stop device
* It issues stop endpoint command for EP 0 to 30. And wait the last command * 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, ...@@ -932,7 +898,6 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
struct xhci_bus_state *bus_state; struct xhci_bus_state *bus_state;
struct xhci_hcd *xhci; struct xhci_hcd *xhci;
struct usb_hcd *hcd; struct usb_hcd *hcd;
int slot_id;
u32 wIndex; u32 wIndex;
hcd = port->rhub->hcd; hcd = port->rhub->hcd;
...@@ -988,13 +953,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, ...@@ -988,13 +953,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
spin_lock_irqsave(&xhci->lock, *flags); spin_lock_irqsave(&xhci->lock, *flags);
if (time_left) { if (time_left) {
slot_id = xhci_find_slot_id_by_port(hcd, xhci, if (!port->slot_id) {
wIndex + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n"); xhci_dbg(xhci, "slot_id is zero\n");
return -ENODEV; return -ENODEV;
} }
xhci_ring_device(xhci, slot_id); xhci_ring_device(xhci, port->slot_id);
} else { } else {
int port_status = readl(port->addr); int port_status = readl(port->addr);
...@@ -1204,7 +1167,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -1204,7 +1167,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
unsigned long flags; unsigned long flags;
u32 temp, status; u32 temp, status;
int retval = 0; int retval = 0;
int slot_id;
struct xhci_bus_state *bus_state; struct xhci_bus_state *bus_state;
u16 link_state = 0; u16 link_state = 0;
u16 wake_mask = 0; u16 wake_mask = 0;
...@@ -1334,15 +1296,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -1334,15 +1296,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
goto error; goto error;
} }
slot_id = xhci_find_slot_id_by_port(hcd, xhci, if (!port->slot_id) {
portnum1);
if (!slot_id) {
xhci_warn(xhci, "slot_id is zero\n"); xhci_warn(xhci, "slot_id is zero\n");
goto error; goto error;
} }
/* unlock to execute stop endpoint commands */ /* unlock to execute stop endpoint commands */
spin_unlock_irqrestore(&xhci->lock, flags); 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); spin_lock_irqsave(&xhci->lock, flags);
xhci_set_link_state(xhci, port, XDEV_U3); xhci_set_link_state(xhci, port, XDEV_U3);
...@@ -1465,14 +1425,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -1465,14 +1425,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (link_state == USB_SS_PORT_LS_U3) { if (link_state == USB_SS_PORT_LS_U3) {
int retries = 16; int retries = 16;
slot_id = xhci_find_slot_id_by_port(hcd, xhci, if (port->slot_id) {
portnum1);
if (slot_id) {
/* unlock to execute stop endpoint /* unlock to execute stop endpoint
* commands */ * commands */
spin_unlock_irqrestore(&xhci->lock, spin_unlock_irqrestore(&xhci->lock,
flags); flags);
xhci_stop_device(xhci, slot_id, 1); xhci_stop_device(xhci, port->slot_id, 1);
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
} }
xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U3); 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, ...@@ -1586,13 +1544,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
} }
bus_state->port_c_suspend |= 1 << wIndex; bus_state->port_c_suspend |= 1 << wIndex;
slot_id = xhci_find_slot_id_by_port(hcd, xhci, if (!port->slot_id) {
portnum1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n"); xhci_dbg(xhci, "slot_id is zero\n");
goto error; goto error;
} }
xhci_ring_device(xhci, slot_id); xhci_ring_device(xhci, port->slot_id);
break; break;
case USB_PORT_FEAT_C_SUSPEND: case USB_PORT_FEAT_C_SUSPEND:
bus_state->port_c_suspend &= ~(1 << wIndex); bus_state->port_c_suspend &= ~(1 << wIndex);
...@@ -1823,10 +1779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) ...@@ -1823,10 +1779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
if (!portsc_buf[port_index]) if (!portsc_buf[port_index])
continue; continue;
if (test_bit(port_index, &bus_state->bus_suspended)) { if (test_bit(port_index, &bus_state->bus_suspended)) {
int slot_id; int slot_id = ports[port_index]->slot_id;
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
port_index + 1);
if (slot_id) { if (slot_id) {
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
xhci_stop_device(xhci, slot_id, 1); xhci_stop_device(xhci, slot_id, 1);
...@@ -1879,7 +1832,6 @@ int xhci_bus_resume(struct usb_hcd *hcd) ...@@ -1879,7 +1832,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
struct xhci_bus_state *bus_state; struct xhci_bus_state *bus_state;
unsigned long flags; unsigned long flags;
int max_ports, port_index; int max_ports, port_index;
int slot_id;
int sret; int sret;
u32 next_state; u32 next_state;
u32 temp, portsc; u32 temp, portsc;
...@@ -1972,9 +1924,8 @@ int xhci_bus_resume(struct usb_hcd *hcd) ...@@ -1972,9 +1924,8 @@ int xhci_bus_resume(struct usb_hcd *hcd)
continue; continue;
} }
xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC); 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 (ports[port_index]->slot_id)
if (slot_id) xhci_ring_device(xhci, ports[port_index]->slot_id);
xhci_ring_device(xhci, slot_id);
} }
(void) readl(&xhci->op_regs->command); (void) readl(&xhci->op_regs->command);
......
...@@ -907,6 +907,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) ...@@ -907,6 +907,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
if (dev->udev && dev->udev->slot_id) if (dev->udev && dev->udev->slot_id)
dev->udev->slot_id = 0; 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]); kfree(xhci->devs[slot_id]);
xhci->devs[slot_id] = NULL; xhci->devs[slot_id] = NULL;
} }
...@@ -1124,6 +1126,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud ...@@ -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); dev->rhub_port = xhci_find_rhub_port(xhci, udev);
if (!dev->rhub_port) if (!dev->rhub_port)
return -EINVAL; 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)); 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", 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); udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum);
......
...@@ -820,7 +820,6 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup) ...@@ -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_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_port *port; struct xhci_port *port;
struct usb_device *udev; struct usb_device *udev;
unsigned int slot_id;
u32 portsc; u32 portsc;
int i; int i;
...@@ -843,15 +842,14 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup) ...@@ -843,15 +842,14 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
if ((portsc & PORT_PLS_MASK) != XDEV_U3) if ((portsc & PORT_PLS_MASK) != XDEV_U3)
continue; continue;
slot_id = xhci_find_slot_id_by_port(port->rhub->hcd, xhci, if (!port->slot_id || !xhci->devs[port->slot_id]) {
port->hcd_portnum + 1);
if (!slot_id || !xhci->devs[slot_id]) {
xhci_err(xhci, "No dev for slot_id %d for port %d-%d in U3\n", 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; 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 wakeup is enabled then don't disable the port */
if (udev->do_remote_wakeup && do_wakeup) if (udev->do_remote_wakeup && do_wakeup)
......
...@@ -1870,7 +1870,6 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -1870,7 +1870,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
u32 port_id; u32 port_id;
u32 portsc, cmd_reg; u32 portsc, cmd_reg;
int max_ports; int max_ports;
int slot_id;
unsigned int hcd_portnum; unsigned int hcd_portnum;
struct xhci_bus_state *bus_state; struct xhci_bus_state *bus_state;
bool bogus_port_status = false; bool bogus_port_status = false;
...@@ -1922,9 +1921,8 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -1922,9 +1921,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
if (hcd->speed >= HCD_USB3 && if (hcd->speed >= HCD_USB3 &&
(portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); if (port->slot_id && xhci->devs[port->slot_id])
if (slot_id && xhci->devs[slot_id]) xhci->devs[port->slot_id]->flags |= VDEV_PORT_ERROR;
xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
} }
if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
...@@ -1982,9 +1980,8 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -1982,9 +1980,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
* so the roothub behavior is consistent with external * so the roothub behavior is consistent with external
* USB 3.0 hub behavior. * USB 3.0 hub behavior.
*/ */
slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); if (port->slot_id && xhci->devs[port->slot_id])
if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, port->slot_id);
xhci_ring_device(xhci, slot_id);
if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) { if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
xhci_test_and_clear_bit(xhci, port, PORT_PLC); xhci_test_and_clear_bit(xhci, port, PORT_PLC);
usb_wakeup_notification(hcd->self.root_hub, usb_wakeup_notification(hcd->self.root_hub,
......
...@@ -1462,6 +1462,8 @@ struct xhci_port { ...@@ -1462,6 +1462,8 @@ struct xhci_port {
unsigned int lpm_incapable:1; unsigned int lpm_incapable:1;
unsigned long resume_timestamp; unsigned long resume_timestamp;
bool rexit_active; 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 rexit_done;
struct completion u3exit_done; struct completion u3exit_done;
}; };
...@@ -1944,8 +1946,6 @@ unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd); ...@@ -1944,8 +1946,6 @@ unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
u32 xhci_port_state_to_neutral(u32 state); 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); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
/* xHCI contexts */ /* xHCI contexts */
......
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