cacheinfo: Allow early detection and population of cache attributes

Some architecture/platforms may need to setup cache properties very
early in the boot along with other cpu topologies so that all these
information can be used to build sched_domains which is used by the
scheduler.

Allow detect_cache_attributes to be called quite early during the boot.

Link: https://lore.kernel.org/r/20220704101605.1318280-7-sudeep.holla@arm.com
Tested-by: Ionela Voinescu <ionela.voinescu@arm.com>
Tested-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
Sudeep Holla 2022-07-04 11:15:50 +01:00
parent cc1cfc47ea
commit 36bbc5b4ff
2 changed files with 38 additions and 18 deletions

View File

@ -193,14 +193,8 @@ static int cache_setup_of_node(unsigned int cpu)
{ {
struct device_node *np; struct device_node *np;
struct cacheinfo *this_leaf; struct cacheinfo *this_leaf;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
unsigned int index = 0; unsigned int index = 0;
/* skip if fw_token is already populated */
if (this_cpu_ci->info_list->fw_token) {
return 0;
}
np = of_cpu_device_node_get(cpu); np = of_cpu_device_node_get(cpu);
if (!np) { if (!np) {
pr_err("Failed to find cpu%d device node\n", cpu); pr_err("Failed to find cpu%d device node\n", cpu);
@ -236,6 +230,18 @@ int __weak cache_setup_acpi(unsigned int cpu)
unsigned int coherency_max_size; unsigned int coherency_max_size;
static int cache_setup_properties(unsigned int cpu)
{
int ret = 0;
if (of_have_populated_dt())
ret = cache_setup_of_node(cpu);
else if (!acpi_disabled)
ret = cache_setup_acpi(cpu);
return ret;
}
static int cache_shared_cpu_map_setup(unsigned int cpu) static int cache_shared_cpu_map_setup(unsigned int cpu)
{ {
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@ -246,21 +252,21 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
if (this_cpu_ci->cpu_map_populated) if (this_cpu_ci->cpu_map_populated)
return 0; return 0;
if (of_have_populated_dt()) /*
ret = cache_setup_of_node(cpu); * skip setting up cache properties if LLC is valid, just need
else if (!acpi_disabled) * to update the shared cpu_map if the cache attributes were
ret = cache_setup_acpi(cpu); * populated early before all the cpus are brought online
*/
if (ret) if (!last_level_cache_is_valid(cpu)) {
return ret; ret = cache_setup_properties(cpu);
if (ret)
return ret;
}
for (index = 0; index < cache_leaves(cpu); index++) { for (index = 0; index < cache_leaves(cpu); index++) {
unsigned int i; unsigned int i;
this_leaf = per_cpu_cacheinfo_idx(cpu, index); this_leaf = per_cpu_cacheinfo_idx(cpu, index);
/* skip if shared_cpu_map is already populated */
if (!cpumask_empty(&this_leaf->shared_cpu_map))
continue;
cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
for_each_online_cpu(i) { for_each_online_cpu(i) {
@ -330,17 +336,28 @@ int __weak populate_cache_leaves(unsigned int cpu)
return -ENOENT; return -ENOENT;
} }
static int detect_cache_attributes(unsigned int cpu) int detect_cache_attributes(unsigned int cpu)
{ {
int ret; int ret;
/* Since early detection of the cacheinfo is allowed via this
* function and this also gets called as CPU hotplug callbacks via
* cacheinfo_cpu_online, the initialisation can be skipped and only
* CPU maps can be updated as the CPU online status would be update
* if called via cacheinfo_cpu_online path.
*/
if (per_cpu_cacheinfo(cpu))
goto update_cpu_map;
if (init_cache_level(cpu) || !cache_leaves(cpu)) if (init_cache_level(cpu) || !cache_leaves(cpu))
return -ENOENT; return -ENOENT;
per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
sizeof(struct cacheinfo), GFP_KERNEL); sizeof(struct cacheinfo), GFP_KERNEL);
if (per_cpu_cacheinfo(cpu) == NULL) if (per_cpu_cacheinfo(cpu) == NULL) {
cache_leaves(cpu) = 0;
return -ENOMEM; return -ENOMEM;
}
/* /*
* populate_cache_leaves() may completely setup the cache leaves and * populate_cache_leaves() may completely setup the cache leaves and
@ -349,6 +366,8 @@ static int detect_cache_attributes(unsigned int cpu)
ret = populate_cache_leaves(cpu); ret = populate_cache_leaves(cpu);
if (ret) if (ret)
goto free_ci; goto free_ci;
update_cpu_map:
/* /*
* For systems using DT for cache hierarchy, fw_token * For systems using DT for cache hierarchy, fw_token
* and shared_cpu_map will be set up here only if they are * and shared_cpu_map will be set up here only if they are

View File

@ -84,6 +84,7 @@ int populate_cache_leaves(unsigned int cpu);
int cache_setup_acpi(unsigned int cpu); int cache_setup_acpi(unsigned int cpu);
bool last_level_cache_is_valid(unsigned int cpu); bool last_level_cache_is_valid(unsigned int cpu);
bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y); bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y);
int detect_cache_attributes(unsigned int cpu);
#ifndef CONFIG_ACPI_PPTT #ifndef CONFIG_ACPI_PPTT
/* /*
* acpi_find_last_cache_level is only called on ACPI enabled * acpi_find_last_cache_level is only called on ACPI enabled