浏览代码

usb: dwc2: gadget: Transfer length limit checking for DDMA

Add dwc2_gadget_get_chain_limit() function and its call in transfer
start routine to correctly estimate one go on transfer size if
descriptor DMA mode is selected.

Signed-off-by: Vahram Aharonyan <vahrama@synopsys.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Vahram Aharonyan 8 年之前
父节点
当前提交
cf77b5fb9b
共有 1 个文件被更改,包括 31 次插入1 次删除
  1. 31 1
      drivers/usb/dwc2/gadget.c

+ 31 - 1
drivers/usb/dwc2/gadget.c

@@ -601,6 +601,32 @@ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
 	return dsts;
 	return dsts;
 }
 }
 
 
+/**
+ * dwc2_gadget_get_chain_limit - get the maximum data payload value of the
+ * DMA descriptor chain prepared for specific endpoint
+ * @hs_ep: The endpoint
+ *
+ * Return the maximum data that can be queued in one go on a given endpoint
+ * depending on its descriptor chain capacity so that transfers that
+ * are too long can be split.
+ */
+static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep)
+{
+	int is_isoc = hs_ep->isochronous;
+	unsigned int maxsize;
+
+	if (is_isoc)
+		maxsize = hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_LIMIT :
+					   DEV_DMA_ISOC_RX_NBYTES_LIMIT;
+	else
+		maxsize = DEV_DMA_NBYTES_LIMIT;
+
+	/* Above size of one descriptor was chosen, multiple it */
+	maxsize *= MAX_DMA_DESC_NUM_GENERIC;
+
+	return maxsize;
+}
+
 /**
 /**
  * dwc2_hsotg_start_req - start a USB request from an endpoint's queue
  * dwc2_hsotg_start_req - start a USB request from an endpoint's queue
  * @hsotg: The controller state.
  * @hsotg: The controller state.
@@ -659,7 +685,11 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
 	dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n",
 	dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n",
 		ureq->length, ureq->actual);
 		ureq->length, ureq->actual);
 
 
-	maxreq = get_ep_limit(hs_ep);
+	if (!using_desc_dma(hsotg))
+		maxreq = get_ep_limit(hs_ep);
+	else
+		maxreq = dwc2_gadget_get_chain_limit(hs_ep);
+
 	if (length > maxreq) {
 	if (length > maxreq) {
 		int round = maxreq % hs_ep->ep.maxpacket;
 		int round = maxreq % hs_ep->ep.maxpacket;