Report the port state on a port status change notification. Clear the change bits so further change notifications are delivered.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/usb-xhci.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 654feba..5f44239 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -658,9 +658,15 @@ static void xhci_process_events(struct usb_xhci_s *xhci) } case ER_PORT_STATUS_CHANGE: { - u32 portid = (etrb->ptr_low >> 24) & 0xff; - dprintf(3, "%s: status change port #%d\n", - __func__, portid); + u32 port = ((etrb->ptr_low >> 24) & 0xff) - 1; + // Read status, and clear port status change bits + u32 portsc = readl(&xhci->pr[port].portsc); + u32 pclear = (((portsc & ~(XHCI_PORTSC_PED|XHCI_PORTSC_PR)) + & ~(XHCI_PORTSC_PLS_MASK<<XHCI_PORTSC_PLS_SHIFT)) + | (1<<XHCI_PORTSC_PLS_SHIFT)); + writel(&xhci->pr[port].portsc, pclear); + + xhci_print_port_state(3, __func__, port, portsc); break; } default:
If the set_address command fails, attempt to free up the slot resource associated with the attempt.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/usb-xhci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c index 5f44239..3359cff 100644 --- a/src/hw/usb-xhci.c +++ b/src/hw/usb-xhci.c @@ -785,7 +785,6 @@ static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci) return (xhci->cmds->evt.control >> 24) & 0xff; }
-#if 0 static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid) { struct xhci_trb cmd = { @@ -797,7 +796,6 @@ static int xhci_cmd_disable_slot(struct usb_xhci_s *xhci, u32 slotid) dprintf(3, "%s: slotid %d\n", __func__, slotid); return xhci_cmd_submit(xhci, &cmd); } -#endif
static int xhci_cmd_address_device(struct usb_xhci_s *xhci, u32 slotid , struct xhci_inctx *inctx) @@ -992,7 +990,6 @@ xhci_alloc_pipe(struct usbdevice_s *usbdev } dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid); memset(dev, 0, size); - pipe->slotid = usbdev->slotid = slotid; xhci->devs[slotid].ptr_low = (u32)dev; xhci->devs[slotid].ptr_high = 0;
@@ -1000,8 +997,16 @@ xhci_alloc_pipe(struct usbdevice_s *usbdev int cc = xhci_cmd_address_device(xhci, slotid, in); if (cc != CC_SUCCESS) { dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc); + cc = xhci_cmd_disable_slot(xhci, slotid); + if (cc != CC_SUCCESS) { + dprintf(1, "%s: disable failed (cc %d)\n", __func__, cc); + goto fail; + } + xhci->devs[slotid].ptr_low = 0; + free(dev); goto fail; } + pipe->slotid = usbdev->slotid = slotid; } else { pipe->slotid = usbdev->slotid; // Send configure command.