[RAMEN9610-11637][COMMON] usb: host: allocate dma memory in booting time
authortaehyun.cho <taehyun.cho@samsung.com>
Wed, 31 Oct 2018 08:15:22 +0000 (17:15 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:14 +0000 (20:23 +0300)
Change-Id: If6dd884c7a8bedbddf81a97dcb48a94e18c634f8
Signed-off-by: taehyun.cho <taehyun.cho@samsung.com>
drivers/usb/dwc3/host.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-plat.h
drivers/usb/host/xhci.h

index 903d0962d1b2be450e7bd320435f3021a9975f0f..6efc1ec491f89f06cf9c58301b228f54cf2369a4 100644 (file)
 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.
index 3d169b4f37a4958c2e72526b2df2358eaf67db3e..3603f0d3bda062ecc378125d58f1f088bdcb83ec 100644 (file)
 #include <linux/slab.h>
 #include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
+#include <linux/types.h>
 
 #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)
index 90fdbc237e6cd8bb23b45f999488ed2131fa617f..2469d9561e4bb5b3e9cfacbb53ffffd35d73d6e2 100644 (file)
@@ -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);
index 29b227895b0732352765afa042819b4d0ae9c864..33951d6213972726cbe717f4f7526e8fd4d858a3 100644 (file)
@@ -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 */
index eaa3547b7ee0d189f8eb6e9c4f8aeed177fc0099..a86e59374e9a56b80f0b07f8a6eca234d2a2001e 100644 (file)
@@ -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));
 };