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: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
parent
2c78c0295f
commit
1f512119a0
@ -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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user