[{"id":1771634,"web_url":"http://patchwork.ozlabs.org/comment/1771634/","msgid":"<f0194dff-6fb4-b2ba-93a8-2dd3a5dd9186@huawei.com>","list_archive_url":null,"date":"2017-09-20T06:56:52","subject":"Re: [PATCH v2 0/6] Support PPTT for ARM64","submitter":{"id":72343,"url":"http://patchwork.ozlabs.org/api/people/72343/","name":"Xiongfeng Wang","email":"wangxiongfeng2@huawei.com"},"content":"Hi Jeremy,\n\nI have tested it on D05 board, the sysfs can display right information about\ncpu topo and cache topo, except that the core_id and physical_package_id are\nnot continuous and counting from zero. But this doesn't influence the system.\n\nThanks,\nXiongfeng Wang\n\nOn 2017/9/20 2:47, Jeremy Linton wrote:\n> ACPI 6.2 adds the Processor Properties Topology Table (PPTT), which is\n> used to describe the processor and cache topology. Ideally it is\n> used to extend/override information provided by the hardware, but\n> right now ARM64 is entirely dependent on firmware provided tables.\n> \n> This patch parses the table for the cache topology and CPU topology.\n> For the latter we also add an additional topology_cod_id() macro,\n> and a package_id for arm64. Initially the physical id will match\n> the cluster id, but we update users of the cluster to utilize\n> the new macro. When we enable ACPI/PPTT for arm64 we map the socket\n> to the physical id as the remainder of the kernel expects.\n> \n> For example on juno:\n> [root@mammon-juno-rh topology]# lstopo-no-graphics\n>   Package L#0\n>     L2 L#0 (1024KB)\n>       L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0 + PU L#0 (P#0)\n>       L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1 + PU L#1 (P#1)\n>       L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2 + PU L#2 (P#2)\n>       L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3 + PU L#3 (P#3)\n>     L2 L#1 (2048KB)\n>       L1d L#4 (32KB) + L1i L#4 (48KB) + Core L#4 + PU L#4 (P#4)\n>       L1d L#5 (32KB) + L1i L#5 (48KB) + Core L#5 + PU L#5 (P#5)\n>   HostBridge L#0\n>     PCIBridge\n>       PCIBridge\n>         PCIBridge\n>           PCI 1095:3132\n>             Block(Disk) L#0 \"sda\"\n>         PCIBridge\n>           PCI 1002:68f9\n>             GPU L#1 \"renderD128\"\n>             GPU L#2 \"card0\"\n>             GPU L#3 \"controlD64\"\n>         PCIBridge\n>           PCI 11ab:4380\n>             Net L#4 \"enp8s0\"\n> \n> v1->v2:\n> \n> The parser keys off the acpi_pptt_processor node to determine\n>   unique cache's rather than the acpi_pptt_cache referenced by the\n>   processor node. This allows PPTT tables which \"share\" cache nodes\n>   across cpu nodes despite not being a shared cache.\n> \n> Normalize the socket, cluster and thread mapping so that they match\n>   linux's traditional mapping for the physical id, and thread id.\n>   Adding explicit scheduler knowledge of clusters (rather than just\n>   their cache sharing attributes) is a subject for a future patch.\n> \n> Jeremy Linton (6):\n>   ACPI/PPTT: Add Processor Properties Topology Table parsing\n>   ACPI: Enable PPTT support on ARM64\n>   drivers: base: cacheinfo: arm64: Add support for ACPI based firmware\n>     tables\n>   Topology: Add cluster on die macros and arm64 decoding\n>   arm64: Fixup users of topology_physical_package_id\n>   arm64: topology: Enable ACPI/PPTT based CPU topology.\n> \n>  arch/arm64/Kconfig                |   1 +\n>  arch/arm64/include/asm/topology.h |   4 +-\n>  arch/arm64/kernel/cacheinfo.c     |  23 +-\n>  arch/arm64/kernel/topology.c      |  62 ++++-\n>  drivers/acpi/Makefile             |   1 +\n>  drivers/acpi/arm64/Kconfig        |   3 +\n>  drivers/acpi/pptt.c               | 459 ++++++++++++++++++++++++++++++++++++++\n>  drivers/base/cacheinfo.c          |  17 +-\n>  drivers/clk/clk-mb86s7x.c         |   2 +-\n>  drivers/cpufreq/arm_big_little.c  |   2 +-\n>  drivers/firmware/psci_checker.c   |   2 +-\n>  include/linux/cacheinfo.h         |  10 +-\n>  include/linux/topology.h          |   4 +\n>  13 files changed, 570 insertions(+), 20 deletions(-)\n>  create mode 100644 drivers/acpi/pptt.c\n>","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"ibYCcJHR\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xxrFK3yvdz9s7h\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tWed, 20 Sep 2017 16:59:01 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duYyI-0002CN-2t; Wed, 20 Sep 2017 06:58:58 +0000","from szxga04-in.huawei.com ([45.249.212.190])\n\tby bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duYxO-0001Ys-R9 for linux-arm-kernel@lists.infradead.org;\n\tWed, 20 Sep 2017 06:58:08 +0000","from 172.30.72.60 (EHLO DGGEMS402-HUB.china.huawei.com)\n\t([172.30.72.60])\n\tby dggrg04-dlp.huawei.com (MOS 4.4.6-GA FastPath queued)\n\twith ESMTP id DHP38245; Wed, 20 Sep 2017 14:57:09 +0800 (CST)","from [127.0.0.1] (10.177.32.209) by DGGEMS402-HUB.china.huawei.com\n\t(10.3.19.202) with Microsoft SMTP Server id 14.3.301.0;\n\tWed, 20 Sep 2017 14:57:00 +0800"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:\n\tMessage-ID:From:References:To:Subject:Reply-To:Content-ID:Content-Description\n\t:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=Admc3OwlZTshCMhpYVPVekS3hUIFGES9t5ue/uVpqXs=;\n\tb=ibYCcJHROhxfpI\n\tJ0fPtz/sDSHmEZzpN9amNU535Kooqj22US3maLg2pKAuq0lPwSywzgT1TbbndU0reEjiV9Ww9X1kd\n\t6gc6bcmjCeaNbicCd1AEKvAUy2jFIVJ4gUqHonjhVqWu9lC8FgqUGLqPgpmvhtf3uliTK4+7JwjJZ\n\tz9g+mhERjUBFqK+MfLyfzINzfKXgD3KD5hHoYlhSBm2kW/vflynSz0mT5RJiBxLL/7jg1VwHO5eTK\n\thCZAl4Ix0NKqqX+2vDn1zBJEBtK5PpJYdKJAhRYzFV3jUjAzMc2+p7E2DqGfAHjKiGfNhqhsQfFlL\n\tZtGdqIyFvLCkpl56+hKw==;","Subject":"Re: [PATCH v2 0/6] Support PPTT for ARM64","To":"Jeremy Linton <jeremy.linton@arm.com>, <linux-acpi@vger.kernel.org>","References":"<20170919184751.25110-1-jeremy.linton@arm.com>","From":"Xiongfeng Wang <wangxiongfeng2@huawei.com>","Message-ID":"<f0194dff-6fb4-b2ba-93a8-2dd3a5dd9186@huawei.com>","Date":"Wed, 20 Sep 2017 14:56:52 +0800","User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101\n\tThunderbird/45.2.0","MIME-Version":"1.0","In-Reply-To":"<20170919184751.25110-1-jeremy.linton@arm.com>","X-Originating-IP":"[10.177.32.209]","X-CFilter-Loop":"Reflected","X-Mirapoint-Virus-RAPID-Raw":"score=unknown(0),\n\trefid=str=0001.0A020202.59C21146.00B0, ss=1, re=0.000, recu=0.000,\n\treip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0,\n\tso=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32","X-Mirapoint-Loop-Id":"f996fa67d775ceb8805228288609d238","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170919_235803_523070_51815A65 ","X-CRM114-Status":"GOOD (  12.72  )","X-Spam-Score":"-1.9 (-)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-1.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\trjw@rjwysocki.net, mturquette@baylibre.com, linux-pm@vger.kernel.org, \n\twill.deacon@arm.com, linux-kernel@vger.kernel.org,\n\tlinux-clk@vger.kernel.org, \n\tviresh.kumar@linaro.org, hanjun.guo@linaro.org, ahs3@redhat.com,\n\tsudeep.holla@arm.com, sboyd@codeaurora.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}},{"id":1771640,"web_url":"http://patchwork.ozlabs.org/comment/1771640/","msgid":"<4c9cfa18-507b-01c4-7464-ff2b149fbb68@huawei.com>","list_archive_url":null,"date":"2017-09-20T07:15:53","subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","submitter":{"id":72343,"url":"http://patchwork.ozlabs.org/api/people/72343/","name":"Xiongfeng Wang","email":"wangxiongfeng2@huawei.com"},"content":"Hi Jeremy,\n\nOn 2017/9/20 2:47, Jeremy Linton wrote:\n> ACPI 6.2 adds a new table, which describes how processing units\n> are related to each other in tree like fashion. Caches are\n> also sprinkled throughout the tree and describe the properties\n> of the caches in relation to other caches and processing units.\n> \n> Add the code to parse the cache hierarchy and report the total\n> number of levels of cache for a given core using\n> acpi_find_last_cache_level() as well as fill out the individual\n> cores cache information with cache_setup_acpi() once the\n> cpu_cacheinfo structure has been populated by the arch specific\n> code.\n> \n> Further, report peers in the topology using setup_acpi_cpu_topology()\n> to report a unique ID for each processing unit at a given level\n> in the tree. These unique id's can then be used to match related\n> processing units which exist as threads, COD (clusters\n> on die), within a given package, etc.\n> \n> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>\n> ---\n>  drivers/acpi/pptt.c | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 458 insertions(+)\n>  create mode 100644 drivers/acpi/pptt.c\n> \n> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c\n> new file mode 100644\n> index 000000000000..f7694fa1e0bd\n> --- /dev/null\n> +++ b/drivers/acpi/pptt.c\n> @@ -0,0 +1,458 @@\n> +/*\n> + * Copyright (C) 2017, ARM\n> + *\n> + * This program is free software; you can redistribute it and/or modify it\n> + * under the terms and conditions of the GNU General Public License,\n> + * version 2, as published by the Free Software Foundation.\n> + *\n> + * This program is distributed in the hope it will be useful, but WITHOUT\n> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n> + * more details.\n> + *\n> + * This file implements parsing of Processor Properties Topology Table (PPTT)\n> + * which is optionally used to describe the processor and cache topology.\n> + * Due to the relative pointers used throughout the table, this doesn't\n> + * leverage the existing subtable parsing in the kernel.\n> + */\n> +#define pr_fmt(fmt) \"ACPI PPTT: \" fmt\n> +\n> +#include <linux/acpi.h>\n> +#include <linux/cacheinfo.h>\n> +#include <acpi/processor.h>\n> +\n> +/*\n> + * Given the PPTT table, find and verify that the subtable entry\n> + * is located within the table\n> + */\n> +static struct acpi_subtable_header *fetch_pptt_subtable(\n> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n> +{\n> +\tstruct acpi_subtable_header *entry;\n> +\n> +\t/* there isn't a subtable at reference 0 */\n> +\tif (!pptt_ref)\n> +\t\treturn NULL;\n> +\n> +\tif (pptt_ref + sizeof(struct acpi_subtable_header) > table_hdr->length)\n> +\t\treturn NULL;\n> +\n> +\tentry = (struct acpi_subtable_header *)((u8 *)table_hdr + pptt_ref);\n> +\n> +\tif (pptt_ref + entry->length > table_hdr->length)\n> +\t\treturn NULL;\n> +\n> +\treturn entry;\n> +}\n> +\n> +static struct acpi_pptt_processor *fetch_pptt_node(\n> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n> +{\n> +\treturn (struct acpi_pptt_processor *)fetch_pptt_subtable(table_hdr, pptt_ref);\n> +}\n> +\n> +static struct acpi_pptt_cache *fetch_pptt_cache(\n> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n> +{\n> +\treturn (struct acpi_pptt_cache *)fetch_pptt_subtable(table_hdr, pptt_ref);\n> +}\n> +\n> +static struct acpi_subtable_header *acpi_get_pptt_resource(\n> +\tstruct acpi_table_header *table_hdr,\n> +\tstruct acpi_pptt_processor *node, int resource)\n> +{\n> +\tu32 ref;\n> +\n> +\tif (resource >= node->number_of_priv_resources)\n> +\t\treturn NULL;\n> +\n> +\tref = *(u32 *)((u8 *)node + sizeof(struct acpi_pptt_processor) +\n> +\t\t      sizeof(u32) * resource);\n> +\n> +\treturn fetch_pptt_subtable(table_hdr, ref);\n> +}\n> +\n> +/*\n> + * given a pptt resource, verify that it is a cache node, then walk\n> + * down each level of caches, counting how many levels are found\n> + * as well as checking the cache type (icache, dcache, unified). If a\n> + * level & type match, then we set found, and continue the search.\n> + * Once the entire cache branch has been walked return its max\n> + * depth.\n> + */\n> +static int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr,\n> +\t\t\t\tint local_level,\n> +\t\t\t\tstruct acpi_subtable_header *res,\n> +\t\t\t\tstruct acpi_pptt_cache **found,\n> +\t\t\t\tint level, int type)\n> +{\n> +\tstruct acpi_pptt_cache *cache;\n> +\n> +\tif (res->type != ACPI_PPTT_TYPE_CACHE)\n> +\t\treturn 0;\n> +\n> +\tcache = (struct acpi_pptt_cache *) res;\n> +\twhile (cache) {\n> +\t\tlocal_level++;\n> +\n> +\t\tif ((local_level == level) &&\n> +\t\t    (cache->flags & ACPI_PPTT_CACHE_TYPE_VALID) &&\n> +\t\t    ((cache->attributes & ACPI_PPTT_MASK_CACHE_TYPE) == type)) {\n> +\t\t\tif (*found != NULL)\n> +\t\t\t\tpr_err(\"Found duplicate cache level/type unable to determine uniqueness\\n\");\n> +\n> +\t\t\tpr_debug(\"Found cache @ level %d\\n\", level);\n> +\t\t\t*found = cache;\n> +\t\t\t/*\n> +\t\t\t * continue looking at this node's resource list\n> +\t\t\t * to verify that we don't find a duplicate\n> +\t\t\t * cache node.\n> +\t\t\t */\n> +\t\t}\n> +\t\tcache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache);\n> +\t}\n> +\treturn local_level;\n> +}\n> +\n> +/*\n> + * Given a CPU node look for cache levels that exist at this level, and then\n> + * for each cache node, count how many levels exist below (logically above) it.\n> + * If a level and type are specified, and we find that level/type, abort\n> + * processing and return the acpi_pptt_cache structure.\n> + */\n> +static struct acpi_pptt_cache *acpi_find_cache_level(\n> +\tstruct acpi_table_header *table_hdr,\n> +\tstruct acpi_pptt_processor *cpu_node,\n> +\tint *starting_level, int level, int type)\n> +{\n> +\tstruct acpi_subtable_header *res;\n> +\tint number_of_levels = *starting_level;\n> +\tint resource = 0;\n> +\tstruct acpi_pptt_cache *ret = NULL;\n> +\tint local_level;\n> +\n> +\t/* walk down from processor node */\n> +\twhile ((res = acpi_get_pptt_resource(table_hdr, cpu_node, resource))) {\n> +\t\tresource++;\n> +\n> +\t\tlocal_level = acpi_pptt_walk_cache(table_hdr, *starting_level,\n> +\t\t\t\t\t\t   res, &ret, level, type);\n> +\t\t/*\n> +\t\t * we are looking for the max depth. Since its potentially\n> +\t\t * possible for a given node to have resources with differing\n> +\t\t * depths verify that the depth we have found is the largest.\n> +\t\t */\n> +\t\tif (number_of_levels < local_level)\n> +\t\t\tnumber_of_levels = local_level;\n> +\t}\n> +\tif (number_of_levels > *starting_level)\n> +\t\t*starting_level = number_of_levels;\n> +\n> +\treturn ret;\n> +}\n> +\n> +/*\n> + * given a processor node containing a processing unit, walk into it and count\n> + * how many levels exist solely for it, and then walk up each level until we hit\n> + * the root node (ignore the package level because it may be possible to have\n> + * caches that exist across packages). Count the number of cache levels that\n> + * exist at each level on the way up.\n> + */\n> +static int acpi_process_node(struct acpi_table_header *table_hdr,\n> +\t\t\t     struct acpi_pptt_processor *cpu_node)\n> +{\n> +\tint total_levels = 0;\n> +\n> +\tdo {\n> +\t\tacpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0);\n> +\t\tcpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);\n> +\t} while (cpu_node);\n> +\n> +\treturn total_levels;\n> +}\n> +\n> +/*\n> + * Find the subtable entry describing the provided processor\n> + */\n> +static struct acpi_pptt_processor *acpi_find_processor_node(\n> +\tstruct acpi_table_header *table_hdr,\n> +\tu32 acpi_cpu_id)\n> +{\n> +\tstruct acpi_subtable_header *entry;\n> +\tunsigned long table_end;\n> +\tstruct acpi_pptt_processor *cpu_node;\n> +\n> +\ttable_end = (unsigned long)table_hdr + table_hdr->length;\n> +\tentry = (struct acpi_subtable_header *)((u8 *)table_hdr +\n> +\t\t\t\t\t\tsizeof(struct acpi_table_pptt));\n> +\n> +\t/* find the processor structure associated with this cpuid */\n> +\twhile (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < table_end) {\n> +\t\tcpu_node = (struct acpi_pptt_processor *)entry;\n> +\n> +\t\tif ((entry->type == ACPI_PPTT_TYPE_PROCESSOR) &&\n> +\t\t    (cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)) {\n> +\t\t\tpr_debug(\"checking phy_cpu_id %d against acpi id %d\\n\",\n> +\t\t\t\t acpi_cpu_id, cpu_node->acpi_processor_id);\n> +\t\t\tif (acpi_cpu_id == cpu_node->acpi_processor_id) {\n> +\t\t\t\t/* found the correct entry */\n> +\t\t\t\tpr_debug(\"match found!\\n\");\n> +\t\t\t\treturn (struct acpi_pptt_processor *)entry;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (entry->length == 0) {\n> +\t\t\tpr_err(\"Invalid zero length subtable\\n\");\n> +\t\t\tbreak;\n> +\t\t}\n> +\t\tentry = (struct acpi_subtable_header *)\n> +\t\t\t((u8 *)entry + entry->length);\n> +\t}\n> +\n> +\treturn NULL;\n> +}\n> +\n> +/*\n> + * Given a acpi_pptt_processor node, walk up until we identify the\n> + * package that the node is associated with or we run out of levels\n> + * to request.\n> + */\n> +static struct acpi_pptt_processor *acpi_find_processor_package_id(\n> +\tstruct acpi_table_header *table_hdr,\n> +\tstruct acpi_pptt_processor *cpu,\n> +\tint level)\n> +{\n> +\tstruct acpi_pptt_processor *prev_node;\n> +\n> +\twhile (cpu && level && !(cpu->flags & ACPI_PPTT_PHYSICAL_PACKAGE)) {\n> +\t\tpr_debug(\"level %d\\n\", level);\n> +\t\tprev_node = fetch_pptt_node(table_hdr, cpu->parent);\n> +\t\tif (prev_node == NULL)\n> +\t\t\tbreak;\n> +\t\tcpu = prev_node;\n> +\t\tlevel--;\n> +\t}\n> +\treturn cpu;\n> +}\n> +\n> +static int acpi_parse_pptt(struct acpi_table_header *table_hdr, u32 acpi_cpu_id)\n> +{\n> +\tint number_of_levels = 0;\n> +\tstruct acpi_pptt_processor *cpu;\n> +\n> +\tcpu = acpi_find_processor_node(table_hdr, acpi_cpu_id);\n> +\tif (cpu)\n> +\t\tnumber_of_levels = acpi_process_node(table_hdr, cpu);\n> +\n> +\treturn number_of_levels;\n> +}\n> +\n> +#define ACPI_6_2_CACHE_TYPE_DATA\t\t      (0x0)\n> +#define ACPI_6_2_CACHE_TYPE_INSTR\t\t      (1<<2)\n> +#define ACPI_6_2_CACHE_TYPE_UNIFIED\t\t      (1<<3)\n> +#define ACPI_6_2_CACHE_POLICY_WB\t\t      (0x0)\n> +#define ACPI_6_2_CACHE_POLICY_WT\t\t      (1<<4)\n> +#define ACPI_6_2_CACHE_READ_ALLOCATE\t\t      (0x0)\n> +#define ACPI_6_2_CACHE_WRITE_ALLOCATE\t\t      (0x01)\n> +#define ACPI_6_2_CACHE_RW_ALLOCATE\t\t      (0x02)\n> +\n> +static u8 acpi_cache_type(enum cache_type type)\n> +{\n> +\tswitch (type) {\n> +\tcase CACHE_TYPE_DATA:\n> +\t\tpr_debug(\"Looking for data cache\\n\");\n> +\t\treturn ACPI_6_2_CACHE_TYPE_DATA;\n> +\tcase CACHE_TYPE_INST:\n> +\t\tpr_debug(\"Looking for instruction cache\\n\");\n> +\t\treturn ACPI_6_2_CACHE_TYPE_INSTR;\n> +\tdefault:\n> +\t\tpr_debug(\"Unknown cache type, assume unified\\n\");\n> +\tcase CACHE_TYPE_UNIFIED:\n> +\t\tpr_debug(\"Looking for unified cache\\n\");\n> +\t\treturn ACPI_6_2_CACHE_TYPE_UNIFIED;\n> +\t}\n> +}\n> +\n> +/* find the ACPI node describing the cache type/level for the given CPU */\n> +static struct acpi_pptt_cache *acpi_find_cache_node(\n> +\tstruct acpi_table_header *table_hdr, u32 acpi_cpu_id,\n> +\tenum cache_type type, unsigned int level,\n> +\tstruct acpi_pptt_processor **node)\n> +{\n> +\tint total_levels = 0;\n> +\tstruct acpi_pptt_cache *found = NULL;\n> +\tstruct acpi_pptt_processor *cpu_node;\n> +\tu8 acpi_type = acpi_cache_type(type);\n> +\n> +\tpr_debug(\"Looking for CPU %d's level %d cache type %d\\n\",\n> +\t\t acpi_cpu_id, level, acpi_type);\n> +\n> +\tcpu_node = acpi_find_processor_node(table_hdr, acpi_cpu_id);\n> +\tif (!cpu_node)\n> +\t\treturn NULL;\n> +\n> +\tdo {\n> +\t\tfound = acpi_find_cache_level(table_hdr, cpu_node, &total_levels, level, acpi_type);\n> +\t\t*node = cpu_node;\n> +\t\tcpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);\n> +\t} while ((cpu_node) && (!found));\n> +\n> +\treturn found;\n> +}\n> +\n> +int acpi_find_last_cache_level(unsigned int cpu)\n> +{\n> +\tu32 acpi_cpu_id;\n> +\tstruct acpi_table_header *table;\n> +\tint number_of_levels = 0;\n> +\tacpi_status status;\n> +\n> +\tpr_debug(\"Cache Setup find last level cpu=%d\\n\", cpu);\n> +\n> +\tacpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n> +\tif (ACPI_FAILURE(status)) {\n> +\t\tpr_err_once(\"No PPTT table found, cache topology may be inaccurate\\n\");\n> +\t} else {\n> +\t\tnumber_of_levels = acpi_parse_pptt(table, acpi_cpu_id);\n> +\t\tacpi_put_table(table);\n> +\t}\n> +\tpr_debug(\"Cache Setup find last level level=%d\\n\", number_of_levels);\n> +\n> +\treturn number_of_levels;\n> +}\n> +\n> +/*\n> + * The ACPI spec implies that the fields in the cache structures are used to\n> + * extend and correct the information probed from the hardware. In the case\n> + * of arm64 the CCSIDR probing has been removed because it might be incorrect.\n> + */\n> +static void update_cache_properties(struct cacheinfo *this_leaf,\n> +\t\t\t\t    struct acpi_pptt_cache *found_cache,\n> +\t\t\t\t    struct acpi_pptt_processor *cpu_node)\n> +{\n> +\tif (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID)\n> +\t\tthis_leaf->size = found_cache->size;\n> +\tif (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID)\n> +\t\tthis_leaf->coherency_line_size = found_cache->line_size;\n> +\tif (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID)\n> +\t\tthis_leaf->number_of_sets = found_cache->number_of_sets;\n> +\tif (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID)\n> +\t\tthis_leaf->ways_of_associativity = found_cache->associativity;\n> +\tif (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID)\n> +\t\tswitch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) {\n> +\t\tcase ACPI_6_2_CACHE_POLICY_WT:\n> +\t\t\tthis_leaf->attributes = CACHE_WRITE_THROUGH;\n> +\t\t\tbreak;\n> +\t\tcase ACPI_6_2_CACHE_POLICY_WB:\n> +\t\t\tthis_leaf->attributes = CACHE_WRITE_BACK;\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\tpr_err(\"Unknown ACPI cache policy %d\\n\",\n> +\t\t\t      found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY);\n> +\t\t}\n> +\tif (found_cache->flags & ACPI_PPTT_ALLOCATION_TYPE_VALID)\n> +\t\tswitch (found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE) {\n> +\t\tcase ACPI_6_2_CACHE_READ_ALLOCATE:\n> +\t\t\tthis_leaf->attributes |= CACHE_READ_ALLOCATE;\n> +\t\t\tbreak;\n> +\t\tcase ACPI_6_2_CACHE_WRITE_ALLOCATE:\n> +\t\t\tthis_leaf->attributes |= CACHE_WRITE_ALLOCATE;\n> +\t\t\tbreak;\n> +\t\tcase ACPI_6_2_CACHE_RW_ALLOCATE:\n> +\t\t\tthis_leaf->attributes |=\n> +\t\t\t\tCACHE_READ_ALLOCATE|CACHE_WRITE_ALLOCATE;\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\tpr_err(\"Unknown ACPI cache allocation policy %d\\n\",\n> +\t\t\t   found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE);\n> +\t\t}\n> +}\n> +\n> +static void cache_setup_acpi_cpu(struct acpi_table_header *table,\n> +\t\t\t\t unsigned int cpu)\n> +{\n> +\tstruct acpi_pptt_cache *found_cache;\n> +\tstruct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);\n> +\tu32 acpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n> +\tstruct cacheinfo *this_leaf;\n> +\tunsigned int index = 0;\n> +\tstruct acpi_pptt_processor *cpu_node = NULL;\n> +\n> +\twhile (index < get_cpu_cacheinfo(cpu)->num_leaves) {\n> +\t\tthis_leaf = this_cpu_ci->info_list + index;\n> +\t\tfound_cache = acpi_find_cache_node(table, acpi_cpu_id,\n> +\t\t\t\t\t\t   this_leaf->type,\n> +\t\t\t\t\t\t   this_leaf->level,\n> +\t\t\t\t\t\t   &cpu_node);\n> +\t\tpr_debug(\"found = %p %p\\n\", found_cache, cpu_node);\n> +\t\tif (found_cache)\n> +\t\t\tupdate_cache_properties(this_leaf,\n> +\t\t\t\t\t\tfound_cache,\n> +\t\t\t\t\t\tcpu_node);\n> +\n> +\t\tindex++;\n> +\t}\n> +}\n> +\n> +static int topology_setup_acpi_cpu(struct acpi_table_header *table,\n> +\t\t\t\t    unsigned int cpu, int level)\n> +{\n> +\tstruct acpi_pptt_processor *cpu_node;\n> +\tu32 acpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n> +\n> +\tcpu_node = acpi_find_processor_node(table, acpi_cpu_id);\n> +\tif (cpu_node) {\n> +\t\tcpu_node = acpi_find_processor_package_id(table, cpu_node, level);\n> +\t\treturn (int)((u8 *)cpu_node - (u8 *)table);\n> +\t}\n> +\tpr_err_once(\"PPTT table found, but unable to locate core for %d\\n\",\n> +\t\t    cpu);\n> +\treturn -ENOENT;\n\nCan we return -1 when PPTT doesn't exist? So that we can still get topo info from MPIDR.\n'store_cpu_topology()' determine whether cpu topology has been populated by checking\nwhether cluster_id is -1. If cluster_id is not -1, it won't read cpu topo info from MPIDR.\nOr maybe we can change 'store_cpu_topology()' as well. If cluster_id is less than zero,\nwe read cpu topo info from MPIDR.\n\n> +}\n> +\n> +/*\n> + * simply assign a ACPI cache entry to each known CPU cache entry\n> + * determining which entries are shared is done later.\n> + */\n> +int cache_setup_acpi(unsigned int cpu)\n> +{\n> +\tstruct acpi_table_header *table;\n> +\tacpi_status status;\n> +\n> +\tpr_debug(\"Cache Setup ACPI cpu %d\\n\", cpu);\n> +\n> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n> +\tif (ACPI_FAILURE(status)) {\n> +\t\tpr_err_once(\"No PPTT table found, cache topology may be inaccurate\\n\");\n> +\t\treturn -ENOENT;\n> +\t}\n> +\n> +\tcache_setup_acpi_cpu(table, cpu);\n> +\tacpi_put_table(table);\n> +\n> +\treturn status;\n> +}\n> +\n> +/*\n> + * Determine a topology unique ID for each thread/core/cluster/socket/etc.\n> + * This ID can then be used to group peers.\n> + */\n> +int setup_acpi_cpu_topology(unsigned int cpu, int level)\n> +{\n> +\tstruct acpi_table_header *table;\n> +\tacpi_status status;\n> +\tint retval;\n\nCan we add a static int array to record already assigned id for each level?\nSo that we can count the id starting from zero. And also the id can be successive.\n\n> +\n> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n> +\tif (ACPI_FAILURE(status)) {\n> +\t\tpr_err_once(\"No PPTT table found, cpu topology may be inaccurate\\n\");\n> +\t\treturn -ENOENT;\n> +\t}\n> +\tretval = topology_setup_acpi_cpu(table, cpu, level);\n> +\tpr_debug(\"Topology Setup ACPI cpu %d, level %d ret = %d\\n\",\n> +\t\t cpu, level, retval);\n> +\tacpi_put_table(table);\n> +\n> +\treturn retval;\n> +}\n>","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"dEJYQ/kd\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xxrfZ4z54z9s81\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tWed, 20 Sep 2017 17:17:26 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duZG6-00058Y-U5; Wed, 20 Sep 2017 07:17:22 +0000","from szxga05-in.huawei.com ([45.249.212.191])\n\tby bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duZFy-00051p-KQ for linux-arm-kernel@lists.infradead.org;\n\tWed, 20 Sep 2017 07:17:20 +0000","from 172.30.72.59 (EHLO DGGEMS406-HUB.china.huawei.com)\n\t([172.30.72.59])\n\tby dggrg05-dlp.huawei.com (MOS 4.4.6-GA FastPath queued)\n\twith ESMTP id DHR43369; Wed, 20 Sep 2017 15:16:16 +0800 (CST)","from [127.0.0.1] (10.177.32.209) by DGGEMS406-HUB.china.huawei.com\n\t(10.3.19.206) with Microsoft SMTP Server id 14.3.301.0;\n\tWed, 20 Sep 2017 15:16:02 +0800"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:\n\tMessage-ID:From:References:To:Subject:Reply-To:Content-ID:Content-Description\n\t:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=rOF060IyzCfDKF3Pwl8v88ZbRyt5ihM7pWq3jVtWk1I=;\n\tb=dEJYQ/kdLw0Os0\n\tcr1LK7tr+D8iY6YSDlWNgJ5NS+B78iSBrokHQuqzDXejul9UMFKVtrdW04MFiKjr7JrENpoWvdKb4\n\tH35mEZuK7bzxhAU4XJFNeTRJ6pfNwf7i+FecdG45yEGm/h90xtMNp97UKhikV7ggsj2zF86DotGYg\n\tgGfd/NCWPhB8ehJlEAN7gd8pu11v9AKQgeCv/Ds6ahGWxJ6oHPXtblMtRRVhsr4ZCK2qgReFQVEH/\n\tiiIVw9/7XagQiSazvz+VKTLKq4DX2yoEuJ+mxrT41GvoEjjDkCFj5Lw0F6lIK6KCkC+4QVEnISez+\n\toeNs1GiZpDu1CSLJzhNw==;","Subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","To":"Jeremy Linton <jeremy.linton@arm.com>, <linux-acpi@vger.kernel.org>","References":"<20170919184751.25110-1-jeremy.linton@arm.com>\n\t<20170919184751.25110-2-jeremy.linton@arm.com>","From":"Xiongfeng Wang <wangxiongfeng2@huawei.com>","Message-ID":"<4c9cfa18-507b-01c4-7464-ff2b149fbb68@huawei.com>","Date":"Wed, 20 Sep 2017 15:15:53 +0800","User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101\n\tThunderbird/45.2.0","MIME-Version":"1.0","In-Reply-To":"<20170919184751.25110-2-jeremy.linton@arm.com>","X-Originating-IP":"[10.177.32.209]","X-CFilter-Loop":"Reflected","X-Mirapoint-Virus-RAPID-Raw":"score=unknown(0),\n\trefid=str=0001.0A010201.59C215C5.003A, ss=1, re=0.000, recu=0.000,\n\treip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0,\n\tso=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32","X-Mirapoint-Loop-Id":"a64af2f2721ca95098a95fccf2ed6ad2","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170920_001715_495097_A110C50C ","X-CRM114-Status":"GOOD (  28.53  )","X-Spam-Score":"-1.9 (-)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-1.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\trjw@rjwysocki.net, mturquette@baylibre.com, linux-pm@vger.kernel.org, \n\twill.deacon@arm.com, linux-kernel@vger.kernel.org,\n\tlinux-clk@vger.kernel.org, \n\tviresh.kumar@linaro.org, hanjun.guo@linaro.org, ahs3@redhat.com,\n\tsudeep.holla@arm.com, sboyd@codeaurora.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}},{"id":1772000,"web_url":"http://patchwork.ozlabs.org/comment/1772000/","msgid":"<5b8cdaa2-7ab4-078a-8a00-6fc54d94863e@arm.com>","list_archive_url":null,"date":"2017-09-20T15:45:23","subject":"Re: [PATCH v2 3/6] drivers: base: cacheinfo: arm64: Add support for\n\tACPI based firmware tables","submitter":{"id":67035,"url":"http://patchwork.ozlabs.org/api/people/67035/","name":"Jeremy Linton","email":"jeremy.linton@arm.com"},"content":"Hi,\n\n\nOn 09/19/2017 01:47 PM, Jeremy Linton wrote:\n> The /sys cache entries should support ACPI/PPTT generated cache\n> topology information. Lets detect ACPI systems and call\n> an arch specific cache_setup_acpi() routine to update the hardware\n> probed cache topology.\n> \n> For arm64, if ACPI is enabled, determine the max number of cache\n> levels and populate them using a PPTT table if one is available.\n> \n> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>\n> ---\n>   arch/arm64/kernel/cacheinfo.c | 23 ++++++++++++++++++-----\n>   drivers/acpi/pptt.c           |  1 +\n>   drivers/base/cacheinfo.c      | 17 +++++++++++------\n>   include/linux/cacheinfo.h     | 10 ++++++++--\n>   4 files changed, 38 insertions(+), 13 deletions(-)\n> \n> diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c\n> index 380f2e2fbed5..2e2cf0d312ba 100644\n> --- a/arch/arm64/kernel/cacheinfo.c\n> +++ b/arch/arm64/kernel/cacheinfo.c\n> @@ -17,6 +17,7 @@\n>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n>    */\n>   \n> +#include <linux/acpi.h>\n>   #include <linux/cacheinfo.h>\n>   #include <linux/of.h>\n>   \n> @@ -44,9 +45,17 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,\n>   \tthis_leaf->type = type;\n>   }\n>   \n> +#ifndef CONFIG_ACPI\n> +int acpi_find_last_cache_level(unsigned int cpu)\n> +{\n> +\t/*ACPI kernels should be built with PPTT support*/\n> +\treturn 0;\n> +}\n> +#endif\n> +\n>   static int __init_cache_level(unsigned int cpu)\n>   {\n> -\tunsigned int ctype, level, leaves, of_level;\n> +\tunsigned int ctype, level, leaves, fw_level;\n>   \tstruct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);\n>   \n>   \tfor (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {\n> @@ -59,15 +68,19 @@ static int __init_cache_level(unsigned int cpu)\n>   \t\tleaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;\n>   \t}\n>   \n> -\tof_level = of_find_last_cache_level(cpu);\n> -\tif (level < of_level) {\n> +\tif (acpi_disabled)\n> +\t\tfw_level = of_find_last_cache_level(cpu);\n> +\telse\n> +\t\tfw_level = acpi_find_last_cache_level(cpu);\n> +\n> +\tif (level < fw_level) {\n>   \t\t/*\n>   \t\t * some external caches not specified in CLIDR_EL1\n>   \t\t * the information may be available in the device tree\n>   \t\t * only unified external caches are considered here\n>   \t\t */\n> -\t\tleaves += (of_level - level);\n> -\t\tlevel = of_level;\n> +\t\tleaves += (fw_level - level);\n> +\t\tlevel = fw_level;\n>   \t}\n>   \n>   \tthis_cpu_ci->num_levels = level;\n> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c\n> index f7694fa1e0bd..0dd918c3782c 100644\n> --- a/drivers/acpi/pptt.c\n> +++ b/drivers/acpi/pptt.c\n> @@ -331,6 +331,7 @@ static void update_cache_properties(struct cacheinfo *this_leaf,\n>   \t\t\t\t    struct acpi_pptt_cache *found_cache,\n>   \t\t\t\t    struct acpi_pptt_processor *cpu_node)\n>   {\n> +\tthis_leaf->firmware_node = found_cache;\n\nNaturally, I messed up the v2 changes when I merged them. This line \nshould equal the cpu_node.\n\n\n\n>   \tif (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID)\n>   \t\tthis_leaf->size = found_cache->size;\n>   \tif (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID)\n> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c\n> index eb3af2739537..8eca279e50d1 100644\n> --- a/drivers/base/cacheinfo.c\n> +++ b/drivers/base/cacheinfo.c\n> @@ -86,7 +86,7 @@ static int cache_setup_of_node(unsigned int cpu)\n>   static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf,\n>   \t\t\t\t\t   struct cacheinfo *sib_leaf)\n>   {\n> -\treturn sib_leaf->of_node == this_leaf->of_node;\n> +\treturn sib_leaf->firmware_node == this_leaf->firmware_node;\n>   }\n>   \n>   /* OF properties to query for a given cache type */\n> @@ -215,6 +215,11 @@ static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf,\n>   }\n>   #endif\n>   \n> +int __weak cache_setup_acpi(unsigned int cpu)\n> +{\n> +\treturn -ENOTSUPP;\n> +}\n> +\n>   static int cache_shared_cpu_map_setup(unsigned int cpu)\n>   {\n>   \tstruct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);\n> @@ -225,11 +230,11 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)\n>   \tif (this_cpu_ci->cpu_map_populated)\n>   \t\treturn 0;\n>   \n> -\tif (of_have_populated_dt())\n> +\tif (!acpi_disabled)\n> +\t\tret = cache_setup_acpi(cpu);\n> +\telse if (of_have_populated_dt())\n>   \t\tret = cache_setup_of_node(cpu);\n> -\telse if (!acpi_disabled)\n> -\t\t/* No cache property/hierarchy support yet in ACPI */\n> -\t\tret = -ENOTSUPP;\n> +\n>   \tif (ret)\n>   \t\treturn ret;\n>   \n> @@ -286,7 +291,7 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)\n>   \n>   static void cache_override_properties(unsigned int cpu)\n>   {\n> -\tif (of_have_populated_dt())\n> +\tif (acpi_disabled && of_have_populated_dt())\n>   \t\treturn cache_of_override_properties(cpu);\n>   }\n>   \n> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h\n> index 6a524bf6a06d..0114eb9ab67b 100644\n> --- a/include/linux/cacheinfo.h\n> +++ b/include/linux/cacheinfo.h\n> @@ -36,6 +36,9 @@ enum cache_type {\n>    * @of_node: if devicetree is used, this represents either the cpu node in\n>    *\tcase there's no explicit cache node or the cache node itself in the\n>    *\tdevice tree\n> + * @firmware_node: Shared with of_node. When not using DT, this may contain\n> + *\tpointers to other firmware based values. Particularly ACPI/PPTT\n> + *\tunique values.\n>    * @disable_sysfs: indicates whether this node is visible to the user via\n>    *\tsysfs or not\n>    * @priv: pointer to any private data structure specific to particular\n> @@ -64,8 +67,10 @@ struct cacheinfo {\n>   #define CACHE_ALLOCATE_POLICY_MASK\t\\\n>   \t(CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE)\n>   #define CACHE_ID\t\tBIT(4)\n> -\n> -\tstruct device_node *of_node;\n> +\tunion {\n> +\t\tstruct device_node *of_node;\n> +\t\tvoid *firmware_node;\n> +\t};\n>   \tbool disable_sysfs;\n>   \tvoid *priv;\n>   };\n> @@ -98,6 +103,7 @@ int func(unsigned int cpu)\t\t\t\t\t\\\n>   struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);\n>   int init_cache_level(unsigned int cpu);\n>   int populate_cache_leaves(unsigned int cpu);\n> +int acpi_find_last_cache_level(unsigned int cpu);\n>   \n>   const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf);\n>   \n>","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"cn7rbCPj\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xy3xQ0dHHz9s8J\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tThu, 21 Sep 2017 01:46:02 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duhCG-0000ta-Jy; Wed, 20 Sep 2017 15:45:56 +0000","from foss.arm.com ([217.140.101.70])\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1duhCC-0000rE-Vj for linux-arm-kernel@lists.infradead.org;\n\tWed, 20 Sep 2017 15:45:54 +0000","from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E69BC15A2;\n\tWed, 20 Sep 2017 08:45:30 -0700 (PDT)","from [192.168.229.136] (usa-sjc-mx-foss1.foss.arm.com\n\t[217.140.101.70])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id\n\t9B0FA3F58C; Wed, 20 Sep 2017 08:45:28 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:Content-Type:\n\tContent-Transfer-Encoding:Cc:List-Subscribe:List-Help:List-Post:List-Archive:\n\tList-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From:\n\tReferences:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date:\n\tResent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner;\n\tbh=1lVNTkhBh6KMsb3nt8NpIJpBknEFGgFZFGDUIhHDYz8=;\n\tb=cn7rbCPj1N9I8QqbexohcHR1B\n\tTmLC+bfcfVGR/WNRPN1E/z1TmROemsRd37+s3Gt1iD2LIdgPWENR7v8NKbYye4Fm8ypqK3q207UuL\n\tM9qpH7mFpdnHY3lyGsSgH7nGZUeZVGZaWReoHoyI9lQfpS7K7JogznIorYBnDsdTPPAcPYwiubJw2\n\tSlPGICdeOPKhZpF9tfJ8H+LEzaxDbgxrdTJeLOiVcszpS8X3IRSPS1JINy36cf2KMC7d4Bb9x0I5k\n\tdcTMA8MtqN0SGoeSTlDaR20hgbngv0SGWIEPCK2naiAv2zX/CriZ4s1SbMbbuk4lKsn45j66Axjs6\n\tS9vfw8LvQ==;","Subject":"Re: [PATCH v2 3/6] drivers: base: cacheinfo: arm64: Add support for\n\tACPI based firmware tables","To":"linux-acpi@vger.kernel.org","References":"<20170919184751.25110-1-jeremy.linton@arm.com>\n\t<20170919184751.25110-4-jeremy.linton@arm.com>","From":"Jeremy Linton <jeremy.linton@arm.com>","Message-ID":"<5b8cdaa2-7ab4-078a-8a00-6fc54d94863e@arm.com>","Date":"Wed, 20 Sep 2017 10:45:23 -0500","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<20170919184751.25110-4-jeremy.linton@arm.com>","Content-Language":"en-US","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170920_084553_037324_8201562E ","X-CRM114-Status":"GOOD (  22.20  )","X-Spam-Score":"-6.9 (------)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-6.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/,\n\thigh trust [217.140.101.70 listed in list.dnswl.org]\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\trjw@rjwysocki.net, mturquette@baylibre.com, linux-pm@vger.kernel.org, \n\twill.deacon@arm.com, linux-kernel@vger.kernel.org,\n\tlinux-clk@vger.kernel.org, \n\twangxiongfeng2@huawei.com, viresh.kumar@linaro.org,\n\thanjun.guo@linaro.org, \n\tahs3@redhat.com, sudeep.holla@arm.com, sboyd@codeaurora.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Transfer-Encoding":"7bit","Content-Type":"text/plain; charset=\"us-ascii\"; Format=\"flowed\"","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}},{"id":1773064,"web_url":"http://patchwork.ozlabs.org/comment/1773064/","msgid":"<03912538-f7bf-f235-c87f-3ba275502db0@arm.com>","list_archive_url":null,"date":"2017-09-21T18:48:51","subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","submitter":{"id":67035,"url":"http://patchwork.ozlabs.org/api/people/67035/","name":"Jeremy Linton","email":"jeremy.linton@arm.com"},"content":"Hi,\n\nOn 09/20/2017 02:15 AM, Xiongfeng Wang wrote:\n> Hi Jeremy,\n> \n> On 2017/9/20 2:47, Jeremy Linton wrote:\n>> ACPI 6.2 adds a new table, which describes how processing units\n>> are related to each other in tree like fashion. Caches are\n>> also sprinkled throughout the tree and describe the properties\n>> of the caches in relation to other caches and processing units.\n>>\n>> Add the code to parse the cache hierarchy and report the total\n>> number of levels of cache for a given core using\n>> acpi_find_last_cache_level() as well as fill out the individual\n>> cores cache information with cache_setup_acpi() once the\n>> cpu_cacheinfo structure has been populated by the arch specific\n>> code.\n>>\n>> Further, report peers in the topology using setup_acpi_cpu_topology()\n>> to report a unique ID for each processing unit at a given level\n>> in the tree. These unique id's can then be used to match related\n>> processing units which exist as threads, COD (clusters\n>> on die), within a given package, etc.\n>>\n>> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>\n>> ---\n>>   drivers/acpi/pptt.c | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n>>   1 file changed, 458 insertions(+)\n>>   create mode 100644 drivers/acpi/pptt.c\n>>\n>> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c\n>> new file mode 100644\n>> index 000000000000..f7694fa1e0bd\n>> --- /dev/null\n>> +++ b/drivers/acpi/pptt.c\n>> @@ -0,0 +1,458 @@\n>> +/*\n>> + * Copyright (C) 2017, ARM\n>> + *\n>> + * This program is free software; you can redistribute it and/or modify it\n>> + * under the terms and conditions of the GNU General Public License,\n>> + * version 2, as published by the Free Software Foundation.\n>> + *\n>> + * This program is distributed in the hope it will be useful, but WITHOUT\n>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n>> + * more details.\n>> + *\n>> + * This file implements parsing of Processor Properties Topology Table (PPTT)\n>> + * which is optionally used to describe the processor and cache topology.\n>> + * Due to the relative pointers used throughout the table, this doesn't\n>> + * leverage the existing subtable parsing in the kernel.\n>> + */\n>> +#define pr_fmt(fmt) \"ACPI PPTT: \" fmt\n>> +\n>> +#include <linux/acpi.h>\n>> +#include <linux/cacheinfo.h>\n>> +#include <acpi/processor.h>\n>> +\n>> +/*\n>> + * Given the PPTT table, find and verify that the subtable entry\n>> + * is located within the table\n>> + */\n>> +static struct acpi_subtable_header *fetch_pptt_subtable(\n>> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n>> +{\n>> +\tstruct acpi_subtable_header *entry;\n>> +\n>> +\t/* there isn't a subtable at reference 0 */\n>> +\tif (!pptt_ref)\n>> +\t\treturn NULL;\n>> +\n>> +\tif (pptt_ref + sizeof(struct acpi_subtable_header) > table_hdr->length)\n>> +\t\treturn NULL;\n>> +\n>> +\tentry = (struct acpi_subtable_header *)((u8 *)table_hdr + pptt_ref);\n>> +\n>> +\tif (pptt_ref + entry->length > table_hdr->length)\n>> +\t\treturn NULL;\n>> +\n>> +\treturn entry;\n>> +}\n>> +\n>> +static struct acpi_pptt_processor *fetch_pptt_node(\n>> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n>> +{\n>> +\treturn (struct acpi_pptt_processor *)fetch_pptt_subtable(table_hdr, pptt_ref);\n>> +}\n>> +\n>> +static struct acpi_pptt_cache *fetch_pptt_cache(\n>> +\tstruct acpi_table_header *table_hdr, u32 pptt_ref)\n>> +{\n>> +\treturn (struct acpi_pptt_cache *)fetch_pptt_subtable(table_hdr, pptt_ref);\n>> +}\n>> +\n>> +static struct acpi_subtable_header *acpi_get_pptt_resource(\n>> +\tstruct acpi_table_header *table_hdr,\n>> +\tstruct acpi_pptt_processor *node, int resource)\n>> +{\n>> +\tu32 ref;\n>> +\n>> +\tif (resource >= node->number_of_priv_resources)\n>> +\t\treturn NULL;\n>> +\n>> +\tref = *(u32 *)((u8 *)node + sizeof(struct acpi_pptt_processor) +\n>> +\t\t      sizeof(u32) * resource);\n>> +\n>> +\treturn fetch_pptt_subtable(table_hdr, ref);\n>> +}\n>> +\n>> +/*\n>> + * given a pptt resource, verify that it is a cache node, then walk\n>> + * down each level of caches, counting how many levels are found\n>> + * as well as checking the cache type (icache, dcache, unified). If a\n>> + * level & type match, then we set found, and continue the search.\n>> + * Once the entire cache branch has been walked return its max\n>> + * depth.\n>> + */\n>> +static int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr,\n>> +\t\t\t\tint local_level,\n>> +\t\t\t\tstruct acpi_subtable_header *res,\n>> +\t\t\t\tstruct acpi_pptt_cache **found,\n>> +\t\t\t\tint level, int type)\n>> +{\n>> +\tstruct acpi_pptt_cache *cache;\n>> +\n>> +\tif (res->type != ACPI_PPTT_TYPE_CACHE)\n>> +\t\treturn 0;\n>> +\n>> +\tcache = (struct acpi_pptt_cache *) res;\n>> +\twhile (cache) {\n>> +\t\tlocal_level++;\n>> +\n>> +\t\tif ((local_level == level) &&\n>> +\t\t    (cache->flags & ACPI_PPTT_CACHE_TYPE_VALID) &&\n>> +\t\t    ((cache->attributes & ACPI_PPTT_MASK_CACHE_TYPE) == type)) {\n>> +\t\t\tif (*found != NULL)\n>> +\t\t\t\tpr_err(\"Found duplicate cache level/type unable to determine uniqueness\\n\");\n>> +\n>> +\t\t\tpr_debug(\"Found cache @ level %d\\n\", level);\n>> +\t\t\t*found = cache;\n>> +\t\t\t/*\n>> +\t\t\t * continue looking at this node's resource list\n>> +\t\t\t * to verify that we don't find a duplicate\n>> +\t\t\t * cache node.\n>> +\t\t\t */\n>> +\t\t}\n>> +\t\tcache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache);\n>> +\t}\n>> +\treturn local_level;\n>> +}\n>> +\n>> +/*\n>> + * Given a CPU node look for cache levels that exist at this level, and then\n>> + * for each cache node, count how many levels exist below (logically above) it.\n>> + * If a level and type are specified, and we find that level/type, abort\n>> + * processing and return the acpi_pptt_cache structure.\n>> + */\n>> +static struct acpi_pptt_cache *acpi_find_cache_level(\n>> +\tstruct acpi_table_header *table_hdr,\n>> +\tstruct acpi_pptt_processor *cpu_node,\n>> +\tint *starting_level, int level, int type)\n>> +{\n>> +\tstruct acpi_subtable_header *res;\n>> +\tint number_of_levels = *starting_level;\n>> +\tint resource = 0;\n>> +\tstruct acpi_pptt_cache *ret = NULL;\n>> +\tint local_level;\n>> +\n>> +\t/* walk down from processor node */\n>> +\twhile ((res = acpi_get_pptt_resource(table_hdr, cpu_node, resource))) {\n>> +\t\tresource++;\n>> +\n>> +\t\tlocal_level = acpi_pptt_walk_cache(table_hdr, *starting_level,\n>> +\t\t\t\t\t\t   res, &ret, level, type);\n>> +\t\t/*\n>> +\t\t * we are looking for the max depth. Since its potentially\n>> +\t\t * possible for a given node to have resources with differing\n>> +\t\t * depths verify that the depth we have found is the largest.\n>> +\t\t */\n>> +\t\tif (number_of_levels < local_level)\n>> +\t\t\tnumber_of_levels = local_level;\n>> +\t}\n>> +\tif (number_of_levels > *starting_level)\n>> +\t\t*starting_level = number_of_levels;\n>> +\n>> +\treturn ret;\n>> +}\n>> +\n>> +/*\n>> + * given a processor node containing a processing unit, walk into it and count\n>> + * how many levels exist solely for it, and then walk up each level until we hit\n>> + * the root node (ignore the package level because it may be possible to have\n>> + * caches that exist across packages). Count the number of cache levels that\n>> + * exist at each level on the way up.\n>> + */\n>> +static int acpi_process_node(struct acpi_table_header *table_hdr,\n>> +\t\t\t     struct acpi_pptt_processor *cpu_node)\n>> +{\n>> +\tint total_levels = 0;\n>> +\n>> +\tdo {\n>> +\t\tacpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0);\n>> +\t\tcpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);\n>> +\t} while (cpu_node);\n>> +\n>> +\treturn total_levels;\n>> +}\n>> +\n>> +/*\n>> + * Find the subtable entry describing the provided processor\n>> + */\n>> +static struct acpi_pptt_processor *acpi_find_processor_node(\n>> +\tstruct acpi_table_header *table_hdr,\n>> +\tu32 acpi_cpu_id)\n>> +{\n>> +\tstruct acpi_subtable_header *entry;\n>> +\tunsigned long table_end;\n>> +\tstruct acpi_pptt_processor *cpu_node;\n>> +\n>> +\ttable_end = (unsigned long)table_hdr + table_hdr->length;\n>> +\tentry = (struct acpi_subtable_header *)((u8 *)table_hdr +\n>> +\t\t\t\t\t\tsizeof(struct acpi_table_pptt));\n>> +\n>> +\t/* find the processor structure associated with this cpuid */\n>> +\twhile (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < table_end) {\n>> +\t\tcpu_node = (struct acpi_pptt_processor *)entry;\n>> +\n>> +\t\tif ((entry->type == ACPI_PPTT_TYPE_PROCESSOR) &&\n>> +\t\t    (cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)) {\n>> +\t\t\tpr_debug(\"checking phy_cpu_id %d against acpi id %d\\n\",\n>> +\t\t\t\t acpi_cpu_id, cpu_node->acpi_processor_id);\n>> +\t\t\tif (acpi_cpu_id == cpu_node->acpi_processor_id) {\n>> +\t\t\t\t/* found the correct entry */\n>> +\t\t\t\tpr_debug(\"match found!\\n\");\n>> +\t\t\t\treturn (struct acpi_pptt_processor *)entry;\n>> +\t\t\t}\n>> +\t\t}\n>> +\n>> +\t\tif (entry->length == 0) {\n>> +\t\t\tpr_err(\"Invalid zero length subtable\\n\");\n>> +\t\t\tbreak;\n>> +\t\t}\n>> +\t\tentry = (struct acpi_subtable_header *)\n>> +\t\t\t((u8 *)entry + entry->length);\n>> +\t}\n>> +\n>> +\treturn NULL;\n>> +}\n>> +\n>> +/*\n>> + * Given a acpi_pptt_processor node, walk up until we identify the\n>> + * package that the node is associated with or we run out of levels\n>> + * to request.\n>> + */\n>> +static struct acpi_pptt_processor *acpi_find_processor_package_id(\n>> +\tstruct acpi_table_header *table_hdr,\n>> +\tstruct acpi_pptt_processor *cpu,\n>> +\tint level)\n>> +{\n>> +\tstruct acpi_pptt_processor *prev_node;\n>> +\n>> +\twhile (cpu && level && !(cpu->flags & ACPI_PPTT_PHYSICAL_PACKAGE)) {\n>> +\t\tpr_debug(\"level %d\\n\", level);\n>> +\t\tprev_node = fetch_pptt_node(table_hdr, cpu->parent);\n>> +\t\tif (prev_node == NULL)\n>> +\t\t\tbreak;\n>> +\t\tcpu = prev_node;\n>> +\t\tlevel--;\n>> +\t}\n>> +\treturn cpu;\n>> +}\n>> +\n>> +static int acpi_parse_pptt(struct acpi_table_header *table_hdr, u32 acpi_cpu_id)\n>> +{\n>> +\tint number_of_levels = 0;\n>> +\tstruct acpi_pptt_processor *cpu;\n>> +\n>> +\tcpu = acpi_find_processor_node(table_hdr, acpi_cpu_id);\n>> +\tif (cpu)\n>> +\t\tnumber_of_levels = acpi_process_node(table_hdr, cpu);\n>> +\n>> +\treturn number_of_levels;\n>> +}\n>> +\n>> +#define ACPI_6_2_CACHE_TYPE_DATA\t\t      (0x0)\n>> +#define ACPI_6_2_CACHE_TYPE_INSTR\t\t      (1<<2)\n>> +#define ACPI_6_2_CACHE_TYPE_UNIFIED\t\t      (1<<3)\n>> +#define ACPI_6_2_CACHE_POLICY_WB\t\t      (0x0)\n>> +#define ACPI_6_2_CACHE_POLICY_WT\t\t      (1<<4)\n>> +#define ACPI_6_2_CACHE_READ_ALLOCATE\t\t      (0x0)\n>> +#define ACPI_6_2_CACHE_WRITE_ALLOCATE\t\t      (0x01)\n>> +#define ACPI_6_2_CACHE_RW_ALLOCATE\t\t      (0x02)\n>> +\n>> +static u8 acpi_cache_type(enum cache_type type)\n>> +{\n>> +\tswitch (type) {\n>> +\tcase CACHE_TYPE_DATA:\n>> +\t\tpr_debug(\"Looking for data cache\\n\");\n>> +\t\treturn ACPI_6_2_CACHE_TYPE_DATA;\n>> +\tcase CACHE_TYPE_INST:\n>> +\t\tpr_debug(\"Looking for instruction cache\\n\");\n>> +\t\treturn ACPI_6_2_CACHE_TYPE_INSTR;\n>> +\tdefault:\n>> +\t\tpr_debug(\"Unknown cache type, assume unified\\n\");\n>> +\tcase CACHE_TYPE_UNIFIED:\n>> +\t\tpr_debug(\"Looking for unified cache\\n\");\n>> +\t\treturn ACPI_6_2_CACHE_TYPE_UNIFIED;\n>> +\t}\n>> +}\n>> +\n>> +/* find the ACPI node describing the cache type/level for the given CPU */\n>> +static struct acpi_pptt_cache *acpi_find_cache_node(\n>> +\tstruct acpi_table_header *table_hdr, u32 acpi_cpu_id,\n>> +\tenum cache_type type, unsigned int level,\n>> +\tstruct acpi_pptt_processor **node)\n>> +{\n>> +\tint total_levels = 0;\n>> +\tstruct acpi_pptt_cache *found = NULL;\n>> +\tstruct acpi_pptt_processor *cpu_node;\n>> +\tu8 acpi_type = acpi_cache_type(type);\n>> +\n>> +\tpr_debug(\"Looking for CPU %d's level %d cache type %d\\n\",\n>> +\t\t acpi_cpu_id, level, acpi_type);\n>> +\n>> +\tcpu_node = acpi_find_processor_node(table_hdr, acpi_cpu_id);\n>> +\tif (!cpu_node)\n>> +\t\treturn NULL;\n>> +\n>> +\tdo {\n>> +\t\tfound = acpi_find_cache_level(table_hdr, cpu_node, &total_levels, level, acpi_type);\n>> +\t\t*node = cpu_node;\n>> +\t\tcpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);\n>> +\t} while ((cpu_node) && (!found));\n>> +\n>> +\treturn found;\n>> +}\n>> +\n>> +int acpi_find_last_cache_level(unsigned int cpu)\n>> +{\n>> +\tu32 acpi_cpu_id;\n>> +\tstruct acpi_table_header *table;\n>> +\tint number_of_levels = 0;\n>> +\tacpi_status status;\n>> +\n>> +\tpr_debug(\"Cache Setup find last level cpu=%d\\n\", cpu);\n>> +\n>> +\tacpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n>> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n>> +\tif (ACPI_FAILURE(status)) {\n>> +\t\tpr_err_once(\"No PPTT table found, cache topology may be inaccurate\\n\");\n>> +\t} else {\n>> +\t\tnumber_of_levels = acpi_parse_pptt(table, acpi_cpu_id);\n>> +\t\tacpi_put_table(table);\n>> +\t}\n>> +\tpr_debug(\"Cache Setup find last level level=%d\\n\", number_of_levels);\n>> +\n>> +\treturn number_of_levels;\n>> +}\n>> +\n>> +/*\n>> + * The ACPI spec implies that the fields in the cache structures are used to\n>> + * extend and correct the information probed from the hardware. In the case\n>> + * of arm64 the CCSIDR probing has been removed because it might be incorrect.\n>> + */\n>> +static void update_cache_properties(struct cacheinfo *this_leaf,\n>> +\t\t\t\t    struct acpi_pptt_cache *found_cache,\n>> +\t\t\t\t    struct acpi_pptt_processor *cpu_node)\n>> +{\n>> +\tif (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID)\n>> +\t\tthis_leaf->size = found_cache->size;\n>> +\tif (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID)\n>> +\t\tthis_leaf->coherency_line_size = found_cache->line_size;\n>> +\tif (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID)\n>> +\t\tthis_leaf->number_of_sets = found_cache->number_of_sets;\n>> +\tif (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID)\n>> +\t\tthis_leaf->ways_of_associativity = found_cache->associativity;\n>> +\tif (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID)\n>> +\t\tswitch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) {\n>> +\t\tcase ACPI_6_2_CACHE_POLICY_WT:\n>> +\t\t\tthis_leaf->attributes = CACHE_WRITE_THROUGH;\n>> +\t\t\tbreak;\n>> +\t\tcase ACPI_6_2_CACHE_POLICY_WB:\n>> +\t\t\tthis_leaf->attributes = CACHE_WRITE_BACK;\n>> +\t\t\tbreak;\n>> +\t\tdefault:\n>> +\t\t\tpr_err(\"Unknown ACPI cache policy %d\\n\",\n>> +\t\t\t      found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY);\n>> +\t\t}\n>> +\tif (found_cache->flags & ACPI_PPTT_ALLOCATION_TYPE_VALID)\n>> +\t\tswitch (found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE) {\n>> +\t\tcase ACPI_6_2_CACHE_READ_ALLOCATE:\n>> +\t\t\tthis_leaf->attributes |= CACHE_READ_ALLOCATE;\n>> +\t\t\tbreak;\n>> +\t\tcase ACPI_6_2_CACHE_WRITE_ALLOCATE:\n>> +\t\t\tthis_leaf->attributes |= CACHE_WRITE_ALLOCATE;\n>> +\t\t\tbreak;\n>> +\t\tcase ACPI_6_2_CACHE_RW_ALLOCATE:\n>> +\t\t\tthis_leaf->attributes |=\n>> +\t\t\t\tCACHE_READ_ALLOCATE|CACHE_WRITE_ALLOCATE;\n>> +\t\t\tbreak;\n>> +\t\tdefault:\n>> +\t\t\tpr_err(\"Unknown ACPI cache allocation policy %d\\n\",\n>> +\t\t\t   found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE);\n>> +\t\t}\n>> +}\n>> +\n>> +static void cache_setup_acpi_cpu(struct acpi_table_header *table,\n>> +\t\t\t\t unsigned int cpu)\n>> +{\n>> +\tstruct acpi_pptt_cache *found_cache;\n>> +\tstruct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);\n>> +\tu32 acpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n>> +\tstruct cacheinfo *this_leaf;\n>> +\tunsigned int index = 0;\n>> +\tstruct acpi_pptt_processor *cpu_node = NULL;\n>> +\n>> +\twhile (index < get_cpu_cacheinfo(cpu)->num_leaves) {\n>> +\t\tthis_leaf = this_cpu_ci->info_list + index;\n>> +\t\tfound_cache = acpi_find_cache_node(table, acpi_cpu_id,\n>> +\t\t\t\t\t\t   this_leaf->type,\n>> +\t\t\t\t\t\t   this_leaf->level,\n>> +\t\t\t\t\t\t   &cpu_node);\n>> +\t\tpr_debug(\"found = %p %p\\n\", found_cache, cpu_node);\n>> +\t\tif (found_cache)\n>> +\t\t\tupdate_cache_properties(this_leaf,\n>> +\t\t\t\t\t\tfound_cache,\n>> +\t\t\t\t\t\tcpu_node);\n>> +\n>> +\t\tindex++;\n>> +\t}\n>> +}\n>> +\n>> +static int topology_setup_acpi_cpu(struct acpi_table_header *table,\n>> +\t\t\t\t    unsigned int cpu, int level)\n>> +{\n>> +\tstruct acpi_pptt_processor *cpu_node;\n>> +\tu32 acpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n>> +\n>> +\tcpu_node = acpi_find_processor_node(table, acpi_cpu_id);\n>> +\tif (cpu_node) {\n>> +\t\tcpu_node = acpi_find_processor_package_id(table, cpu_node, level);\n>> +\t\treturn (int)((u8 *)cpu_node - (u8 *)table);\n>> +\t}\n>> +\tpr_err_once(\"PPTT table found, but unable to locate core for %d\\n\",\n>> +\t\t    cpu);\n>> +\treturn -ENOENT;\n> \n> Can we return -1 when PPTT doesn't exist? So that we can still get topo info from MPIDR.\n> 'store_cpu_topology()' determine whether cpu topology has been populated by checking\n> whether cluster_id is -1. If cluster_id is not -1, it won't read cpu topo info from MPIDR.\n> Or maybe we can change 'store_cpu_topology()' as well. If cluster_id is less than zero,\n> we read cpu topo info from MPIDR.\n\n? I will retest this, but any negative return from setup_acpi_topology() \nfor the initial node (subsequent requests should minimally duplicate the \ncpu node rather than failing) request, should result in a call to \nreset_cpu_topology(), and the information being sourced from the MPIDR \nin store_cpu_topology(). There are various ways the tree could be \n\"damaged\" but if all the system cpus have matching valid acpi_id/cpu \nnodes, then that reflects a valid topology and there really isn't enough \ninformation to decide if its damaged. The one case where this isn't \naccurate is missing socket identifiers, but the code actually handles \nthis as well as the lack of missing cluster/thread ids (which don't \nexist in the standard).\n\n> \n>> +}\n>> +\n>> +/*\n>> + * simply assign a ACPI cache entry to each known CPU cache entry\n>> + * determining which entries are shared is done later.\n>> + */\n>> +int cache_setup_acpi(unsigned int cpu)\n>> +{\n>> +\tstruct acpi_table_header *table;\n>> +\tacpi_status status;\n>> +\n>> +\tpr_debug(\"Cache Setup ACPI cpu %d\\n\", cpu);\n>> +\n>> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n>> +\tif (ACPI_FAILURE(status)) {\n>> +\t\tpr_err_once(\"No PPTT table found, cache topology may be inaccurate\\n\");\n>> +\t\treturn -ENOENT;\n>> +\t}\n>> +\n>> +\tcache_setup_acpi_cpu(table, cpu);\n>> +\tacpi_put_table(table);\n>> +\n>> +\treturn status;\n>> +}\n>> +\n>> +/*\n>> + * Determine a topology unique ID for each thread/core/cluster/socket/etc.\n>> + * This ID can then be used to group peers.\n>> + */\n>> +int setup_acpi_cpu_topology(unsigned int cpu, int level)\n>> +{\n>> +\tstruct acpi_table_header *table;\n>> +\tacpi_status status;\n>> +\tint retval;\n> \n> Can we add a static int array to record already assigned id for each level?\n> So that we can count the id starting from zero. And also the id can be successive.\n\nI don't like the idea of a node<->generated_id array/map in this module, \nalthough I've considered a number of ways to create more normalized \nvalues. Particularly, the one area that might be useful is utilizing the \nacpi id for the cores, which is problematic in the MT case. One of my \nother alternative ideas was to plug a unique node id into a reserved \nfield in the table as the node is traversed. That idea is a little evil, \nand really should be part of the ACPI standard so the firmware is \nproviding the ID's rather than dependent on the traversal order of the \ntree.\n\nIf it turns out that these ID's need to be zero based, or some other \nlimitation I would prefer just renumbering them in \nupdate_siblings_mask() or parse_acpi_topology(). I hacked together a \npatch to renumber the package_id yesterday, but i'm pretty sure I've \nseen (non arm) machines with odd package/core ids in the past, and I \ndon't really see anything in the ABI the dictating this. Let me clean it \nup a bit and I can post it as an additional patch on top of the PPTT \npatches.\n\nSo, is this an actual use case/problem, or its just an \"appearance\" type \nof thing?\n\n\n\n> \n>> +\n>> +\tstatus = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n>> +\tif (ACPI_FAILURE(status)) {\n>> +\t\tpr_err_once(\"No PPTT table found, cpu topology may be inaccurate\\n\");\n>> +\t\treturn -ENOENT;\n>> +\t}\n>> +\tretval = topology_setup_acpi_cpu(table, cpu, level);\n>> +\tpr_debug(\"Topology Setup ACPI cpu %d, level %d ret = %d\\n\",\n>> +\t\t cpu, level, retval);\n>> +\tacpi_put_table(table);\n>> +\n>> +\treturn retval;\n>> +}\n>>\n>","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"pJLOTLKz\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xylyX6xZnz9t5Y\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 04:49:24 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dv6XJ-00021l-Ek; Thu, 21 Sep 2017 18:49:21 +0000","from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]\n\thelo=foss.arm.com)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dv6XD-0001nI-Dk for linux-arm-kernel@lists.infradead.org;\n\tThu, 21 Sep 2017 18:49:18 +0000","from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C477280D;\n\tThu, 21 Sep 2017 11:48:53 -0700 (PDT)","from [192.168.229.136] (u201426.usa.arm.com [10.118.105.55])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id\n\t86C7F3F483; Thu, 21 Sep 2017 11:48:52 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:Content-Type:\n\tContent-Transfer-Encoding:Cc:List-Subscribe:List-Help:List-Post:List-Archive:\n\tList-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From:\n\tReferences:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date:\n\tResent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner;\n\tbh=x7oUz40nU0O99nOxk5tW+TGLkAIsuZ7ZDCFyj2r7Ydc=;\n\tb=pJLOTLKzPHBKggFy3bkPzrRcO\n\t3ZNHE27Ed/t3OHFCWdkLHGK1TnLzOw0Bw8CEksxgnArYEzHJv8Ko4YWbw2SKnRS3AK9LmUH4nobDJ\n\tKpAoQLc02M44x1IE//GiWZ/uZD5CCmYl539QfTzG/bUN+OrILnE8SP0XdbOMc2ps8D7q6irjkr0Dh\n\to86X1NpyZaZJaM9o+H83HiMsMk/OWGnSLLJizMkoCOUfKLzW8lQ1MZzHTuoYwhMxPyOUKn8uEG/yN\n\t96Hkx3b5NjK8HMkc3n8YDdAfo8Qog7pvOaGnqtwOmLKbdqibB6oaOdhNkRZYa55mw6jjcjJn8hwAJ\n\t2s4yTIv7Q==;","Subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","To":"Xiongfeng Wang <wangxiongfeng2@huawei.com>, linux-acpi@vger.kernel.org","References":"<20170919184751.25110-1-jeremy.linton@arm.com>\n\t<20170919184751.25110-2-jeremy.linton@arm.com>\n\t<4c9cfa18-507b-01c4-7464-ff2b149fbb68@huawei.com>","From":"Jeremy Linton <jeremy.linton@arm.com>","Message-ID":"<03912538-f7bf-f235-c87f-3ba275502db0@arm.com>","Date":"Thu, 21 Sep 2017 13:48:51 -0500","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.2.1","MIME-Version":"1.0","In-Reply-To":"<4c9cfa18-507b-01c4-7464-ff2b149fbb68@huawei.com>","Content-Language":"en-US","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170921_114915_568869_2456F249 ","X-CRM114-Status":"GOOD (  23.62  )","X-Spam-Score":"-6.9 (------)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-6.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/,\n\thigh trust [217.140.101.70 listed in list.dnswl.org]\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\trjw@rjwysocki.net, mturquette@baylibre.com, linux-pm@vger.kernel.org, \n\twill.deacon@arm.com, linux-kernel@vger.kernel.org,\n\tlinux-clk@vger.kernel.org, \n\tviresh.kumar@linaro.org, hanjun.guo@linaro.org, ahs3@redhat.com,\n\tsudeep.holla@arm.com, sboyd@codeaurora.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Transfer-Encoding":"7bit","Content-Type":"text/plain; charset=\"us-ascii\"; Format=\"flowed\"","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}},{"id":1773220,"web_url":"http://patchwork.ozlabs.org/comment/1773220/","msgid":"<f1752bf4-b62e-e41a-bd58-783c15bba868@huawei.com>","list_archive_url":null,"date":"2017-09-22T01:15:21","subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","submitter":{"id":72343,"url":"http://patchwork.ozlabs.org/api/people/72343/","name":"Xiongfeng Wang","email":"wangxiongfeng2@huawei.com"},"content":"Hi Jeremy,\n\nOn 2017/9/22 2:48, Jeremy Linton wrote:\n> Hi,\n> \n> On 09/20/2017 02:15 AM, Xiongfeng Wang wrote:\n>> Hi Jeremy,\n>>\n>> On 2017/9/20 2:47, Jeremy Linton wrote:\n>>> ACPI 6.2 adds a new table, which describes how processing units\n>>> are related to each other in tree like fashion. Caches are\n>>> also sprinkled throughout the tree and describe the properties\n>>> of the caches in relation to other caches and processing units.\n>>>\n>>> Add the code to parse the cache hierarchy and report the total\n>>> number of levels of cache for a given core using\n>>> acpi_find_last_cache_level() as well as fill out the individual\n>>> cores cache information with cache_setup_acpi() once the\n>>> cpu_cacheinfo structure has been populated by the arch specific\n>>> code.\n>>>\n>>> Further, report peers in the topology using setup_acpi_cpu_topology()\n>>> to report a unique ID for each processing unit at a given level\n>>> in the tree. These unique id's can then be used to match related\n>>> processing units which exist as threads, COD (clusters\n>>> on die), within a given package, etc.\n>>>\n>>> +\n>>> +static int topology_setup_acpi_cpu(struct acpi_table_header *table,\n>>> +                    unsigned int cpu, int level)\n>>> +{\n>>> +    struct acpi_pptt_processor *cpu_node;\n>>> +    u32 acpi_cpu_id = acpi_cpu_get_madt_gicc(cpu)->uid;\n>>> +\n>>> +    cpu_node = acpi_find_processor_node(table, acpi_cpu_id);\n>>> +    if (cpu_node) {\n>>> +        cpu_node = acpi_find_processor_package_id(table, cpu_node, level);\n>>> +        return (int)((u8 *)cpu_node - (u8 *)table);\n>>> +    }\n>>> +    pr_err_once(\"PPTT table found, but unable to locate core for %d\\n\",\n>>> +            cpu);\n>>> +    return -ENOENT;\n>>\n>> Can we return -1 when PPTT doesn't exist? So that we can still get topo info from MPIDR.\n>> 'store_cpu_topology()' determine whether cpu topology has been populated by checking\n>> whether cluster_id is -1. If cluster_id is not -1, it won't read cpu topo info from MPIDR.\n>> Or maybe we can change 'store_cpu_topology()' as well. If cluster_id is less than zero,\n>> we read cpu topo info from MPIDR.\n> \n> ? I will retest this, but any negative return from setup_acpi_topology() for the initial node (subsequent requests should minimally duplicate the cpu node rather than failing) request, should result in a call to reset_cpu_topology(), and the information being sourced from the MPIDR in store_cpu_topology(). There are various ways the tree could be \"damaged\" but if all the system cpus have matching valid acpi_id/cpu nodes, then that reflects a valid topology and there really isn't enough information to decide if its damaged. The one case where this isn't accurate is missing socket identifiers, but the code actually handles this as well as the lack of missing cluster/thread ids (which don't exist in the standard).\n> \nYes, you are right. I didn't notice the function reset_cpu_topology() before. Thanks for your explanation.\n>>\n>>> +}\n>>> +\n>>> +/*\n>>> + * simply assign a ACPI cache entry to each known CPU cache entry\n>>> + * determining which entries are shared is done later.\n>>> + */\n>>> +int cache_setup_acpi(unsigned int cpu)\n>>> +{\n>>> +    struct acpi_table_header *table;\n>>> +    acpi_status status;\n>>> +\n>>> +    pr_debug(\"Cache Setup ACPI cpu %d\\n\", cpu);\n>>> +\n>>> +    status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);\n>>> +    if (ACPI_FAILURE(status)) {\n>>> +        pr_err_once(\"No PPTT table found, cache topology may be inaccurate\\n\");\n>>> +        return -ENOENT;\n>>> +    }\n>>> +\n>>> +    cache_setup_acpi_cpu(table, cpu);\n>>> +    acpi_put_table(table);\n>>> +\n>>> +    return status;\n>>> +}\n>>> +\n>>> +/*\n>>> + * Determine a topology unique ID for each thread/core/cluster/socket/etc.\n>>> + * This ID can then be used to group peers.\n>>> + */\n>>> +int setup_acpi_cpu_topology(unsigned int cpu, int level)\n>>> +{\n>>> +    struct acpi_table_header *table;\n>>> +    acpi_status status;\n>>> +    int retval;\n>>\n>> Can we add a static int array to record already assigned id for each level?\n>> So that we can count the id starting from zero. And also the id can be successive.\n> \n> I don't like the idea of a node<->generated_id array/map in this module, although I've considered a number of ways to create more normalized values. Particularly, the one area that might be useful is utilizing the acpi id for the cores, which is problematic in the MT case. One of my other alternative ideas was to plug a unique node id into a reserved field in the table as the node is traversed. That idea is a little evil, and really should be part of the ACPI standard so the firmware is providing the ID's rather than dependent on the traversal order of the tree.\n> \n> If it turns out that these ID's need to be zero based, or some other limitation I would prefer just renumbering them in update_siblings_mask() or parse_acpi_topology(). I hacked together a patch to renumber the package_id yesterday, but i'm pretty sure I've seen (non arm) machines with odd package/core ids in the past, and I don't really see anything in the ABI the dictating this. Let me clean it up a bit and I can post it as an additional patch on top of the PPTT patches.\n> \nYes, I agree. Renumbering the IDs in parse_acpi_topology() is better.\n\n> So, is this an actual use case/problem, or its just an \"appearance\" type of thing?\n> \nIt is not an actual use problem, just an \"appearance\".\n\n\nThanks,\nXiongfeng Wang","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"brxG/SVH\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xywY90SLVz9t32\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 11:16:29 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dvCZt-0008Be-P7; Fri, 22 Sep 2017 01:16:25 +0000","from szxga04-in.huawei.com ([45.249.212.190])\n\tby bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dvCZm-00082W-91 for linux-arm-kernel@lists.infradead.org;\n\tFri, 22 Sep 2017 01:16:22 +0000","from 172.30.72.60 (EHLO DGGEMS401-HUB.china.huawei.com)\n\t([172.30.72.60])\n\tby dggrg04-dlp.huawei.com (MOS 4.4.6-GA FastPath queued)\n\twith ESMTP id DHS29053; Fri, 22 Sep 2017 09:15:33 +0800 (CST)","from [127.0.0.1] (10.177.32.209) by DGGEMS401-HUB.china.huawei.com\n\t(10.3.19.201) with Microsoft SMTP Server id 14.3.301.0;\n\tFri, 22 Sep 2017 09:15:25 +0800"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:\n\tMessage-ID:From:References:To:Subject:Reply-To:Content-ID:Content-Description\n\t:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=gmzgRLgwZLO38DeajMl3Hb82uULnOKSe4VSkGHdrIaE=;\n\tb=brxG/SVHP0f518\n\tdIocECs4+f+p+vwwNXPMgwR/LDVBid8KEeQIaVuFW06FGrLcyE6LuZwXWrLxzkHBXgcKGUTfjv+VT\n\td743g3SL5D2oG1gkG6M7oy5mpv/ZOcrsOCLSZ+QtMU24xef+A4kviZoHiCBwIUXXVkjcCl/ZZWG9g\n\t2VW6GkPO+yTGOZILt+P5dLu4xeWW9UXp7vxRuBJx27jbh9j95OMhDgD1sxg1pYxRTunYC8+/iVv3w\n\taQPILgW4a7uMNL/R4ku7xCRC1TRzUPxUpdR8htG3VuTEnuTs7EKttA62pJj4LH+2omyhULpLgucD6\n\tNGHqAuk6U60W6Cv1MUwA==;","Subject":"Re: [PATCH v2 1/6] ACPI/PPTT: Add Processor Properties Topology\n\tTable parsing","To":"Jeremy Linton <jeremy.linton@arm.com>, <linux-acpi@vger.kernel.org>","References":"<20170919184751.25110-1-jeremy.linton@arm.com>\n\t<20170919184751.25110-2-jeremy.linton@arm.com>\n\t<4c9cfa18-507b-01c4-7464-ff2b149fbb68@huawei.com>\n\t<03912538-f7bf-f235-c87f-3ba275502db0@arm.com>","From":"Xiongfeng Wang <wangxiongfeng2@huawei.com>","Message-ID":"<f1752bf4-b62e-e41a-bd58-783c15bba868@huawei.com>","Date":"Fri, 22 Sep 2017 09:15:21 +0800","User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101\n\tThunderbird/45.2.0","MIME-Version":"1.0","In-Reply-To":"<03912538-f7bf-f235-c87f-3ba275502db0@arm.com>","X-Originating-IP":"[10.177.32.209]","X-CFilter-Loop":"Reflected","X-Mirapoint-Virus-RAPID-Raw":"score=unknown(0),\n\trefid=str=0001.0A0B0207.59C46436.0078, ss=1, re=0.000, recu=0.000,\n\treip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0,\n\tso=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32","X-Mirapoint-Loop-Id":"6f499bf0af06c573b72220070e891270","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170921_181619_092393_2007EEA6 ","X-CRM114-Status":"GOOD (  21.08  )","X-Spam-Score":"-1.9 (-)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-1.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\trjw@rjwysocki.net, mturquette@baylibre.com, linux-pm@vger.kernel.org, \n\twill.deacon@arm.com, linux-kernel@vger.kernel.org,\n\tlinux-clk@vger.kernel.org, \n\tviresh.kumar@linaro.org, hanjun.guo@linaro.org, ahs3@redhat.com,\n\tsudeep.holla@arm.com, sboyd@codeaurora.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}},{"id":1778629,"web_url":"http://patchwork.ozlabs.org/comment/1778629/","msgid":"<20171002215621.GS457@codeaurora.org>","list_archive_url":null,"date":"2017-10-02T21:56:21","subject":"Re: [PATCH v2 5/6] arm64: Fixup users of\n\ttopology_physical_package_id","submitter":{"id":6071,"url":"http://patchwork.ozlabs.org/api/people/6071/","name":"Stephen Boyd","email":"sboyd@codeaurora.org"},"content":"On 09/19, Jeremy Linton wrote:\n> There are a few arm64 specific users (cpufreq, psci, etc) which really\n> want the cluster rather than the topology_physical_package_id(). Lets\n> convert those users to topology_cod_id(). That way when we start\n> differentiating the socket/cluster they will continue to behave correctly.\n> \n> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>\n> ---\n\nFor:\n\n>  drivers/clk/clk-mb86s7x.c        | 2 +-\n\nAcked-by: Stephen Boyd <sboyd@codeaurora.org>","headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org header.b=\"GZmF6/za\"; \n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=codeaurora.org header.i=@codeaurora.org\n\theader.b=\"G5CLNjHR\"; \n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n\theader.d=codeaurora.org header.i=@codeaurora.org header.b=\"G5CLNjHR\"; \n\tdkim-atps=neutral","pdx-caf-mail.web.codeaurora.org;\n\tdmarc=none (p=none dis=none) header.from=codeaurora.org","pdx-caf-mail.web.codeaurora.org;\n\tspf=none smtp.mailfrom=sboyd@codeaurora.org"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3y5bbk5D95z9s9Y\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tTue,  3 Oct 2017 08:56:50 +1100 (AEDT)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dz8hj-0006sv-DL; Mon, 02 Oct 2017 21:56:47 +0000","from smtp.codeaurora.org ([198.145.29.96])\n\tby bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dz8hf-0006oT-L2 for linux-arm-kernel@lists.infradead.org;\n\tMon, 02 Oct 2017 21:56:45 +0000","by smtp.codeaurora.org (Postfix, from userid 1000)\n\tid DADFE60227; Mon,  2 Oct 2017 21:56:22 +0000 (UTC)","from localhost (i-global254.qualcomm.com [199.106.103.254])\n\t(using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits))\n\t(No client certificate requested)\n\t(Authenticated sender: sboyd@smtp.codeaurora.org)\n\tby smtp.codeaurora.org (Postfix) with ESMTPSA id D46B860227;\n\tMon,  2 Oct 2017 21:56:21 +0000 (UTC)"],"DKIM-Signature":["v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References:\n\tMessage-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=TwDH19rH5NEhXccPOPYgDzombgJGftQhAtT2igtN5NU=;\n\tb=GZmF6/zaPQnlGe\n\tZHbDjeJboVv6G3pUUELtQak9OqvUYhe6rgW6FF2O9ibDz43EiKbBqyW7/gLwari5FNRSCOdOOJlYO\n\t64eB6AIYHky+PnNlkUAJRBNuFdc0CQBhBJphwfrCsnRq05LURfbO8p7HmFIHALB3rYs96M3lAldAe\n\tPJNFVaZD7eet4b51k5hp4lmCtcvlf+4Ng/3TPLPa7O5vjt296Mc3Oqxc4TEsyj+FLv4fecL2oV1qt\n\tvEk0MYDk1GwJMHpVhwPrRyQFU1O+vNbbI4grJcb5+28gaOO0lXvq7Bt7fjwzZCilwsyKUCyCdOh7g\n\tR6sN6Ns4BDW0Gvqh+DaA==;","v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1506981382;\n\tbh=CM6NpUHFCz6to0bobRj1hdIREL+HHM+qtiFvqOhSfk8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=G5CLNjHRg3Kvq3VsQBIJsFV7AsnS8m5sj0YWVKMJTINYMz1xDQAptV/rh12zG7CL1\n\tJgvmF+qgBtFcYpw1T91x6TBs/Kpm3JuHPI9RepsZIOJZQYGgpQDPfhkZuEoZAYujy7\n\tFDaX0P8Fb2ACpbjb/N6BCJjabRfzSwWKOm8AysQM=","v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1506981382;\n\tbh=CM6NpUHFCz6to0bobRj1hdIREL+HHM+qtiFvqOhSfk8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=G5CLNjHRg3Kvq3VsQBIJsFV7AsnS8m5sj0YWVKMJTINYMz1xDQAptV/rh12zG7CL1\n\tJgvmF+qgBtFcYpw1T91x6TBs/Kpm3JuHPI9RepsZIOJZQYGgpQDPfhkZuEoZAYujy7\n\tFDaX0P8Fb2ACpbjb/N6BCJjabRfzSwWKOm8AysQM="],"X-Spam-Checker-Version":"SpamAssassin 3.4.0 (2014-02-07) on\n\tpdx-caf-mail.web.codeaurora.org","X-Spam-Level":"","X-Spam-Status":"No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00,\n\tDKIM_SIGNED,\n\tT_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0","DMARC-Filter":"OpenDMARC Filter v1.3.2 smtp.codeaurora.org D46B860227","Date":"Mon, 2 Oct 2017 14:56:21 -0700","From":"Stephen Boyd <sboyd@codeaurora.org>","To":"Jeremy Linton <jeremy.linton@arm.com>","Subject":"Re: [PATCH v2 5/6] arm64: Fixup users of\n\ttopology_physical_package_id","Message-ID":"<20171002215621.GS457@codeaurora.org>","References":"<20170919184751.25110-1-jeremy.linton@arm.com>\n\t<20170919184751.25110-6-jeremy.linton@arm.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20170919184751.25110-6-jeremy.linton@arm.com>","User-Agent":"Mutt/1.5.21 (2010-09-15)","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20171002_145643_721389_F3074F52 ","X-CRM114-Status":"UNSURE (   9.98  )","X-CRM114-Notice":"Please train this message.","X-Spam-Score":"-4.3 (----)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-4.3 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/,\n\tmedium trust [198.145.29.96 listed in list.dnswl.org]\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]\n\t-0.1 DKIM_VALID Message has at least one valid DKIM or DK signature\n\t0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n\tnot necessarily valid\n\t-0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from\n\tauthor's domain","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"mark.rutland@arm.com, Jonathan.Zhang@cavium.com,\n\tlorenzo.pieralisi@arm.com, \n\tcatalin.marinas@arm.com, gregkh@linuxfoundation.org,\n\tjhugo@codeaurora.org, \n\twill.deacon@arm.com, mturquette@baylibre.com, linux-pm@vger.kernel.org,\n\trjw@rjwysocki.net, linux-kernel@vger.kernel.org,\n\twangxiongfeng2@huawei.com, \n\tlinux-acpi@vger.kernel.org, viresh.kumar@linaro.org,\n\thanjun.guo@linaro.org, \n\tahs3@redhat.com, sudeep.holla@arm.com, linux-clk@vger.kernel.org,\n\tlinux-arm-kernel@lists.infradead.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"}}]