Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754269AbbGPIa7 (ORCPT ); Thu, 16 Jul 2015 04:30:59 -0400 Received: from 8bytes.org ([81.169.241.247]:33798 "EHLO theia.8bytes.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754118AbbGPIaz (ORCPT ); Thu, 16 Jul 2015 04:30:55 -0400 From: Joerg Roedel To: Will Deacon , Grant Likely , Rob Herring Cc: linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Joerg Roedel Subject: [PATCH 1/2] of: base: Allow more args than MAX_PHANDLE_ARGS if required Date: Thu, 16 Jul 2015 10:30:43 +0200 Message-Id: <1437035444-13867-2-git-send-email-joro@8bytes.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1437035444-13867-1-git-send-email-joro@8bytes.org> References: <1437035444-13867-1-git-send-email-joro@8bytes.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5352 Lines: 155 From: Joerg Roedel The main use of MAX_PHANDLE_ARGS is to define the number of args elements in 'struct of_phandle_args'. This struct is often declared on the stack and thus it is impractical to increase MAX_PHANDLE_ARGS again and again. To handle situations where more than MAX_PHANDLE_ARGS elements may appear in a device-tree, introduce functions to allocate/free 'struct of_phandle_args' with more than MAX_PHANDLE_ARGS elements and provide the new function of_parse_phandle_with_var_args(), which can handle those variable-size structs. This is necessary for the ARM-SMMU driver, where the number of mmu-masters can be up to 128. Signed-off-by: Joerg Roedel --- drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++------- include/linux/of.h | 7 +++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 8b5a187..2b288db 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -54,6 +54,24 @@ DEFINE_MUTEX(of_mutex); */ DEFINE_RAW_SPINLOCK(devtree_lock); +struct of_phandle_args *of_alloc_phandle_args(int size) +{ + struct of_phandle_args *args; + int e = max(0, size - MAX_PHANDLE_ARGS); + + args = kzalloc(sizeof(struct of_phandle_args) + e * sizeof(uint32_t), + GFP_KERNEL); + + return args; +} +EXPORT_SYMBOL(of_alloc_phandle_args); + +void of_free_phandle_args(struct of_phandle_args *args) +{ + kfree(args); +} +EXPORT_SYMBOL(of_free_phandle_args); + int of_n_addr_cells(struct device_node *np) { const __be32 *ip; @@ -1446,7 +1464,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int cell_count, int index, - struct of_phandle_args *out_args) + struct of_phandle_args *out_args, + int elems) { const __be32 *list, *list_end; int rc = 0, size, cur_index = 0; @@ -1525,8 +1544,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np, if (out_args) { int i; - if (WARN_ON(count > MAX_PHANDLE_ARGS)) - count = MAX_PHANDLE_ARGS; + if (WARN_ON(count > elems)) + count = elems; out_args->np = node; out_args->args_count = count; for (i = 0; i < count; i++) @@ -1577,7 +1596,7 @@ struct device_node *of_parse_phandle(const struct device_node *np, return NULL; if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, - index, &args)) + index, &args, MAX_PHANDLE_ARGS)) return NULL; return args.np; @@ -1623,10 +1642,20 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na if (index < 0) return -EINVAL; return __of_parse_phandle_with_args(np, list_name, cells_name, 0, - index, out_args); + index, out_args, MAX_PHANDLE_ARGS); } EXPORT_SYMBOL(of_parse_phandle_with_args); +int of_parse_phandle_with_var_args(const struct device_node *np, const char *list_name, + const char *cells_name, int index, + struct of_phandle_args *out_args, int elems) +{ + if (index < 0) + return -EINVAL; + return __of_parse_phandle_with_args(np, list_name, cells_name, 0, + index, out_args, elems); +} +EXPORT_SYMBOL(of_parse_phandle_with_var_args); /** * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list * @np: pointer to a device tree node containing a list @@ -1664,7 +1693,7 @@ int of_parse_phandle_with_fixed_args(const struct device_node *np, if (index < 0) return -EINVAL; return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, - index, out_args); + index, out_args, MAX_PHANDLE_ARGS); } EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); @@ -1687,7 +1716,7 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na const char *cells_name) { return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1, - NULL); + NULL, MAX_PHANDLE_ARGS); } EXPORT_SYMBOL(of_count_phandle_with_args); diff --git a/include/linux/of.h b/include/linux/of.h index edc068d..cd9f225 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -75,6 +75,10 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; +/* Use these if you need more that MAX_PHANDLE_ARGS */ +extern struct of_phandle_args *of_alloc_phandle_args(int size); +extern void of_free_phandle_args(struct of_phandle_args *args); + struct of_reconfig_data { struct device_node *dn; struct property *prop; @@ -327,6 +331,9 @@ extern struct device_node *of_parse_phandle(const struct device_node *np, extern int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args); +extern int of_parse_phandle_with_var_args(const struct device_node *np, + const char *list_name, const char *cells_name, int index, + struct of_phandle_args *out_args, int elems); extern int of_parse_phandle_with_fixed_args(const struct device_node *np, const char *list_name, int cells_count, int index, struct of_phandle_args *out_args); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/