usb: dwc3: gadget: allocate bounce buffer for unaligned xfers
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 5 Jan 2017 12:46:52 +0000 (14:46 +0200)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 24 Jan 2017 09:04:12 +0000 (11:04 +0200)
Allocate a coherent buffer of 1024 bytes (size of a single superspeed
bulk packet) to serve as bounce buffer for an extra TRB needed to align
transfers to wMaxPacketSize.

Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index 14b760209680920e65e92fbbb75a14c3bd4a3b18..9b4b79ae0beb4df05c57ee651d142a79493cde6d 100644 (file)
@@ -40,6 +40,7 @@
 /* Global constants */
 #define DWC3_PULL_UP_TIMEOUT   500     /* ms */
 #define DWC3_ZLP_BUF_SIZE      1024    /* size of a superspeed bulk */
+#define DWC3_BOUNCE_SIZE       1024    /* size of a superspeed bulk */
 #define DWC3_EP0_BOUNCE_SIZE   512
 #define DWC3_ENDPOINTS_NUM     32
 #define DWC3_XHCI_RESOURCES_NUM        2
@@ -857,12 +858,14 @@ struct dwc3_scratchpad_array {
 struct dwc3 {
        struct usb_ctrlrequest  *ctrl_req;
        struct dwc3_trb         *ep0_trb;
+       void                    *bounce;
        void                    *ep0_bounce;
        void                    *zlp_buf;
        void                    *scratchbuf;
        u8                      *setup_buf;
        dma_addr_t              ctrl_req_addr;
        dma_addr_t              ep0_trb_addr;
+       dma_addr_t              bounce_addr;
        dma_addr_t              ep0_bounce_addr;
        dma_addr_t              scratch_addr;
        struct dwc3_request     ep0_usb_req;
index f1ffbf789e0a3a73dbc4491829e8a80b451af5d8..653251751e3843cbc2b4364f90584f31cade05f2 100644 (file)
@@ -3021,6 +3021,13 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err4;
        }
 
+       dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE,
+                       &dwc->bounce_addr, GFP_KERNEL);
+       if (!dwc->bounce) {
+               ret = -ENOMEM;
+               goto err5;
+       }
+
        init_completion(&dwc->ep0_in_setup);
 
        dwc->gadget.ops                 = &dwc3_gadget_ops;
@@ -3064,15 +3071,18 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 
        ret = dwc3_gadget_init_endpoints(dwc);
        if (ret)
-               goto err5;
+               goto err6;
 
        ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
        if (ret) {
                dev_err(dwc->dev, "failed to register udc\n");
-               goto err5;
+               goto err6;
        }
 
        return 0;
+err6:
+       dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
+                       dwc->bounce_addr);
 
 err5:
        kfree(dwc->zlp_buf);
@@ -3105,6 +3115,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
        dwc3_gadget_free_endpoints(dwc);
 
+       dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
+                       dwc->bounce_addr);
        dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE,
                        dwc->ep0_bounce, dwc->ep0_bounce_addr);