usb: cdns3: gadget: using correct sg operations
authorPeter Chen <peter.chen@nxp.com>
Thu, 10 Sep 2020 09:11:23 +0000 (17:11 +0800)
committerFelipe Balbi <balbi@kernel.org>
Fri, 2 Oct 2020 06:57:45 +0000 (09:57 +0300)
It needs to use request->num_mapped_sgs to indicate mapped sg number,
the request->num_sgs is the sg number before the mapping. These two
entries have different values for the platforms which iommu or
swiotlb is used. Besides, it needs to use correct sg APIs for
mapped sg list for TRB assignment.

Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/cdns3/gadget.c

index 26ba4170067262742074f47c194bdb31b58c72ac..caf011f59a4c6f03651e7cec05aa4f52331b67a6 100644 (file)
@@ -1098,11 +1098,13 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
        u32 control;
        int pcs;
        u16 total_tdl = 0;
+       struct scatterlist *s = NULL;
+       bool sg_supported = !!(request->num_mapped_sgs);
 
        if (priv_ep->type == USB_ENDPOINT_XFER_ISOC)
                num_trb = priv_ep->interval;
        else
-               num_trb = request->num_sgs ? request->num_sgs : 1;
+               num_trb = sg_supported ? request->num_mapped_sgs : 1;
 
        if (num_trb > priv_ep->free_trbs) {
                priv_ep->flags |= EP_RING_FULL;
@@ -1162,6 +1164,9 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
        if (priv_dev->dev_ver <= DEV_VER_V2)
                togle_pcs = cdns3_wa1_update_guard(priv_ep, trb);
 
+       if (sg_supported)
+               s = request->sg;
+
        /* set incorrect Cycle Bit for first trb*/
        control = priv_ep->pcs ? 0 : TRB_CYCLE;
 
@@ -1171,13 +1176,13 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
 
                /* fill TRB */
                control |= TRB_TYPE(TRB_NORMAL);
-               trb->buffer = cpu_to_le32(TRB_BUFFER(request->num_sgs == 0
-                               ? trb_dma : request->sg[sg_iter].dma_address));
-
-               if (likely(!request->num_sgs))
+               if (sg_supported) {
+                       trb->buffer = cpu_to_le32(TRB_BUFFER(sg_dma_address(s)));
+                       length = sg_dma_len(s);
+               } else {
+                       trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma));
                        length = request->length;
-               else
-                       length = request->sg[sg_iter].length;
+               }
 
                if (likely(priv_dev->dev_ver >= DEV_VER_V2))
                        td_size = DIV_ROUND_UP(length,
@@ -1215,6 +1220,9 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
                else
                        priv_req->trb->control = cpu_to_le32(control);
 
+               if (sg_supported)
+                       s = sg_next(s);
+
                control = 0;
                ++sg_iter;
                priv_req->end_trb = priv_ep->enqueue;