summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/cdns3/gadget.c21
-rw-r--r--drivers/usb/cdns3/gadget.h8
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)