]> git.ipfire.org Git - thirdparty/kernel/stable.git/blobdiff - drivers/usb/dwc2/hcd.c
usb: dwc2: Fix DMA cache alignment issues
[thirdparty/kernel/stable.git] / drivers / usb / dwc2 / hcd.c
index 2bd6e6bfc241b8673b0fcd558f874381493ce6bd..9221a02e795801f9794f6957b644f47e93db9596 100644 (file)
@@ -2673,8 +2673,10 @@ static void dwc2_free_dma_aligned_buffer(struct urb *urb)
                return;
 
        /* Restore urb->transfer_buffer from the end of the allocated area */
-       memcpy(&stored_xfer_buffer, urb->transfer_buffer +
-              urb->transfer_buffer_length, sizeof(urb->transfer_buffer));
+       memcpy(&stored_xfer_buffer,
+              PTR_ALIGN(urb->transfer_buffer + urb->transfer_buffer_length,
+                        dma_get_cache_alignment()),
+              sizeof(urb->transfer_buffer));
 
        if (usb_urb_dir_in(urb)) {
                if (usb_pipeisoc(urb->pipe))
@@ -2706,6 +2708,7 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
         * DMA
         */
        kmalloc_size = urb->transfer_buffer_length +
+               (dma_get_cache_alignment() - 1) +
                sizeof(urb->transfer_buffer);
 
        kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
@@ -2716,7 +2719,8 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
         * Position value of original urb->transfer_buffer pointer to the end
         * of allocation for later referencing
         */
-       memcpy(kmalloc_ptr + urb->transfer_buffer_length,
+       memcpy(PTR_ALIGN(kmalloc_ptr + urb->transfer_buffer_length,
+                        dma_get_cache_alignment()),
               &urb->transfer_buffer, sizeof(urb->transfer_buffer));
 
        if (usb_urb_dir_out(urb))
@@ -4393,6 +4397,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
        struct usb_bus *bus = hcd_to_bus(hcd);
        unsigned long flags;
+       int ret;
 
        dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
 
@@ -4408,6 +4413,13 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
 
        dwc2_hcd_reinit(hsotg);
 
+       /* enable external vbus supply before resuming root hub */
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+       ret = dwc2_vbus_supply_init(hsotg);
+       if (ret)
+               return ret;
+       spin_lock_irqsave(&hsotg->lock, flags);
+
        /* Initialize and connect root hub if one is not already attached */
        if (bus->root_hub) {
                dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n");
@@ -4417,7 +4429,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
-       return dwc2_vbus_supply_init(hsotg);
+       return 0;
 }
 
 /*
@@ -4482,7 +4494,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
                hprt0 |= HPRT0_SUSP;
                hprt0 &= ~HPRT0_PWR;
                dwc2_writel(hsotg, hprt0, HPRT0);
+               spin_unlock_irqrestore(&hsotg->lock, flags);
                dwc2_vbus_supply_exit(hsotg);
+               spin_lock_irqsave(&hsotg->lock, flags);
        }
 
        /* Enter partial_power_down */