mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
![Jeremy Linton](/assets/img/avatar_default.png)
The original intent in cacheinfo was that an architecture specific populate_cache_leaves() would probe the hardware and then cache_shared_cpu_map_setup() and cache_override_properties() would provide firmware help to extend/expand upon what was probed. Arm64 was really the only architecture that was working this way, and with the removal of most of the hardware probing logic it became clear that it was possible to simplify the logic a bit. This patch combines the walk of the DT nodes with the code updating the cache size/line_size and nr_sets. cache_override_properties() (which was DT specific) is then removed. The result is that cacheinfo.of_node is no longer used as a temporary place to hold DT references for future calls that update cache properties. That change helps to clarify its one remaining use (matching cacheinfo nodes that represent shared caches) which will be used by the ACPI/PPTT code in the following patches. Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Vijaya Kumar K <vkilari@codeaurora.org> Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> Tested-by: Tomasz Nowicki <Tomasz.Nowicki@cavium.com> Acked-by: Sudeep Holla <sudeep.holla@arm.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
104 lines
3 KiB
C
104 lines
3 KiB
C
/*
|
|
* Copyright (C) 2017 SiFive
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation, version 2.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/cacheinfo.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
|
|
static void ci_leaf_init(struct cacheinfo *this_leaf,
|
|
struct device_node *node,
|
|
enum cache_type type, unsigned int level)
|
|
{
|
|
this_leaf->level = level;
|
|
this_leaf->type = type;
|
|
/* not a sector cache */
|
|
this_leaf->physical_line_partition = 1;
|
|
/* TODO: Add to DTS */
|
|
this_leaf->attributes =
|
|
CACHE_WRITE_BACK
|
|
| CACHE_READ_ALLOCATE
|
|
| CACHE_WRITE_ALLOCATE;
|
|
}
|
|
|
|
static int __init_cache_level(unsigned int cpu)
|
|
{
|
|
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
|
struct device_node *np = of_cpu_device_node_get(cpu);
|
|
int levels = 0, leaves = 0, level;
|
|
|
|
if (of_property_read_bool(np, "cache-size"))
|
|
++leaves;
|
|
if (of_property_read_bool(np, "i-cache-size"))
|
|
++leaves;
|
|
if (of_property_read_bool(np, "d-cache-size"))
|
|
++leaves;
|
|
if (leaves > 0)
|
|
levels = 1;
|
|
|
|
while ((np = of_find_next_cache_node(np))) {
|
|
if (!of_device_is_compatible(np, "cache"))
|
|
break;
|
|
if (of_property_read_u32(np, "cache-level", &level))
|
|
break;
|
|
if (level <= levels)
|
|
break;
|
|
if (of_property_read_bool(np, "cache-size"))
|
|
++leaves;
|
|
if (of_property_read_bool(np, "i-cache-size"))
|
|
++leaves;
|
|
if (of_property_read_bool(np, "d-cache-size"))
|
|
++leaves;
|
|
levels = level;
|
|
}
|
|
|
|
this_cpu_ci->num_levels = levels;
|
|
this_cpu_ci->num_leaves = leaves;
|
|
return 0;
|
|
}
|
|
|
|
static int __populate_cache_leaves(unsigned int cpu)
|
|
{
|
|
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
|
struct cacheinfo *this_leaf = this_cpu_ci->info_list;
|
|
struct device_node *np = of_cpu_device_node_get(cpu);
|
|
int levels = 1, level = 1;
|
|
|
|
if (of_property_read_bool(np, "cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
|
|
if (of_property_read_bool(np, "i-cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
|
|
if (of_property_read_bool(np, "d-cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
|
|
|
|
while ((np = of_find_next_cache_node(np))) {
|
|
if (!of_device_is_compatible(np, "cache"))
|
|
break;
|
|
if (of_property_read_u32(np, "cache-level", &level))
|
|
break;
|
|
if (level <= levels)
|
|
break;
|
|
if (of_property_read_bool(np, "cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
|
|
if (of_property_read_bool(np, "i-cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
|
|
if (of_property_read_bool(np, "d-cache-size"))
|
|
ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
|
|
levels = level;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
|
|
DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
|