diff options
author | Gregory Herrero <gregory.herrero@intel.com> | 2015-04-29 16:09:16 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2015-04-29 16:20:00 -0400 |
commit | db62b9a804b465f5050438eb06151c99c625ec9a (patch) | |
tree | dd167e381e31826ef95c1d9718908494c2f8fdcf | |
parent | 33ad261aa62be02f0cedeb4d5735cc726de84a3f (diff) |
usb: dwc2: host: don't use dma_alloc_coherent with irqs disabled
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.
Reviewed-by: Julius Werner <jwerner@chromium.org>
Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Gregory Herrero <gregory.herrero@intel.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/dwc2/hcd.c | 13 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd_intr.c | 53 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd_queue.c | 10 |
3 files changed, 54 insertions, 22 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index d72557cfc052..745230d0d8b3 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c | |||
@@ -719,9 +719,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | |||
719 | /* 3072 = 3 max-size Isoc packets */ | 719 | /* 3072 = 3 max-size Isoc packets */ |
720 | buf_size = 3072; | 720 | buf_size = 3072; |
721 | 721 | ||
722 | qh->dw_align_buf = dma_alloc_coherent(hsotg->dev, buf_size, | 722 | qh->dw_align_buf = kmalloc(buf_size, GFP_ATOMIC | GFP_DMA); |
723 | &qh->dw_align_buf_dma, | ||
724 | GFP_ATOMIC); | ||
725 | if (!qh->dw_align_buf) | 723 | if (!qh->dw_align_buf) |
726 | return -ENOMEM; | 724 | return -ENOMEM; |
727 | qh->dw_align_buf_size = buf_size; | 725 | qh->dw_align_buf_size = buf_size; |
@@ -746,6 +744,15 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | |||
746 | } | 744 | } |
747 | } | 745 | } |
748 | 746 | ||
747 | qh->dw_align_buf_dma = dma_map_single(hsotg->dev, | ||
748 | qh->dw_align_buf, qh->dw_align_buf_size, | ||
749 | chan->ep_is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
750 | if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) { | ||
751 | dev_err(hsotg->dev, "can't map align_buf\n"); | ||
752 | chan->align_buf = (dma_addr_t)NULL; | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
749 | chan->align_buf = qh->dw_align_buf_dma; | 756 | chan->align_buf = qh->dw_align_buf_dma; |
750 | return 0; | 757 | return 0; |
751 | } | 758 | } |
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 6927bba86245..6ea8eb6899f4 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c | |||
@@ -466,10 +466,15 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, | |||
466 | } | 466 | } |
467 | 467 | ||
468 | /* Non DWORD-aligned buffer case handling */ | 468 | /* Non DWORD-aligned buffer case handling */ |
469 | if (chan->align_buf && xfer_length && chan->ep_is_in) { | 469 | if (chan->align_buf && xfer_length) { |
470 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); | 470 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); |
471 | memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, | 471 | dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, |
472 | xfer_length); | 472 | chan->qh->dw_align_buf_size, |
473 | chan->ep_is_in ? | ||
474 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
475 | if (chan->ep_is_in) | ||
476 | memcpy(urb->buf + urb->actual_length, | ||
477 | chan->qh->dw_align_buf, xfer_length); | ||
473 | } | 478 | } |
474 | 479 | ||
475 | dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n", | 480 | dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n", |
@@ -555,13 +560,18 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( | |||
555 | chan, chnum, qtd, halt_status, NULL); | 560 | chan, chnum, qtd, halt_status, NULL); |
556 | 561 | ||
557 | /* Non DWORD-aligned buffer case handling */ | 562 | /* Non DWORD-aligned buffer case handling */ |
558 | if (chan->align_buf && frame_desc->actual_length && | 563 | if (chan->align_buf && frame_desc->actual_length) { |
559 | chan->ep_is_in) { | ||
560 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", | 564 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", |
561 | __func__); | 565 | __func__); |
562 | memcpy(urb->buf + frame_desc->offset + | 566 | dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, |
563 | qtd->isoc_split_offset, chan->qh->dw_align_buf, | 567 | chan->qh->dw_align_buf_size, |
564 | frame_desc->actual_length); | 568 | chan->ep_is_in ? |
569 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
570 | if (chan->ep_is_in) | ||
571 | memcpy(urb->buf + frame_desc->offset + | ||
572 | qtd->isoc_split_offset, | ||
573 | chan->qh->dw_align_buf, | ||
574 | frame_desc->actual_length); | ||
565 | } | 575 | } |
566 | break; | 576 | break; |
567 | case DWC2_HC_XFER_FRAME_OVERRUN: | 577 | case DWC2_HC_XFER_FRAME_OVERRUN: |
@@ -584,13 +594,18 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( | |||
584 | chan, chnum, qtd, halt_status, NULL); | 594 | chan, chnum, qtd, halt_status, NULL); |
585 | 595 | ||
586 | /* Non DWORD-aligned buffer case handling */ | 596 | /* Non DWORD-aligned buffer case handling */ |
587 | if (chan->align_buf && frame_desc->actual_length && | 597 | if (chan->align_buf && frame_desc->actual_length) { |
588 | chan->ep_is_in) { | ||
589 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", | 598 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", |
590 | __func__); | 599 | __func__); |
591 | memcpy(urb->buf + frame_desc->offset + | 600 | dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, |
592 | qtd->isoc_split_offset, chan->qh->dw_align_buf, | 601 | chan->qh->dw_align_buf_size, |
593 | frame_desc->actual_length); | 602 | chan->ep_is_in ? |
603 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
604 | if (chan->ep_is_in) | ||
605 | memcpy(urb->buf + frame_desc->offset + | ||
606 | qtd->isoc_split_offset, | ||
607 | chan->qh->dw_align_buf, | ||
608 | frame_desc->actual_length); | ||
594 | } | 609 | } |
595 | 610 | ||
596 | /* Skip whole frame */ | 611 | /* Skip whole frame */ |
@@ -926,6 +941,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, | |||
926 | 941 | ||
927 | if (chan->align_buf) { | 942 | if (chan->align_buf) { |
928 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); | 943 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); |
944 | dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, | ||
945 | chan->qh->dw_align_buf_size, DMA_FROM_DEVICE); | ||
929 | memcpy(qtd->urb->buf + frame_desc->offset + | 946 | memcpy(qtd->urb->buf + frame_desc->offset + |
930 | qtd->isoc_split_offset, chan->qh->dw_align_buf, len); | 947 | qtd->isoc_split_offset, chan->qh->dw_align_buf, len); |
931 | } | 948 | } |
@@ -1155,8 +1172,14 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, | |||
1155 | /* Non DWORD-aligned buffer case handling */ | 1172 | /* Non DWORD-aligned buffer case handling */ |
1156 | if (chan->align_buf && xfer_length && chan->ep_is_in) { | 1173 | if (chan->align_buf && xfer_length && chan->ep_is_in) { |
1157 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); | 1174 | dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); |
1158 | memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, | 1175 | dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma, |
1159 | xfer_length); | 1176 | chan->qh->dw_align_buf_size, |
1177 | chan->ep_is_in ? | ||
1178 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
1179 | if (chan->ep_is_in) | ||
1180 | memcpy(urb->buf + urb->actual_length, | ||
1181 | chan->qh->dw_align_buf, | ||
1182 | xfer_length); | ||
1160 | } | 1183 | } |
1161 | 1184 | ||
1162 | urb->actual_length += xfer_length; | 1185 | urb->actual_length += xfer_length; |
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 63207dc3cb22..9b5c36256627 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c | |||
@@ -229,11 +229,13 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, | |||
229 | */ | 229 | */ |
230 | void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | 230 | void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) |
231 | { | 231 | { |
232 | if (hsotg->core_params->dma_desc_enable > 0) | 232 | if (hsotg->core_params->dma_desc_enable > 0) { |
233 | dwc2_hcd_qh_free_ddma(hsotg, qh); | 233 | dwc2_hcd_qh_free_ddma(hsotg, qh); |
234 | else if (qh->dw_align_buf) | 234 | } else { |
235 | dma_free_coherent(hsotg->dev, qh->dw_align_buf_size, | 235 | /* kfree(NULL) is safe */ |
236 | qh->dw_align_buf, qh->dw_align_buf_dma); | 236 | kfree(qh->dw_align_buf); |
237 | qh->dw_align_buf_dma = (dma_addr_t)0; | ||
238 | } | ||
237 | kfree(qh); | 239 | kfree(qh); |
238 | } | 240 | } |
239 | 241 | ||