DM USB: fix an USB endpoint reset flow issue

Original code will reset the whole USB device when xHCI Reset
Endpoint command is received, this behavior is not right. This
patch is used to fix it.

And according to xhci spec 4.6.8, if the endpoint is not in the
halted state, xHC should reject to execute this command and the
Context State Error should be returned. This patch also add this
logic.

Change-Id: I55a5918148d82d103fb3eb27d582f9676f9f61d3
Tracked-On:
Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com>
Reviewed-by: Liang Yang <liang3.yang@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Xiaoguang Wu
2018-07-11 14:38:34 +08:00
committed by lijinxia
parent cb938870b4
commit 00fbfd6da3
2 changed files with 81 additions and 27 deletions

View File

@@ -1748,15 +1748,19 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_vdev *xdev,
goto done;
}
dev_ctx = dev->dev_ctx;
assert(dev_ctx != NULL);
ep_ctx = &dev_ctx->ctx_ep[epid];
if ((ep_ctx->dwEpCtx0 & 0x7) != XHCI_ST_EPCTX_HALTED) {
cmderr = XHCI_TRB_ERROR_CONTEXT_STATE;
goto done;
}
devep = &dev->eps[epid];
if (devep->ep_xfer != NULL)
USB_DATA_XFER_RESET(devep->ep_xfer);
dev_ctx = dev->dev_ctx;
assert(dev_ctx != NULL);
ep_ctx = &dev_ctx->ctx_ep[epid];
ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED;
if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) == 0)
@@ -1766,13 +1770,6 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_vdev *xdev,
epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2,
ep_ctx->dwEpCtx4);
if (type == XHCI_TRB_TYPE_RESET_EP &&
(dev->dev_ue->ue_reset == NULL ||
dev->dev_ue->ue_reset(dev->dev_instance) < 0)) {
cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON;
goto done;
}
done:
return cmderr;
}
@@ -2159,7 +2156,7 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
uint32_t trbflags;
uint32_t edtla;
uint32_t i;
int err;
int err = XHCI_TRB_ERROR_SUCCESS;
dev = XHCI_SLOTDEV_PTR(xdev, slot);
devep = &dev->eps[epid];
@@ -2169,7 +2166,20 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
ep_ctx = &dev_ctx->ctx_ep[epid];
err = XHCI_TRB_ERROR_SUCCESS;
/* err is used as completion code and sent to guest driver */
switch (xfer->status) {
case USB_ERR_STALLED:
ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) |
XHCI_ST_EPCTX_HALTED;
err = XHCI_TRB_ERROR_STALL;
break;
case USB_ERR_NORMAL_COMPLETION:
break;
default:
/* FIXME: should process other failures */
UPRINTF(LFTL, "unknown error %d\r\n", xfer->status);
}
*do_intr = 0;
edtla = 0;
@@ -2494,6 +2504,9 @@ retry:
UPRINTF(LDBG, "[%d]: xfer->ndata %u\r\n", __LINE__, xfer->ndata);
if (xfer->ndata <= 0)
goto errout;
if (epid == 1) {
err = USB_ERR_NOT_STARTED;
if (dev->dev_ue->ue_request != NULL)
@@ -2525,7 +2538,9 @@ errout:
pci_xhci_assert_interrupt(xdev);
if (do_retry) {
USB_DATA_XFER_RESET(xfer);
if (epid == 1)
USB_DATA_XFER_RESET(xfer);
UPRINTF(LDBG, "[%d]: retry:continuing with next TRBs\r\n",
__LINE__);
goto retry;