From: Gregory Herrero <gregory.herr...@intel.com>

Align buffer must be allocated using kmalloc since irqs are disabled.
Coherency is handled through dma_map_single which can be used with irqs
disabled.

Signed-off-by: Gregory Herrero <gregory.herr...@intel.com>
---
 drivers/usb/dwc2/hcd.c       |  8 +++++---
 drivers/usb/dwc2/hcd_intr.c  | 10 ++++++++++
 drivers/usb/dwc2/hcd_queue.c |  7 ++++---
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 06be7f2..3c8f68c 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -711,9 +711,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg 
*hsotg, struct dwc2_qh *qh,
                        /* 3072 = 3 max-size Isoc packets */
                        buf_size = 3072;
 
-               qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size,
-                                                     &qh->dw_align_buf_dma,
-                                                     GFP_ATOMIC);
+               qh->dw_align_buf = kmalloc(buf_size, GFP_ATOMIC);
                if (!qh->dw_align_buf)
                        return -ENOMEM;
                qh->dw_align_buf_size = buf_size;
@@ -738,6 +736,10 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg 
*hsotg, struct dwc2_qh *qh,
                }
        }
 
+       qh->dw_align_buf_dma = dma_map_single(hsotg->dev,
+                       qh->dw_align_buf, qh->dw_align_buf_size,
+                       chan->ep_is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+
        chan->align_buf = qh->dw_align_buf_dma;
        return 0;
 }
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 6927bba..22f1476 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -468,6 +468,8 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
        /* Non DWORD-aligned buffer case handling */
        if (chan->align_buf && xfer_length && chan->ep_is_in) {
                dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+               dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
+                               chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
                memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
                       xfer_length);
        }
@@ -559,6 +561,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
                    chan->ep_is_in) {
                        dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
                                 __func__);
+                       dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
+                               chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
                        memcpy(urb->buf + frame_desc->offset +
                               qtd->isoc_split_offset, chan->qh->dw_align_buf,
                               frame_desc->actual_length);
@@ -588,6 +592,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
                    chan->ep_is_in) {
                        dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
                                 __func__);
+                       dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
+                               chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
                        memcpy(urb->buf + frame_desc->offset +
                               qtd->isoc_split_offset, chan->qh->dw_align_buf,
                               frame_desc->actual_length);
@@ -926,6 +932,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg 
*hsotg,
 
        if (chan->align_buf) {
                dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+               dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
+                               chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
                memcpy(qtd->urb->buf + frame_desc->offset +
                       qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
        }
@@ -1155,6 +1163,8 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg 
*hsotg,
        /* Non DWORD-aligned buffer case handling */
        if (chan->align_buf && xfer_length && chan->ep_is_in) {
                dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+               dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
+                               chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
                memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
                       xfer_length);
        }
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 63207dc..3735ae6 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -231,9 +231,10 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh)
 {
        if (hsotg->core_params->dma_desc_enable > 0)
                dwc2_hcd_qh_free_ddma(hsotg, qh);
-       else if (qh->dw_align_buf)
-               dma_free_coherent(hsotg->dev, qh->dw_align_buf_size,
-                                 qh->dw_align_buf, qh->dw_align_buf_dma);
+       else if (qh->dw_align_buf) {
+               kfree(qh->dw_align_buf);
+               qh->dw_align_buf_dma = (dma_addr_t)0;
+       }
        kfree(qh);
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to