]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
thermal/of: Fix cdev lookup in thermal_of_should_bind()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 21 Feb 2025 16:57:11 +0000 (17:57 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 25 Feb 2025 11:19:10 +0000 (12:19 +0100)
Since thermal_of_should_bind() terminates the loop after processing
the first child found in cooling-maps, it will never match more than
one cdev to a given trip point which is incorrect, as there may be
cooling-maps associating one trip point with multiple cooling devices.

Address this by letting the loop continue until either all
children have been processed or a matching one has been found.

To avoid adding conditionals or goto statements, put the loop in
question into a separate function and make that function return
right away after finding a matching cooling-maps entry.

Fixes: 94c6110b0b13 ("thermal/of: Use the .should_bind() thermal zone callback")
Link: https://lore.kernel.org/linux-pm/20250219-fix-thermal-of-v1-1-de36e7a590c4@chromium.org/
Reported-by: Yu-Che Cheng <giver@chromium.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Yu-Che Cheng <giver@chromium.org>
Tested-by: Yu-Che Cheng <giver@chromium.org>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Tested-by: Lukasz Luba <lukasz.luba@arm.com>
Link: https://patch.msgid.link/2788228.mvXUDI8C0e@rjwysocki.net
drivers/thermal/thermal_of.c

index 5ab4ce4daaebdf0210d9b318ae17b3eb8a4bccaf..5401f03d6b6c1462dd1f466c7daf1296c2e9ab3a 100644 (file)
@@ -274,6 +274,34 @@ static bool thermal_of_get_cooling_spec(struct device_node *map_np, int index,
        return true;
 }
 
+static bool thermal_of_cm_lookup(struct device_node *cm_np,
+                                const struct thermal_trip *trip,
+                                struct thermal_cooling_device *cdev,
+                                struct cooling_spec *c)
+{
+       for_each_child_of_node_scoped(cm_np, child) {
+               struct device_node *tr_np;
+               int count, i;
+
+               tr_np = of_parse_phandle(child, "trip", 0);
+               if (tr_np != trip->priv)
+                       continue;
+
+               /* The trip has been found, look up the cdev. */
+               count = of_count_phandle_with_args(child, "cooling-device",
+                                                  "#cooling-cells");
+               if (count <= 0)
+                       pr_err("Add a cooling_device property with at least one device\n");
+
+               for (i = 0; i < count; i++) {
+                       if (thermal_of_get_cooling_spec(child, i, cdev, c))
+                               return true;
+               }
+       }
+
+       return false;
+}
+
 static bool thermal_of_should_bind(struct thermal_zone_device *tz,
                                   const struct thermal_trip *trip,
                                   struct thermal_cooling_device *cdev,
@@ -293,27 +321,7 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz,
                goto out;
 
        /* Look up the trip and the cdev in the cooling maps. */
-       for_each_child_of_node_scoped(cm_np, child) {
-               struct device_node *tr_np;
-               int count, i;
-
-               tr_np = of_parse_phandle(child, "trip", 0);
-               if (tr_np != trip->priv)
-                       continue;
-
-               /* The trip has been found, look up the cdev. */
-               count = of_count_phandle_with_args(child, "cooling-device", "#cooling-cells");
-               if (count <= 0)
-                       pr_err("Add a cooling_device property with at least one device\n");
-
-               for (i = 0; i < count; i++) {
-                       result = thermal_of_get_cooling_spec(child, i, cdev, c);
-                       if (result)
-                               break;
-               }
-
-               break;
-       }
+       result = thermal_of_cm_lookup(cm_np, trip, cdev, c);
 
        of_node_put(cm_np);
 out: