From 82f68756e94c70767a5b4747dc084a1a81e61a00 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 3 Feb 2016 23:39:01 +0530 Subject: of: resolver: Add missing of_node_get and of_node_put In __of_find_node_by_full_name, add an of_node_get when detecting the desired element, to ensure that it ends up with a reference count that is one greater than on entering the function. Also in __of_find_node_by_full_name, add an of_node_put on breaking out of the for_each_child_of_node loop, to ensure that the reference count of the returned value is not double incremented. This change was made using Coccinelle. The semantic patch used for this is as follows: // @@ expression e; local idexpression n; @@ for_each_child_of_node(..., n) { ... when != of_node_put(n) when != e = n ( return n; | + of_node_put(n); ? return ...; ) ... } // Signed-off-by: Rob Herring --- drivers/of/resolver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 640eb4cb46e3..d313d492f278 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -36,12 +36,14 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node, /* check */ if (of_node_cmp(node->full_name, full_name) == 0) - return node; + return of_node_get(node); for_each_child_of_node(node, child) { found = __of_find_node_by_full_name(child, full_name); - if (found != NULL) + if (found != NULL) { + of_node_put(child); return found; + } } return NULL; @@ -174,6 +176,7 @@ static int __of_adjust_phandle_ref(struct device_node *node, if (of_prop_cmp(sprop->name, propstr) == 0) break; } + of_node_put(refnode); if (!sprop) { pr_err("%s: Could not find property '%s'\n", -- cgit v1.2.3-59-g8ed1b From e53b50c0cbe392c946807abf7d07615a3c588642 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Mon, 22 Feb 2016 19:15:44 +0530 Subject: of: alloc anywhere from memblock if range not specified early_init_dt_alloc_reserved_memory_arch passes end as 0 to __memblock_alloc_base, when limits are not specified. But __memblock_alloc_base takes end value of 0 as MEMBLOCK_ALLOC_ACCESSIBLE and limits the end to memblock.current_limit. This results in regions never being placed in HIGHMEM area, for e.g. CMA. Let __memblock_alloc_base allocate from anywhere in memory if limits are not specified. Acked-by: Marek Szyprowski Signed-off-by: Vinayak Menon Cc: stable@vger.kernel.org Signed-off-by: Rob Herring --- drivers/of/of_reserved_mem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/of') diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 1a3556a9e9ea..ed01c0172e4a 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -32,11 +32,13 @@ 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) { + phys_addr_t 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); + end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end; + base = __memblock_alloc_base(size, align, end); if (!base) return -ENOMEM; -- cgit v1.2.3-59-g8ed1b From 815d74b35e3366261ac2519af64b53f76fb0c0e1 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 2 Mar 2016 20:24:49 +0900 Subject: of/unittest: fix infinite loop in of_unittest_destroy_tracked_overlays() of_overlay_destroy() can return `-ENODEV' error code once it failed to find the requested overlay in `ov_idr'. However, of_unittest_destroy_tracked_overlays() does not handle this error code correctly and continues to call of_overlay_destroy() on the 'missing' overlay over and over again. This results in a printk flood [..] [ 33.497583] of_overlay_destroy: Could not find overlay #6 [ 33.497583] of_overlay_destroy: Could not find overlay #6 [ 33.497584] ### dt-test ### of_unittest_destroy_tracked_overlays: overlay destroy failed for #6 [ 33.497584] ### dt-test ### of_unittest_destroy_tracked_overlays: overlay destroy failed for #6 [ 33.497586] of_overlay_destroy: Could not find overlay #6 [ 33.497586] of_overlay_destroy: Could not find overlay #6 [ 33.497587] ### dt-test ### of_unittest_destroy_tracked_overlays: overlay destroy failed for #6 [ 33.497587] ### dt-test ### of_unittest_destroy_tracked_overlays: overlay destroy failed for #6 [..] which is not really good due to printk design, and can lead to soft lockups, hard lockups, etc. (depending on the context console_unlock() is being called from). The problem has bee observed in real life and reported by Ying Huang. This patch does not address the root cause of missing overlay in `ov_idr', it fixes the endless loop only. Signed-off-by: Sergey Senozhatsky Reported-by: kernel test robot Link: lkml.kernel.org/r/87fuwk1c0o.fsf@yhuang-dev.intel.com Signed-off-by: Rob Herring --- drivers/of/unittest.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/of') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 979b6e415cea..e986e6ee52e0 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1165,6 +1165,11 @@ static void of_unittest_destroy_tracked_overlays(void) continue; ret = of_overlay_destroy(id + overlay_first_id); + if (ret == -ENODEV) { + pr_warn("%s: no overlay to destroy for #%d\n", + __func__, id + overlay_first_id); + continue; + } if (ret != 0) { defers++; pr_warn("%s: overlay destroy failed for #%d\n", -- cgit v1.2.3-59-g8ed1b From fe99c707fc7bb0baba75b26ed585ee3464612dbe Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Wed, 2 Mar 2016 16:35:51 -0500 Subject: of: add 'const' for of_property_*_string*() parameter '*np' The of_property_{read,count,match}_string* family of functions never modify the struct device_node pointer that is passed in, so there is no reason for it to be non-const. Equivalent functions for all other types already take a 'const struct device_node *np'. Signed-off-by: David Rivshin Signed-off-by: Rob Herring --- drivers/of/base.c | 15 ++++++++------- include/linux/of.h | 18 +++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers/of') diff --git a/drivers/of/base.c b/drivers/of/base.c index 017dd94f16ea..b299de2b3afa 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1341,10 +1341,10 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_array); * * The out_string pointer is modified only if a valid string can be decoded. */ -int of_property_read_string(struct device_node *np, const char *propname, +int of_property_read_string(const struct device_node *np, const char *propname, const char **out_string) { - struct property *prop = of_find_property(np, propname, NULL); + const struct property *prop = of_find_property(np, propname, NULL); if (!prop) return -EINVAL; if (!prop->value) @@ -1365,10 +1365,10 @@ EXPORT_SYMBOL_GPL(of_property_read_string); * This function searches a string list property and returns the index * of a specific string value. */ -int of_property_match_string(struct device_node *np, const char *propname, +int of_property_match_string(const struct device_node *np, const char *propname, const char *string) { - struct property *prop = of_find_property(np, propname, NULL); + const struct property *prop = of_find_property(np, propname, NULL); size_t l; int i; const char *p, *end; @@ -1404,10 +1404,11 @@ EXPORT_SYMBOL_GPL(of_property_match_string); * Don't call this function directly. It is a utility helper for the * of_property_read_string*() family of functions. */ -int of_property_read_string_helper(struct device_node *np, const char *propname, - const char **out_strs, size_t sz, int skip) +int of_property_read_string_helper(const struct device_node *np, + const char *propname, const char **out_strs, + size_t sz, int skip) { - struct property *prop = of_find_property(np, propname, NULL); + const struct property *prop = of_find_property(np, propname, NULL); int l = 0, i = 0; const char *p, *end; diff --git a/include/linux/of.h b/include/linux/of.h index dd10626a615f..588fdd5d21ad 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -296,13 +296,13 @@ extern int of_property_read_u64_array(const struct device_node *np, u64 *out_values, size_t sz); -extern int of_property_read_string(struct device_node *np, +extern int of_property_read_string(const struct device_node *np, const char *propname, const char **out_string); -extern int of_property_match_string(struct device_node *np, +extern int of_property_match_string(const struct device_node *np, const char *propname, const char *string); -extern int of_property_read_string_helper(struct device_node *np, +extern int of_property_read_string_helper(const struct device_node *np, const char *propname, const char **out_strs, size_t sz, int index); extern int of_device_is_compatible(const struct device_node *device, @@ -538,14 +538,14 @@ static inline int of_property_read_u64_array(const struct device_node *np, return -ENOSYS; } -static inline int of_property_read_string(struct device_node *np, +static inline int of_property_read_string(const struct device_node *np, const char *propname, const char **out_string) { return -ENOSYS; } -static inline int of_property_read_string_helper(struct device_node *np, +static inline int of_property_read_string_helper(const struct device_node *np, const char *propname, const char **out_strs, size_t sz, int index) { @@ -571,7 +571,7 @@ static inline int of_property_read_u64(const struct device_node *np, return -ENOSYS; } -static inline int of_property_match_string(struct device_node *np, +static inline int of_property_match_string(const struct device_node *np, const char *propname, const char *string) { @@ -773,7 +773,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np, * * If @out_strs is NULL, the number of strings in the property is returned. */ -static inline int of_property_read_string_array(struct device_node *np, +static inline int of_property_read_string_array(const struct device_node *np, const char *propname, const char **out_strs, size_t sz) { @@ -792,7 +792,7 @@ static inline int of_property_read_string_array(struct device_node *np, * does not have a value, and -EILSEQ if the string is not null-terminated * within the length of the property data. */ -static inline int of_property_count_strings(struct device_node *np, +static inline int of_property_count_strings(const struct device_node *np, const char *propname) { return of_property_read_string_helper(np, propname, NULL, 0, 0); @@ -816,7 +816,7 @@ static inline int of_property_count_strings(struct device_node *np, * * The out_string pointer is modified only if a valid string can be decoded. */ -static inline int of_property_read_string_index(struct device_node *np, +static inline int of_property_read_string_index(const struct device_node *np, const char *propname, int index, const char **output) { -- cgit v1.2.3-59-g8ed1b