ACRN: xHCI: Fix Transfer TRBs error transfer handler
According to xHCI Spec 4.10.1 Transfer TRBS chapter, there have three scenarios shall generate a Transfer Event TRB when transfer TRBS: 1. If upon transfer completion of a TRB the Interrupt On Completion(IOC) flag is set, the xHC shall generate a Transfer Event TRB. 2. A Short Packet will trigger the generation of a Transfer Event TRB on the Event Ring if the Interrupt-on-Short (ISP) or Interrupt On Completion (IOC) flags are set in the TRB that the Short Packet was detected on. 3. The detection of an error during a transfer shall always generate a Transfer Event, irrespective of whether the Interrupt-on-Short or Interrupt On Completion (IOC) flags are set in the Transfer TRB. When an error condition is encountered which requires an endpoint to halt; the xHC shall stop on the TRB in error, the endpoint shall be halted, and software shall use a Set TR Dequeue Pointer Command to advance the Transfer Ring to the next TD. Tracked-On: #5263 Signed-off-by: Long Liu <long.liu@intel.com> Acked-by: Yu Wang yu1.wang@intel.com
This commit is contained in:
parent
64efb36c0e
commit
b66e8797fa
|
@ -2845,11 +2845,14 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev, struct usb_xfer *xfer,
|
|||
if (err == XHCI_TRB_ERROR_SUCCESS && rem_len > 0)
|
||||
err = XHCI_TRB_ERROR_SHORT_PKT;
|
||||
|
||||
/* Only interrupt if IOC or short packet */
|
||||
if (!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT) &&
|
||||
!((err == XHCI_TRB_ERROR_SHORT_PKT) &&
|
||||
(trb->dwTrb3 & XHCI_TRB_3_ISP_BIT))) {
|
||||
|
||||
/* When transfer success and IOC bit not set or
|
||||
* transfer is short packet and ISP bit is not set.
|
||||
* */
|
||||
if (((err == XHCI_TRB_ERROR_SUCCESS) &&
|
||||
!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT)) ||
|
||||
((err == XHCI_TRB_ERROR_SHORT_PKT) &&
|
||||
(!(trb->dwTrb3 & XHCI_TRB_3_ISP_BIT) &&
|
||||
!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT)))) {
|
||||
i = index_inc(i, xfer->max_blk_cnt);
|
||||
continue;
|
||||
}
|
||||
|
@ -2871,8 +2874,10 @@ pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev, struct usb_xfer *xfer,
|
|||
|
||||
*do_intr = 1;
|
||||
|
||||
err = pci_xhci_insert_event(xdev, &evtrb, 0);
|
||||
if (err != XHCI_TRB_ERROR_SUCCESS)
|
||||
pci_xhci_insert_event(xdev, &evtrb, *do_intr);
|
||||
/* The xHC stop on the TRB in error.*/
|
||||
if (err != XHCI_TRB_ERROR_SUCCESS &&
|
||||
err != XHCI_TRB_ERROR_SHORT_PKT)
|
||||
break;
|
||||
|
||||
i = index_inc(i, xfer->max_blk_cnt);
|
||||
|
|
Loading…
Reference in New Issue