]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci: Fix debugfs bandwidth reporting
authorMichal Pecio <michal.pecio@gmail.com>
Thu, 2 Apr 2026 13:13:20 +0000 (16:13 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Apr 2026 13:55:36 +0000 (15:55 +0200)
Replace kernel USB speed numbers with xHCI protocol IDs expected by HW.
They are numerically equal up to high speed, but instead of SuperSpeed
we were querying SuperSpeed+.

Gen1 hardware rejects such commands with TRB Error, which resulted in
zero available bandwidth being shown.

While at that, report failures properly. No attempt made at "tunneling"
all possible comp codes through errno, debugfs users may inspect the
result through event-ring/trbs.

Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20260402131342.2628648-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-debugfs.c
drivers/usb/host/xhci.c

index ade178ab34a786eb962d33e99a2dad876d0bbda1..d07276192256b6172924d8e301f4d32b764e8f97 100644 (file)
@@ -700,6 +700,10 @@ static int xhci_port_bw_show(struct xhci_hcd *xhci, u8 dev_speed,
                seq_printf(s, "port[%d] available bw: %d%%.\n", i,
                                ctx->bytes[i]);
 err_out:
+       if (ret == -EIO) {
+               seq_puts(s, "Get Port Bandwidth failed\n");
+               ret = 0;
+       }
        pm_runtime_put_sync(dev);
        xhci_free_port_bw_ctx(xhci, ctx);
        return ret;
@@ -710,7 +714,7 @@ static int xhci_ss_bw_show(struct seq_file *s, void *unused)
        int ret;
        struct xhci_hcd         *xhci = (struct xhci_hcd *)s->private;
 
-       ret = xhci_port_bw_show(xhci, USB_SPEED_SUPER, s);
+       ret = xhci_port_bw_show(xhci, DEV_PORT_SPEED(XDEV_SS), s);
        return ret;
 }
 
@@ -719,7 +723,7 @@ static int xhci_hs_bw_show(struct seq_file *s, void *unused)
        int ret;
        struct xhci_hcd         *xhci = (struct xhci_hcd *)s->private;
 
-       ret = xhci_port_bw_show(xhci, USB_SPEED_HIGH, s);
+       ret = xhci_port_bw_show(xhci, DEV_PORT_SPEED(XDEV_HS), s);
        return ret;
 }
 
@@ -728,7 +732,7 @@ static int xhci_fs_bw_show(struct seq_file *s, void *unused)
        int ret;
        struct xhci_hcd         *xhci = (struct xhci_hcd *)s->private;
 
-       ret = xhci_port_bw_show(xhci, USB_SPEED_FULL, s);
+       ret = xhci_port_bw_show(xhci, DEV_PORT_SPEED(XDEV_FS), s);
        return ret;
 }
 
index ef6d8662adecf4a64b3225554355aa19f628ad4b..eb6927779b1e0f753347c34e857ddb8aa39897ce 100644 (file)
@@ -3201,7 +3201,12 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(xhci_reset_bandwidth);
 
-/* Get the available bandwidth of the ports under the xhci roothub */
+/*
+ * Get the available bandwidth of the ports under the xhci roothub.
+ * EIO means the command failed: command not implemented or unsupported
+ * speed (TRB Error), some ASMedia complete with Parameter Error when
+ * querying the root hub (slot_id = 0), or other error or timeout.
+ */
 int xhci_get_port_bandwidth(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx,
                            u8 dev_speed)
 {
@@ -3230,6 +3235,8 @@ int xhci_get_port_bandwidth(struct xhci_hcd *xhci, struct xhci_container_ctx *ct
        spin_unlock_irqrestore(&xhci->lock, flags);
 
        wait_for_completion(cmd->completion);
+       if (cmd->status != COMP_SUCCESS)
+               ret = -EIO;
 err_out:
        kfree(cmd->completion);
        kfree(cmd);