diff mbox series

[v4,03/11] drivers/char: add support for selecting specific xhci

Message ID 2dd1245d3c969359e0e6e3545692756024dc613e.1660354597.git-series.marmarek@invisiblethingslab.com (mailing list archive)
State Superseded
Headers show
Series Add Xue - console over USB 3 Debug Capability | expand

Commit Message

Marek Marczykowski-Górecki Aug. 13, 2022, 1:38 a.m. UTC
Handle parameters similar to dbgp=ehci.

Implement this by not resettting dbc->sbdf again in dbc_init_xhc(), but
using a value found there if non-zero. Additionally, add xue->xhc_num to
select n-th controller.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Changes in v4:
 - adjust error message
Changes in v3:
 - adjust for xhci-dbc rename
 - drop redundant check in parsing dbgp= option
Changes in v2:
 - unsigned int xhc_num
 - code style
---
 docs/misc/xen-command-line.pandoc |  2 +-
 xen/drivers/char/xhci-dbc.c       | 59 +++++++++++++++++++++++++-------
 2 files changed, 48 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 88c70d133951..6b1e515bfc8c 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -721,7 +721,7 @@  Available alternatives, with their meaning, are:
 
 ### dbgp
 > `= ehci[ <integer> | @pci<bus>:<slot>.<func> ]`
-> `= xhci`
+> `= xhci[ <integer> | @pci<bus>:<slot>.<func> ]`
 
 Specify the USB controller to use, either by instance number (when going
 over the PCI busses sequentially) or by PCI device (must be on segment 0).
diff --git a/xen/drivers/char/xhci-dbc.c b/xen/drivers/char/xhci-dbc.c
index 8c9dfa6cfcc0..ca7d4a62139e 100644
--- a/xen/drivers/char/xhci-dbc.c
+++ b/xen/drivers/char/xhci-dbc.c
@@ -246,6 +246,7 @@  struct dbc {
     void __iomem *xhc_mmio;
 
     bool open;
+    unsigned int xhc_num; /* look for n-th xhc */
 };
 
 static void *dbc_sys_map_xhc(uint64_t phys, size_t size)
@@ -278,24 +279,37 @@  static bool __init dbc_init_xhc(struct dbc *dbc)
     uint16_t cmd;
     size_t xhc_mmio_size;
 
-    /*
-     * Search PCI bus 0 for the xHC. All the host controllers supported so far
-     * are part of the chipset and are on bus 0.
-     */
-    for ( devfn = 0; devfn < 256; devfn++ )
+    if ( dbc->sbdf.sbdf == 0 )
     {
-        pci_sbdf_t sbdf = PCI_SBDF(0, 0, devfn);
-        uint8_t hdr = pci_conf_read8(sbdf, PCI_HEADER_TYPE);
-
-        if ( hdr == 0 || hdr == 0x80 )
+        /*
+         * Search PCI bus 0 for the xHC. All the host controllers supported so
+         * far are part of the chipset and are on bus 0.
+         */
+        for ( devfn = 0; devfn < 256; devfn++ )
         {
-            if ( (pci_conf_read32(sbdf, PCI_CLASS_REVISION) >> 8) == DBC_XHC_CLASSC )
+            pci_sbdf_t sbdf = PCI_SBDF(0, 0, devfn);
+            uint8_t hdr = pci_conf_read8(sbdf, PCI_HEADER_TYPE);
+
+            if ( hdr == 0 || hdr == 0x80 )
             {
-                dbc->sbdf = sbdf;
-                break;
+                if ( (pci_conf_read32(sbdf, PCI_CLASS_REVISION) >> 8) ==
+                     DBC_XHC_CLASSC )
+                {
+                    if ( dbc->xhc_num-- )
+                        continue;
+                    dbc->sbdf = sbdf;
+                    break;
+                }
             }
         }
     }
+    else
+    {
+        /* Verify if selected device is really xHC */
+        if ( (pci_conf_read32(dbc->sbdf, PCI_CLASS_REVISION) >> 8) !=
+             DBC_XHC_CLASSC )
+            dbc->sbdf.sbdf = 0;
+    }
 
     if ( !dbc->sbdf.sbdf )
     {
@@ -1052,12 +1066,33 @@  void __init xhci_dbc_uart_init(void)
 {
     struct dbc_uart *uart = &dbc_uart;
     struct dbc *dbc = &uart->dbc;
+    const char *e;
 
     if ( strncmp(opt_dbgp, "xhci", 4) )
         return;
 
     memset(dbc, 0, sizeof(*dbc));
 
+    if ( isdigit(opt_dbgp[4]) )
+    {
+        dbc->xhc_num = simple_strtoul(opt_dbgp + 4, &e, 10);
+    }
+    else if ( strncmp(opt_dbgp + 4, "@pci", 4) == 0 )
+    {
+        unsigned int bus, slot, func;
+
+        e = parse_pci(opt_dbgp + 8, NULL, &bus, &slot, &func);
+        if ( !e || *e )
+        {
+            printk(XENLOG_ERR
+                   "Invalid dbgp= PCI device spec: '%s'\n",
+                   opt_dbgp + 8);
+            return;
+        }
+
+        dbc->sbdf = PCI_SBDF(0, bus, slot, func);
+    }
+
     dbc->dbc_ctx = &ctx;
     dbc->dbc_erst = &erst;
     dbc->dbc_ering.trb = evt_trb;