aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/dwc2/core.h3
-rw-r--r--drivers/usb/dwc2/hcd.c89
-rw-r--r--drivers/usb/dwc2/hcd.h8
-rw-r--r--drivers/usb/dwc2/hcd_intr.c8
-rw-r--r--drivers/usb/dwc2/hcd_queue.c3
5 files changed, 106 insertions, 5 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 4a56ac772a3c..71b3b08ad516 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1004,6 +1004,7 @@ struct dwc2_hregs_backup {
1004 * @frame_list_sz: Frame list size 1004 * @frame_list_sz: Frame list size
1005 * @desc_gen_cache: Kmem cache for generic descriptors 1005 * @desc_gen_cache: Kmem cache for generic descriptors
1006 * @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors 1006 * @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors
1007 * @unaligned_cache: Kmem cache for DMA mode to handle non-aligned buf
1007 * 1008 *
1008 * These are for peripheral mode: 1009 * These are for peripheral mode:
1009 * 1010 *
@@ -1177,6 +1178,8 @@ struct dwc2_hsotg {
1177 u32 frame_list_sz; 1178 u32 frame_list_sz;
1178 struct kmem_cache *desc_gen_cache; 1179 struct kmem_cache *desc_gen_cache;
1179 struct kmem_cache *desc_hsisoc_cache; 1180 struct kmem_cache *desc_hsisoc_cache;
1181 struct kmem_cache *unaligned_cache;
1182#define DWC2_KMEM_UNALIGNED_BUF_SIZE 1024
1180 1183
1181#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */ 1184#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */
1182 1185
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index bae08a7d7abd..b1104be3429c 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1567,11 +1567,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
1567 } 1567 }
1568 1568
1569 if (hsotg->params.host_dma) { 1569 if (hsotg->params.host_dma) {
1570 dwc2_writel((u32)chan->xfer_dma, 1570 dma_addr_t dma_addr;
1571 hsotg->regs + HCDMA(chan->hc_num)); 1571
1572 if (chan->align_buf) {
1573 if (dbg_hc(chan))
1574 dev_vdbg(hsotg->dev, "align_buf\n");
1575 dma_addr = chan->align_buf;
1576 } else {
1577 dma_addr = chan->xfer_dma;
1578 }
1579 dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
1580
1572 if (dbg_hc(chan)) 1581 if (dbg_hc(chan))
1573 dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n", 1582 dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
1574 (unsigned long)chan->xfer_dma, chan->hc_num); 1583 (unsigned long)dma_addr, chan->hc_num);
1575 } 1584 }
1576 1585
1577 /* Start the split */ 1586 /* Start the split */
@@ -2625,6 +2634,35 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
2625 } 2634 }
2626} 2635}
2627 2636
2637static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg,
2638 struct dwc2_qh *qh,
2639 struct dwc2_host_chan *chan)
2640{
2641 if (!hsotg->unaligned_cache ||
2642 chan->max_packet > DWC2_KMEM_UNALIGNED_BUF_SIZE)
2643 return -ENOMEM;
2644
2645 if (!qh->dw_align_buf) {
2646 qh->dw_align_buf = kmem_cache_alloc(hsotg->unaligned_cache,
2647 GFP_ATOMIC | GFP_DMA);
2648 if (!qh->dw_align_buf)
2649 return -ENOMEM;
2650 }
2651
2652 qh->dw_align_buf_dma = dma_map_single(hsotg->dev, qh->dw_align_buf,
2653 DWC2_KMEM_UNALIGNED_BUF_SIZE,
2654 DMA_FROM_DEVICE);
2655
2656 if (dma_mapping_error(hsotg->dev, qh->dw_align_buf_dma)) {
2657 dev_err(hsotg->dev, "can't map align_buf\n");
2658 chan->align_buf = 0;
2659 return -EINVAL;
2660 }
2661
2662 chan->align_buf = qh->dw_align_buf_dma;
2663 return 0;
2664}
2665
2628#define DWC2_USB_DMA_ALIGN 4 2666#define DWC2_USB_DMA_ALIGN 4
2629 2667
2630struct dma_aligned_buffer { 2668struct dma_aligned_buffer {
@@ -2802,6 +2840,32 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
2802 /* Set the transfer attributes */ 2840 /* Set the transfer attributes */
2803 dwc2_hc_init_xfer(hsotg, chan, qtd); 2841 dwc2_hc_init_xfer(hsotg, chan, qtd);
2804 2842
2843 /* For non-dword aligned buffers */
2844 if (hsotg->params.host_dma && qh->do_split &&
2845 chan->ep_is_in && (chan->xfer_dma & 0x3)) {
2846 dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
2847 if (dwc2_alloc_split_dma_aligned_buf(hsotg, qh, chan)) {
2848 dev_err(hsotg->dev,
2849 "Failed to allocate memory to handle non-aligned buffer\n");
2850 /* Add channel back to free list */
2851 chan->align_buf = 0;
2852 chan->multi_count = 0;
2853 list_add_tail(&chan->hc_list_entry,
2854 &hsotg->free_hc_list);
2855 qtd->in_process = 0;
2856 qh->channel = NULL;
2857 return -ENOMEM;
2858 }
2859 } else {
2860 /*
2861 * We assume that DMA is always aligned in non-split
2862 * case or split out case. Warn if not.
2863 */
2864 WARN_ON_ONCE(hsotg->params.host_dma &&
2865 (chan->xfer_dma & 0x3));
2866 chan->align_buf = 0;
2867 }
2868
2805 if (chan->ep_type == USB_ENDPOINT_XFER_INT || 2869 if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
2806 chan->ep_type == USB_ENDPOINT_XFER_ISOC) 2870 chan->ep_type == USB_ENDPOINT_XFER_ISOC)
2807 /* 2871 /*
@@ -5246,6 +5310,19 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
5246 } 5310 }
5247 } 5311 }
5248 5312
5313 if (hsotg->params.host_dma) {
5314 /*
5315 * Create kmem caches to handle non-aligned buffer
5316 * in Buffer DMA mode.
5317 */
5318 hsotg->unaligned_cache = kmem_cache_create("dwc2-unaligned-dma",
5319 DWC2_KMEM_UNALIGNED_BUF_SIZE, 4,
5320 SLAB_CACHE_DMA, NULL);
5321 if (!hsotg->unaligned_cache)
5322 dev_err(hsotg->dev,
5323 "unable to create dwc2 unaligned cache\n");
5324 }
5325
5249 hsotg->otg_port = 1; 5326 hsotg->otg_port = 1;
5250 hsotg->frame_list = NULL; 5327 hsotg->frame_list = NULL;
5251 hsotg->frame_list_dma = 0; 5328 hsotg->frame_list_dma = 0;
@@ -5280,8 +5357,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
5280 return 0; 5357 return 0;
5281 5358
5282error4: 5359error4:
5283 kmem_cache_destroy(hsotg->desc_gen_cache); 5360 kmem_cache_destroy(hsotg->unaligned_cache);
5284 kmem_cache_destroy(hsotg->desc_hsisoc_cache); 5361 kmem_cache_destroy(hsotg->desc_hsisoc_cache);
5362 kmem_cache_destroy(hsotg->desc_gen_cache);
5285error3: 5363error3:
5286 dwc2_hcd_release(hsotg); 5364 dwc2_hcd_release(hsotg);
5287error2: 5365error2:
@@ -5322,8 +5400,9 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg)
5322 usb_remove_hcd(hcd); 5400 usb_remove_hcd(hcd);
5323 hsotg->priv = NULL; 5401 hsotg->priv = NULL;
5324 5402
5325 kmem_cache_destroy(hsotg->desc_gen_cache); 5403 kmem_cache_destroy(hsotg->unaligned_cache);
5326 kmem_cache_destroy(hsotg->desc_hsisoc_cache); 5404 kmem_cache_destroy(hsotg->desc_hsisoc_cache);
5405 kmem_cache_destroy(hsotg->desc_gen_cache);
5327 5406
5328 dwc2_hcd_release(hsotg); 5407 dwc2_hcd_release(hsotg);
5329 usb_put_hcd(hcd); 5408 usb_put_hcd(hcd);
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index 7db1ee7e7a77..5502a501f516 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -76,6 +76,8 @@ struct dwc2_qh;
76 * (micro)frame 76 * (micro)frame
77 * @xfer_buf: Pointer to current transfer buffer position 77 * @xfer_buf: Pointer to current transfer buffer position
78 * @xfer_dma: DMA address of xfer_buf 78 * @xfer_dma: DMA address of xfer_buf
79 * @align_buf: In Buffer DMA mode this will be used if xfer_buf is not
80 * DWORD aligned
79 * @xfer_len: Total number of bytes to transfer 81 * @xfer_len: Total number of bytes to transfer
80 * @xfer_count: Number of bytes transferred so far 82 * @xfer_count: Number of bytes transferred so far
81 * @start_pkt_count: Packet count at start of transfer 83 * @start_pkt_count: Packet count at start of transfer
@@ -133,6 +135,7 @@ struct dwc2_host_chan {
133 135
134 u8 *xfer_buf; 136 u8 *xfer_buf;
135 dma_addr_t xfer_dma; 137 dma_addr_t xfer_dma;
138 dma_addr_t align_buf;
136 u32 xfer_len; 139 u32 xfer_len;
137 u32 xfer_count; 140 u32 xfer_count;
138 u16 start_pkt_count; 141 u16 start_pkt_count;
@@ -302,6 +305,9 @@ struct dwc2_hs_transfer_time {
302 * speed. Note that this is in "schedule slice" which 305 * speed. Note that this is in "schedule slice" which
303 * is tightly packed. 306 * is tightly packed.
304 * @ntd: Actual number of transfer descriptors in a list 307 * @ntd: Actual number of transfer descriptors in a list
308 * @dw_align_buf: Used instead of original buffer if its physical address
309 * is not dword-aligned
310 * @dw_align_buf_dma: DMA address for dw_align_buf
305 * @qtd_list: List of QTDs for this QH 311 * @qtd_list: List of QTDs for this QH
306 * @channel: Host channel currently processing transfers for this QH 312 * @channel: Host channel currently processing transfers for this QH
307 * @qh_list_entry: Entry for QH in either the periodic or non-periodic 313 * @qh_list_entry: Entry for QH in either the periodic or non-periodic
@@ -350,6 +356,8 @@ struct dwc2_qh {
350 struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES]; 356 struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES];
351 u32 ls_start_schedule_slice; 357 u32 ls_start_schedule_slice;
352 u16 ntd; 358 u16 ntd;
359 u8 *dw_align_buf;
360 dma_addr_t dw_align_buf_dma;
353 struct list_head qtd_list; 361 struct list_head qtd_list;
354 struct dwc2_host_chan *channel; 362 struct dwc2_host_chan *channel;
355 struct list_head qh_list_entry; 363 struct list_head qh_list_entry;
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index fbea5e3fb947..f3429ac4a6bb 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -950,6 +950,14 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
950 950
951 frame_desc->actual_length += len; 951 frame_desc->actual_length += len;
952 952
953 if (chan->align_buf) {
954 dev_vdbg(hsotg->dev, "non-aligned buffer\n");
955 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
956 DWC2_KMEM_UNALIGNED_BUF_SIZE, DMA_FROM_DEVICE);
957 memcpy(qtd->urb->buf + (chan->xfer_dma - qtd->urb->dma),
958 chan->qh->dw_align_buf, len);
959 }
960
953 qtd->isoc_split_offset += len; 961 qtd->isoc_split_offset += len;
954 962
955 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); 963 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 9c55d1addba9..301ced1618f8 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -1696,6 +1696,9 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
1696 1696
1697 if (qh->desc_list) 1697 if (qh->desc_list)
1698 dwc2_hcd_qh_free_ddma(hsotg, qh); 1698 dwc2_hcd_qh_free_ddma(hsotg, qh);
1699 else if (hsotg->unaligned_cache && qh->dw_align_buf)
1700 kmem_cache_free(hsotg->unaligned_cache, qh->dw_align_buf);
1701
1699 kfree(qh); 1702 kfree(qh);
1700} 1703}
1701 1704