mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Early DMA Allocator patch.
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
diff -urpN a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
|
||||
--- a/arch/x86/kernel/setup.c 2016-11-20 01:17:41.000000000 +0000
|
||||
+++ b/arch/x86/kernel/setup.c 2017-01-04 23:10:26.473086206 +0000
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <asm/pci-direct.h>
|
||||
#include <linux/init_ohci1394_dma.h>
|
||||
#include <linux/kvm_para.h>
|
||||
+#include <linux/early_dma_alloc.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
|
||||
#include <linux/errno.h>
|
||||
@@ -1243,6 +1244,10 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
arch_init_ideal_nops();
|
||||
|
||||
+#ifdef CONFIG_EARLY_DMA_ALLOC
|
||||
+ eda_init();
|
||||
+#endif
|
||||
+
|
||||
register_refined_jiffies(CLOCK_TICK_RATE);
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
diff -urpN a/drivers/misc/Kconfig b/drivers/misc/Kconfig
|
||||
--- a/drivers/misc/Kconfig 2016-11-20 01:17:41.000000000 +0000
|
||||
+++ b/drivers/misc/Kconfig 2017-01-04 23:11:14.305087244 +0000
|
||||
@@ -496,6 +496,34 @@ config USB_SWITCH_FSA9480
|
||||
stereo and mono audio, video, microphone and UART data to use
|
||||
a common connector port.
|
||||
|
||||
+config EARLY_DMA_ALLOC
|
||||
+ bool "Early DMA Memory Allocator"
|
||||
+ depends on HAS_DMA
|
||||
+
|
||||
+ ---help---
|
||||
+ This driver locks down a region of DMA accessible memory
|
||||
+ early in the boot process. This memory can be used by other
|
||||
+ drivers that might rmmod/insmod, insuring the memory region
|
||||
+ does not become fragmented.
|
||||
+
|
||||
+config EDA_DEF_SIZE
|
||||
+ hex "EDA Default Region Size"
|
||||
+ depends on EARLY_DMA_ALLOC
|
||||
+ default 0x04000000
|
||||
+ help
|
||||
+ Default size of the reserved memory pool, if not altered by the
|
||||
+ open firmware interface or kernel boot parameter. This memory
|
||||
+ will not be accessable to the rest of the system. Default is
|
||||
+ 64MB.
|
||||
+
|
||||
+config EDA_DEF_ALIGN
|
||||
+ hex "EDA Default Alignment"
|
||||
+ depends on EARLY_DMA_ALLOC
|
||||
+ default 0x00100000
|
||||
+ help
|
||||
+ Default alignment of the memory region. Default is 1MB.
|
||||
+
|
||||
+
|
||||
config LATTICE_ECP3_CONFIG
|
||||
tristate "Lattice ECP3 FPGA bitstream configuration via SPI"
|
||||
depends on SPI && SYSFS
|
||||
diff -urpN a/drivers/misc/Makefile b/drivers/misc/Makefile
|
||||
--- a/drivers/misc/Makefile 2016-11-20 01:17:41.000000000 +0000
|
||||
+++ b/drivers/misc/Makefile 2017-01-04 23:12:15.781088578 +0000
|
||||
@@ -56,3 +56,4 @@ obj-y += mic/
|
||||
obj-$(CONFIG_GENWQE) += genwqe/
|
||||
obj-$(CONFIG_ECHO) += echo/
|
||||
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
|
||||
+obj-$(CONFIG_EARLY_DMA_ALLOC) += early_dma_alloc.o
|
||||
diff -urpN a/drivers/misc/early_dma_alloc.c b/drivers/misc/early_dma_alloc.c
|
||||
--- a/drivers/misc/early_dma_alloc.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/misc/early_dma_alloc.c 2017-01-04 23:13:09.209089737 +0000
|
||||
@@ -0,0 +1,223 @@
|
||||
+/*
|
||||
+ * Early DMA Memory Allocator
|
||||
+ *
|
||||
+ * Copyright © 2013,2014 Cumulus Networks, Inc.
|
||||
+ *
|
||||
+ * Author: Curt Brune <curt@cumulusnetworks.com>
|
||||
+ * Modified: Jonathan Toppins <jtoppins@cumulusnetworks.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * This driver allocates a region of DMA accessible memory, making it
|
||||
+ * available to one other device driver.
|
||||
+ *
|
||||
+ * The client device driver may be unloaded and reloaded over time.
|
||||
+ * This driver keeps the DMA region from becoming fragmented across
|
||||
+ * module reloads.
|
||||
+ *
|
||||
+ * Memory Region Restrictions
|
||||
+ * --------------------------
|
||||
+ * The memory region allocated by EDA MUST exist below a 4GB limit. This
|
||||
+ * is because EDA's primary (only at time of writing) user is the
|
||||
+ * Broadcom BDE driver wich assumes a 32-bit physical address space and
|
||||
+ * assumes paddr is no more than 32-bits wide. Furthermore, before porting
|
||||
+ * the BDE driver to use EDA the BDE driver specifically checked if the
|
||||
+ * memory region provided by highmem was less than 4GB. We assume Broadcom
|
||||
+ * knew what they were doing and there is a specific reason why this 4GB
|
||||
+ * limit is needed, so we enforce this limit by checking the physical address
|
||||
+ * after allocation.
|
||||
+ *
|
||||
+ * Memory Region Size and Alignment
|
||||
+ * --------------------------------
|
||||
+ * This driver allows three ways for the user to define the DMA memory
|
||||
+ * that will be created, listed in order of preference.
|
||||
+ * 1. The user may specify on the kernel command line in the boot loader
|
||||
+ * the "eda_mem" option, this option has the format "size@alignment",
|
||||
+ * example: eda_mem=0x04000000@0x00100000
|
||||
+ * 2. This driver looks for a device tree node compatible with
|
||||
+ * "early-dma-alloc". The "region_size" property of the node contains
|
||||
+ * the size, in bytes, of the desired DMA memory region. The
|
||||
+ * "alignment" property contains the desired memory alignment of the
|
||||
+ * region.
|
||||
+ * 3. Finally if neither of the above are provided the Kbuild changable,
|
||||
+ * compiled in default size and alignment will be used.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/unistd.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/bootmem.h>
|
||||
+#include <linux/early_dma_alloc.h>
|
||||
+
|
||||
+#if (!defined CONFIG_EDA_DEF_SIZE) || \
|
||||
+ (!defined CONFIG_EDA_DEF_ALIGN)
|
||||
+#error incorrect kernel config - fix it
|
||||
+#endif
|
||||
+
|
||||
+// #define DEBUG
|
||||
+#if (defined DEBUG)
|
||||
+#define eda_debug(fmt, ... ) \
|
||||
+ printk(KERN_ERR "eda-debug:%s(): " fmt "\n", __func__ , \
|
||||
+ ##__VA_ARGS__)
|
||||
+#else
|
||||
+#define eda_debug(fmt, ... )
|
||||
+#endif
|
||||
+
|
||||
+#define eda_info(fmt, ... ) \
|
||||
+ printk(KERN_INFO "eda: " fmt "\n", ##__VA_ARGS__)
|
||||
+
|
||||
+static uint32_t dma_size;
|
||||
+static void *dma_vaddr;
|
||||
+static u32 dma_align __initdata;
|
||||
+static bool eda_cmdline __initdata;
|
||||
+
|
||||
+static int __init setup_eda_mem(char *str)
|
||||
+{
|
||||
+ char *endp;
|
||||
+
|
||||
+ dma_size = memparse(str, &endp) & PAGE_MASK;
|
||||
+ if (*endp == '@')
|
||||
+ dma_align = memparse(endp + 1, NULL) & PAGE_MASK;
|
||||
+ eda_cmdline = true;
|
||||
+ return 0;
|
||||
+}
|
||||
+early_param("eda_mem", setup_eda_mem);
|
||||
+
|
||||
+static int __init of_eda_init(uint32_t *size, u32 *align)
|
||||
+#ifdef CONFIG_OF_FLATTREE
|
||||
+{
|
||||
+ int rc = -ENODEV;
|
||||
+ struct device_node *np = NULL;
|
||||
+ const u32 *region_sz_p = NULL;
|
||||
+ const u32 *align_p = NULL;
|
||||
+ u32 prop_sz = 0;
|
||||
+
|
||||
+ eda_debug("entry");
|
||||
+
|
||||
+ /* is a programming error make it really painful so it gets fixed */
|
||||
+ BUG_ON(NULL == size || NULL == align);
|
||||
+
|
||||
+ np = of_find_compatible_node(NULL, NULL, "early-dma-alloc");
|
||||
+ if (!np) {
|
||||
+ printk(KERN_WARNING "WARN: Can not find `early-dma-alloc'"
|
||||
+ " device tree node.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ region_sz_p = of_get_property(np, "region_size", &prop_sz);
|
||||
+ if (!region_sz_p || (prop_sz != sizeof(*region_sz_p))) {
|
||||
+ printk(KERN_ERR "ERROR: Can not find `region_size' property"
|
||||
+ " in early-dma-alloc device tree node.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ *size = *region_sz_p;
|
||||
+
|
||||
+ align_p = of_get_property(np, "alignment", &prop_sz);
|
||||
+ if (!align_p || (prop_sz != sizeof(*align_p))) {
|
||||
+ printk(KERN_ERR "ERROR: Can not find `alignment' property in"
|
||||
+ "early-dma-alloc device tree node.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ *align = *align_p;
|
||||
+ rc = 0;
|
||||
+
|
||||
+ eda_debug("cleanup");
|
||||
+
|
||||
+cleanup:
|
||||
+ of_node_put(np);
|
||||
+ return rc;
|
||||
+
|
||||
+}
|
||||
+#else
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+int eda_dma_info_get(void **vaddr, uint32_t *paddr, uint32_t *size)
|
||||
+{
|
||||
+ eda_debug("entry");
|
||||
+
|
||||
+ if (!dma_vaddr)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (!vaddr || !paddr || !size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *vaddr = dma_vaddr;
|
||||
+ *paddr = (uint32_t) virt_to_phys(dma_vaddr);
|
||||
+ *size = dma_size;
|
||||
+
|
||||
+ eda_debug("returning -- dma_vaddr: 0x%pK, dma_paddr: 0x%08x,"
|
||||
+ " size: 0x%08x", *vaddr, *paddr, *size);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(eda_dma_info_get);
|
||||
+
|
||||
+int __init eda_init(void)
|
||||
+{
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ if (eda_cmdline) {
|
||||
+ if (!dma_align)
|
||||
+ dma_align = CONFIG_EDA_DEF_ALIGN;
|
||||
+ if (!dma_size)
|
||||
+ dma_size = CONFIG_EDA_DEF_SIZE;
|
||||
+ eda_debug("size & alignment came from: kernel cmdline");
|
||||
+ } else if (!of_eda_init(&dma_size, &dma_align)) {
|
||||
+ eda_debug("size & alignment came from: open firmware entry");
|
||||
+ } else {
|
||||
+ dma_align = CONFIG_EDA_DEF_ALIGN;
|
||||
+ dma_size = CONFIG_EDA_DEF_SIZE;
|
||||
+ eda_debug("size & alignment came from: compiled in defaults");
|
||||
+ }
|
||||
+
|
||||
+ dma_vaddr = __alloc_bootmem_low(dma_size, dma_align, 0);
|
||||
+ /*
|
||||
+ * enforce EDA's requirement to allocate the memory region below a
|
||||
+ * 32-bit limit.
|
||||
+ */
|
||||
+ if (virt_to_phys(dma_vaddr) > 0xFFFFFFFFULL) {
|
||||
+ rc = -ENOMEM;
|
||||
+ printk(KERN_ERR "ERROR: DMA memory beyond 32-bit address"
|
||||
+ " space not supported.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ eda_info("dma_vaddr: 0x%pK, dma_paddr: 0x%016llx, size: 0x%08x,"
|
||||
+ " alignment: 0x%08x",
|
||||
+ dma_vaddr, (unsigned long long) virt_to_phys(dma_vaddr),
|
||||
+ dma_size, dma_align);
|
||||
+cleanup:
|
||||
+ if (rc && dma_vaddr) {
|
||||
+ free_bootmem(dma_vaddr, dma_size);
|
||||
+ }
|
||||
+ if (rc) {
|
||||
+ dma_vaddr = NULL;
|
||||
+ dma_size = 0;
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+EXPORT_SYMBOL(eda_init);
|
||||
diff -urpN a/include/linux/early_dma_alloc.h b/include/linux/early_dma_alloc.h
|
||||
--- a/include/linux/early_dma_alloc.h 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/include/linux/early_dma_alloc.h 2017-01-04 23:13:59.405090826 +0000
|
||||
@@ -0,0 +1,36 @@
|
||||
+/*
|
||||
+ * Early DMA Memory Allocator
|
||||
+ *
|
||||
+ * Copyright © 2013 Cumulus Networks, Inc.
|
||||
+ *
|
||||
+ * Author: Curt Brune <curt@cumulusnetworks.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef EARLY_DMA_ALLOC_H__
|
||||
+#define EARLY_DMA_ALLOC_H__
|
||||
+
|
||||
+#ifdef __KERNEL__
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+extern int eda_init(void);
|
||||
+extern int eda_dma_info_get(void** vaddr, uint32_t* paddr, uint32_t* size);
|
||||
+
|
||||
+#endif /* __KERNEL__ */
|
||||
+
|
||||
+#endif /* EARLY_DMA_ALLOC_H__ */
|
||||
@@ -16,3 +16,4 @@ driver-support-intel-igb-bcm5461X-phy.patch
|
||||
driver-i2c-bus-intel-ismt-enable-param.patch
|
||||
drivers-i2c-busses-i2c-isch-probe-param.patch
|
||||
drivers-i2c-muxes-pca954x-deselect-on-exit.patch
|
||||
driver-early-dma-allocator.patch
|
||||
|
||||
Reference in New Issue
Block a user