From cba7caf71fd81efcf66fc3494124efdaf8b97610 Mon Sep 17 00:00:00 2001 From: Liu Long Date: Fri, 5 Feb 2021 14:45:12 +0800 Subject: [PATCH] DM: xHCI: Implement the USB PLS Machine flow spec. From the Figure 11-10. Downstream Facing Hub Port State Machine the device connect status should be disabled and the PLS should be polling for USB2.0, when the device be connected, then the xHCD send the port reset, for acrn we use libusb_reset_device to emulate the bus reset action. Tracked-On: #5795 Signed-off-by: Liu Long Acked-by: Wang, Yu1 --- devicemodel/hw/pci/xhci.c | 54 ++++++++++++++++++--------- devicemodel/hw/platform/usb_pmapper.c | 8 +++- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/devicemodel/hw/pci/xhci.c b/devicemodel/hw/pci/xhci.c index b9322d8b4..c3c8410e3 100644 --- a/devicemodel/hw/pci/xhci.c +++ b/devicemodel/hw/pci/xhci.c @@ -1135,6 +1135,11 @@ pci_xhci_change_port(struct pci_xhci_vdev *xdev, int port, int usb_speed, speed = pci_xhci_convert_speed(usb_speed); reg->portsc = XHCI_PS_CCS | XHCI_PS_PP | XHCI_PS_CSC; reg->portsc |= XHCI_PS_SPEED_SET(speed); + if (speed == USB_SPEED_SUPER) { + reg->portsc |= XHCI_PS_PED; + reg->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_U0); + } else + reg->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_POLL); } if (!need_intr) @@ -1831,7 +1836,7 @@ pci_xhci_insert_event(struct pci_xhci_vdev *xdev, evts = XHCI_GADDR(xdev, erst->qwRingSegBase); if (!evts) { - UPRINTF(LFTL, "Invalid gpa 0x%x in insert event!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in insert event!\r\n", erst->qwRingSegBase); return -EINVAL; } @@ -2032,7 +2037,7 @@ pci_xhci_cmd_address_device(struct pci_xhci_vdev *xdev, input_ctx = XHCI_GADDR(xdev, trb->qwTrb0 & ~0xFUL); if (!input_ctx) { - UPRINTF(LFTL, "Invalid gpa 0x%x in address device!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in address device!\r\n", trb->qwTrb0 & ~0xFUL); cmderr = XHCI_TRB_ERROR_TRB; goto done; @@ -2227,7 +2232,7 @@ pci_xhci_cmd_config_ep(struct pci_xhci_vdev *xdev, input_ctx = XHCI_GADDR(xdev, trb->qwTrb0 & ~0xFUL); if (!input_ctx) { - UPRINTF(LFTL, "Invalid gpa 0x%x in configure endpoint!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in configure endpoint!\r\n", trb->qwTrb0 & ~0xFUL); cmderr = XHCI_TRB_ERROR_TRB; goto done; @@ -2418,7 +2423,7 @@ pci_xhci_find_stream(struct pci_xhci_vdev *xdev, sctx = XHCI_GADDR(xdev, ep->qwEpCtx2 & ~0xFUL) + streamid; if (!sctx) { - UPRINTF(LFTL, "Invalid gpa 0x%x in find stream!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in find stream!\r\n", ep->qwEpCtx2 & ~0xFUL); return XHCI_TRB_ERROR_TRB; } @@ -2525,7 +2530,7 @@ pci_xhci_cmd_eval_ctx(struct pci_xhci_vdev *xdev, input_ctx = XHCI_GADDR(xdev, trb->qwTrb0 & ~0xFUL); if (!input_ctx) { - UPRINTF(LFTL, "Invalid gpa 0x%x in eval context!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in eval context!\r\n", trb->qwTrb0 & ~0xFUL); cmderr = XHCI_TRB_ERROR_TRB; goto done; @@ -2848,7 +2853,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev, struct usb_xfer *xfer, evtrb.qwTrb0 = hcb->trb_addr; trb = XHCI_GADDR(xdev, evtrb.qwTrb0); if (!trb) { - UPRINTF(LFTL, "Invalid gpa 0x%x when get the trb!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx when get the trb!\r\n", evtrb.qwTrb0); continue; } @@ -3345,7 +3350,7 @@ pci_xhci_device_doorbell(struct pci_xhci_vdev *xdev, ccs = sctx_tr->ccs; trb = XHCI_GADDR(xdev, sctx_tr->ringaddr & ~0xFUL); if (!trb) { - UPRINTF(LDBG, "Invalid gpa 0x%x in write device doorbell!\r\n", + UPRINTF(LDBG, "Invalid gpa 0x%lx in write device doorbell!\r\n", sctx_tr->ringaddr & ~0xFUL); return; } @@ -3455,7 +3460,7 @@ pci_xhci_rtsregs_write(struct pci_xhci_vdev *xdev, rts->erstba_p->qwRingSegBase, rts->erstba_p->dwRingSegSize); else - UPRINTF(LFTL, "Invalid gpa 0x%x in write runtime register!\r\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx in write runtime register!\r\n", xdev->rtsregs.intrreg.erstba & ~0x3FUL); break; @@ -3591,7 +3596,7 @@ pci_xhci_hostop_write(struct pci_xhci_vdev *xdev, UPRINTF(LDBG, "opregs dcbaap = 0x%lx (vaddr 0x%lx)\r\n", xdev->opregs.dcbaap, (uint64_t)xdev->opregs.dcbaa_p); else - UPRINTF(LFTL, "Invalid gpa 0x%x when get XHCI_DCBAAP_HI\n", + UPRINTF(LFTL, "Invalid gpa 0x%lx when get XHCI_DCBAAP_HI\n", xdev->opregs.dcbaap & ~0x3FUL); break; @@ -3903,8 +3908,10 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm) struct pci_xhci_portregs *port; struct xhci_trb evtrb; struct usb_native_devinfo *di; + struct pci_xhci_dev_emu *dev; int speed; int index; + int rc = 0; UPRINTF(LINF, "reset port %d\r\n", portn); @@ -3915,11 +3922,24 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm) return; } di = &xdev->native_ports[index].info; + dev = xdev->devices[portn]; + if (dev && dev->dev_ue->ue_reset != NULL) + rc = dev->dev_ue->ue_reset(dev->dev_instance); - speed = pci_xhci_convert_speed(di->speed); - port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC); - port->portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed); - + port->portsc &= ~(XHCI_PS_PR | XHCI_PS_PLS_MASK); + /* + * From xHCI spec 4.19.5 USB2 protocol ports never fail the bus + * reset seqence. + */ + if (rc != 0 && di->bcd >= 0x300) { + port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET) + | XHCI_PS_SPEED_SET(USB_SPEED_VARIABLE); + port->portsc &= ~XHCI_PS_CCS; + } else { + speed = pci_xhci_convert_speed(di->speed); + port->portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed) + | XHCI_PS_PLS_SET(UPS_PORT_LS_U0); + } if (warm && di->bcd >= 0x300) port->portsc |= XHCI_PS_WRC; @@ -3927,10 +3947,10 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm) port->portsc |= XHCI_PS_PRC; pci_xhci_set_evtrb(&evtrb, portn, - XHCI_TRB_ERROR_SUCCESS, - XHCI_TRB_EVENT_PORT_STS_CHANGE); - if (pci_xhci_insert_event(xdev, &evtrb, 1) != 0) - UPRINTF(LFTL, "Failed to inject reset port event!\n"); + XHCI_TRB_ERROR_SUCCESS, + XHCI_TRB_EVENT_PORT_STS_CHANGE); + if (pci_xhci_insert_event(xdev, &evtrb, 1) != 0) + UPRINTF(LFTL, "Failed to inject reset port event!\n"); } } diff --git a/devicemodel/hw/platform/usb_pmapper.c b/devicemodel/hw/platform/usb_pmapper.c index 96a98cb53..7abe6f618 100644 --- a/devicemodel/hw/platform/usb_pmapper.c +++ b/devicemodel/hw/platform/usb_pmapper.c @@ -730,6 +730,7 @@ int usb_dev_reset(void *pdata) { struct usb_dev *udev; + int rc = 0; udev = pdata; @@ -737,7 +738,12 @@ usb_dev_reset(void *pdata) libusb_reset_device(udev->handle); usb_dev_reset_ep(udev); usb_dev_update_ep(udev); - return 0; + rc = libusb_reset_device(udev->handle); + if (!rc) { + usb_dev_reset_ep(udev); + usb_dev_update_ep(udev); + } + return rc; } int