Skip to content

Commit 2c8f7ef

Browse files
committed
Merge tag 'arch-cache-topo-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into driver-core-next
Sudeep writes: cacheinfo and arch_topology updates for v5.20 These are updates to fix some discrepancies we have in the CPU topology parsing from the device tree /cpu-map node and the divergence from the behaviour on a ACPI enabled platform. The expectation is that both DT and ACPI enabled systems must present consistent view of the CPU topology. The current assignment of generated cluster count as the physical package identifier for each CPU is wrong. The device tree bindings for CPU topology supports sockets to infer the socket or physical package identifier for a given CPU. It is now being made use of you address the issue. These updates also assigns the cluster identifier as parsed from the device tree cluster nodes within /cpu-map without support for nesting of the clusters as there are no such reported/known platforms. In order to be on par with ACPI PPTT physical package/socket support, these updates also include support for socket nodes in /cpu-map. The only exception is that the last level cache id information can be inferred from the same ACPI PPTT while we need to parse CPU cache nodes in the device tree. The cacheinfo changes here is to enable the re-use of the cacheinfo to detect the cache attributes for all the CPU quite early even before the scondardaries are booted so that the information can be used to build the schedular domains especially the last level cache(LLC). * tag 'arch-cache-topo-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: (21 commits) ACPI: Remove the unused find_acpi_cpu_cache_topology() arch_topology: Warn that topology for nested clusters is not supported arch_topology: Add support for parsing sockets in /cpu-map arch_topology: Set cluster identifier in each core/thread from /cpu-map arch_topology: Limit span of cpu_clustergroup_mask() arch_topology: Don't set cluster identifier as physical package identifier arch_topology: Avoid parsing through all the CPUs once a outlier CPU is found arch_topology: Check for non-negative value rather than -1 for IDs validity arch_topology: Set thread sibling cpumask only within the cluster arch_topology: Drop LLC identifier stash from the CPU topology arm64: topology: Remove redundant setting of llc_id in CPU topology arch_topology: Use the last level cache information from the cacheinfo arch_topology: Add support to parse and detect cache attributes cacheinfo: Align checks in cache_shared_cpu_map_{setup,remove} for readability cacheinfo: Use cache identifiers to check if the caches are shared if available cacheinfo: Allow early detection and population of cache attributes cacheinfo: Add support to check if last level cache(LLC) is valid or shared cacheinfo: Move cache_leaves_are_shared out of CONFIG_OF cacheinfo: Add helper to access any cache index for a given CPU cacheinfo: Use of_cpu_device_node_get instead cpu_dev->of_node ...
2 parents 2fd2697 + 7128af8 commit 2c8f7ef

File tree

7 files changed

+175
-133
lines changed

7 files changed

+175
-133
lines changed

arch/arm64/kernel/topology.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ int __init parse_acpi_topology(void)
8989
return 0;
9090

9191
for_each_possible_cpu(cpu) {
92-
int i, cache_id;
93-
9492
topology_id = find_acpi_cpu_topology(cpu, 0);
9593
if (topology_id < 0)
9694
return topology_id;
@@ -107,18 +105,6 @@ int __init parse_acpi_topology(void)
107105
cpu_topology[cpu].cluster_id = topology_id;
108106
topology_id = find_acpi_cpu_topology_package(cpu);
109107
cpu_topology[cpu].package_id = topology_id;
110-
111-
i = acpi_find_last_cache_level(cpu);
112-
113-
if (i > 0) {
114-
/*
115-
* this is the only part of cpu_topology that has
116-
* a direct relationship with the cache topology
117-
*/
118-
cache_id = find_acpi_cpu_cache_topology(cpu, i);
119-
if (cache_id > 0)
120-
cpu_topology[cpu].llc_id = cache_id;
121-
}
122108
}
123109

124110
return 0;

drivers/acpi/pptt.c

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ static void cache_setup_acpi_cpu(struct acpi_table_header *table,
437437
pr_debug("found = %p %p\n", found_cache, cpu_node);
438438
if (found_cache)
439439
update_cache_properties(this_leaf, found_cache,
440-
cpu_node, table->revision);
440+
ACPI_TO_POINTER(ACPI_PTR_DIFF(cpu_node, table)),
441+
table->revision);
441442

442443
index++;
443444
}
@@ -690,43 +691,6 @@ int find_acpi_cpu_topology(unsigned int cpu, int level)
690691
return find_acpi_cpu_topology_tag(cpu, level, 0);
691692
}
692693

693-
/**
694-
* find_acpi_cpu_cache_topology() - Determine a unique cache topology value
695-
* @cpu: Kernel logical CPU number
696-
* @level: The cache level for which we would like a unique ID
697-
*
698-
* Determine a unique ID for each unified cache in the system
699-
*
700-
* Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found.
701-
* Otherwise returns a value which represents a unique topological feature.
702-
*/
703-
int find_acpi_cpu_cache_topology(unsigned int cpu, int level)
704-
{
705-
struct acpi_table_header *table;
706-
struct acpi_pptt_cache *found_cache;
707-
acpi_status status;
708-
u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
709-
struct acpi_pptt_processor *cpu_node = NULL;
710-
int ret = -1;
711-
712-
status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
713-
if (ACPI_FAILURE(status)) {
714-
acpi_pptt_warn_missing();
715-
return -ENOENT;
716-
}
717-
718-
found_cache = acpi_find_cache_node(table, acpi_cpu_id,
719-
CACHE_TYPE_UNIFIED,
720-
level,
721-
&cpu_node);
722-
if (found_cache)
723-
ret = ACPI_PTR_DIFF(cpu_node, table);
724-
725-
acpi_put_table(table);
726-
727-
return ret;
728-
}
729-
730694
/**
731695
* find_acpi_cpu_topology_package() - Determine a unique CPU package value
732696
* @cpu: Kernel logical CPU number

drivers/base/arch_topology.c

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include <linux/acpi.h>
10+
#include <linux/cacheinfo.h>
1011
#include <linux/cpu.h>
1112
#include <linux/cpufreq.h>
1213
#include <linux/device.h>
@@ -496,7 +497,7 @@ static int __init get_cpu_for_node(struct device_node *node)
496497
}
497498

498499
static int __init parse_core(struct device_node *core, int package_id,
499-
int core_id)
500+
int cluster_id, int core_id)
500501
{
501502
char name[20];
502503
bool leaf = true;
@@ -512,6 +513,7 @@ static int __init parse_core(struct device_node *core, int package_id,
512513
cpu = get_cpu_for_node(t);
513514
if (cpu >= 0) {
514515
cpu_topology[cpu].package_id = package_id;
516+
cpu_topology[cpu].cluster_id = cluster_id;
515517
cpu_topology[cpu].core_id = core_id;
516518
cpu_topology[cpu].thread_id = i;
517519
} else if (cpu != -ENODEV) {
@@ -533,6 +535,7 @@ static int __init parse_core(struct device_node *core, int package_id,
533535
}
534536

535537
cpu_topology[cpu].package_id = package_id;
538+
cpu_topology[cpu].cluster_id = cluster_id;
536539
cpu_topology[cpu].core_id = core_id;
537540
} else if (leaf && cpu != -ENODEV) {
538541
pr_err("%pOF: Can't get CPU for leaf core\n", core);
@@ -542,13 +545,13 @@ static int __init parse_core(struct device_node *core, int package_id,
542545
return 0;
543546
}
544547

545-
static int __init parse_cluster(struct device_node *cluster, int depth)
548+
static int __init parse_cluster(struct device_node *cluster, int package_id,
549+
int cluster_id, int depth)
546550
{
547551
char name[20];
548552
bool leaf = true;
549553
bool has_cores = false;
550554
struct device_node *c;
551-
static int package_id __initdata;
552555
int core_id = 0;
553556
int i, ret;
554557

@@ -563,7 +566,9 @@ static int __init parse_cluster(struct device_node *cluster, int depth)
563566
c = of_get_child_by_name(cluster, name);
564567
if (c) {
565568
leaf = false;
566-
ret = parse_cluster(c, depth + 1);
569+
ret = parse_cluster(c, package_id, i, depth + 1);
570+
if (depth > 0)
571+
pr_warn("Topology for clusters of clusters not yet supported\n");
567572
of_node_put(c);
568573
if (ret != 0)
569574
return ret;
@@ -587,7 +592,8 @@ static int __init parse_cluster(struct device_node *cluster, int depth)
587592
}
588593

589594
if (leaf) {
590-
ret = parse_core(c, package_id, core_id++);
595+
ret = parse_core(c, package_id, cluster_id,
596+
core_id++);
591597
} else {
592598
pr_err("%pOF: Non-leaf cluster with core %s\n",
593599
cluster, name);
@@ -604,10 +610,33 @@ static int __init parse_cluster(struct device_node *cluster, int depth)
604610
if (leaf && !has_cores)
605611
pr_warn("%pOF: empty cluster\n", cluster);
606612

607-
if (leaf)
613+
return 0;
614+
}
615+
616+
static int __init parse_socket(struct device_node *socket)
617+
{
618+
char name[20];
619+
struct device_node *c;
620+
bool has_socket = false;
621+
int package_id = 0, ret;
622+
623+
do {
624+
snprintf(name, sizeof(name), "socket%d", package_id);
625+
c = of_get_child_by_name(socket, name);
626+
if (c) {
627+
has_socket = true;
628+
ret = parse_cluster(c, package_id, -1, 0);
629+
of_node_put(c);
630+
if (ret != 0)
631+
return ret;
632+
}
608633
package_id++;
634+
} while (c);
609635

610-
return 0;
636+
if (!has_socket)
637+
ret = parse_cluster(socket, 0, -1, 0);
638+
639+
return ret;
611640
}
612641

613642
static int __init parse_dt_topology(void)
@@ -630,7 +659,7 @@ static int __init parse_dt_topology(void)
630659
if (!map)
631660
goto out;
632661

633-
ret = parse_cluster(map, 0);
662+
ret = parse_socket(map);
634663
if (ret != 0)
635664
goto out_map;
636665

@@ -641,8 +670,10 @@ static int __init parse_dt_topology(void)
641670
* only mark cores described in the DT as possible.
642671
*/
643672
for_each_possible_cpu(cpu)
644-
if (cpu_topology[cpu].package_id == -1)
673+
if (cpu_topology[cpu].package_id < 0) {
645674
ret = -EINVAL;
675+
break;
676+
}
646677

647678
out_map:
648679
of_node_put(map);
@@ -667,7 +698,8 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
667698
/* not numa in package, lets use the package siblings */
668699
core_mask = &cpu_topology[cpu].core_sibling;
669700
}
670-
if (cpu_topology[cpu].llc_id != -1) {
701+
702+
if (last_level_cache_is_valid(cpu)) {
671703
if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask))
672704
core_mask = &cpu_topology[cpu].llc_sibling;
673705
}
@@ -686,6 +718,14 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
686718

687719
const struct cpumask *cpu_clustergroup_mask(int cpu)
688720
{
721+
/*
722+
* Forbid cpu_clustergroup_mask() to span more or the same CPUs as
723+
* cpu_coregroup_mask().
724+
*/
725+
if (cpumask_subset(cpu_coregroup_mask(cpu),
726+
&cpu_topology[cpu].cluster_sibling))
727+
return get_cpu_mask(cpu);
728+
689729
return &cpu_topology[cpu].cluster_sibling;
690730
}
691731

@@ -698,23 +738,25 @@ void update_siblings_masks(unsigned int cpuid)
698738
for_each_online_cpu(cpu) {
699739
cpu_topo = &cpu_topology[cpu];
700740

701-
if (cpu_topo->llc_id != -1 && cpuid_topo->llc_id == cpu_topo->llc_id) {
741+
if (last_level_cache_is_shared(cpu, cpuid)) {
702742
cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
703743
cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
704744
}
705745

706746
if (cpuid_topo->package_id != cpu_topo->package_id)
707747
continue;
708748

709-
if (cpuid_topo->cluster_id == cpu_topo->cluster_id &&
710-
cpuid_topo->cluster_id != -1) {
749+
cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
750+
cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
751+
752+
if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
753+
continue;
754+
755+
if (cpuid_topo->cluster_id >= 0) {
711756
cpumask_set_cpu(cpu, &cpuid_topo->cluster_sibling);
712757
cpumask_set_cpu(cpuid, &cpu_topo->cluster_sibling);
713758
}
714759

715-
cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
716-
cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
717-
718760
if (cpuid_topo->core_id != cpu_topo->core_id)
719761
continue;
720762

@@ -750,7 +792,6 @@ void __init reset_cpu_topology(void)
750792
cpu_topo->core_id = -1;
751793
cpu_topo->cluster_id = -1;
752794
cpu_topo->package_id = -1;
753-
cpu_topo->llc_id = -1;
754795

755796
clear_cpu_topology(cpu);
756797
}
@@ -780,15 +821,28 @@ __weak int __init parse_acpi_topology(void)
780821
#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
781822
void __init init_cpu_topology(void)
782823
{
824+
int ret, cpu;
825+
783826
reset_cpu_topology();
827+
ret = parse_acpi_topology();
828+
if (!ret)
829+
ret = of_have_populated_dt() && parse_dt_topology();
784830

785-
/*
786-
* Discard anything that was parsed if we hit an error so we
787-
* don't use partial information.
788-
*/
789-
if (parse_acpi_topology())
790-
reset_cpu_topology();
791-
else if (of_have_populated_dt() && parse_dt_topology())
831+
if (ret) {
832+
/*
833+
* Discard anything that was parsed if we hit an error so we
834+
* don't use partial information.
835+
*/
792836
reset_cpu_topology();
837+
return;
838+
}
839+
840+
for_each_possible_cpu(cpu) {
841+
ret = detect_cache_attributes(cpu);
842+
if (ret) {
843+
pr_info("Early cacheinfo failed, ret = %d\n", ret);
844+
break;
845+
}
846+
}
793847
}
794848
#endif

0 commit comments

Comments
 (0)