Allow usb hubs to map (software) ports to physical ports via op callback. This is needed to make bootorder work in case there isn't a simple linear mapping.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/usb.h | 1 + src/boot.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/hw/usb.h b/src/hw/usb.h index 94e12b20dd..2cfb572177 100644 --- a/src/hw/usb.h +++ b/src/hw/usb.h @@ -56,6 +56,7 @@ struct usbhub_s { struct usbhub_op_s { int (*detect)(struct usbhub_s *hub, u32 port); int (*reset)(struct usbhub_s *hub, u32 port); + int (*portmap)(struct usbhub_s *hub, u32 port); void (*disconnect)(struct usbhub_s *hub, u32 port); };
diff --git a/src/boot.c b/src/boot.c index 59623fb63d..8f6802c89b 100644 --- a/src/boot.c +++ b/src/boot.c @@ -207,6 +207,13 @@ int bootprio_find_named_rom(const char *name, int instance) return find_prio(desc); }
+static int usb_portmap(struct usbdevice_s *usbdev) +{ + if (usbdev->hub->op->portmap) + return usbdev->hub->op->portmap(usbdev->hub, usbdev->port); + return usbdev->port + 1; +} + static char * build_usb_path(char *buf, int max, struct usbhub_s *hub) { @@ -214,7 +221,7 @@ build_usb_path(char *buf, int max, struct usbhub_s *hub) // Root hub - nothing to add. return buf; char *p = build_usb_path(buf, max, hub->usbdev->hub); - p += snprintf(p, buf+max-p, "/hub@%x", hub->usbdev->port+1); + p += snprintf(p, buf+max-p, "/hub@%x", usb_portmap(hub->usbdev)); return p; }
@@ -232,7 +239,7 @@ int bootprio_find_usb(struct usbdevice_s *usbdev, int lun) if (ret >= 0) return ret; // Try usb-host/redir - for example: /pci@i0cf8/usb@1,2/usb-host@1 - snprintf(p, desc+sizeof(desc)-p, "/usb-*@%x", usbdev->port+1); + snprintf(p, desc+sizeof(desc)-p, "/usb-*@%x", usb_portmap(usbdev)); return find_prio(desc); }
xhci controllers have two virtual ports per (usb3 capable) physical port, one for usb2 and one for usb3 devices. Add a hub portmap callback to map the virtual ports to physical ports. For now assume we simply have the same number of usb2 and usb3 ports.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/usb-xhci.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 69954b9d8d..803822aece 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -374,6 +374,16 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port) return rc; }
+static int +xhci_hub_portmap(struct usbhub_s *hub, u32 port) +{ + struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); + + // we don't parse the extended capabilities, so we take a shortcut + // here and assumes we have the same number of usb2 and usb3 ports + return port % (xhci->ports/2) + 1; +} + static void xhci_hub_disconnect(struct usbhub_s *hub, u32 port) { @@ -383,6 +393,7 @@ xhci_hub_disconnect(struct usbhub_s *hub, u32 port) static struct usbhub_op_s xhci_hub_ops = { .detect = xhci_hub_detect, .reset = xhci_hub_reset, + .portmap = xhci_hub_portmap, .disconnect = xhci_hub_disconnect, };
Dear Gerd,
On 07/18/17 13:36, Gerd Hoffmann wrote:
xhci controllers have two virtual ports per (usb3 capable) physical port, one for usb2 and one for usb3 devices. Add a hub portmap callback to map the virtual ports to physical ports. For now assume we simply have the same number of usb2 and usb3 ports.
How can the change be tested? Do you have some QEMU command?
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
src/hw/usb-xhci.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 69954b9d8d..803822aece 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -374,6 +374,16 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port) return rc; }
+static int +xhci_hub_portmap(struct usbhub_s *hub, u32 port) +{
- struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
- // we don't parse the extended capabilities, so we take a shortcut
- // here and assumes we have the same number of usb2 and usb3 ports
*assume* without the 3rd person singular s?
- return port % (xhci->ports/2) + 1;
+}
- static void xhci_hub_disconnect(struct usbhub_s *hub, u32 port) {
@@ -383,6 +393,7 @@ xhci_hub_disconnect(struct usbhub_s *hub, u32 port) static struct usbhub_op_s xhci_hub_ops = { .detect = xhci_hub_detect, .reset = xhci_hub_reset,
- .portmap = xhci_hub_portmap, .disconnect = xhci_hub_disconnect, };
Kind regards,
Paul
On Tue, 2017-07-18 at 13:51 +0200, Paul Menzel wrote:
Dear Gerd,
On 07/18/17 13:36, Gerd Hoffmann wrote:
xhci controllers have two virtual ports per (usb3 capable) physical port, one for usb2 and one for usb3 devices. Add a hub portmap callback to map the virtual ports to physical ports. For now assume we simply have the same number of usb2 and usb3 ports.
How can the change be tested? Do you have some QEMU command?
The qemu xhci controller has the virtual usb3 ports first, then the usb2 ports. So this problem shows up when you try to boot from usb2 storage devices, because for the usb2 ports the virtual port numbering differs from the physical port numbering. Typically happens when you pass-through usb2 sticks (via -device usb-host) and try to boot from them. The emulated usb-storage works fine as it has usb3 support.
cheers, Gerd
On Tue, Jul 18, 2017 at 01:36:35PM +0200, Gerd Hoffmann wrote:
xhci controllers have two virtual ports per (usb3 capable) physical port, one for usb2 and one for usb3 devices. Add a hub portmap callback to map the virtual ports to physical ports. For now assume we simply have the same number of usb2 and usb3 ports.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
src/hw/usb-xhci.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 69954b9d8d..803822aece 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -374,6 +374,16 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port) return rc; }
+static int +xhci_hub_portmap(struct usbhub_s *hub, u32 port) +{
- struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
- // we don't parse the extended capabilities, so we take a shortcut
- // here and assumes we have the same number of usb2 and usb3 ports
- return port % (xhci->ports/2) + 1;
Real hardware often does not have the same number of usb3 ports as usb2 ports, so I think this would break the bootorder on coreboot. (As well as on qemu with pci passthrough.)
-Kevin