On 8/25/2016 2:20 AM, Felipe Balbi wrote:
> 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: Felipe Balbi <felipe.ba...@linux.intel.com>
> ---
> 
> Changes since v1:
>       - none
> 
> Changes since v2:
>       - fix regression found by John Youn
> 
>  drivers/usb/dwc3/gadget.c | 33 ++++++++++++++++++++++++---------
>  1 file changed, 24 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 90b3d7965136..c18bf1caad54 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -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,
>               struct dwc3_request *req, unsigned int trbs_left)
>  {
> -     struct usb_request *request = &req->request;
> -     struct scatterlist *sg = request->sg;
> +     struct scatterlist *sg = req->sg;
>       struct scatterlist *s;
>       unsigned int    length;
>       dma_addr_t      dma;
>       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;
>  
>               length = sg_dma_len(s);
> @@ -945,7 +944,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
>               return;
>  
>       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--);
>               else
>                       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)
>       if (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);
>  
>       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,
>       int                     ret;
>  
>       list_for_each_entry_safe(req, n, &dep->started_list, list) {
> -
> +             unsigned length;
> +             unsigned actual;
>               int chain;
>  
> -             chain = req->request.num_mapped_sgs > 0;
> +             length = req->request.length;
> +             chain = req->num_pending_sgs > 0;
>               if (chain) {
> -                     struct scatterlist *sg = req->request.sg;
> +                     struct scatterlist *sg = req->sg;
>                       struct scatterlist *s;
> +                     unsigned int pending = req->num_pending_sgs;
>                       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];
>                               count += trb->size & DWC3_TRB_SIZE_MASK;
>                               dwc3_ep_inc_deq(dep);
>  
> +                             req->sg = sg_next(s);
> +                             req->num_pending_sgs--;
> +
>                               ret = __dwc3_cleanup_done_trbs(dwc, dep, req, 
> trb,
>                                               event, status, chain);
> +                             if (ret)
> +                                     break;
>                       }
>               } else {
>                       trb = &dep->trb_pool[dep->trb_dequeue];
> @@ -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
>                * 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);
>  
>               if (ret)
> 

Seems to work fine now on testing/next

Thanks,
John
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to