From 04ac7b666de39c05eef566cd80358c16ea8c69a0 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:47 +0100 Subject: drivers: of: add initialization code for static reserved memory This patch adds support for static (defined by 'reg' property) reserved memory regions declared in device tree. Memory blocks can be reliably reserved only during early boot. This must happen before the whole memory management subsystem is initialized, because we need to ensure that the given contiguous blocks are not yet allocated by kernel. Also it must happen before kernel mappings for the whole low memory are created, to ensure that there will be no mappings (for reserved blocks). Typically, all this happens before device tree structures are unflattened, so we need to get reserved memory layout directly from fdt. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely (cherry picked from commit e8d9d1f5485b52ec3c4d7af839e6914438f6c285) Signed-off-by: Mark Brown --- drivers/of/fdt.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 4 ++ 2 files changed, 135 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 758b4f8b30b7..819e11209718 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,118 @@ struct boot_param_header *initial_boot_params; #ifdef CONFIG_OF_EARLY_FLATTREE +/** + * res_mem_reserve_reg() - reserve all memory described in 'reg' property + */ +static int __init __reserved_mem_reserve_reg(unsigned long node, + const char *uname) +{ + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); + phys_addr_t base, size; + unsigned long len; + __be32 *prop; + int nomap; + + prop = of_get_flat_dt_prop(node, "reg", &len); + if (!prop) + return -ENOENT; + + if (len && len % t_len != 0) { + pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n", + uname); + return -EINVAL; + } + + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + + while (len >= t_len) { + base = dt_mem_next_cell(dt_root_addr_cells, &prop); + size = dt_mem_next_cell(dt_root_size_cells, &prop); + + if (base && size && + early_init_dt_reserve_memory_arch(base, size, nomap) == 0) + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + else + pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + + len -= t_len; + } + return 0; +} + +/** + * __reserved_mem_check_root() - check if #size-cells, #address-cells provided + * in /reserved-memory matches the values supported by the current implementation, + * also check if ranges property has been provided + */ +static int __reserved_mem_check_root(unsigned long node) +{ + __be32 *prop; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + if (!prop || be32_to_cpup(prop) != dt_root_size_cells) + return -EINVAL; + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + if (!prop || be32_to_cpup(prop) != dt_root_addr_cells) + return -EINVAL; + + prop = of_get_flat_dt_prop(node, "ranges", NULL); + if (!prop) + return -EINVAL; + return 0; +} + +/** + * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory + */ +static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, + int depth, void *data) +{ + static int found; + const char *status; + + if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { + if (__reserved_mem_check_root(node) != 0) { + pr_err("Reserved memory: unsupported node format, ignoring\n"); + /* break scan */ + return 1; + } + found = 1; + /* scan next node */ + return 0; + } else if (!found) { + /* scan next node */ + return 0; + } else if (found && depth < 2) { + /* scanning of /reserved-memory has been finished */ + return 1; + } + + status = of_get_flat_dt_prop(node, "status", NULL); + if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) + return 0; + + __reserved_mem_reserve_reg(node, uname); + + /* scan next node */ + return 0; +} + +/** + * early_init_fdt_scan_reserved_mem() - create reserved memory regions + * + * This function grabs memory from early allocator for device exclusive use + * defined in device tree structures. It should be called by arch specific code + * once the early allocator (i.e. memblock) has been fully activated. + */ +void __init early_init_fdt_scan_reserved_mem(void) +{ + of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); +} + /** * of_scan_flat_dt - scan flattened tree blob and call callback on each. * @it: callback function @@ -856,6 +969,16 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) memblock_add(base, size); } +int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + if (nomap) + return memblock_remove(base, size); + return memblock_reserve(base, size); +} + /* * called from unflatten_device_tree() to bootstrap devicetree itself * Architectures can override this definition if memblock isn't used @@ -864,6 +987,14 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) { return __va(memblock_alloc(size, align)); } +#else +int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", + base, size, nomap ? " (nomap)" : ""); + return -ENOSYS; +} #endif bool __init early_init_dt_scan(void *params) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 2b77058a7335..ddd7219af8ac 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -98,7 +98,10 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); +extern void early_init_fdt_scan_reserved_mem(void); extern void early_init_dt_add_memory_arch(u64 base, u64 size); +extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, + bool no_map); extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); extern u64 dt_mem_next_cell(int s, __be32 **cellp); @@ -118,6 +121,7 @@ extern void unflatten_and_copy_device_tree(void); extern void early_init_devtree(void *); extern void early_get_first_memblock_info(void *, phys_addr_t *); #else /* CONFIG_OF_FLATTREE */ +static inline void early_init_fdt_scan_reserved_mem(void) {} static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } static inline void unflatten_device_tree(void) {} static inline void unflatten_and_copy_device_tree(void) {} -- cgit v1.2.3 From e337f7e8b0fe7cec6a72fe6f5e3ac09c72b4152d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:48 +0100 Subject: drivers: of: add initialization code for dynamic reserved memory This patch adds support for dynamically allocated reserved memory regions declared in device tree. Such regions are defined by 'size', 'alignment' and 'alloc-ranges' properties. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely (cherry picked from commit 3f0c8206644836e4f10a6b9fc47cda6a9a372f9b) Signed-off-by: Mark Brown --- drivers/of/Kconfig | 6 ++ drivers/of/Makefile | 1 + drivers/of/fdt.c | 13 ++- drivers/of/of_reserved_mem.c | 188 ++++++++++++++++++++++++++++++++++++++++ include/linux/of_reserved_mem.h | 21 +++++ 5 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 drivers/of/of_reserved_mem.c create mode 100644 include/linux/of_reserved_mem.h diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c6973f101a3e..30a7d87a8077 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -75,4 +75,10 @@ config OF_MTD depends on MTD def_bool y +config OF_RESERVED_MEM + depends on OF_EARLY_FLATTREE + bool + help + Helpers to allow for reservation of memory regions + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index efd05102c405..ed9660adad77 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_MTD) += of_mtd.o +obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 819e11209718..510c0d8de8a0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -450,7 +451,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, phys_addr_t base, size; unsigned long len; __be32 *prop; - int nomap; + int nomap, first = 1; prop = of_get_flat_dt_prop(node, "reg", &len); if (!prop) @@ -477,6 +478,10 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, uname, &base, (unsigned long)size / SZ_1M); len -= t_len; + if (first) { + fdt_reserved_mem_save_node(node, uname, base, size); + first = 0; + } } return 0; } @@ -512,6 +517,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, { static int found; const char *status; + int err; if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { if (__reserved_mem_check_root(node) != 0) { @@ -534,7 +540,9 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) return 0; - __reserved_mem_reserve_reg(node, uname); + err = __reserved_mem_reserve_reg(node, uname); + if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL)) + fdt_reserved_mem_save_node(node, uname, 0, 0); /* scan next node */ return 0; @@ -550,6 +558,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, void __init early_init_fdt_scan_reserved_mem(void) { of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); + fdt_init_reserved_mem(); } /** diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c new file mode 100644 index 000000000000..69b811779585 --- /dev/null +++ b/drivers/of/of_reserved_mem.c @@ -0,0 +1,188 @@ +/* + * Device tree based initialization code for reserved memory. + * + * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. + * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + * Author: Josh Cartwright + * + * 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 optional) any later version of the license. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_RESERVED_REGIONS 16 +static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; +static int reserved_mem_count; + +#if defined(CONFIG_HAVE_MEMBLOCK) +#include +int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, + phys_addr_t *res_base) +{ + /* + * We use __memblock_alloc_base() because memblock_alloc_base() + * panic()s on allocation failure. + */ + phys_addr_t base = __memblock_alloc_base(size, align, end); + if (!base) + return -ENOMEM; + + /* + * Check if the allocated region fits in to start..end window + */ + if (base < start) { + memblock_free(base, size); + return -ENOMEM; + } + + *res_base = base; + if (nomap) + return memblock_remove(base, size); + return 0; +} +#else +int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, + phys_addr_t *res_base) +{ + pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", + size, nomap ? " (nomap)" : ""); + return -ENOSYS; +} +#endif + +/** + * res_mem_save_node() - save fdt node for second pass initialization + */ +void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, + phys_addr_t base, phys_addr_t size) +{ + struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; + + if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { + pr_err("Reserved memory: not enough space all defined regions.\n"); + return; + } + + rmem->fdt_node = node; + rmem->name = uname; + rmem->base = base; + rmem->size = size; + + reserved_mem_count++; + return; +} + +/** + * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' + * and 'alloc-ranges' properties + */ +static int __init __reserved_mem_alloc_size(unsigned long node, + const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) +{ + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); + phys_addr_t start = 0, end = 0; + phys_addr_t base = 0, align = 0, size; + unsigned long len; + __be32 *prop; + int nomap; + int ret; + + prop = of_get_flat_dt_prop(node, "size", &len); + if (!prop) + return -EINVAL; + + if (len != dt_root_size_cells * sizeof(__be32)) { + pr_err("Reserved memory: invalid size property in '%s' node.\n", + uname); + return -EINVAL; + } + size = dt_mem_next_cell(dt_root_size_cells, &prop); + + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + + prop = of_get_flat_dt_prop(node, "alignment", &len); + if (prop) { + if (len != dt_root_addr_cells * sizeof(__be32)) { + pr_err("Reserved memory: invalid alignment property in '%s' node.\n", + uname); + return -EINVAL; + } + align = dt_mem_next_cell(dt_root_addr_cells, &prop); + } + + prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); + if (prop) { + + if (len % t_len != 0) { + pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", + uname); + return -EINVAL; + } + + base = 0; + + while (len > 0) { + start = dt_mem_next_cell(dt_root_addr_cells, &prop); + end = start + dt_mem_next_cell(dt_root_size_cells, + &prop); + + ret = early_init_dt_alloc_reserved_memory_arch(size, + align, start, end, nomap, &base); + if (ret == 0) { + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + uname, &base, + (unsigned long)size / SZ_1M); + break; + } + len -= t_len; + } + + } else { + ret = early_init_dt_alloc_reserved_memory_arch(size, align, + 0, 0, nomap, &base); + if (ret == 0) + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + } + + if (base == 0) { + pr_info("Reserved memory: failed to allocate memory for node '%s'\n", + uname); + return -ENOMEM; + } + + *res_base = base; + *res_size = size; + + return 0; +} + +/** + * fdt_init_reserved_mem - allocate and init all saved reserved memory regions + */ +void __init fdt_init_reserved_mem(void) +{ + int i; + for (i = 0; i < reserved_mem_count; i++) { + struct reserved_mem *rmem = &reserved_mem[i]; + unsigned long node = rmem->fdt_node; + int err = 0; + + if (rmem->size == 0) + err = __reserved_mem_alloc_size(node, rmem->name, + &rmem->base, &rmem->size); + } +} diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h new file mode 100644 index 000000000000..89226ed7d954 --- /dev/null +++ b/include/linux/of_reserved_mem.h @@ -0,0 +1,21 @@ +#ifndef __OF_RESERVED_MEM_H +#define __OF_RESERVED_MEM_H + +struct reserved_mem { + const char *name; + unsigned long fdt_node; + phys_addr_t base; + phys_addr_t size; +}; + +#ifdef CONFIG_OF_RESERVED_MEM +void fdt_init_reserved_mem(void); +void fdt_reserved_mem_save_node(unsigned long node, const char *uname, + phys_addr_t base, phys_addr_t size); +#else +static inline void fdt_init_reserved_mem(void) { } +static inline void fdt_reserved_mem_save_node(unsigned long node, + const char *uname, phys_addr_t base, phys_addr_t size) { } +#endif + +#endif /* __OF_RESERVED_MEM_H */ -- cgit v1.2.3 From 61c2521e81afc2c2286f633e6130d0ffa2b93684 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:49 +0100 Subject: drivers: of: add support for custom reserved memory drivers Add support for custom reserved memory drivers. Call their init() function for each reserved region and prepare for using operations provided by them with by the reserved_mem->ops array. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely (cherry picked from commit f618c4703a14672d27bc2ca5d132a844363d6f5f) Signed-off-by: Mark Brown --- drivers/of/of_reserved_mem.c | 29 +++++++++++++++++++++++++++++ include/asm-generic/vmlinux.lds.h | 11 +++++++++++ include/linux/of_reserved_mem.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 69b811779585..daaaf935911d 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -170,6 +170,33 @@ static int __init __reserved_mem_alloc_size(unsigned long node, return 0; } +static const struct of_device_id __rmem_of_table_sentinel + __used __section(__reservedmem_of_table_end); + +/** + * res_mem_init_node() - call region specific reserved memory init code + */ +static int __init __reserved_mem_init_node(struct reserved_mem *rmem) +{ + extern const struct of_device_id __reservedmem_of_table[]; + const struct of_device_id *i; + + for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { + reservedmem_of_init_fn initfn = i->data; + const char *compat = i->compatible; + + if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) + continue; + + if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { + pr_info("Reserved memory: initialized node %s, compatible id %s\n", + rmem->name, compat); + return 0; + } + } + return -ENOENT; +} + /** * fdt_init_reserved_mem - allocate and init all saved reserved memory regions */ @@ -184,5 +211,7 @@ void __init fdt_init_reserved_mem(void) if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); + if (err == 0) + __reserved_mem_init_node(rmem); } } diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bc2121fa9132..f10f64fcc815 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,16 @@ #define CLK_OF_TABLES() #endif +#ifdef CONFIG_OF_RESERVED_MEM +#define RESERVEDMEM_OF_TABLES() \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__reservedmem_of_table) = .; \ + *(__reservedmem_of_table) \ + *(__reservedmem_of_table_end) +#else +#define RESERVEDMEM_OF_TABLES() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -490,6 +500,7 @@ TRACE_SYSCALLS() \ MEM_DISCARD(init.rodata) \ CLK_OF_TABLES() \ + RESERVEDMEM_OF_TABLES() \ CLKSRC_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h index 89226ed7d954..9b1fbb7f29fc 100644 --- a/include/linux/of_reserved_mem.h +++ b/include/linux/of_reserved_mem.h @@ -1,21 +1,53 @@ #ifndef __OF_RESERVED_MEM_H #define __OF_RESERVED_MEM_H +struct device; +struct of_phandle_args; +struct reserved_mem_ops; + struct reserved_mem { const char *name; unsigned long fdt_node; + const struct reserved_mem_ops *ops; phys_addr_t base; phys_addr_t size; + void *priv; +}; + +struct reserved_mem_ops { + void (*device_init)(struct reserved_mem *rmem, + struct device *dev); + void (*device_release)(struct reserved_mem *rmem, + struct device *dev); }; +typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, + unsigned long node, const char *uname); + #ifdef CONFIG_OF_RESERVED_MEM void fdt_init_reserved_mem(void); void fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size); + +#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ + static const struct of_device_id __reservedmem_of_table_##name \ + __used __section(__reservedmem_of_table) \ + = { .compatible = compat, \ + .data = (init == (reservedmem_of_init_fn)NULL) ? \ + init : init } + #else static inline void fdt_init_reserved_mem(void) { } static inline void fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size) { } + +#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ + static const struct of_device_id __reservedmem_of_table_##name \ + __attribute__((unused)) \ + = { .compatible = compat, \ + .data = (init == (reservedmem_of_init_fn)NULL) ? \ + init : init } + #endif #endif /* __OF_RESERVED_MEM_H */ -- cgit v1.2.3 From 878ad60e55f492f196938a981c014d10a0258be5 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Thu, 13 Mar 2014 16:36:36 -0500 Subject: of: only scan for reserved mem when fdt present When the reserved memory patches hit -next, several legacy (non-DT) boot failures were detected and bisected down to that commit. There needs to be some sanity checking whether a DT is even present before parsing the reserved ranges. Reported-by: Kevin Hilman Signed-off-by: Josh Cartwright Tested-by: Kevin Hilman Signed-off-by: Grant Likely (cherry picked from commit 2040b52768ebab6e7bd73af0dc63703269c62f17) Signed-off-by: Mark Brown --- drivers/of/fdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 510c0d8de8a0..501bc83f8cdf 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -557,6 +557,9 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, */ void __init early_init_fdt_scan_reserved_mem(void) { + if (!initial_boot_params) + return; + of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); fdt_init_reserved_mem(); } -- cgit v1.2.3 From e81c5fcf26784ca99edc9c99a8e435f9cdf82378 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 8 Apr 2014 13:48:07 +0800 Subject: of: Fix the section mismatch warnings. In tag next-20140407, building with CONFIG_DEBUG_SECTION_MISMATCH enabled, the following WARNING is occured: WARNING: drivers/built-in.o(.text.unlikely+0x2220): Section mismatch in reference from the function __reserved_mem_check_root() to the function .init.text:of_get_flat_dt_prop() The function __reserved_mem_check_root() references the function __init of_get_flat_dt_prop(). This is often because __reserved_mem_check_root lacks a __init annotation or the annotation of of_get_flat_dt_prop is wrong. WARNING: vmlinux.o(.text.unlikely+0xb9d0): Section mismatch in reference from the function __reserved_mem_check_root() to the (unknown reference) .init.data:(unknown) The function __reserved_mem_check_root() references the (unknown reference) __initdata (unknown). This is often because __reserved_mem_check_root lacks a __initdata annotation or the annotation of (unknown) is wrong. This is cause by : 'drivers: of: add initialization code for dynamic reserved memory'. Signed-off-by: Xiubo Li Signed-off-by: Rob Herring (cherry picked from commit 5b6241185e2cded07ca3f5f646b55c641928ba4e) Signed-off-by: Mark Brown --- drivers/of/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 501bc83f8cdf..9184602f1aa1 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, * in /reserved-memory matches the values supported by the current implementation, * also check if ranges property has been provided */ -static int __reserved_mem_check_root(unsigned long node) +static int __init __reserved_mem_check_root(unsigned long node) { __be32 *prop; -- cgit v1.2.3 From d90d1980c1ae2c5df3824d9f6d8c7d01eedec34b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 29 Mar 2014 14:14:17 -0500 Subject: of/fdt: remove unused of_scan_flat_dt_by_path of_scan_flat_dt_by_path is unused anywhere in the kernel, so remove it. Signed-off-by: Rob Herring Tested-by: Michal Simek Tested-by: Grant Likely Tested-by: Stephen Chivers (cherry picked from commit bba04d965d06abbbe10afd3687742389107e198e) Signed-off-by: Mark Brown --- drivers/of/fdt.c | 67 -------------------------------------------------- include/linux/of_fdt.h | 3 --- 2 files changed, 70 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9184602f1aa1..359b5b71f294 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -676,73 +676,6 @@ struct fdt_scan_status { void *data; }; -/** - * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function - */ -static int __init fdt_scan_node_by_path(unsigned long node, const char *uname, - int depth, void *data) -{ - struct fdt_scan_status *st = data; - - /* - * if scan at the requested fdt node has been completed, - * return -ENXIO to abort further scanning - */ - if (depth <= st->depth) - return -ENXIO; - - /* requested fdt node has been found, so call iterator function */ - if (st->found) - return st->iterator(node, uname, depth, st->data); - - /* check if scanning automata is entering next level of fdt nodes */ - if (depth == st->depth + 1 && - strncmp(st->name, uname, st->namelen) == 0 && - uname[st->namelen] == 0) { - st->depth += 1; - if (st->name[st->namelen] == 0) { - st->found = 1; - } else { - const char *next = st->name + st->namelen + 1; - st->name = next; - st->namelen = strcspn(next, "/"); - } - return 0; - } - - /* scan next fdt node */ - return 0; -} - -/** - * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each - * child of the given path. - * @path: path to start searching for children - * @it: callback function - * @data: context data pointer - * - * This function is used to scan the flattened device-tree starting from the - * node given by path. It is used to extract information (like reserved - * memory), which is required on ealy boot before we can unflatten the tree. - */ -int __init of_scan_flat_dt_by_path(const char *path, - int (*it)(unsigned long node, const char *name, int depth, void *data), - void *data) -{ - struct fdt_scan_status st = {path, 0, -1, 0, it, data}; - int ret = 0; - - if (initial_boot_params) - ret = of_scan_flat_dt(fdt_scan_node_by_path, &st); - - if (!st.found) - return -ENOENT; - else if (ret == -ENXIO) /* scan has been completed */ - return 0; - else - return ret; -} - const char * __init of_flat_dt_get_machine_name(void) { const char *name; diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index ddd7219af8ac..89c5a7211e13 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -90,9 +90,6 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name, extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern int of_flat_dt_match(unsigned long node, const char *const *matches); extern unsigned long of_get_flat_dt_root(void); -extern int of_scan_flat_dt_by_path(const char *path, - int (*it)(unsigned long node, const char *name, int depth, void *data), - void *data); extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); -- cgit v1.2.3 From 11d5af3ce42bb4dd36cc6a5bb2764c6a66ff2212 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 1 Apr 2014 23:49:03 -0500 Subject: of/fdt: update of_get_flat_dt_prop in prep for libfdt Make of_get_flat_dt_prop arguments compatible with libfdt fdt_getprop call in preparation to convert FDT code to use libfdt. Make the return value const and the property length ptr type an int. Signed-off-by: Rob Herring Tested-by: Michal Simek Tested-by: Grant Likely Tested-by: Stephen Chivers (cherry picked from commit 9d0c4dfedd96ee54fc075b16d02f82499c8cc3a6) Signed-off-by: Mark Brown Conflicts: arch/arm/plat-samsung/s5p-dev-mfc.c arch/powerpc/platforms/powernv/opal.c --- arch/arc/kernel/devtree.c | 2 +- arch/arm/kernel/devtree.c | 2 +- arch/arm/mach-exynos/common.c | 2 +- arch/arm/mach-vexpress/platsmp.c | 2 +- arch/arm/plat-samsung/s5p-dev-mfc.c | 16 ++++---- arch/microblaze/kernel/prom.c | 8 ++-- arch/powerpc/kernel/epapr_paravirt.c | 2 +- arch/powerpc/kernel/fadump.c | 4 +- arch/powerpc/kernel/prom.c | 24 ++++++------ arch/powerpc/kernel/rtas.c | 2 +- arch/powerpc/mm/hash_utils_64.c | 22 +++++------ arch/powerpc/platforms/52xx/efika.c | 4 +- arch/powerpc/platforms/chrp/setup.c | 4 +- arch/powerpc/platforms/powernv/opal.c | 72 +++++++++++++++++++++++++++++++--- arch/powerpc/platforms/pseries/setup.c | 4 +- arch/xtensa/kernel/setup.c | 2 +- drivers/of/fdt.c | 39 +++++++++--------- drivers/of/of_reserved_mem.c | 4 +- include/linux/of_fdt.h | 8 ++-- 19 files changed, 144 insertions(+), 79 deletions(-) diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index b6dc4e21fd32..0b3ef4025d89 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -42,7 +42,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) const struct machine_desc *mdesc; unsigned long dt_root; void *clk; - unsigned long len; + int len; if (!early_init_dt_scan(dt)) return NULL; diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index f751714d52c1..97707977144c 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -212,7 +212,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) if (!mdesc) { const char *prop; - long size; + int size; unsigned long dt_root; early_print("\nError: unrecognized/unsupported " diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index f18be40e5b21..1bf303f8dfe3 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -322,7 +322,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, { struct map_desc iodesc; __be32 *reg; - unsigned long len; + int len; if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 993c9ae5dc5e..b4a5f0d8390d 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -53,7 +53,7 @@ static int __init vexpress_dt_find_scu(unsigned long node, { if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) { phys_addr_t phys_addr; - __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); + const __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); if (WARN_ON(!reg)) return -EINVAL; diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c index ad51f85fbd01..97ece99521ca 100644 --- a/arch/arm/plat-samsung/s5p-dev-mfc.c +++ b/arch/arm/plat-samsung/s5p-dev-mfc.c @@ -125,29 +125,29 @@ device_initcall(s5p_mfc_memory_init); int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, int depth, void *data) { - __be32 *prop; - unsigned long len; - struct s5p_mfc_dt_meminfo *mfc_mem = data; + const __be32 *prop; + int len; + struct s5p_mfc_dt_meminfo mfc_mem; if (!data) return 0; - if (!of_flat_dt_is_compatible(node, mfc_mem->compatible)) + if (!of_flat_dt_is_compatible(node, mfc_mem.compatible)) return 0; prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); if (!prop || (len != 2 * sizeof(unsigned long))) return 0; - mfc_mem->loff = be32_to_cpu(prop[0]); - mfc_mem->lsize = be32_to_cpu(prop[1]); + mfc_mem.loff = be32_to_cpu(prop[0]); + mfc_mem.lsize = be32_to_cpu(prop[1]); prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); if (!prop || (len != 2 * sizeof(unsigned long))) return 0; - mfc_mem->roff = be32_to_cpu(prop[0]); - mfc_mem->rsize = be32_to_cpu(prop[1]); + mfc_mem.roff = be32_to_cpu(prop[0]); + mfc_mem.rsize = be32_to_cpu(prop[1]); return 1; } diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index abdfb10e7eca..c76630603058 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -43,13 +43,13 @@ #include #ifdef CONFIG_EARLY_PRINTK -static char *stdout; +static const char *stdout; static int __init early_init_dt_scan_chosen_serial(unsigned long node, const char *uname, int depth, void *data) { - unsigned long l; - char *p; + int l; + const char *p; pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname); @@ -80,7 +80,7 @@ static int __init early_init_dt_scan_chosen_serial(unsigned long node, (strncmp(p, "xlnx,opb-uartlite", 17) == 0) || (strncmp(p, "xlnx,axi-uartlite", 17) == 0) || (strncmp(p, "xlnx,mdm", 8) == 0)) { - unsigned int *addrp; + const unsigned int *addrp; *(u32 *)data = UARTLITE; diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c index 7898be90f2dc..d64e92b22dd8 100644 --- a/arch/powerpc/kernel/epapr_paravirt.c +++ b/arch/powerpc/kernel/epapr_paravirt.c @@ -36,7 +36,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node, int depth, void *data) { const u32 *insts; - unsigned long len; + int len; int i; insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 2230fd0ca3e4..7213d930918d 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -55,9 +55,9 @@ int crash_mem_ranges; int __init early_init_dt_scan_fw_dump(unsigned long node, const char *uname, int depth, void *data) { - __be32 *sections; + const __be32 *sections; int i, num_sections; - unsigned long size; + int size; const int *token; if (depth != 1 || strcmp(uname, "rtas") != 0) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f58c0d3aaeb4..8dd5a093195b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -162,7 +162,7 @@ static struct ibm_pa_feature { {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, }; -static void __init scan_features(unsigned long node, unsigned char *ftrs, +static void __init scan_features(unsigned long node, const unsigned char *ftrs, unsigned long tablelen, struct ibm_pa_feature *fp, unsigned long ft_size) @@ -201,8 +201,8 @@ static void __init scan_features(unsigned long node, unsigned char *ftrs, static void __init check_cpu_pa_features(unsigned long node) { - unsigned char *pa_ftrs; - unsigned long tablelen; + const unsigned char *pa_ftrs; + int tablelen; pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); if (pa_ftrs == NULL) @@ -215,7 +215,7 @@ static void __init check_cpu_pa_features(unsigned long node) #ifdef CONFIG_PPC_STD_MMU_64 static void __init check_cpu_slb_size(unsigned long node) { - __be32 *slb_size_ptr; + const __be32 *slb_size_ptr; slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL); if (slb_size_ptr != NULL) { @@ -256,7 +256,7 @@ static struct feature_property { static inline void identical_pvr_fixup(unsigned long node) { unsigned int pvr; - char *model = of_get_flat_dt_prop(node, "model", NULL); + const char *model = of_get_flat_dt_prop(node, "model", NULL); /* * Since 440GR(x)/440EP(x) processors have the same pvr, @@ -294,11 +294,11 @@ static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); const __be32 *prop; const __be32 *intserv; int i, nthreads; - unsigned long len; + int len; int found = -1; int found_thread = 0; @@ -391,7 +391,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, int depth, void *data) { - unsigned long *lprop; /* All these set by kernel, so no need to convert endian */ + const unsigned long *lprop; /* All these set by kernel, so no need to convert endian */ /* Use common scan routine to determine if this is the chosen node */ if (early_init_dt_scan_chosen(node, uname, depth, data) == 0) @@ -442,8 +442,9 @@ int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, */ static int __init early_init_dt_scan_drconf_memory(unsigned long node) { - __be32 *dm, *ls, *usm; - unsigned long l, n, flags; + const __be32 *dm, *ls, *usm; + int l; + unsigned long n, flags; u64 base, size, memblock_size; unsigned int is_kexec_kdump = 0, rngs; @@ -563,7 +564,8 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) static void __init early_reserve_mem_dt(void) { - unsigned long i, len, dt_root; + unsigned long i, dt_root; + int len; const __be32 *prop; dt_root = of_get_flat_dt_root(); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4cf674d7d5ae..8c923bac430f 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1135,7 +1135,7 @@ void __init rtas_initialize(void) int __init early_init_dt_scan_rtas(unsigned long node, const char *uname, int depth, void *data) { - u32 *basep, *entryp, *sizep; + const u32 *basep, *entryp, *sizep; if (depth != 1 || strcmp(uname, "rtas") != 0) return 0; diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index d766d6ee33fe..59cc19a23a7a 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -265,9 +265,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *prop; - unsigned long size = 0; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const __be32 *prop; + int size = 0; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) @@ -320,9 +320,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *prop; - unsigned long size = 0; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const __be32 *prop; + int size = 0; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) @@ -402,9 +402,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, static int __init htab_dt_scan_hugepage_blocks(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be64 *addr_prop; - __be32 *page_count_prop; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const __be64 *addr_prop; + const __be32 *page_count_prop; unsigned int expected_pages; long unsigned int phys_addr; long unsigned int block_size; @@ -546,8 +546,8 @@ static int __init htab_dt_scan_pftsize(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *prop; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const __be32 *prop; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 18c104820198..6e19b0ad5d26 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -199,8 +199,8 @@ static void __init efika_setup_arch(void) static int __init efika_probe(void) { - char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), - "model", NULL); + const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), + "model", NULL); if (model == NULL) return 0; diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index c665d7de6c99..7044fd36197b 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -574,8 +574,8 @@ chrp_init2(void) static int __init chrp_probe(void) { - char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), - "device_type", NULL); + const char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); if (dtype == NULL) return 0; if (strcmp(dtype, "chrp")) diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 65499adaecff..3bf1eb433112 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -50,7 +50,7 @@ int __init early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data) { const void *basep, *entryp; - unsigned long basesz, entrysz; + int basesz, entrysz, runtimesz; if (depth != 1 || strcmp(uname, "ibm,opal") != 0) return 0; @@ -64,10 +64,10 @@ int __init early_init_dt_scan_opal(unsigned long node, opal.base = of_read_number(basep, basesz/4); opal.entry = of_read_number(entryp, entrysz/4); - pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n", + pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n", opal.base, basep, basesz); - pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n", - opal.entry, entryp, entrysz); + pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n", + opal.size, sizep, runtimesz); powerpc_firmware_features |= FW_FEATURE_OPAL; if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { @@ -84,6 +84,68 @@ int __init early_init_dt_scan_opal(unsigned long node, return 1; } +<<<<<<< HEAD +======= +int __init early_init_dt_scan_recoverable_ranges(unsigned long node, + const char *uname, int depth, void *data) +{ + int i, psize, size; + const __be32 *prop; + + if (depth != 1 || strcmp(uname, "ibm,opal") != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize); + + if (!prop) + return 1; + + pr_debug("Found machine check recoverable ranges.\n"); + + /* + * Calculate number of available entries. + * + * Each recoverable address range entry is (start address, len, + * recovery address), 2 cells each for start and recovery address, + * 1 cell for len, totalling 5 cells per entry. + */ + mc_recoverable_range_len = psize / (sizeof(*prop) * 5); + + /* Sanity check */ + if (!mc_recoverable_range_len) + return 1; + + /* Size required to hold all the entries. */ + size = mc_recoverable_range_len * + sizeof(struct mcheck_recoverable_range); + + /* + * Allocate a buffer to hold the MC recoverable ranges. We would be + * accessing them in real mode, hence it needs to be within + * RMO region. + */ + mc_recoverable_range =__va(memblock_alloc_base(size, __alignof__(u64), + ppc64_rma_size)); + memset(mc_recoverable_range, 0, size); + + for (i = 0; i < mc_recoverable_range_len; i++) { + mc_recoverable_range[i].start_addr = + of_read_number(prop + (i * 5) + 0, 2); + mc_recoverable_range[i].end_addr = + mc_recoverable_range[i].start_addr + + of_read_number(prop + (i * 5) + 2, 1); + mc_recoverable_range[i].recover_addr = + of_read_number(prop + (i * 5) + 3, 2); + + pr_debug("Machine check recoverable range: %llx..%llx: %llx\n", + mc_recoverable_range[i].start_addr, + mc_recoverable_range[i].end_addr, + mc_recoverable_range[i].recover_addr); + } + return 1; +} + +>>>>>>> 9d0c4dfedd96... of/fdt: update of_get_flat_dt_prop in prep for libfdt static int __init opal_register_exception_handlers(void) { #ifdef __BIG_ENDIAN__ @@ -269,7 +331,7 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count) if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0) return 0; len = cpu_to_be64(count); - rc = opal_console_read(vtermno, &len, buf); + rc = opal_console_read(vtermno, &len, buf); if (rc == OPAL_SUCCESS) return be64_to_cpu(len); return 0; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 972df0ffd4dc..0b84df948ed6 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -671,7 +671,7 @@ static int __init pseries_probe_fw_features(unsigned long node, void *data) { const char *prop; - unsigned long len; + int len; static int hypertas_found; static int vec5_found; @@ -704,7 +704,7 @@ static int __init pseries_probe_fw_features(unsigned long node, static int __init pSeries_probe(void) { unsigned long root = of_get_flat_dt_root(); - char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); + const char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); if (dtype == NULL) return 0; diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 84fe931bb60e..555f75cff7d3 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -221,7 +221,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, int depth, void *data) { const __be32 *ranges; - unsigned long len; + int len; if (depth > 1) return 0; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 359b5b71f294..dfd5b730d4b7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -40,7 +40,7 @@ char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) */ void *of_fdt_get_property(struct boot_param_header *blob, unsigned long node, const char *name, - unsigned long *size) + int *size) { unsigned long p = node; @@ -90,7 +90,8 @@ int of_fdt_is_compatible(struct boot_param_header *blob, unsigned long node, const char *compat) { const char *cp; - unsigned long cplen, l, score = 0; + int cplen; + unsigned long l, score = 0; cp = of_fdt_get_property(blob, node, "compatible", &cplen); if (cp == NULL) @@ -449,8 +450,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, { int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); phys_addr_t base, size; - unsigned long len; - __be32 *prop; + int len; + const __be32 *prop; int nomap, first = 1; prop = of_get_flat_dt_prop(node, "reg", &len); @@ -493,7 +494,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, */ static int __init __reserved_mem_check_root(unsigned long node) { - __be32 *prop; + const __be32 *prop; prop = of_get_flat_dt_prop(node, "#size-cells", NULL); if (!prop || be32_to_cpup(prop) != dt_root_size_cells) @@ -643,8 +644,8 @@ unsigned long __init of_get_flat_dt_root(void) * This function can be used within scan_flattened_dt callback to get * access to properties */ -void *__init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) +const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + int *size) { return of_fdt_get_property(initial_boot_params, node, name, size); } @@ -715,7 +716,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match, } if (!best_data) { const char *prop; - long size; + int size; pr_err("\n unrecognized device tree list:\n[ "); @@ -744,8 +745,8 @@ const void * __init of_flat_dt_match_machine(const void *default_match, static void __init early_init_dt_check_for_initrd(unsigned long node) { u64 start, end; - unsigned long len; - __be32 *prop; + int len; + const __be32 *prop; pr_debug("Looking for initrd properties... "); @@ -778,7 +779,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) int __init early_init_dt_scan_root(unsigned long node, const char *uname, int depth, void *data) { - __be32 *prop; + const __be32 *prop; if (depth != 0) return 0; @@ -800,9 +801,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, return 1; } -u64 __init dt_mem_next_cell(int s, __be32 **cellp) +u64 __init dt_mem_next_cell(int s, const __be32 **cellp) { - __be32 *p = *cellp; + const __be32 *p = *cellp; *cellp = p + s; return of_read_number(p, s); @@ -814,9 +815,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp) int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *reg, *endp; - unsigned long l; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const __be32 *reg, *endp; + int l; /* We are scanning "memory" nodes only */ if (type == NULL) { @@ -837,7 +838,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, endp = reg + (l / sizeof(__be32)); - pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", + pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n", uname, l, reg[0], reg[1], reg[2], reg[3]); while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { @@ -860,8 +861,8 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { - unsigned long l; - char *p; + int l; + const char *p; pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index daaaf935911d..e420eb52e5c9 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -95,8 +95,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); phys_addr_t start = 0, end = 0; phys_addr_t base = 0, align = 0, size; - unsigned long len; - __be32 *prop; + int len; + const __be32 *prop; int nomap; int ret; diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 89c5a7211e13..e00da2e2b601 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -66,7 +66,7 @@ extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset); extern void *of_fdt_get_property(struct boot_param_header *blob, unsigned long node, const char *name, - unsigned long *size); + int *size); extern int of_fdt_is_compatible(struct boot_param_header *blob, unsigned long node, const char *compat); @@ -85,8 +85,8 @@ extern char *find_flat_dt_string(u32 offset); extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, int depth, void *data), void *data); -extern void *of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size); +extern const void *of_get_flat_dt_prop(unsigned long node, const char *name, + int *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern int of_flat_dt_match(unsigned long node, const char *const *matches); extern unsigned long of_get_flat_dt_root(void); @@ -100,7 +100,7 @@ extern void early_init_dt_add_memory_arch(u64 base, u64 size); extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool no_map); extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); -extern u64 dt_mem_next_cell(int s, __be32 **cellp); +extern u64 dt_mem_next_cell(int s, const __be32 **cellp); /* Early flat tree scan hooks */ extern int early_init_dt_scan_root(unsigned long node, const char *uname, -- cgit v1.2.3 From 0cbd5ff23b51aed014bd0027517fcf9833f13eae Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 2 Apr 2014 15:10:14 -0500 Subject: of/fdt: Convert FDT functions to use libfdt The kernel FDT functions predate libfdt and are much more limited in functionality. Also, the kernel functions and libfdt functions are not compatible with each other because they have different definitions of node offsets. To avoid this incompatibility and in preparation to add more FDT parsing functions which will need libfdt, let's first convert the existing code to use libfdt. The FDT unflattening, top-level FDT scanning, and property retrieval functions are converted to use libfdt. The scanning code should be re-worked to be more efficient and understandable by using libfdt to find nodes directly by path or compatible strings. Signed-off-by: Rob Herring Tested-by: Michal Simek Tested-by: Grant Likely Tested-by: Stephen Chivers (cherry picked from commit e6a6928c3ea1d0195ed75a091e345696b916c09b) Signed-off-by: Mark Brown --- drivers/of/Kconfig | 1 + drivers/of/Makefile | 2 + drivers/of/fdt.c | 209 ++++++++++++++----------------------------------- include/linux/of_fdt.h | 1 - 4 files changed, 60 insertions(+), 153 deletions(-) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 30a7d87a8077..ec919a9160a5 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -28,6 +28,7 @@ config OF_SELFTEST config OF_FLATTREE bool select DTC + select LIBFDT config OF_EARLY_FLATTREE bool diff --git a/drivers/of/Makefile b/drivers/of/Makefile index ed9660adad77..9891232f999e 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -10,3 +10,5 @@ obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o + +CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index dfd5b730d4b7..024b8f99d480 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* for COMMAND_LINE_SIZE */ #ifdef CONFIG_PPC @@ -28,54 +29,6 @@ #include -char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) -{ - return ((char *)blob) + - be32_to_cpu(blob->off_dt_strings) + offset; -} - -/** - * of_fdt_get_property - Given a node in the given flat blob, return - * the property ptr - */ -void *of_fdt_get_property(struct boot_param_header *blob, - unsigned long node, const char *name, - int *size) -{ - unsigned long p = node; - - do { - u32 tag = be32_to_cpup((__be32 *)p); - u32 sz, noff; - const char *nstr; - - p += 4; - if (tag == OF_DT_NOP) - continue; - if (tag != OF_DT_PROP) - return NULL; - - sz = be32_to_cpup((__be32 *)p); - noff = be32_to_cpup((__be32 *)(p + 4)); - p += 8; - if (be32_to_cpu(blob->version) < 0x10) - p = ALIGN(p, sz >= 8 ? 8 : 4); - - nstr = of_fdt_get_string(blob, noff); - if (nstr == NULL) { - pr_warning("Can't find property index name !\n"); - return NULL; - } - if (strcmp(name, nstr) == 0) { - if (size) - *size = sz; - return (void *)p; - } - p += sz; - p = ALIGN(p, 4); - } while (1); -} - /** * of_fdt_is_compatible - Return true if given node from the given blob has * compat in its compatible list @@ -93,7 +46,7 @@ int of_fdt_is_compatible(struct boot_param_header *blob, int cplen; unsigned long l, score = 0; - cp = of_fdt_get_property(blob, node, "compatible", &cplen); + cp = fdt_getprop(blob, node, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -152,28 +105,27 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, */ static void * unflatten_dt_node(struct boot_param_header *blob, void *mem, - void **p, + int *poffset, struct device_node *dad, struct device_node ***allnextpp, unsigned long fpsize) { + const __be32 *p; struct device_node *np; struct property *pp, **prev_pp = NULL; - char *pathp; - u32 tag; + const char *pathp; unsigned int l, allocl; + static int depth = 0; + int old_depth; + int offset; int has_name = 0; int new_format = 0; - tag = be32_to_cpup(*p); - if (tag != OF_DT_BEGIN_NODE) { - pr_err("Weird tag at start of node: %x\n", tag); + pathp = fdt_get_name(blob, *poffset, &l); + if (!pathp) return mem; - } - *p += 4; - pathp = *p; - l = allocl = strlen(pathp) + 1; - *p = PTR_ALIGN(*p + l, 4); + + allocl = l++; /* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild @@ -191,7 +143,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob, fpsize = 1; allocl = 2; l = 1; - *pathp = '\0'; + pathp = ""; } else { /* account for '/' and path size minus terminal 0 * already in 'l' @@ -238,32 +190,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob, kref_init(&np->kref); } /* process properties */ - while (1) { - u32 sz, noff; - char *pname; - - tag = be32_to_cpup(*p); - if (tag == OF_DT_NOP) { - *p += 4; - continue; - } - if (tag != OF_DT_PROP) + for (offset = fdt_first_property_offset(blob, *poffset); + (offset >= 0); + (offset = fdt_next_property_offset(blob, offset))) { + const char *pname; + u32 sz; + + if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) { + offset = -FDT_ERR_INTERNAL; break; - *p += 4; - sz = be32_to_cpup(*p); - noff = be32_to_cpup(*p + 4); - *p += 8; - if (be32_to_cpu(blob->version) < 0x10) - *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4); - - pname = of_fdt_get_string(blob, noff); + } + if (pname == NULL) { pr_info("Can't find property name in list !\n"); break; } if (strcmp(pname, "name") == 0) has_name = 1; - l = strlen(pname) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); if (allnextpp) { @@ -275,26 +218,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob, if ((strcmp(pname, "phandle") == 0) || (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) - np->phandle = be32_to_cpup((__be32*)*p); + np->phandle = be32_to_cpup(p); } /* And we process the "ibm,phandle" property * used in pSeries dynamic device tree * stuff */ if (strcmp(pname, "ibm,phandle") == 0) - np->phandle = be32_to_cpup((__be32 *)*p); - pp->name = pname; + np->phandle = be32_to_cpup(p); + pp->name = (char *)pname; pp->length = sz; - pp->value = *p; + pp->value = (__be32 *)p; *prev_pp = pp; prev_pp = &pp->next; } - *p = PTR_ALIGN((*p) + sz, 4); } /* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent */ if (!has_name) { - char *p1 = pathp, *ps = pathp, *pa = NULL; + const char *p1 = pathp, *ps = pathp, *pa = NULL; int sz; while (*p1) { @@ -331,19 +273,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob, if (!np->type) np->type = ""; } - while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { - if (tag == OF_DT_NOP) - *p += 4; - else - mem = unflatten_dt_node(blob, mem, p, np, allnextpp, - fpsize); - tag = be32_to_cpup(*p); - } - if (tag != OF_DT_END_NODE) { - pr_err("Weird tag at end of node: %x\n", tag); - return mem; - } - *p += 4; + + old_depth = depth; + *poffset = fdt_next_node(blob, *poffset, &depth); + if (depth < 0) + depth = 0; + while (*poffset > 0 && depth > old_depth) + mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, + fpsize); + + if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) + pr_err("unflatten: error %d processing FDT\n", *poffset); + return mem; } @@ -364,7 +305,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, void * (*dt_alloc)(u64 size, u64 align)) { unsigned long size; - void *start, *mem; + int start; + void *mem; struct device_node **allnextp = mynodes; pr_debug(" -> unflatten_device_tree()\n"); @@ -385,7 +327,7 @@ static void __unflatten_device_tree(struct boot_param_header *blob, } /* First pass, scan for size */ - start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); + start = 0; size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); size = ALIGN(size, 4); @@ -400,10 +342,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ - start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); + start = 0; unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); - if (be32_to_cpup(start) != OF_DT_END) - pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start)); if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", be32_to_cpup(mem + size)); @@ -579,47 +519,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, void *data), void *data) { - unsigned long p = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - int rc = 0; - int depth = -1; - - do { - u32 tag = be32_to_cpup((__be32 *)p); - const char *pathp; - - p += 4; - if (tag == OF_DT_END_NODE) { - depth--; - continue; - } - if (tag == OF_DT_NOP) - continue; - if (tag == OF_DT_END) - break; - if (tag == OF_DT_PROP) { - u32 sz = be32_to_cpup((__be32 *)p); - p += 8; - if (be32_to_cpu(initial_boot_params->version) < 0x10) - p = ALIGN(p, sz >= 8 ? 8 : 4); - p += sz; - p = ALIGN(p, 4); - continue; - } - if (tag != OF_DT_BEGIN_NODE) { - pr_err("Invalid tag %x in flat device tree!\n", tag); - return -EINVAL; - } - depth++; - pathp = (char *)p; - p = ALIGN(p + strlen(pathp) + 1, 4); + const void *blob = initial_boot_params; + const char *pathp; + int offset, rc = 0, depth = -1; + + for (offset = fdt_next_node(blob, -1, &depth); + offset >= 0 && depth >= 0 && !rc; + offset = fdt_next_node(blob, offset, &depth)) { + + pathp = fdt_get_name(blob, offset, NULL); if (*pathp == '/') pathp = kbasename(pathp); - rc = it(p, pathp, depth, data); - if (rc != 0) - break; - } while (1); - + rc = it(offset, pathp, depth, data); + } return rc; } @@ -628,14 +540,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, */ unsigned long __init of_get_flat_dt_root(void) { - unsigned long p = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - - while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) - p += 4; - BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); - p += 4; - return ALIGN(p + strlen((char *)p) + 1, 4); + return 0; } /** @@ -647,7 +552,7 @@ unsigned long __init of_get_flat_dt_root(void) const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, int *size) { - return of_fdt_get_property(initial_boot_params, node, name, size); + return fdt_getprop(initial_boot_params, node, name, size); } /** diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index e00da2e2b601..5f5b83461a81 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -81,7 +81,6 @@ extern int __initdata dt_root_size_cells; extern struct boot_param_header *initial_boot_params; /* For scanning the flat device-tree at boot time */ -extern char *find_flat_dt_string(u32 offset); extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, int depth, void *data), void *data); -- cgit v1.2.3 From a7d43c3d6f103c145437d75265c1e91918d205c3 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Tue, 4 Feb 2014 11:11:10 -0500 Subject: lib: add fdt_empty_tree.c CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter Signed-off-by: Leif Lindholm Acked-by: Catalin Marinas Signed-off-by: Matt Fleming (cherry picked from commit adaf5687846c25613d58c0a2f5d9e024547cdbec) Signed-off-by: Mark Brown --- lib/Makefile | 3 ++- lib/fdt_empty_tree.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 48140e3ba73f..befe5554a34f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -147,7 +147,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000000000000..5d30c58150ad --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include +#include "../scripts/dtc/libfdt/fdt_empty_tree.c" -- cgit v1.2.3 From 0cdc050ea0aa3df82784b31c4475bce01240301d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 11 Sep 2014 21:39:05 +0100 Subject: ARM: samsung: Fix mismerge with new libfdt changes The merge with the new FDT changes incorrectly changed mfc_mem to be a local variable causing boot failures. Signed-off-by: Mark Brown --- arch/arm/plat-samsung/s5p-dev-mfc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c index 97ece99521ca..a29272818c36 100644 --- a/arch/arm/plat-samsung/s5p-dev-mfc.c +++ b/arch/arm/plat-samsung/s5p-dev-mfc.c @@ -127,27 +127,27 @@ int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, { const __be32 *prop; int len; - struct s5p_mfc_dt_meminfo mfc_mem; + struct s5p_mfc_dt_meminfo *mfc_mem = data; if (!data) return 0; - if (!of_flat_dt_is_compatible(node, mfc_mem.compatible)) + if (!of_flat_dt_is_compatible(node, mfc_mem->compatible)) return 0; prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); if (!prop || (len != 2 * sizeof(unsigned long))) return 0; - mfc_mem.loff = be32_to_cpu(prop[0]); - mfc_mem.lsize = be32_to_cpu(prop[1]); + mfc_mem->loff = be32_to_cpu(prop[0]); + mfc_mem->lsize = be32_to_cpu(prop[1]); prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); if (!prop || (len != 2 * sizeof(unsigned long))) return 0; - mfc_mem.roff = be32_to_cpu(prop[0]); - mfc_mem.rsize = be32_to_cpu(prop[1]); + mfc_mem->roff = be32_to_cpu(prop[0]); + mfc_mem->rsize = be32_to_cpu(prop[1]); return 1; } -- cgit v1.2.3