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 <long.liu@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
e3a8b09e62
commit
cba7caf71f
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue