]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: xhci: simplify handling of Structural Parameters 1 values
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Wed, 19 Nov 2025 14:24:09 +0000 (16:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Nov 2025 13:53:00 +0000 (14:53 +0100)
The 32-bit read-only HCSPARAMS1 register contains the following fields:
 Bits  7:0   - Number of Device Slots (MaxSlots)
 Bits 18:8   - Number of Interrupters (MaxIntrs)
 Bits 23:19  - Reserved
 Bits 31:24  - Number of Ports (MaxPorts)

Since the register value is constant for the lifetime of the controller,
it is cached in 'xhci->hcs_params1'. However, platform drivers may
override the number of interrupters through a separate variable,
'xhci->max_interrupters', leaving only the maximum slots and ports values
still derived from the cached register.

To simplify the code and improve readability, replace 'xhci->hcs_params1'
with two dedicated 'u8' fields: 'xhci->max_slots' and 'xhci->max_ports'.
These values are initialized once and used directly instead of calling
'HCS_MAX_SLOTS()' and 'HCS_MAX_PORTS()' macros.

This change reduces code clutter without increasing memory usage.

Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20251119142417.2820519-16-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-debugfs.c
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.c
drivers/usb/host/xhci.h

index d32ac8f84691cf17d7b87112bf2dbf0b77a1eddd..ae50b667a54871cc78ec6b1eb4855bc62bee95eb 100644 (file)
@@ -613,20 +613,16 @@ void xhci_debugfs_remove_slot(struct xhci_hcd *xhci, int slot_id)
 static void xhci_debugfs_create_ports(struct xhci_hcd *xhci,
                                      struct dentry *parent)
 {
-       unsigned int            num_ports;
        char                    port_name[8];
        struct xhci_port        *port;
        struct dentry           *dir;
 
-       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-
        parent = debugfs_create_dir("ports", parent);
 
-       while (num_ports--) {
-               scnprintf(port_name, sizeof(port_name), "port%02d",
-                         num_ports + 1);
+       for (int i = 0; i < xhci->max_ports; i++) {
+               scnprintf(port_name, sizeof(port_name), "port%02d", i + 1);
                dir = debugfs_create_dir(port_name, parent);
-               port = &xhci->hw_ports[num_ports];
+               port = &xhci->hw_ports[i];
                debugfs_create_file("portsc", 0644, dir, port, &port_fops);
        }
 }
@@ -634,7 +630,6 @@ static void xhci_debugfs_create_ports(struct xhci_hcd *xhci,
 static int xhci_port_bw_show(struct xhci_hcd *xhci, u8 dev_speed,
                                struct seq_file *s)
 {
-       unsigned int                    num_ports;
        unsigned int                    i;
        int                             ret;
        struct xhci_container_ctx       *ctx;
@@ -645,8 +640,6 @@ static int xhci_port_bw_show(struct xhci_hcd *xhci, u8 dev_speed,
        if (ret < 0)
                return ret;
 
-       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-
        ctx = xhci_alloc_port_bw_ctx(xhci, 0);
        if (!ctx) {
                pm_runtime_put_sync(dev);
@@ -661,7 +654,7 @@ static int xhci_port_bw_show(struct xhci_hcd *xhci, u8 dev_speed,
        /* print all roothub ports available bandwidth
         * refer to xhci rev1_2 protocol 6.2.6 , byte 0 is reserved
         */
-       for (i = 1; i < num_ports+1; i++)
+       for (i = 1; i <= xhci->max_ports; i++)
                seq_printf(s, "port[%d] available bw: %d%%.\n", i,
                                ctx->bytes[i]);
 err_out:
index c4c85312b04c8fed224c2be67595a0e8ad8e4ee6..cf358e5c664215eb48f141e9e11afb67d0ff4d16 100644 (file)
@@ -700,7 +700,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci,
        /* Disable all Device Slots */
        xhci_dbg(xhci, "Disable all slots\n");
        spin_unlock_irqrestore(&xhci->lock, *flags);
-       for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+       for (i = 1; i <= xhci->max_slots; i++) {
                if (!xhci->devs[i])
                        continue;
 
index 9a6a8d9f377072d1592c664747631bf6541f4979..2bbbf64a32c8754cc40cd6c7c2a274aef5bc2988 100644 (file)
@@ -951,7 +951,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i
                /* is this a hub device that added a tt_info to the tts list */
                if (tt_info->slot_id == slot_id) {
                        /* are any devices using this tt_info? */
-                       for (i = 1; i < HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+                       for (i = 1; i < xhci->max_slots; i++) {
                                vdev = xhci->devs[i];
                                if (vdev && (vdev->tt_info == tt_info))
                                        xhci_free_virt_devices_depth_first(
@@ -1899,7 +1899,7 @@ EXPORT_SYMBOL_GPL(xhci_remove_secondary_interrupter);
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
        struct device   *dev = xhci_to_hcd(xhci)->self.sysdev;
-       int i, j, num_ports;
+       int i, j;
 
        cancel_delayed_work_sync(&xhci->cmd_timer);
 
@@ -1918,8 +1918,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed command ring");
        xhci_cleanup_command_queue(xhci);
 
-       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-       for (i = 0; i < num_ports && xhci->rh_bw; i++) {
+       for (i = 0; i < xhci->max_ports && xhci->rh_bw; i++) {
                struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
                for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
                        struct list_head *ep = &bwt->interval_bw[j].endpoints;
@@ -1928,7 +1927,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                }
        }
 
-       for (i = HCS_MAX_SLOTS(xhci->hcs_params1); i > 0; i--)
+       for (i = xhci->max_slots; i > 0; i--)
                xhci_free_virt_devices_depth_first(xhci, i);
 
        dma_pool_destroy(xhci->segment_pool);
@@ -1964,7 +1963,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        if (!xhci->rh_bw)
                goto no_bw;
 
-       for (i = 0; i < num_ports; i++) {
+       for (i = 0; i < xhci->max_ports; i++) {
                struct xhci_tt_bw_info *tt, *n;
                list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) {
                        list_del(&tt->tt_list);
@@ -2165,7 +2164,7 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
        if (!rhub->ports)
                return;
 
-       for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
+       for (i = 0; i < xhci->max_ports; i++) {
                if (xhci->hw_ports[i].rhub != rhub ||
                    xhci->hw_ports[i].hcd_portnum == DUPLICATE_ENTRY)
                        continue;
@@ -2188,19 +2187,17 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 {
        void __iomem *base;
        u32 offset;
-       unsigned int num_ports;
        int i, j;
        int cap_count = 0;
        u32 cap_start;
        struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
 
-       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-       xhci->hw_ports = kcalloc_node(num_ports, sizeof(*xhci->hw_ports),
-                               flags, dev_to_node(dev));
+       xhci->hw_ports = kcalloc_node(xhci->max_ports, sizeof(*xhci->hw_ports),
+                                     flags, dev_to_node(dev));
        if (!xhci->hw_ports)
                return -ENOMEM;
 
-       for (i = 0; i < num_ports; i++) {
+       for (i = 0; i < xhci->max_ports; i++) {
                xhci->hw_ports[i].port_reg = &xhci->op_regs->port_regs[i];
                xhci->hw_ports[i].hw_portnum = i;
 
@@ -2208,11 +2205,10 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
                init_completion(&xhci->hw_ports[i].u3exit_done);
        }
 
-       xhci->rh_bw = kcalloc_node(num_ports, sizeof(*xhci->rh_bw), flags,
-                                  dev_to_node(dev));
+       xhci->rh_bw = kcalloc_node(xhci->max_ports, sizeof(*xhci->rh_bw), flags, dev_to_node(dev));
        if (!xhci->rh_bw)
                return -ENOMEM;
-       for (i = 0; i < num_ports; i++) {
+       for (i = 0; i < xhci->max_ports; i++) {
                struct xhci_interval_bw_table *bw_table;
 
                INIT_LIST_HEAD(&xhci->rh_bw[i].tts);
@@ -2244,9 +2240,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        offset = cap_start;
 
        while (offset) {
-               xhci_add_in_port(xhci, num_ports, base + offset, cap_count);
-               if (xhci->usb2_rhub.num_ports + xhci->usb3_rhub.num_ports ==
-                   num_ports)
+               xhci_add_in_port(xhci, xhci->max_ports, base + offset, cap_count);
+               if (xhci->usb2_rhub.num_ports + xhci->usb3_rhub.num_ports == xhci->max_ports)
                        break;
                offset = xhci_find_next_ext_cap(base, offset,
                                                XHCI_EXT_CAPS_PROTOCOL);
index 2ba0261a29c1b24e74e3a8728b579fe9c09149ba..585b2f3117b08ad9abc3fd9d37a40a1ca2d58079 100644 (file)
@@ -896,7 +896,7 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
        if (!(xhci->quirks & XHCI_RESET_TO_DEFAULT))
                return 0;
 
-       for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
+       for (i = 0; i < xhci->max_ports; i++) {
                port = &xhci->hw_ports[i];
                portsc = xhci_portsc_readl(port);
 
index f1582360d96aeecf8d5360e181192726eb2bf9ba..0ac7f9870d3d4368b354d694fbd5ace9a8c6bb70 100644 (file)
@@ -1394,7 +1394,7 @@ void xhci_hc_died(struct xhci_hcd *xhci)
        xhci_cleanup_command_queue(xhci);
 
        /* return any pending urbs, remove may be waiting for them */
-       for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+       for (i = 0; i <= xhci->max_slots; i++) {
                if (!xhci->devs[i])
                        continue;
                for (j = 0; j < 31; j++)
@@ -1994,7 +1994,6 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
        struct usb_hcd *hcd;
        u32 port_id;
        u32 portsc, cmd_reg;
-       int max_ports;
        unsigned int hcd_portnum;
        struct xhci_bus_state *bus_state;
        bool bogus_port_status = false;
@@ -2006,9 +2005,8 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
                          "WARN: xHC returned failed port status event\n");
 
        port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0]));
-       max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
 
-       if ((port_id <= 0) || (port_id > max_ports)) {
+       if ((port_id <= 0) || (port_id > xhci->max_ports)) {
                xhci_warn(xhci, "Port change event with invalid port ID %d\n",
                          port_id);
                return;
index dbe64ea479361522b152834e5bed53c982dee637..ad5ef294d4f3489a6dbd9077f5eac1fb0f525abf 100644 (file)
@@ -291,8 +291,7 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
        if (upper_32_bits(val))
                xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
 
-       intrs = min_t(u32, HCS_MAX_INTRS(xhci->hcs_params1),
-                     ARRAY_SIZE(xhci->run_regs->ir_set));
+       intrs = min_t(u32, xhci->max_interrupters, ARRAY_SIZE(xhci->run_regs->ir_set));
 
        for (i = 0; i < intrs; i++) {
                struct xhci_intr_reg __iomem *ir;
@@ -484,15 +483,13 @@ static void xhci_hcd_page_size(struct xhci_hcd *xhci)
 static void xhci_enable_max_dev_slots(struct xhci_hcd *xhci)
 {
        u32 config_reg;
-       u32 max_slots;
 
-       max_slots = HCS_MAX_SLOTS(xhci->hcs_params1);
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xHC can handle at most %d device slots",
-                      max_slots);
+                      xhci->max_slots);
 
        config_reg = readl(&xhci->op_regs->config_reg);
        config_reg &= ~HCS_SLOTS_MASK;
-       config_reg |= max_slots;
+       config_reg |= xhci->max_slots;
 
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Setting Max device slots reg = 0x%x",
                       config_reg);
@@ -4235,7 +4232,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
                xhci_err(xhci, "Error while assigning device slot ID: %s\n",
                         xhci_trb_comp_code_string(command->status));
                xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n",
-                        HCS_MAX_SLOTS(xhci->hcs_params1));
+                        xhci->max_slots);
                xhci_free_command(xhci, command);
                return 0;
        }
@@ -5416,6 +5413,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
         */
        struct device           *dev = hcd->self.sysdev;
        int                     retval;
+       u32                     hcs_params1;
 
        /* Accept arbitrarily long scatter-gather lists */
        hcd->self.sg_tablesize = ~0;
@@ -5441,7 +5439,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        xhci->run_regs = hcd->regs +
                (readl(&xhci->cap_regs->run_regs_off) & RTSOFF_MASK);
        /* Cache read-only capability registers */
-       xhci->hcs_params1 = readl(&xhci->cap_regs->hcs_params1);
+       hcs_params1 = readl(&xhci->cap_regs->hcs_params1);
        xhci->hcs_params2 = readl(&xhci->cap_regs->hcs_params2);
        xhci->hcs_params3 = readl(&xhci->cap_regs->hcs_params3);
        xhci->hci_version = HC_VERSION(readl(&xhci->cap_regs->hc_capbase));
@@ -5449,10 +5447,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        if (xhci->hci_version > 0x100)
                xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
 
+       xhci->max_slots = HCS_MAX_SLOTS(hcs_params1);
+       xhci->max_ports = HCS_MAX_PORTS(hcs_params1);
        /* xhci-plat or xhci-pci might have set max_interrupters already */
-       if ((!xhci->max_interrupters) ||
-           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
-               xhci->max_interrupters = HCS_MAX_INTRS(xhci->hcs_params1);
+       if ((!xhci->max_interrupters) || xhci->max_interrupters > HCS_MAX_INTRS(hcs_params1))
+               xhci->max_interrupters = HCS_MAX_INTRS(hcs_params1);
 
        xhci->quirks |= quirks;
 
index 3d644d16d9fbc2a3a15262d89d3e45c7e7f95348..fface54dbc7ab311b1e1f233271af35cb189a338 100644 (file)
@@ -1500,7 +1500,6 @@ struct xhci_hcd {
        struct xhci_doorbell_array __iomem *dba;
 
        /* Cached register copies of read-only HC data */
-       __u32           hcs_params1;
        __u32           hcs_params2;
        __u32           hcs_params3;
        __u32           hcc_params;
@@ -1511,6 +1510,8 @@ struct xhci_hcd {
        /* packed release number */
        u16             hci_version;
        u16             max_interrupters;
+       u8              max_slots;
+       u8              max_ports;
        /* imod_interval in ns (I * 250ns) */
        u32             imod_interval;
        u32             page_size;