[RFC PATCH v2 1/1] base/of/cacheinfo: support l1 entry in dt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Existing device tree bindings do not properly describe caches shared
between SMT (Simultaneous Multithreading) threads.

For example, in a system with two CPU cores, each supporting two SMT
threads, current bindings treat each thread as an independent logical
CPU with its own L1 cache. However, in reality, these threads share
resources within a physical CPU, including caches. There are two ways to
do this, first using multiple reg entries (PowerPC) which all share the
same CPU core resources [1], which was turn down based on
discussions with Mark Rutland [2], because every node in the cpu-map should
point to a CPU node in the device tree. Second, to go with the proposed
method.

Allow CPU node entries to reference a shared L1 cache node. Some CPU
nodes may omit explicit cache descriptions and instead use a
next-level-cache property to point to the corresponding L1 cache node.

Link: https://lore.kernel.org/linux-devicetree/CAL_JsqLGEvGBQ0W_B6+5cME1UEhuKXadBB-6=GoN1tmavw9K_w@xxxxxxxxxxxxxx/ # [1]
Link: https://lore.kernel.org/linux-arm-kernel/Z4FYHvbVhMHrGQI4@J2N7QTR9R3/ # [2]

Signed-off-by: Alireza Sanaee <alireza.sanaee@xxxxxxxxxx>
---
 drivers/base/cacheinfo.c | 50 ++++++++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index cf0d455209d7..71d92157591e 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -83,7 +83,27 @@ bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y)
 
 #ifdef CONFIG_OF
 
-static bool of_check_cache_nodes(struct device_node *np);
+static bool of_check_cache_node(struct device_node *np) {
+	if (of_property_present(np, "cache-size")   ||
+	    of_property_present(np, "i-cache-size") ||
+	    of_property_present(np, "d-cache-size") ||
+	    of_property_present(np, "cache-unified"))
+		return true;
+	return false;
+}
+
+static bool of_check_cache_nodes(struct device_node *np)
+{
+	if (of_check_cache_node(np))
+		return true;
+
+	struct device_node *next __free(device_node) = of_find_next_cache_node(np);
+	if (next)
+		return true;
+
+	return false;
+}
+
 
 /* OF properties to query for a given cache type */
 struct cache_type_info {
@@ -218,11 +238,23 @@ static int cache_setup_of_node(unsigned int cpu)
 	while (index < cache_leaves(cpu)) {
 		this_leaf = per_cpu_cacheinfo_idx(cpu, index);
 		if (this_leaf->level != 1) {
+			/* Always go one level down for level > 1 */
 			struct device_node *prev __free(device_node) = np;
 			np = of_find_next_cache_node(np);
 			if (!np)
 				break;
+		} else {
+			/* For level 1, check compatibility */
+			if (!of_device_is_compatible(np, "cache") &&
+			    !of_check_cache_node(np)) {
+				struct device_node *prev __free(device_node) = np;
+				np = of_find_next_cache_node(np);
+				if (!np)
+					break;
+				continue; /* Skip to next index without processing */
+			}
 		}
+
 		cache_of_set_props(this_leaf, np);
 		this_leaf->fw_token = np;
 		index++;
@@ -234,22 +266,6 @@ static int cache_setup_of_node(unsigned int cpu)
 	return 0;
 }
 
-static bool of_check_cache_nodes(struct device_node *np)
-{
-	if (of_property_present(np, "cache-size")   ||
-	    of_property_present(np, "i-cache-size") ||
-	    of_property_present(np, "d-cache-size") ||
-	    of_property_present(np, "cache-unified"))
-		return true;
-
-	struct device_node *next __free(device_node) = of_find_next_cache_node(np);
-	if (next) {
-		return true;
-	}
-
-	return false;
-}
-
 static int of_count_cache_leaves(struct device_node *np)
 {
 	unsigned int leaves = 0;
-- 
2.34.1





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux