usb: gadget: net2280: match interrupt endpoints to PIO endpoints and DMA to bulk
authorJussi Kivilinna <jussi.kivilinna@haltian.com>
Fri, 12 Aug 2016 14:29:35 +0000 (17:29 +0300)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 25 Aug 2016 09:13:10 +0000 (12:13 +0300)
With composite gadget (ACM + NCM), USB3380 to host TCP transfer
speed dropped to 150 Mbit/s compared to 900 Mbit/s with NCM
gadget. Problem seems to be that net2280/USB3380 has only four
DMA channels and those DMA channels are allocated to first HW
endpoints. Endpoint match function was mapping endpoint names
directly, so NCM did not get DMA for bulk endpoints.

This patch changed match_ep to prefer DMA enabled hw endpoints
for bulk usb endpoints and PIO for interrupt usb endpoints.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@haltian.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/udc/net2280.c

index cd876bff51067505d4b462b826e842f6a4f8dc25..a28eb87078ae154891d4d00e7fe690cb4bbac2a7 100644 (file)
@@ -1573,6 +1573,44 @@ static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
                        return ep;
        }
 
+       /* USB3380: Only first four endpoints have DMA channels. Allocate
+        * slower interrupt endpoints from PIO hw endpoints, to allow bulk/isoc
+        * endpoints use DMA hw endpoints.
+        */
+       if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT &&
+           usb_endpoint_dir_in(desc)) {
+               ep = gadget_find_ep_by_name(_gadget, "ep2in");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+               ep = gadget_find_ep_by_name(_gadget, "ep4in");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+       } else if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT &&
+                  !usb_endpoint_dir_in(desc)) {
+               ep = gadget_find_ep_by_name(_gadget, "ep1out");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+               ep = gadget_find_ep_by_name(_gadget, "ep3out");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+       } else if (usb_endpoint_type(desc) != USB_ENDPOINT_XFER_BULK &&
+                  usb_endpoint_dir_in(desc)) {
+               ep = gadget_find_ep_by_name(_gadget, "ep1in");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+               ep = gadget_find_ep_by_name(_gadget, "ep3in");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+       } else if (usb_endpoint_type(desc) != USB_ENDPOINT_XFER_BULK &&
+                  !usb_endpoint_dir_in(desc)) {
+               ep = gadget_find_ep_by_name(_gadget, "ep2out");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+               ep = gadget_find_ep_by_name(_gadget, "ep4out");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+       }
+
        /* USB3380: use same address for usb and hardware endpoints */
        snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
                        usb_endpoint_dir_in(desc) ? "in" : "out");