Commit 1f512119 authored by Felipe Balbi's avatar Felipe Balbi

usb: dwc3: gadget: add remaining sg entries to ring

Upon transfer completion after a full ring, let's
add more TRBs to our ring in order to complete our
request successfully.
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 2c78c029
...@@ -888,14 +888,13 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) ...@@ -888,14 +888,13 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
struct dwc3_request *req, unsigned int trbs_left) struct dwc3_request *req, unsigned int trbs_left)
{ {
struct usb_request *request = &req->request; struct scatterlist *sg = req->sg;
struct scatterlist *sg = request->sg;
struct scatterlist *s; struct scatterlist *s;
unsigned int length; unsigned int length;
dma_addr_t dma; dma_addr_t dma;
int i; int i;
for_each_sg(sg, s, request->num_mapped_sgs, i) { for_each_sg(sg, s, req->num_pending_sgs, i) {
unsigned chain = true; unsigned chain = true;
length = sg_dma_len(s); length = sg_dma_len(s);
...@@ -945,7 +944,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) ...@@ -945,7 +944,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
return; return;
list_for_each_entry_safe(req, n, &dep->pending_list, list) { list_for_each_entry_safe(req, n, &dep->pending_list, list) {
if (req->request.num_mapped_sgs > 0) if (req->num_pending_sgs > 0)
dwc3_prepare_one_trb_sg(dep, req, trbs_left--); dwc3_prepare_one_trb_sg(dep, req, trbs_left--);
else else
dwc3_prepare_one_trb_linear(dep, req, trbs_left--); dwc3_prepare_one_trb_linear(dep, req, trbs_left--);
...@@ -1071,6 +1070,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -1071,6 +1070,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
if (ret) if (ret)
return ret; return ret;
req->sg = req->request.sg;
req->num_pending_sgs = req->request.num_mapped_sgs;
list_add_tail(&req->list, &dep->pending_list); list_add_tail(&req->list, &dep->pending_list);
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
...@@ -1935,22 +1937,30 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, ...@@ -1935,22 +1937,30 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
int ret; int ret;
list_for_each_entry_safe(req, n, &dep->started_list, list) { list_for_each_entry_safe(req, n, &dep->started_list, list) {
unsigned length;
unsigned actual;
int chain; int chain;
chain = req->request.num_mapped_sgs > 0; length = req->request.length;
chain = req->num_pending_sgs > 0;
if (chain) { if (chain) {
struct scatterlist *sg = req->request.sg; struct scatterlist *sg = req->sg;
struct scatterlist *s; struct scatterlist *s;
unsigned int pending = req->num_pending_sgs;
unsigned int i; unsigned int i;
for_each_sg(sg, s, req->request.num_mapped_sgs, i) { for_each_sg(sg, s, pending, i) {
trb = &dep->trb_pool[dep->trb_dequeue]; trb = &dep->trb_pool[dep->trb_dequeue];
count += trb->size & DWC3_TRB_SIZE_MASK; count += trb->size & DWC3_TRB_SIZE_MASK;
dwc3_ep_inc_deq(dep); dwc3_ep_inc_deq(dep);
req->sg = sg_next(s);
req->num_pending_sgs--;
ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
event, status, chain); event, status, chain);
if (ret)
break;
} }
} else { } else {
trb = &dep->trb_pool[dep->trb_dequeue]; trb = &dep->trb_pool[dep->trb_dequeue];
...@@ -1968,7 +1978,12 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, ...@@ -1968,7 +1978,12 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
* should receive and we simply bounce the request back to the * should receive and we simply bounce the request back to the
* gadget driver for further processing. * gadget driver for further processing.
*/ */
req->request.actual += req->request.length - count; actual = length - req->request.actual;
req->request.actual = actual;
if (ret && chain && (actual < length) && req->num_pending_sgs)
return __dwc3_gadget_kick_transfer(dep, 0);
dwc3_gadget_giveback(dep, req, status); dwc3_gadget_giveback(dep, req, status);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment