Received: by 10.223.185.116 with SMTP id b49csp1016260wrg; Fri, 16 Feb 2018 10:52:28 -0800 (PST) X-Google-Smtp-Source: AH8x224UAB/0rTl2wBGa4iNQUPWzT8FxpTjfckuRMU8TMeAtbfC9tWc+GnfEYyMzflK64oBzk0E2 X-Received: by 10.99.127.78 with SMTP id p14mr5861225pgn.346.1518807148699; Fri, 16 Feb 2018 10:52:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518807148; cv=none; d=google.com; s=arc-20160816; b=vehPGJwQ8lJLsUDJr18fe7wHWRc/18nnII25VtcYADyFlx5uPeIaBadAiAKS7WiGSp DbZieiJPxJ3sgsLp8FHT9C/W09arkAbIatYZCqyg6Sz9RyejM5dzU8lncJcHxNaGO3il FCaEMPeByRA0lhnWozkc8CsSq4lXcF1XPXVOcZ/0sO/Ve8VyLXZ/AM/k3PEXAHVg+T6M KUnBLYSnVF0pRC57e8rZ4hoQ9mjdof+rh5N/7KU89fngkFGjtHtctVpIIeAzM1nzMXRX LR3JcEHYjkaBFo3xLsZqLGyl0jhRm3vk6Q70jwbo+uNklg9U8ra6DxHBIdSatCJ6pOG/ 6Rpw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dmarc-filter :dkim-signature:dkim-signature:arc-authentication-results; bh=DxH1f6h07BHCvYH7pAo4346dY/9uoIBrvQpp4rEmVro=; b=P+A6yHkEboANQnyFQgcaWxbxoi6qkZa8Jgv1ExaHLjuFGxg68j4oGIvy6NFAxyR6vj rbPDZV8DiDvL+9xRXQwDx+SNziaRGRAucRAOpDhOefVBdJkG8RJU1lXS8rBHvUWLk0t1 +90iS4MkYv7/WPmfyDvAzQf/euF3TI7vyf8ay9loRXneHsu9seMa8PPOH0HtrFGGffG7 4p8a6OBvArLjeUv5rq6r1SlKvbCOzvi7cj4mfQhx6pmP6VQAzkgNvHBOlj+nqdv2fBaJ DEtqBbJjfwJQg+hRjWFK2Hghfm1nxNzYsNYVIQRnBM1A8ta44Zr+Z4xNIIx77ONphha3 uRjQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=bN+2a7EK; dkim=pass header.i=@codeaurora.org header.s=default header.b=AsxFAYNZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m4si6132764pgd.450.2018.02.16.10.52.14; Fri, 16 Feb 2018 10:52:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=bN+2a7EK; dkim=pass header.i=@codeaurora.org header.s=default header.b=AsxFAYNZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757534AbeBPJEk (ORCPT + 99 others); Fri, 16 Feb 2018 04:04:40 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:48982 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757507AbeBPJEi (ORCPT ); Fri, 16 Feb 2018 04:04:38 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 0EAB86079C; Fri, 16 Feb 2018 09:04:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1518771878; bh=8XK6uK9p69WaV5n7yZb/VaZTtOfcqQkXTSHMv/Vb+sA=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=bN+2a7EKN/cQQlrdkcJYh20lVPmWdYCL9SJhVAPY33JTp9hSo27ikFYj4uUBwHETX XS8DsnNAqo/xLCjf8MHZmzqT8asZXZayyeoXc/s6cWYHd6HIouChIIel4s93lAE2JD ftzJfcut1qEzwYir5HEle9HaFfQ7nQzQlsYS44DE= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from [10.204.100.248] (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: cpandya@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id E0A3060386; Fri, 16 Feb 2018 09:04:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1518771877; bh=8XK6uK9p69WaV5n7yZb/VaZTtOfcqQkXTSHMv/Vb+sA=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=AsxFAYNZsxMnRP3Q5lBCPRIshGCPhAFkV7Y+0P3l+9m1Zv8iBCOurRdgsQns1Wr97 ThLhs3Ll8pmmGl+qJlkUNDzbrqj4Nb3fnX6v20EOHPjJUvOeh+6pJsKeRddnMndtaf JVNKoxUqrPCkNOh7lIU2j5I3IwSyBK68ZAnO4Qco= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org E0A3060386 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=cpandya@codeaurora.org Subject: Re: [PATCH v3] of: cache phandle nodes to reduce cost of of_find_node_by_phandle() To: frowand.list@gmail.com, Rob Herring Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org References: <1518655979-10910-1-git-send-email-frowand.list@gmail.com> From: Chintan Pandya Message-ID: <207e055e-1074-9010-e719-2a4c13ede9f9@codeaurora.org> Date: Fri, 16 Feb 2018 14:34:33 +0530 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: <1518655979-10910-1-git-send-email-frowand.list@gmail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2/15/2018 6:22 AM, frowand.list@gmail.com wrote: > From: Frank Rowand > > Create a cache of the nodes that contain a phandle property. Use this > cache to find the node for a given phandle value instead of scanning > the devicetree to find the node. If the phandle value is not found > in the cache, of_find_node_by_phandle() will fall back to the tree > scan algorithm. > > The cache is initialized in of_core_init(). > > The cache is freed via a late_initcall_sync() if modules are not > enabled. > > If the devicetree is created by the dtc compiler, with all phandle > property values auto generated, then the size required by the cache > could be 4 * (1 + number of phandles) bytes. This results in an O(1) > node lookup cost for a given phandle value. Due to a concern that the > phandle property values might not be consistent with what is generated > by the dtc compiler, a mask has been added to the cache lookup algorithm. > To maintain the O(1) node lookup cost, the size of the cache has been > increased by rounding the number of entries up to the next power of > two. > > The overhead of finding the devicetree node containing a given phandle > value has been noted by several people in the recent past, in some cases > with a patch to add a hashed index of devicetree nodes, based on the > phandle value of the node. One concern with this approach is the extra > space added to each node. This patch takes advantage of the phandle > property values auto generated by the dtc compiler, which begin with > one and monotonically increase by one, resulting in a range of 1..n > for n phandle values. This implementation should also provide a good > reduction of overhead for any range of phandle values that are mostly > in a monotonic range. > > Performance measurements by Chintan Pandya > of several implementations of patches that are similar to this one > suggest an expected reduction of boot time by ~400ms for his test > system. If the cache size was decreased to 64 entries, the boot > time was reduced by ~340 ms. The measurements were on a 4.9.73 kernel > for arch/arm64/boot/dts/qcom/sda670-mtp.dts, contains 2371 nodes and > 814 phandle values. > > Reported-by: Chintan Pandya > Signed-off-by: Frank Rowand > --- > > A follow on patch will add an early boot allocation of the cache. > > Changes since v2: > - add mask to calculation of phandle cache entry > - which results in better overhead reduction for devicetrees with > phandle properties not allocated in the monotonically increasing > range of 1..n > - due to mask, number of entries in cache potentially increased to > next power of two > - minor fixes as suggested by reviewers > - no longer using live_tree_max_phandle() so do not move it from > drivers/of/resolver.c to drivers/of/base.c > > Changes since v1: > - change short description from > of: cache phandle nodes to reduce cost of of_find_node_by_phandle() > - rebase on v4.16-rc1 > - reorder new functions in base.c to avoid forward declaration > - add locking around kfree(phandle_cache) for memory ordering > - add explicit check for non-null of phandle_cache in > of_find_node_by_phandle(). There is already a check for !handle, > which prevents accessing a null phandle_cache, but that dependency > is not obvious, so this check makes it more apparent. > - do not free phandle_cache if modules are enabled, so that > cached phandles will be available when modules are loaded > > drivers/of/base.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++--- > drivers/of/of_private.h | 3 ++ > drivers/of/resolver.c | 3 -- > 3 files changed, 82 insertions(+), 7 deletions(-) > > diff --git a/drivers/of/base.c b/drivers/of/base.c > index ad28de96e13f..ab545dfa9173 100644 > --- a/drivers/of/base.c > +++ b/drivers/of/base.c > @@ -91,10 +91,69 @@ int __weak of_node_to_nid(struct device_node *np) > } > #endif > > +static struct device_node **phandle_cache; > +static u32 phandle_cache_mask; > + > +/* > + * Assumptions behind phandle_cache implementation: > + * - phandle property values are in a contiguous range of 1..n > + * > + * If the assumptions do not hold, then > + * - the phandle lookup overhead reduction provided by the cache > + * will likely be less > + */ > +static void of_populate_phandle_cache(void) > +{ > + unsigned long flags; > + u32 cache_entries; > + struct device_node *np; > + u32 phandles = 0; > + > + raw_spin_lock_irqsave(&devtree_lock, flags); > + > + kfree(phandle_cache); I couldn't understood this. Everything else looks good to me. > + phandle_cache = NULL; > + > + for_each_of_allnodes(np) > + if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) > + phandles++; > + > + cache_entries = roundup_pow_of_two(phandles); > + phandle_cache_mask = cache_entries - 1; > + > + phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache), > + GFP_ATOMIC); > + > + for_each_of_allnodes(np) > + if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) > + phandle_cache[np->phandle & phandle_cache_mask] = np; > + > + raw_spin_unlock_irqrestore(&devtree_lock, flags); > +} > + > +#ifndef CONFIG_MODULES > +static int __init of_free_phandle_cache(void) > +{ > + unsigned long flags; > + > + raw_spin_lock_irqsave(&devtree_lock, flags); > + > + kfree(phandle_cache); > + phandle_cache = NULL; > + > + raw_spin_unlock_irqrestore(&devtree_lock, flags); > + > + return 0; > +} > +late_initcall_sync(of_free_phandle_cache); > +#endif > + > void __init of_core_init(void) > { > struct device_node *np; > > + of_populate_phandle_cache(); > + > /* Create the kset, and register existing nodes */ > mutex_lock(&of_mutex); > of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); > @@ -1021,16 +1080,32 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) > */ > struct device_node *of_find_node_by_phandle(phandle handle) > { > - struct device_node *np; > + struct device_node *np = NULL; > unsigned long flags; > + phandle masked_handle; > > if (!handle) > return NULL; > > raw_spin_lock_irqsave(&devtree_lock, flags); > - for_each_of_allnodes(np) > - if (np->phandle == handle) > - break; > + > + masked_handle = handle & phandle_cache_mask; > + > + if (phandle_cache) { > + if (phandle_cache[masked_handle] && > + handle == phandle_cache[masked_handle]->phandle) > + np = phandle_cache[masked_handle]; > + } > + > + if (!np) { > + for_each_of_allnodes(np) > + if (np->phandle == handle) { > + if (phandle_cache) > + phandle_cache[masked_handle] = np; > + break; > + } > + } > + > of_node_get(np); > raw_spin_unlock_irqrestore(&devtree_lock, flags); > return np; > diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h > index 0c609e7d0334..fa70650136b4 100644 > --- a/drivers/of/of_private.h > +++ b/drivers/of/of_private.h > @@ -131,6 +131,9 @@ extern void __of_update_property_sysfs(struct device_node *np, > extern void __of_sysfs_remove_bin_file(struct device_node *np, > struct property *prop); > > +/* illegal phandle value (set when unresolved) */ > +#define OF_PHANDLE_ILLEGAL 0xdeadbeef > + > /* iterators for transactions, used for overlays */ > /* forward iterator */ > #define for_each_transaction_entry(_oft, _te) \ > diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c > index 740d19bde601..b2ca8185c8c6 100644 > --- a/drivers/of/resolver.c > +++ b/drivers/of/resolver.c > @@ -19,9 +19,6 @@ > > #include "of_private.h" > > -/* illegal phandle value (set when unresolved) */ > -#define OF_PHANDLE_ILLEGAL 0xdeadbeef > - > static phandle live_tree_max_phandle(void) > { > struct device_node *node; > Chintan -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project