From 2d320ce334b124046388e25d91725d19ffb1855c Mon Sep 17 00:00:00 2001 From: "taehyun.cho" Date: Wed, 31 Oct 2018 17:15:22 +0900 Subject: [PATCH] [RAMEN9610-11637][COMMON] usb: host: allocate dma memory in booting time Change-Id: If6dd884c7a8bedbddf81a97dcb48a94e18c634f8 Signed-off-by: taehyun.cho --- drivers/usb/dwc3/host.c | 18 ++++++++ drivers/usb/host/xhci-mem.c | 88 ++++++++++++++---------------------- drivers/usb/host/xhci-plat.c | 3 ++ drivers/usb/host/xhci-plat.h | 10 ++++ drivers/usb/host/xhci.h | 2 + 5 files changed, 66 insertions(+), 55 deletions(-) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 903d0962d1b2..6efc1ec491f8 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -26,6 +26,16 @@ struct host_data xhci_data; #endif +struct usb_xhci_pre_alloc { + u8 *pre_dma_alloc; + u64 offset; + + dma_addr_t dma; +}; + +struct usb_xhci_pre_alloc xhci_pre_alloc; +void __iomem *phycon_base_addr; + static int dwc3_host_get_irq(struct dwc3 *dwc) { struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); @@ -116,6 +126,14 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->usb3_lpm_capable) props[prop_idx++].name = "usb3-lpm-capable"; + /* pre dma_alloc */ + xhci_pre_alloc.pre_dma_alloc = dma_alloc_coherent(dwc->dev, SZ_2M, + &xhci_pre_alloc.dma, GFP_KERNEL); + if (!xhci_pre_alloc.pre_dma_alloc) { + dev_err(dwc->dev, "%s: dma_alloc fail!!!!\n", __func__); + goto err1; + } + /** * WORKAROUND: dwc3 revisions <=3.00a have a limitation * where Port Disable command doesn't work. diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3d169b4f37a4..3603f0d3bda0 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -25,10 +25,29 @@ #include #include #include +#include #include "xhci.h" +#include "xhci-plat.h" #include "xhci-trace.h" +static void *dma_pre_alloc_coherent(struct xhci_hcd *xhci, size_t size, + dma_addr_t *dma_handle, gfp_t gfp) +{ + struct usb_xhci_pre_alloc *xhci_alloc = xhci->xhci_alloc; + u64 align = size % PAGE_SIZE; + u64 b_offset = xhci_alloc->offset; + + if (align) + xhci_alloc->offset = xhci_alloc->offset + size + (PAGE_SIZE - align); + else + xhci_alloc->offset = xhci_alloc->offset + size; + + *dma_handle = xhci_alloc->dma + b_offset; + + return (void *)xhci_alloc->pre_dma_alloc + b_offset; +} + /* * Allocates a generic ring segment from the ring pool, sets the dma address, * initializes the segment to zero, and sets the private next pointer to NULL. @@ -540,13 +559,9 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) { - struct device *dev = xhci_to_hcd(xhci)->self.sysdev; size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; - if (size > MEDIUM_STREAM_ARRAY_SIZE) - dma_free_coherent(dev, size, - stream_ctx, dma); - else if (size <= SMALL_STREAM_ARRAY_SIZE) + if (size <= SMALL_STREAM_ARRAY_SIZE) return dma_pool_free(xhci->small_streams_pool, stream_ctx, dma); else @@ -568,11 +583,10 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, dma_addr_t *dma, gfp_t mem_flags) { - struct device *dev = xhci_to_hcd(xhci)->self.sysdev; size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; if (size > MEDIUM_STREAM_ARRAY_SIZE) - return dma_alloc_coherent(dev, size, + return dma_pre_alloc_coherent(xhci, size, dma, mem_flags); else if (size <= SMALL_STREAM_ARRAY_SIZE) return dma_pool_alloc(xhci->small_streams_pool, @@ -1660,7 +1674,6 @@ void xhci_slot_copy(struct xhci_hcd *xhci, static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) { int i; - struct device *dev = xhci_to_hcd(xhci)->self.sysdev; int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); xhci_dbg_trace(xhci, trace_xhci_dbg_init, @@ -1673,7 +1686,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) if (!xhci->scratchpad) goto fail_sp; - xhci->scratchpad->sp_array = dma_alloc_coherent(dev, + xhci->scratchpad->sp_array = dma_pre_alloc_coherent(xhci, num_sp * sizeof(u64), &xhci->scratchpad->sp_dma, flags); if (!xhci->scratchpad->sp_array) @@ -1681,13 +1694,13 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags); if (!xhci->scratchpad->sp_buffers) - goto fail_sp3; + goto fail_sp2; xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); for (i = 0; i < num_sp; i++) { dma_addr_t dma; - void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma, - flags); + void *buf = dma_pre_alloc_coherent(xhci, xhci->page_size, &dma, + flags | __GFP_ZERO); if (!buf) goto fail_sp4; @@ -1698,19 +1711,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) return 0; fail_sp4: - for (i = i - 1; i >= 0; i--) { - dma_free_coherent(dev, xhci->page_size, - xhci->scratchpad->sp_buffers[i], - xhci->scratchpad->sp_array[i]); - } - kfree(xhci->scratchpad->sp_buffers); - fail_sp3: - dma_free_coherent(dev, num_sp * sizeof(u64), - xhci->scratchpad->sp_array, - xhci->scratchpad->sp_dma); - fail_sp2: kfree(xhci->scratchpad); xhci->scratchpad = NULL; @@ -1722,23 +1724,14 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) static void scratchpad_free(struct xhci_hcd *xhci) { int num_sp; - int i; - struct device *dev = xhci_to_hcd(xhci)->self.sysdev; if (!xhci->scratchpad) return; num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); - for (i = 0; i < num_sp; i++) { - dma_free_coherent(dev, xhci->page_size, - xhci->scratchpad->sp_buffers[i], - xhci->scratchpad->sp_array[i]); - } kfree(xhci->scratchpad->sp_buffers); - dma_free_coherent(dev, num_sp * sizeof(u64), - xhci->scratchpad->sp_array, - xhci->scratchpad->sp_dma); + kfree(xhci->scratchpad); xhci->scratchpad = NULL; } @@ -1795,17 +1788,10 @@ void xhci_free_command(struct xhci_hcd *xhci, void xhci_mem_cleanup(struct xhci_hcd *xhci) { - struct device *dev = xhci_to_hcd(xhci)->self.sysdev; - int size; int i, j, num_ports; cancel_delayed_work_sync(&xhci->cmd_timer); - /* Free the Event Ring Segment Table and the actual Event Ring */ - size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); - if (xhci->erst.entries) - dma_free_coherent(dev, size, - xhci->erst.entries, xhci->erst.erst_dma_addr); xhci->erst.entries = NULL; xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed ERST"); if (xhci->event_ring) @@ -1814,14 +1800,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed event ring"); #ifdef CONFIG_SND_EXYNOS_USB_AUDIO - if (xhci->save_addr) - dma_free_coherent(dev, sizeof(PAGE_SIZE), xhci->save_addr, xhci->save_dma); - xhci_info(xhci, "%s: Freed save-restore buffer for Audio offloading", __func__); - - size = sizeof(struct xhci_erst_entry)*(xhci->erst_audio.num_entries); - if (xhci->erst_audio.entries) - dma_free_coherent(dev, size, - xhci->erst_audio.entries, xhci->erst_audio.erst_dma_addr); xhci->erst_audio.entries = NULL; xhci_info(xhci, "%s: Freed ERST for Audio offloading", __func__); @@ -1871,11 +1849,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed medium stream array pool"); - if (xhci->dcbaa) - dma_free_coherent(dev, sizeof(*xhci->dcbaa), - xhci->dcbaa, xhci->dcbaa->dma); xhci->dcbaa = NULL; + /* init offset about pre alloc CMA */ + xhci->xhci_alloc->offset = 0; + scratchpad_free(xhci); if (!xhci->rh_bw) @@ -2447,7 +2425,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * xHCI section 5.4.6 - doorbell array must be * "physically contiguous and 64-byte (cache line) aligned". */ - xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, + xhci->dcbaa = dma_pre_alloc_coherent(xhci, sizeof(*xhci->dcbaa), &dma, flags); if (!xhci->dcbaa) goto fail; @@ -2544,7 +2522,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (xhci_check_trb_in_td_math(xhci) < 0) goto fail; - xhci->erst.entries = dma_alloc_coherent(dev, + xhci->erst.entries = dma_pre_alloc_coherent(xhci, sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma, flags); if (!xhci->erst.entries) @@ -2598,7 +2576,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci_print_ir_set(xhci, 0); #ifdef CONFIG_SND_EXYNOS_USB_AUDIO - xhci->save_addr = dma_alloc_coherent(dev, sizeof(PAGE_SIZE), &dma, + xhci->save_addr = dma_pre_alloc_coherent(xhci, sizeof(PAGE_SIZE), &dma, flags); xhci->save_dma = dma; xhci_info(xhci, "// Save address = 0x%llx (DMA), %p (virt)", @@ -2611,7 +2589,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (xhci_check_trb_in_td_math(xhci) < 0) goto fail; - xhci->erst_audio.entries = dma_alloc_coherent(dev, + xhci->erst_audio.entries = dma_pre_alloc_coherent(xhci, sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma, flags); if (!xhci->erst_audio.entries) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 90fdbc237e6c..2469d9561e4b 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -437,6 +437,8 @@ static int xhci_plat_probe(struct platform_device *pdev) "can't get xhci l2 support, error = %d\n", ret); } + xhci->xhci_alloc = &xhci_pre_alloc; + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_usb_phy; @@ -540,6 +542,7 @@ static int xhci_plat_remove(struct platform_device *dev) pm_runtime_get_sync(&dev->dev); xhci->xhc_state |= XHCI_STATE_REMOVING; + xhci->xhci_alloc->offset = 0; dev_info(&dev->dev, "WAKE UNLOCK\n"); wake_unlock(xhci->wakelock); diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 29b227895b07..33951d621397 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h @@ -21,4 +21,14 @@ struct xhci_plat_priv { }; #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) + +struct usb_xhci_pre_alloc { + u8 *pre_dma_alloc; + u64 offset; + + dma_addr_t dma; +}; + +extern struct usb_xhci_pre_alloc xhci_pre_alloc; +extern void __iomem *phycon_base_addr; #endif /* _XHCI_PLAT_H */ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index eaa3547b7ee0..a86e59374e9a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1903,6 +1903,8 @@ struct xhci_hcd { /* Compliance Mode Timer Triggered every 2 seconds */ #define COMP_MODE_RCVRY_MSECS 2000 + struct usb_xhci_pre_alloc *xhci_alloc; + /* platform-specific data -- must come last */ unsigned long priv[0] __aligned(sizeof(s64)); }; -- 2.20.1