From: Wu Liang feng Date: Fri, 30 Sep 2016 11:19:40 +0000 (+0800) Subject: usb: dwc3: gadget: fix trb ring full bug X-Git-Tag: firefly_0821_release~1454 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e9cfaddeec509e93d2100fce0d182f995fc159e6;p=firefly-linux-kernel-4.4.55.git usb: dwc3: gadget: fix trb ring full bug The upstream commit 5e8ec28765 (usb: dwc3: gadget: Handle TRB index 0 when full or empty) only use the HWO = 1 to check if the TRB ring is full. But refer to DWC3 databook Version 3.00a, 8.2.3.2 TRB Control Bit Rules: When an OUT endpoint receives a short packet, some TRBs in a chain may still have their HWO bit set to 1 while belonging to software. So if HWO=1 and CSP=1 on OUT endpoint, it also means that TRB ring is empty, software may reclaim those TRBs even though HWO=1. TEST=use MTP to transfer big data, and then cancel the transition, check if it can transfer again. Change-Id: I45cc683dc733ff7a642cfcd3ebc20455ef677753 Signed-off-by: Wu Liang feng --- diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 776de55028f6..ca4229f3a1cc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -876,10 +876,14 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) */ if (dep->trb_enqueue == dep->trb_dequeue) { tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue); - if (tmp->ctrl & DWC3_TRB_CTRL_HWO) - return 0; - return DWC3_TRB_NUM - 1; + if (!(tmp->ctrl & DWC3_TRB_CTRL_HWO) || + ((tmp->ctrl & DWC3_TRB_CTRL_HWO) && + (tmp->ctrl & DWC3_TRB_CTRL_CSP) && + !dep->direction)) + return DWC3_TRB_NUM - 1; + + return 0; } trbs_left = dep->trb_dequeue - dep->trb_enqueue;