1
0
Fork 0

MLK-23181-3 usb: cdns3: gadget: handle multiple trb request properly

We use polling EP_TRADDR to judge if the trb has finished, so for
request which includes multiple trb, we may quit the trb judgement
in the middle of request, in that case, we can't giveback the
request. We should only giveback the request when all the TRB in
this request has finished.

Reviewed-by: Jun Li <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Peter Chen 2020-01-07 12:03:57 +08:00
parent 3e7c6dff3e
commit f9e2ca657f
No known key found for this signature in database
GPG Key ID: 4859298150D671BB
2 changed files with 13 additions and 4 deletions

View File

@ -451,6 +451,8 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
request->length);
priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED);
/* All TRBs have finished, clear the flag */
priv_req->finished_trb = 0;
trace_cdns3_gadget_giveback(priv_req);
/* WA2: */
@ -700,6 +702,7 @@ int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
trb = priv_req->trb;
priv_req->flags |= REQUEST_PENDING;
priv_req->num_of_trb = num_trb;
/* give the TD to the consumer*/
if (sg_iter == 1)
@ -884,7 +887,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
struct cdns3_request *priv_req;
struct usb_request *request;
struct cdns3_trb *trb;
bool trb_handled = false;
bool request_handled = false;
while (!list_empty(&priv_ep->pending_req_list)) {
request = cdns3_next_request(&priv_ep->pending_req_list);
@ -896,7 +899,9 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
cdns3_select_ep(priv_dev, priv_ep->endpoint.address);
while (cdns3_request_handled(priv_ep, priv_req)) {
trb_handled = true;
priv_req->finished_trb++;
if (priv_req->finished_trb >= priv_req->num_of_trb)
request_handled = true;
trb = priv_ep->trb_pool + priv_ep->dequeue;
trace_cdns3_complete_trb(priv_ep, trb);
@ -904,9 +909,9 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
cdns3_ep_inc_deq(priv_ep);
}
if (trb_handled) {
if (request_handled) {
cdns3_gadget_giveback(priv_ep, priv_req, 0);
trb_handled = false;
request_handled = false;
} else {
return;
}

View File

@ -1125,6 +1125,8 @@ struct cdns3_aligned_buf {
* this endpoint
* @flags: flag specifying special usage of request
* @list: used by internally allocated request to add to descmiss_req_list.
* @finished_trb: number of trb has already finished per request
* @num_of_trb: how many trbs in this request
*/
struct cdns3_request {
struct usb_request request;
@ -1140,6 +1142,8 @@ struct cdns3_request {
#define REQUEST_UNALIGNED BIT(4)
u32 flags;
struct list_head list;
int finished_trb;
int num_of_trb;
};
#define to_cdns3_request(r) (container_of(r, struct cdns3_request, request))