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
parent
3e7c6dff3e
commit
f9e2ca657f
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue