USB: dwc3: gadget: Queue data for 16 micro frames ahead in future

While starting transfer for isochronous endpoints, make sure first
request is queued for 16 microframes ahead in future. Also set
PENDING_REQUEST flag before giving back usb request if started_list
is empty to avoid queuing in same context. Else it leads to request
getting queued for micro frame interval which might have expired and
resulting USB HW retiring TRB without sending data to host.

Change-Id: Ia5e4512fa2a3ae6637f2be7ef2f102c26d56213c
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
Signed-off-by: AKASH KUMAR <quic_akakum@quicinc.com>
This commit is contained in:
Vijayavardhan Vennapusa 2021-05-20 12:31:08 +05:30 • committed by Gerrit - the friendly Code Review server
commit c4b2f05b5f
3 changed files with 22 additions and 4 deletions

View file

@ -738,6 +738,7 @@ struct dwc3_ep_events {
* @desc: usb_endpoint_descriptor pointer
* @dwc: pointer to DWC controller
* @saved_state: ep state saved during hibernation
* @missed_isoc_packets: counter for missed packets sent
* @flags: endpoint flags (wedged, stalled, ...)
* @number: endpoint number (1 - 15)
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
@ -771,6 +772,7 @@ struct dwc3_ep {
struct dwc3 *dwc;
u32 saved_state;
u32 missed_isoc_packets;
unsigned flags;
#define DWC3_EP_ENABLED BIT(0)
#define DWC3_EP_STALL BIT(1)

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "debug.h"
@ -150,10 +151,11 @@ void dwc3_dbg_dma_unmap(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req)
req->trb->ctrl & DWC3_TRB_CTRL_HWO);
} else {
ipc_log_string(dwc->dwc_dma_ipc_log_ctxt,
"%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx %d",
"%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx %d %u",
ep_num >> 1, ep_num & 1 ? "IN":"OUT", "UNMAP",
&req->request, req->request.dma, req->request.length,
req->trb_dma, req->trb->ctrl & DWC3_TRB_CTRL_HWO);
req->trb_dma, req->trb->ctrl & DWC3_TRB_CTRL_HWO,
req->request.actual);
}
}

View file

@ -308,6 +308,12 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
dwc3_gadget_del_and_unmap_request(dep, req, status);
req->status = DWC3_REQUEST_STATUS_COMPLETED;
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
(list_empty(&dep->started_list))) {
dep->flags |= DWC3_EP_PENDING_REQUEST;
dbg_event(dep->number, "STARTEDLISTEMPTY", 0);
}
spin_unlock(&dwc->lock);
usb_gadget_giveback_request(&dep->endpoint, &req->request);
spin_lock(&dwc->lock);
@ -983,6 +989,8 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep)
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_disable(dep);
dbg_event(dep->number, "DISABLE", ret);
dbg_event(dep->number, "MISSEDISOCPKTS", dep->missed_isoc_packets);
dep->missed_isoc_packets = 0;
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
@ -1661,6 +1669,7 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
}
for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) {
dep->frame_number = __dwc3_gadget_get_frame(dep->dwc) + 16;
dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1);
ret = __dwc3_gadget_kick_transfer(dep);
@ -1727,8 +1736,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
if ((dep->flags & DWC3_EP_PENDING_REQUEST)) {
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) {
dep->flags &= ~DWC3_EP_PENDING_REQUEST;
return __dwc3_gadget_start_isoc(dep);
}
return 0;
}
}
@ -3391,15 +3402,18 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
if (event->status & DEPEVT_STATUS_BUSERR)
status = -ECONNRESET;
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (event->status & DEPEVT_STATUS_MISSED_ISOC) {
status = -EXDEV;
dep->missed_isoc_packets++;
dbg_event(dep->number, "MISSEDISOC", 0);
if (list_empty(&dep->started_list))
stop = true;
}
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
goto out;