]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
usb: dwc3: Check for IOC/LST bit in both event->status and TRB->ctrl fields
authorAnurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
Tue, 8 Jan 2019 16:03:52 +0000 (21:33 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 3 Apr 2019 08:31:15 +0000 (10:31 +0200)
The present code in dwc3_gadget_ep_reclaim_completed_trb() will check
for IOC/LST bit in the event->status and returns if IOC/LST bit is
set. This logic doesn't work if multiple TRBs are queued per
request and the IOC/LST bit is set on the last TRB of that request.
Consider an example where a queued request has multiple queued TRBs
and IOC/LST bit is set only for the last TRB. In this case, the Core
generates XferComplete/XferInProgress events only for the last TRB
(since IOC/LST are set only for the last TRB). As per the logic in
dwc3_gadget_ep_reclaim_completed_trb() event->status is checked for
IOC/LST bit and returns on the first TRB. This makes the remaining
TRBs left unhandled.
To aviod this, changed the code to check for IOC/LST bits in both
event->status & TRB->ctrl. This patch does the same.

Signed-off-by: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/usb/dwc3/gadget.c

index f6e78ea31dedef027fd664acb2b44fd53baeb4e1..d4e1c01f7b12ae037ed2fdd980d9e31f0311db46 100644 (file)
@@ -2358,7 +2358,12 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
        if (event->status & DEPEVT_STATUS_SHORT && !chain)
                return 1;
 
-       if (event->status & DEPEVT_STATUS_IOC)
+       if ((event->status & DEPEVT_STATUS_IOC) &&
+           (trb->ctrl & DWC3_TRB_CTRL_IOC))
+               return 1;
+
+       if ((event->status & DEPEVT_STATUS_LST) &&
+           (trb->ctrl & DWC3_TRB_CTRL_LST))
                return 1;
 
        return 0;