xhci: replace real & fake port with pointer to root hub port
authorNiklas Neronin <niklas.neronin@intel.com>
Thu, 29 Feb 2024 14:14:31 +0000 (16:14 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 Mar 2024 19:25:27 +0000 (20:25 +0100)
Variables real & fake port do not convey their purpose, thus they are
replaced with a pointer to the root hub port 'struct xhci_port *rhub_port'.
'rhub_port' contains real & fake ports in zero-based format, which happens
to be more widely used inside the xHCI driver:
 - 'real_port' is ('rhub_port->hw_portnum' + 1)
 - 'fake_port' is ('rhub_port->hcd_portnum' + 1)

One reason for real port being one-based, is to signal other functions in
case struct 'xhci_virt_device' initialization failed, in this case the
value will remain 0. This is no longer needed, instead we check whether
or not 'rhub_port' is 'NULL'.

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-3-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-mtk-sch.c
drivers/usb/host/xhci-trace.h
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index 0980ade2a234a38ee6b8d25e674e1da12b624224..37128a777a58ed92d2319043765efa85be42be49 100644 (file)
@@ -464,13 +464,15 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
        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]->fake_port == port) {
+                               && xhci->devs[i]->rhub_port->hcd_portnum == port) {
                        slot_id = i;
                        break;
                }
index 92160b96d4c0c357891c97c5240e4138bcbbf0ec..9fa68fa17ac77735fef3902b97502fe079f06d96 100644 (file)
@@ -789,15 +789,14 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci,
        bool slot_found = false;
 
        /* If the device never made it past the Set Address stage,
-        * it may not have the real_port set correctly.
+        * it may not have the root hub port pointer set correctly.
         */
-       if (virt_dev->real_port == 0 ||
-                       virt_dev->real_port > HCS_MAX_PORTS(xhci->hcs_params1)) {
-               xhci_dbg(xhci, "Bad real port.\n");
+       if (!virt_dev->rhub_port) {
+               xhci_dbg(xhci, "Bad rhub port.\n");
                return;
        }
 
-       tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts);
+       tt_list_head = &(xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts);
        list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
                /* Multi-TT hubs will have more than one entry */
                if (tt_info->slot_id == slot_id) {
@@ -834,7 +833,7 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci,
                        goto free_tts;
                INIT_LIST_HEAD(&tt_info->tt_list);
                list_add(&tt_info->tt_list,
-                               &xhci->rh_bw[virt_dev->real_port - 1].tts);
+                               &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts);
                tt_info->slot_id = virt_dev->udev->slot_id;
                if (tt->multi)
                        tt_info->ttport = i+1;
@@ -929,13 +928,12 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
        if (!vdev)
                return;
 
-       if (vdev->real_port == 0 ||
-                       vdev->real_port > HCS_MAX_PORTS(xhci->hcs_params1)) {
-               xhci_dbg(xhci, "Bad vdev->real_port.\n");
+       if (!vdev->rhub_port) {
+               xhci_dbg(xhci, "Bad rhub port.\n");
                goto out;
        }
 
-       tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts);
+       tt_list_head = &(xhci->rh_bw[vdev->rhub_port->hw_portnum].tts);
        list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
                /* is this a hub device that added a tt_info to the tts list */
                if (tt_info->slot_id == slot_id) {
@@ -1082,7 +1080,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        struct xhci_virt_device *dev;
        struct xhci_ep_ctx      *ep0_ctx;
        struct xhci_slot_ctx    *slot_ctx;
-       struct xhci_port        *rhub_port;
        u32                     max_packets;
 
        dev = xhci->devs[udev->slot_id];
@@ -1124,14 +1121,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
                return -EINVAL;
        }
        /* Find the root hub port this device is under */
-       rhub_port = xhci_find_rhub_port(xhci, udev);
-       if (!rhub_port)
+       dev->rhub_port = xhci_find_rhub_port(xhci, udev);
+       if (!dev->rhub_port)
                return -EINVAL;
-       dev->real_port = rhub_port->hw_portnum + 1;
-       dev->fake_port = rhub_port->hcd_portnum + 1;
-       slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->real_port));
-       xhci_dbg(xhci, "Set root hub portnum to %d\n", dev->real_port);
-       xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->fake_port);
+       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);
 
        /* Find the right bandwidth table that this device will be a part of.
         * If this is a full speed device attached directly to a root port (or a
@@ -1140,12 +1135,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
         * will never be created for the HS root hub.
         */
        if (!udev->tt || !udev->tt->hub->parent) {
-               dev->bw_table = &xhci->rh_bw[dev->real_port - 1].bw_table;
+               dev->bw_table = &xhci->rh_bw[dev->rhub_port->hw_portnum].bw_table;
        } else {
                struct xhci_root_port_bw_info *rh_bw;
                struct xhci_tt_bw_info *tt_bw;
 
-               rh_bw = &xhci->rh_bw[dev->real_port - 1];
+               rh_bw = &xhci->rh_bw[dev->rhub_port->hw_portnum];
                /* Find the right TT. */
                list_for_each_entry(tt_bw, &rh_bw->tts, tt_list) {
                        if (tt_bw->slot_id != udev->tt->hub->slot_id)
index 61f3f8bbdcead3f325b60128c8bf648acf32dc2b..27eb384a3963421402ca6e16ffa21908831fa689 100644 (file)
@@ -122,10 +122,6 @@ static u32 get_bw_boundary(enum usb_device_speed speed)
 * each HS root port is treated as a single bandwidth domain,
 * but each SS root port is treated as two bandwidth domains, one for IN eps,
 * one for OUT eps.
-* @real_port value is defined as follow according to xHCI spec:
-* 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc
-* so the bandwidth domain array is organized as follow for simplification:
-* SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
 */
 static struct mu3h_sch_bw_info *
 get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
@@ -136,19 +132,19 @@ get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
        int bw_index;
 
        virt_dev = xhci->devs[udev->slot_id];
-       if (!virt_dev->real_port) {
-               WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev));
+       if (!virt_dev->rhub_port) {
+               WARN_ONCE(1, "%s invalid rhub port\n", dev_name(&udev->dev));
                return NULL;
        }
 
        if (udev->speed >= USB_SPEED_SUPER) {
                if (usb_endpoint_dir_out(&ep->desc))
-                       bw_index = (virt_dev->real_port - 1) * 2;
+                       bw_index = (virt_dev->rhub_port->hw_portnum) * 2;
                else
-                       bw_index = (virt_dev->real_port - 1) * 2 + 1;
+                       bw_index = (virt_dev->rhub_port->hw_portnum) * 2 + 1;
        } else {
                /* add one more for each SS port */
-               bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1;
+               bw_index = virt_dev->rhub_port->hw_portnum + xhci->usb3_rhub.num_ports;
        }
 
        return &mtk->sch_array[bw_index];
index ac47b1c0544a6836882970add7a7cb50ed54678f..1740000d54c295d4d8884910fc3f3ae04e6a4d6b 100644 (file)
@@ -172,8 +172,8 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
                __field(void *, vdev)
                __field(unsigned long long, out_ctx)
                __field(unsigned long long, in_ctx)
-               __field(u8, fake_port)
-               __field(u8, real_port)
+               __field(int, hcd_portnum)
+               __field(int, hw_portnum)
                __field(u16, current_mel)
 
        ),
@@ -181,13 +181,13 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
                __entry->vdev = vdev;
                __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma;
                __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma;
-               __entry->fake_port = (u8) vdev->fake_port;
-               __entry->real_port = (u8) vdev->real_port;
+               __entry->hcd_portnum = (int) vdev->rhub_port->hcd_portnum;
+               __entry->hw_portnum = (int) vdev->rhub_port->hw_portnum;
                __entry->current_mel = (u16) vdev->current_mel;
                ),
-       TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d",
+       TP_printk("vdev %p ctx %llx | %llx hcd_portnum %d hw_portnum %d current_mel %d",
                __entry->vdev, __entry->in_ctx, __entry->out_ctx,
-               __entry->fake_port, __entry->real_port, __entry->current_mel
+               __entry->hcd_portnum, __entry->hw_portnum, __entry->current_mel
        )
 );
 
index b405b8236134c81d3a02af02af32e26c77a8916d..c50d5881e214b29af4191142dc0c6706924b227c 100644 (file)
@@ -2273,7 +2273,7 @@ static int xhci_check_tt_bw_table(struct xhci_hcd *xhci,
        struct xhci_tt_bw_info *tt_info;
 
        /* Find the bandwidth table for the root port this TT is attached to. */
-       bw_table = &xhci->rh_bw[virt_dev->real_port - 1].bw_table;
+       bw_table = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].bw_table;
        tt_info = virt_dev->tt_info;
        /* If this TT already had active endpoints, the bandwidth for this TT
         * has already been added.  Removing all periodic endpoints (and thus
@@ -2391,7 +2391,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci,
        if (virt_dev->tt_info) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "Recalculating BW for rootport %u",
-                               virt_dev->real_port);
+                               virt_dev->rhub_port->hw_portnum + 1);
                if (xhci_check_tt_bw_table(xhci, virt_dev, old_active_eps)) {
                        xhci_warn(xhci, "Not enough bandwidth on HS bus for "
                                        "newly activated TT.\n");
@@ -2404,7 +2404,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci,
        } else {
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "Recalculating BW for rootport %u",
-                               virt_dev->real_port);
+                               virt_dev->rhub_port->hw_portnum + 1);
        }
 
        /* Add in how much bandwidth will be used for interval zero, or the
@@ -2501,14 +2501,12 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci,
                bw_used += overhead + packet_size;
 
        if (!virt_dev->tt_info && virt_dev->udev->speed == USB_SPEED_HIGH) {
-               unsigned int port_index = virt_dev->real_port - 1;
-
                /* OK, we're manipulating a HS device attached to a
                 * root port bandwidth domain.  Include the number of active TTs
                 * in the bandwidth used.
                 */
                bw_used += TT_HS_OVERHEAD *
-                       xhci->rh_bw[port_index].num_active_tts;
+                       xhci->rh_bw[virt_dev->rhub_port->hw_portnum].num_active_tts;
        }
 
        xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
@@ -2695,7 +2693,7 @@ void xhci_update_tt_active_eps(struct xhci_hcd *xhci,
        if (!virt_dev->tt_info)
                return;
 
-       rh_bw_info = &xhci->rh_bw[virt_dev->real_port - 1];
+       rh_bw_info = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum];
        if (old_active_eps == 0 &&
                                virt_dev->tt_info->active_eps != 0) {
                rh_bw_info->num_active_tts += 1;
index 6e09b9130fae07358b72defd3f57a4e4de45018b..634ab517a7769dea31efc763d02add3a4fde0c32 100644 (file)
@@ -739,8 +739,7 @@ struct xhci_virt_device {
        /* Used for addressing devices and configuration changes */
        struct xhci_container_ctx       *in_ctx;
        struct xhci_virt_ep             eps[EP_CTX_PER_DEV];
-       u8                              fake_port;
-       u8                              real_port;
+       struct xhci_port                *rhub_port;
        struct xhci_interval_bw_table   *bw_table;
        struct xhci_tt_bw_info          *tt_info;
        /*