From patchwork Wed Nov 4 13:12:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 7550141 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 18FB69F327 for ; Wed, 4 Nov 2015 13:14:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2E35B207A6 for ; Wed, 4 Nov 2015 13:14:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 00CC8207BF for ; Wed, 4 Nov 2015 13:14:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965459AbbKDNOh (ORCPT ); Wed, 4 Nov 2015 08:14:37 -0500 Received: from e28smtp05.in.ibm.com ([122.248.162.5]:58641 "EHLO e28smtp05.in.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965409AbbKDNOg (ORCPT ); Wed, 4 Nov 2015 08:14:36 -0500 Received: from /spool/local by e28smtp05.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 4 Nov 2015 18:44:34 +0530 Received: from d28dlp02.in.ibm.com (9.184.220.127) by e28smtp05.in.ibm.com (192.168.1.135) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 4 Nov 2015 18:44:32 +0530 X-Helo: d28dlp02.in.ibm.com X-MailFrom: gwshan@linux.vnet.ibm.com X-RcptTo: linux-pci@vger.kernel.org Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp02.in.ibm.com (Postfix) with ESMTP id 6D800394005E; Wed, 4 Nov 2015 18:44:31 +0530 (IST) Received: from d28av01.in.ibm.com (d28av01.in.ibm.com [9.184.220.63]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id tA4DEUbJ59244710; Wed, 4 Nov 2015 18:44:30 +0530 Received: from d28av01.in.ibm.com (localhost [127.0.0.1]) by d28av01.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id tA4DDNws000396; Wed, 4 Nov 2015 18:43:26 +0530 Received: from gwshan ([9.192.177.12]) by d28av01.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with SMTP id tA4DCxJU030846; Wed, 4 Nov 2015 18:43:19 +0530 Received: by gwshan (Postfix, from userid 1000) id A0C2E942D98; Thu, 5 Nov 2015 00:13:11 +1100 (AEDT) From: Gavin Shan To: linuxppc-dev@lists.ozlabs.org Cc: linux-pci@vger.kernel.org, devicetree@vger.kernel.org, benh@kernel.crashing.org, mpe@ellerman.id.au, aik@ozlabs.ru, bhelgaas@google.com, grant.likely@linaro.org, robherring2@gmail.com, panto@antoniou-consulting.com, frowand.list@gmail.com, Gavin Shan Subject: [PATCH v7 45/50] drivers/of: Avoid recursively calling unflatten_dt_node() Date: Thu, 5 Nov 2015 00:12:45 +1100 Message-Id: <1446642770-4681-46-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1446642770-4681-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1446642770-4681-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15110413-0017-0000-0000-0000083890A7 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In current implementation, unflatten_dt_node() is called recursively to unflatten device nodes in FDT blob. It's stress to limited stack capacity. This avoids calling the function recursively, meaning the device nodes are unflattened in one call on unflatten_dt_node(): two arrays are introduced to track the parent path size and the device node of current level of depth, which will be used by the device node on next level of depth to be unflattened. Also, the parameter "poffset" and "fpsize" are unused and dropped. Signed-off-by: Gavin Shan --- drivers/of/fdt.c | 94 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 173b036..f4793d0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -355,61 +355,82 @@ static unsigned long populate_node(const void *blob, return fpsize; } +static void reverse_nodes(struct device_node *parent) +{ + struct device_node *child, *next; + + /* In-depth first */ + child = parent->child; + while (child) { + reverse_nodes(child); + + child = child->sibling; + } + + /* Reverse the nodes in the child list */ + child = parent->child; + parent->child = NULL; + while (child) { + next = child->sibling; + + child->sibling = parent->child; + parent->child = child; + child = next; + } +} + /** * unflatten_dt_node - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties - * @poffset: pointer to node in flat tree * @dad: Parent struct device_node * @nodepp: The device_node tree created by the call - * @fpsize: Size of the node path up at the current depth. * @dryrun: If true, do not allocate device nodes but still calculate needed * memory size */ static void *unflatten_dt_node(const void *blob, void *mem, - int *poffset, struct device_node *dad, struct device_node **nodepp, - unsigned long fpsize, bool dryrun) { - struct device_node *np; - static int depth; - int old_depth; - - fpsize = populate_node(blob, *poffset, &mem, dad, fpsize, &np, dryrun); - if (!fpsize) - return mem; + struct device_node *root; + int offset = 0, depth = 0; + unsigned long fpsizes[64]; + struct device_node *nps[64]; - 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, NULL, - fpsize, dryrun); + if (nodepp) + *nodepp = NULL; + + root = dad; + fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0; + nps[depth++] = dad; + while (offset >= 0 && depth < 64) { + fpsizes[depth] = populate_node(blob, offset, &mem, + nps[depth - 1], + fpsizes[depth - 1], + &nps[depth], dryrun); + if (!fpsizes[depth]) + return mem; + + if (!dryrun && nodepp && !*nodepp) + *nodepp = nps[depth]; + if (!dryrun && !root) + root = nps[depth]; + + offset = fdt_next_node(blob, offset, &depth); + } - if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) - pr_err("unflatten: error %d processing FDT\n", *poffset); + if (offset < 0 && offset != -FDT_ERR_NOTFOUND) + pr_err("%s: Error %d processing FDT\n", + __func__, offset); /* * Reverse the child list. Some drivers assumes node order matches .dts * node order */ - if (!dryrun && np->child) { - struct device_node *child = np->child; - np->child = NULL; - while (child) { - struct device_node *next = child->sibling; - child->sibling = np->child; - np->child = child; - child = next; - } - } - - if (nodepp) - *nodepp = np; + if (!dryrun) + reverse_nodes(root); return mem; } @@ -431,7 +452,6 @@ static void __unflatten_device_tree(const void *blob, void * (*dt_alloc)(u64 size, u64 align)) { unsigned long size; - int start; void *mem; pr_debug(" -> unflatten_device_tree()\n"); @@ -452,8 +472,7 @@ static void __unflatten_device_tree(const void *blob, } /* First pass, scan for size */ - start = 0; - size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true); + size = (unsigned long)unflatten_dt_node(blob, NULL, NULL, NULL, true); size = ALIGN(size, 4); pr_debug(" size is %lx, allocating...\n", size); @@ -467,8 +486,7 @@ static void __unflatten_device_tree(const void *blob, pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ - start = 0; - unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false); + unflatten_dt_node(blob, mem, NULL, mynodes, false); if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", be32_to_cpup(mem + size));