diff options
-rw-r--r-- | drivers/usb/cdns3/gadget.c | 21 | ||||
-rw-r--r-- | drivers/usb/cdns3/gadget.h | 8 |
2 files changed, 23 insertions, 6 deletions
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index dce0d1c72ef6..86eb9792e767 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -927,12 +927,14 @@ finish: } static void cdns3_transfer_completed(struct cdns3_device *priv_dev, - struct cdns3_endpoint *priv_ep) + struct cdns3_endpoint *priv_ep, + bool is_short) { struct cdns3_request *priv_req; struct usb_request *request; struct cdns3_trb *trb; bool request_handled = false; + bool transfer_end = false; while (!list_empty(&priv_ep->pending_req_list)) { request = cdns3_next_request(&priv_ep->pending_req_list); @@ -958,7 +960,14 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, trb = priv_ep->trb_pool + priv_ep->dequeue; trace_cdns3_complete_trb(priv_ep, trb); - request->actual += TRB_LEN(le32_to_cpu(trb->length)); + if (!transfer_end) + request->actual += + TRB_LEN(le32_to_cpu(trb->length)); + + if (is_short && priv_req->num_of_trb > 1 && + le32_to_cpu(trb->control) & TRB_SMM) + transfer_end = true; + cdns3_ep_inc_deq(priv_ep); } @@ -1072,20 +1081,22 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) */ if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->wa1_set) - cdns3_transfer_completed(priv_dev, priv_ep); + cdns3_transfer_completed(priv_dev, priv_ep, false); else cdns3_rearm_transfer(priv_ep, priv_ep->wa1_set); } if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { + bool is_short = !!(ep_sts_reg & EP_STS_ISP); + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { - if (ep_sts_reg & EP_STS_ISP) + if (is_short) priv_ep->flags |= EP_QUIRK_END_TRANSFER; else priv_ep->flags &= ~EP_QUIRK_END_TRANSFER; } - cdns3_transfer_completed(priv_dev, priv_ep); + cdns3_transfer_completed(priv_dev, priv_ep, is_short); } /* diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h index 2443bc3d06b5..35a4e830f955 100644 --- a/drivers/usb/cdns3/gadget.h +++ b/drivers/usb/cdns3/gadget.h @@ -964,9 +964,15 @@ struct cdns3_trb { /* Cycle bit - indicates TRB ownership by driver or hw*/ #define TRB_CYCLE BIT(0) /* - * When set to '1', the device will toggle its interpretation of the Cycle bit + * When set to '1', the device will toggle its interpretation + * of the Cycle bit, this bit is for link TRB */ #define TRB_TOGGLE BIT(1) +/* + * The controller will set it if OUTSMM (OUT size mismatch) is detected, + * this bit is for normal TRB + */ +#define TRB_SMM BIT(1) /* Interrupt on short packet*/ #define TRB_ISP BIT(2) |