From patchwork Fri Aug 16 08:12:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 819961 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4612A823AC for ; Fri, 16 Aug 2024 08:12:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795969; cv=none; b=upsq3aaKLiI/MEC7QRYpadMI9vDlYm2nwrsgjK+9weka50BOj6gC53FxIBAPiZ9nz7jVVHcsM5fFIuUwGx8iXexwvjtBopRvaPGwtTay9I5bVw/MHu+2EMLKS6it/IUHRZUwW+1h3G7gJirRcCW6Wq97L3Ztc/xaKMmN3QHvtvM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795969; c=relaxed/simple; bh=6ODmSx/BqX1DAmg0Nvvx6v6RGpABj/Zp5OzjuzzjVcc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XDl9343twvVBjq2edeWQauZfXgvogF0+H75ltX3jYPIqJqb8qKlz7s4DWVLGCAb0Ibh2TeIVjZquDY3ih4LpNcuruqp6zA5FVXWHt7sb+okUB46Gxc4O/Sa46gbXqRFrRYgXqemypOcqUkYoIrAmon/SJOZTesRG4HQnCcs2u70= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=kr3ywX73; arc=none smtp.client-ip=209.85.128.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="kr3ywX73" Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-428243f928fso17316665e9.0 for ; Fri, 16 Aug 2024 01:12:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723795965; x=1724400765; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=l7YISoiooozOIq4w+X12WtyZF015lSfecgxPxzmXkaM=; b=kr3ywX73MQ8GBbHv5gBgIB4WKHMKa6Cw4EDAt0jKoywqPRmNMWE4HhHoDttjMvAcSN Qq9UiuAeGvvQQCJim0Cc/szVvPgcax2uw1ATRy2OR7CdbyHfeQK75fOhvs1WPVd++Aya 0Q+ZG77++CXz11F998VHkzVn+g1POPnj72mehM9fJ7rWV1cKCAYYBhVouq0VvtYtZnhl i8yahlmtitTYgTPmIrit68PNiZrN4WnpHQg8Ps2HoQs864wiJ8PzggZUZVRAkfwfngDC AGtxn7KRgohnHN+HafSulKarSL4wMJE1899nhHM5zHpHzvcFiLkhC9GTtvY3ExgLe8Td POhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723795965; x=1724400765; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=l7YISoiooozOIq4w+X12WtyZF015lSfecgxPxzmXkaM=; b=xQK09jlaDVobI3PkF8s2XKJIbRrDOkf8o4m/0W0QmGZsRlJajLDFett8HxFdlyzm+I M03QseECBPYKoUHDaQ8ezTQnS0mS35fCkgCSLD1wfyHpOE6UgRy9Oj6pa1jyvu3HeoKG GRFEgH5SRs6ROF8u6nJDzVcIE7fHTY7baVIdPTYSWhJpGSYXQAd0AxyiDXlwUV3M8Piu YEyGjoCT4rnhs3m2XjnOd53d1J2kAKuDq4+xN0YOfFCplUgipp6dt+lvX6wtH86rPX6T z658wo0JhYnK3FYR/2YdSNOzYWgJxd+46V2hupkJ5SsMIOGwwKjPKVeYR4lDBBP798Vn l8vA== X-Gm-Message-State: AOJu0Ywu0DJp2FFkSBy4Sr+Oj2dP4iRaO58C+DJdQDfXW1g6YVqiQNAV 48HAy/3FhtmBTGoWWNdsEiHv1hohDCrXTncdJJ1edb9HO2InVmi56MjjgZwqs/s= X-Google-Smtp-Source: AGHT+IF+N5KmMjzEAFpZMmAvI8cg8nQMGZEInMqCWMeL9EWr+nlwerecmyeqSUNUGeAT2sYNyaKJLQ== X-Received: by 2002:a05:600c:5487:b0:426:61fc:fc1a with SMTP id 5b1f17b1804b1-429ed784142mr15219635e9.3.1723795964780; Fri, 16 Aug 2024 01:12:44 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ed6593casm16021205e9.28.2024.08.16.01.12.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 01:12:44 -0700 (PDT) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-pm@vger.kernel.org, lukasz.luba@arm.com, quic_manafm@quicinc.com Subject: [PATCH v2 1/7] thermal/core: Compute low and high boundaries in thermal_zone_device_update() Date: Fri, 16 Aug 2024 10:12:32 +0200 Message-ID: <20240816081241.1925221-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240816081241.1925221-1-daniel.lezcano@linaro.org> References: <20240816081241.1925221-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to set the scene for the thresholds support which have to manipulate the low and high temperature boundaries for the interrupt support, we must pass the low and high values to the incoming thresholds routine. The variables are set from the thermal_zone_set_trips() where the function loops the thermal trips to figure out the next and the previous temperatures to set the interrupt to be triggered when they are crossed. These variables will be needed by the function in charge of handling the thresholds in the incoming changes but they are local to the aforementioned function thermal_zone_set_trips(). Move the low and high boundaries computation out of the function in thermal_zone_device_update() so they are accessible from there. The positive side effect is they are computed in the same loop as handle_thermal_trip(), so we remove one loop. Co-developed-by: Rafael J. Wysocki Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 12 ++++++++++-- drivers/thermal/thermal_core.h | 2 +- drivers/thermal/thermal_trip.c | 27 +-------------------------- 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 95c399f94744..166f48071487 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -547,6 +547,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, struct thermal_trip_desc *td; LIST_HEAD(way_down_list); LIST_HEAD(way_up_list); + int low = -INT_MAX, high = INT_MAX; int temp, ret; if (tz->suspended) @@ -580,10 +581,17 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, tz->notify_event = event; - for_each_trip_desc(tz, td) + for_each_trip_desc(tz, td) { handle_thermal_trip(tz, td, &way_up_list, &way_down_list); - thermal_zone_set_trips(tz); + if (td->threshold <= tz->temperature && td->threshold > low) + low = td->threshold; + + if (td->threshold >= tz->temperature && td->threshold < high) + high = td->threshold; + } + + thermal_zone_set_trips(tz, low, high); list_sort(NULL, &way_up_list, thermal_trip_notify_cmp); list_for_each_entry(td, &way_up_list, notify_list_node) diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 4cf2b7230d04..67a09f90eb95 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -259,7 +259,7 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz, const char *thermal_trip_type_name(enum thermal_trip_type trip_type); -void thermal_zone_set_trips(struct thermal_zone_device *tz); +void thermal_zone_set_trips(struct thermal_zone_device *tz, int low, int high); int thermal_zone_trip_id(const struct thermal_zone_device *tz, const struct thermal_trip *trip); void thermal_zone_trip_updated(struct thermal_zone_device *tz, diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 06a0554ddc38..1d43ab52e86a 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -61,25 +61,8 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz) } EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips); -/** - * thermal_zone_set_trips - Computes the next trip points for the driver - * @tz: a pointer to a thermal zone device structure - * - * The function computes the next temperature boundaries by browsing - * the trip points. The result is the closer low and high trip points - * to the current temperature. These values are passed to the backend - * driver to let it set its own notification mechanism (usually an - * interrupt). - * - * This function must be called with tz->lock held. Both tz and tz->ops - * must be valid pointers. - * - * It does not return a value - */ -void thermal_zone_set_trips(struct thermal_zone_device *tz) +void thermal_zone_set_trips(struct thermal_zone_device *tz, int low, int high) { - const struct thermal_trip_desc *td; - int low = -INT_MAX, high = INT_MAX; int ret; lockdep_assert_held(&tz->lock); @@ -87,14 +70,6 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) if (!tz->ops.set_trips) return; - for_each_trip_desc(tz, td) { - if (td->threshold <= tz->temperature && td->threshold > low) - low = td->threshold; - - if (td->threshold >= tz->temperature && td->threshold < high) - high = td->threshold; - } - /* No need to change trip points */ if (tz->prev_low_trip == low && tz->prev_high_trip == high) return; From patchwork Fri Aug 16 08:12:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 819960 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B144382866 for ; Fri, 16 Aug 2024 08:12:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795969; cv=none; b=eoKyqpzVeMPChQOrvZV29jKnpIb24b8bvUO10tB2M9h1bK2jY4QBOGJRU772SWvlv49Zp/diZIiEPP8MVpS76TyG+3fB4cx9tZ6a/hfdXOXM1meMYilZzE57fmlOz3Bec3pd97ot25RX+asBwiftFXRTN81eiG6a5WR8p4WHFO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795969; c=relaxed/simple; bh=q2Mr8T9rpNJu+ahK70QsUjTdsxqn2/E6HDsTHa/q5UU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mnWFrLICZTb1hDaHHdUIN61nlh0CUJVBhuZJZ2jb/5Y74EoU80yy8/imdiYf2WPprKguCJzw0OZa1dNegBTfwdMRT76Xa/DmD7QvLTwhB89AW6TooQnjPwPOb4GEIv3AqFxppiPjZeoji6j6gbqoaF5Lzezor1Vyl3Ur4ZYvLDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=lLRfc+yE; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="lLRfc+yE" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4281ca54fd3so12235745e9.2 for ; Fri, 16 Aug 2024 01:12:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723795966; x=1724400766; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CkeXiVXMve42I4m1rtYHNXv2/48ldT7q4tRb/ChewnI=; b=lLRfc+yEcgah6/yy3AuVQ9JEFoXCUVdBtBKRuP+2hy42q/VBlMeq8L5TY0oc+8/llO e2kXJ1eP4D7C0qNRjR1ZTfFRNfu+KQC+GG0yEUM8rcwVUA2unROL54VRiKY8aoH50xbh sQSAkActh3U5ctileSlW5+bMysHm5bCZW8Z15ODZW90aEmz68hZt1OETKuP8MEhbj0GU t5XvDPX+1LEF+PKVJdSK7nxsXEm2Jsqm8NSWyK3Ool5IfFVXJFZreAgpGAe7Mkz0Ycba HvTNdh+0sUp+YUfQ5C2r0/z4nZpXkOLTpbxGimBFjVOGZMYsjrf4MqNvVRZu3Xbc+AtT KS7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723795966; x=1724400766; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CkeXiVXMve42I4m1rtYHNXv2/48ldT7q4tRb/ChewnI=; b=UzAu625sz5pKB04BVSgs4dWAalGBSqh9ldUSI9QE+VwIZ0QDx7usybh37FuTRxh/6S jGDL9GHVKRUvTWkxtAXbdhj7edsQddVevEaXjTG7b1HLs6SX6XT/dLB67RIMaqv3GEp/ KJNJ7eLewk7xZ9lhttz81H5xdgRr2QDFs3+ekN45vlkk6THdWObf4KAmn2gbWvzU9d57 Ac15QEc9yaGd3Xv2UPC/6FaDSAZVhCrynE+C6KcyzbBXL62EyXybZrbMcv6sZhVidyud jlLjaKVFSnkl+tCpCEVmTCAO2RR1Z2t9VmjyZX3/sVk+wLzEFcVqBUQJw/EVoPgCh2c5 KxPw== X-Gm-Message-State: AOJu0YxtG8xxgd8vWG+3NOUSZYMlLzI7rXMBqsfSls9i/vEKDeT0Fi9V ntDfPOXrND2ufYvB4RregdRHxGSbbuSlNO5ehuDhsGZLrBzDcdRuZU3vp9Vly8A= X-Google-Smtp-Source: AGHT+IGjg9Cc9omCO3+iL+0/SW/evj/tpynxkfYbacNaB8FvBx8Vbyq+2LncOYHIJZlSNJEORW3rUA== X-Received: by 2002:a05:600c:5247:b0:428:1310:b6b5 with SMTP id 5b1f17b1804b1-429ed7e335cmr14447775e9.34.1723795965552; Fri, 16 Aug 2024 01:12:45 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ed6593casm16021205e9.28.2024.08.16.01.12.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 01:12:45 -0700 (PDT) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-pm@vger.kernel.org, lukasz.luba@arm.com, quic_manafm@quicinc.com Subject: [PATCH v2 2/7] thermal/core: Add thresholds support Date: Fri, 16 Aug 2024 10:12:33 +0200 Message-ID: <20240816081241.1925221-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240816081241.1925221-1-daniel.lezcano@linaro.org> References: <20240816081241.1925221-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The trip points are a firmware description of the temperature limits of a specific thermal zone where we associate an action which is done by the kernel. The time resolution is low. The userspace has to deal with a more complex thermal management based on heuristics from different information coming from different places. The logic is much more complex but based on a bigger time resolution, usually one second based. The purpose of the userspace is to monitor the temperatures from different places and take actions. However, it can not be constantly reading the temperature to detect when a temperature threshold has been reached. This is especially bad for mobile or embedded system as that will lead to an unacceptable number of wakeup to check the temperature with nothing to do. On the other side, the sensors are now most of the time interrupt driven. That means the thermal framework will use the temperature trip points to program the sensor to trigger an interrupt when a temperature limit is crossed. Unfortunately, the userspace can not benefit this feature and current solutions found here and there, iow out-of-tree, are to add fake trip points in the firmware and enable the writable trip points. This is bad for different reasons, the trip points are for in-kernel actions, the semantic of their types is used by the thermal framework and by adding trip points in the device tree is a way to overcome the current limitation but tampering with how the thermal framework is supposed to work. The writable trip points is a way to adjust a temperature limit given a specific platform if the firmware is not accurate enough and TBH it is more a debug feature from my POV. The thresholds mechanism is a way to have the userspace to tell thermal framework to send a notification when a temperature limit is crossed. There is no id, no hysteresis, just the temperature and the direction of the limit crossing. That means we can be notified when a threshold is crossed the way up only, or the way down only or both ways. That allows to create hysteresis values if it is needed. A threshold can be added, deleted or flushed. The latter means all thresholds belonging to a thermal zone will be deleted. When a threshold is added: - if the same threshold (temperature and direction) exists, an error is returned - if a threshold is specified with the same temperature but a different direction, the specified direction is added - if there is no threshold with the same temperature then it is created When a threshold is deleted: - if the same threshold (temperature and direction) exists, it is deleted - if a threshold is specified with the same temperature but a different direction, the specified direction is removed - if there is no threshold with the same temperature, then an error is returned When the threshold are flushed: - All thresholds related to a thermal zone are deleted When a threshold is crossed: - the userspace does not need to know which threshold(s) have been crossed, it will be notified with the current temperature and the previous temperature - if multiple thresholds have been crossed between two updates only one notification will be send to the userspace, it is pointless to send a notification per thresholds crossed as the userspace can handle that easily when it has the temperature delta information Signed-off-by: Daniel Lezcano --- drivers/thermal/Kconfig | 15 ++ drivers/thermal/Makefile | 3 + drivers/thermal/thermal_core.h | 4 + drivers/thermal/thermal_thresholds.c | 241 +++++++++++++++++++++++++++ drivers/thermal/thermal_thresholds.h | 57 +++++++ include/linux/thermal.h | 3 + 6 files changed, 323 insertions(+) create mode 100644 drivers/thermal/thermal_thresholds.c create mode 100644 drivers/thermal/thermal_thresholds.h diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index ed16897584b4..84f9643678d6 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -40,6 +40,21 @@ config THERMAL_DEBUGFS Say Y to allow the thermal subsystem to collect diagnostic information that can be accessed via debugfs. +config THERMAL_THRESHOLDS + bool "Thermal thresholds notification mechanism" + depends on THERMAL_NETLINK + help + The userspace implements thermal engines which needs to get + notified when temperature thresholds are crossed the way up + and down. These notification allow them to analyze the + thermal situation of the platform and take decision to + fulfill specific thermal profile like 'balanced', + 'performance' or 'power saving'. In addition, the + temperature of the skin sensor is very important in this + case and must be monitored as well. + + If in doubt, say Y + config THERMAL_EMERGENCY_POWEROFF_DELAY_MS int "Emergency poweroff delay in milli-seconds" default 0 diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index ce7a4752ef52..3b991b1a7db4 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -7,6 +7,9 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o thermal_sys-y += thermal_core.o thermal_sysfs.o thermal_sys-y += thermal_trip.o thermal_helpers.o +# thermal thresholds +thermal_sys-$(CONFIG_THERMAL_THRESHOLDS) += thermal_thresholds.o + # netlink interface to manage the thermal framework thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 67a09f90eb95..0742c0f03d46 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -13,6 +13,7 @@ #include #include "thermal_netlink.h" +#include "thermal_thresholds.h" #include "thermal_debugfs.h" struct thermal_trip_desc { @@ -132,6 +133,9 @@ struct thermal_zone_device { bool resuming; #ifdef CONFIG_THERMAL_DEBUGFS struct thermal_debugfs *debugfs; +#endif +#ifdef CONFIG_THERMAL_THRESHOLDS + struct thresholds *thresholds; #endif struct thermal_trip_desc trips[] __counted_by(num_trips); }; diff --git a/drivers/thermal/thermal_thresholds.c b/drivers/thermal/thermal_thresholds.c new file mode 100644 index 000000000000..0241b468cfbd --- /dev/null +++ b/drivers/thermal/thermal_thresholds.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2024 Linaro Limited + * + * Author: Daniel Lezcano + * + * Thermal thresholds + */ +#include +#include +#include + +#include "thermal_core.h" + +struct thresholds { + struct list_head list; +}; + +int thermal_thresholds_init(struct thermal_zone_device *tz) +{ + struct thresholds *thresholds; + + thresholds = kmalloc(sizeof(*thresholds), GFP_KERNEL); + if (!thresholds) + return -ENOMEM; + + INIT_LIST_HEAD(&thresholds->list); + tz->thresholds = thresholds; + + return 0; +} + +void thermal_thresholds_exit(struct thermal_zone_device *tz) +{ + thermal_thresholds_flush(tz); + kfree(tz->thresholds); + tz->thresholds = NULL; +} + +static int __thermal_thresholds_cmp(void *data, + const struct list_head *l1, + const struct list_head *l2) +{ + struct threshold *t1 = container_of(l1, struct threshold, list); + struct threshold *t2 = container_of(l2, struct threshold, list); + + return t1->temperature - t2->temperature; +} + +static struct threshold *__thermal_thresholds_find(const struct thresholds *thresholds, int temperature) +{ + struct threshold *t; + + list_for_each_entry(t, &thresholds->list, list) + if (t->temperature == temperature) + return t; + + return NULL; +} + +static bool __thermal_threshold_is_crossed(struct threshold *threshold, int temperature, + int last_temperature, int direction, + int *low, int *high) +{ + if (temperature > threshold->temperature && threshold->temperature > *low && + (THERMAL_THRESHOLD_WAY_DOWN & threshold->direction)) + *low = threshold->temperature; + + if (temperature < threshold->temperature && threshold->temperature < *high && + (THERMAL_THRESHOLD_WAY_UP & threshold->direction)) + *high = threshold->temperature; + + if (temperature < threshold->temperature && + last_temperature >= threshold->temperature && + (threshold->direction & direction)) + return true; + + if (temperature >= threshold->temperature && + last_temperature < threshold->temperature && + (threshold->direction & direction)) + return true; + + return false; +} + +static bool thermal_thresholds_handle_raising(struct thresholds *thresholds, int temperature, + int last_temperature, int *low, int *high) +{ + struct threshold *t; + + list_for_each_entry(t, &thresholds->list, list) { + if (__thermal_threshold_is_crossed(t, temperature, last_temperature, + THERMAL_THRESHOLD_WAY_UP, low, high)) + return true; + } + + return false; +} + +static bool thermal_thresholds_handle_dropping(struct thresholds *thresholds, int temperature, + int last_temperature, int *low, int *high) +{ + struct threshold *t; + + list_for_each_entry_reverse(t, &thresholds->list, list) { + if (__thermal_threshold_is_crossed(t, temperature, last_temperature, + THERMAL_THRESHOLD_WAY_DOWN, low, high)) + return true; + } + + return false; +} + +void thermal_thresholds_flush(struct thermal_zone_device *tz) +{ + struct thresholds *thresholds = tz->thresholds; + struct threshold *entry, *tmp; + + lockdep_assert_held(&tz->lock); + + list_for_each_entry_safe(entry, tmp, &thresholds->list, list) { + list_del(&entry->list); + kfree(entry); + } + + __thermal_zone_device_update(tz, THERMAL_THRESHOLD_FLUSHED); +} + +int thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high) +{ + struct thresholds *thresholds = tz->thresholds; + + int temperature = tz->temperature; + int last_temperature = tz->last_temperature; + bool notify; + + lockdep_assert_held(&tz->lock); + + /* + * We need a second update in order to detect a threshold being crossed + */ + if (last_temperature == THERMAL_TEMP_INVALID) + return 0; + + /* + * The temperature is stable, so obviously we can not have + * crossed a threshold. + */ + if (last_temperature == temperature) + return 0; + + /* + * Since last update the temperature: + * - increased : thresholds are crossed the way up + * - decreased : thresholds are crossed the way down + */ + if (temperature > last_temperature) + notify = thermal_thresholds_handle_raising(thresholds, temperature, + last_temperature, low, high); + else + notify = thermal_thresholds_handle_dropping(thresholds, temperature, + last_temperature, low, high); + + if (notify) + pr_debug("A threshold has been crossed the way %s, with a temperature=%d, last_temperature=%d\n", + temperature > last_temperature ? "up" : "down", temperature, last_temperature); + + return 0; +} + +int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction) +{ + struct thresholds *thresholds = tz->thresholds; + struct threshold *t; + + lockdep_assert_held(&tz->lock); + + t = __thermal_thresholds_find(thresholds, temperature); + if (t) { + if (t->direction == direction) + return -EEXIST; + + t->direction |= direction; + } else { + + t = kmalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + + INIT_LIST_HEAD(&t->list); + t->temperature = temperature; + t->direction = direction; + list_add(&t->list, &thresholds->list); + list_sort(NULL, &thresholds->list, __thermal_thresholds_cmp); + } + + __thermal_zone_device_update(tz, THERMAL_THRESHOLD_ADDED); + + return 0; +} + +int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction) +{ + struct thresholds *thresholds = tz->thresholds; + struct threshold *t; + + lockdep_assert_held(&tz->lock); + + t = __thermal_thresholds_find(thresholds, temperature); + if (!t) + return -ENOENT; + + if (t->direction == direction) { + list_del(&t->list); + kfree(t); + } else { + t->direction &= ~direction; + } + + __thermal_zone_device_update(tz, THERMAL_THRESHOLD_DELETED); + + return 0; +} + +int thermal_thresholds_for_each(struct thermal_zone_device *tz, + int (*cb)(struct threshold *, void *arg), void *arg) +{ + struct thresholds *thresholds = tz->thresholds; + struct threshold *entry; + int ret; + + lockdep_assert_held(&tz->lock); + + list_for_each_entry(entry, &thresholds->list, list) { + ret = cb(entry, arg); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/thermal/thermal_thresholds.h b/drivers/thermal/thermal_thresholds.h new file mode 100644 index 000000000000..7c8ce150d6d0 --- /dev/null +++ b/drivers/thermal/thermal_thresholds.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#define THERMAL_THRESHOLD_WAY_UP BIT(0) +#define THERMAL_THRESHOLD_WAY_DOWN BIT(1) + +struct threshold { + int temperature; + int direction; + struct list_head list; +}; + +#ifdef CONFIG_THERMAL_THRESHOLDS +int thermal_thresholds_init(struct thermal_zone_device *tz); +void thermal_thresholds_exit(struct thermal_zone_device *tz); +void thermal_thresholds_flush(struct thermal_zone_device *tz); +int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction); +int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction); +int thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high); +int thermal_thresholds_for_each(struct thermal_zone_device *tz, + int (*cb)(struct threshold *, void *arg), void *arg); +#else +static inline int thermal_thresholds_init(struct thermal_zone_device *tz) +{ + return 0; +} + +static inline void thermal_thresholds_exit(struct thermal_zone_device *tz) +{ + ; +} + +static inline void thermal_thresholds_flush(struct thermal_zone_device *tz) +{ + ; +} + +static inline int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction) +{ + return 0; +} + +static inline int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction) +{ + return 0; +} + +static inline int thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high) +{ + return 0; +} + +static inline int thermal_thresholds_for_each(struct thermal_zone_device *tz, + int (*cb)(struct threshold *, void *arg), void *arg) +{ + return 0; +} +#endif diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 25fbf960b474..bf0b4a8218f6 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -55,6 +55,9 @@ enum thermal_notify_event { THERMAL_TZ_BIND_CDEV, /* Cooling dev is bind to the thermal zone */ THERMAL_TZ_UNBIND_CDEV, /* Cooling dev is unbind from the thermal zone */ THERMAL_INSTANCE_WEIGHT_CHANGED, /* Thermal instance weight changed */ + THERMAL_THRESHOLD_ADDED, /* Threshold added */ + THERMAL_THRESHOLD_DELETED, /* Threshold deleted */ + THERMAL_THRESHOLD_FLUSHED, /* All thresholds deleted */ }; /** From patchwork Fri Aug 16 08:12:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 819959 Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F0F012C49C for ; Fri, 16 Aug 2024 08:12:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795971; cv=none; b=hZhoVlLZcFT3D6mXr02RCN3oecoqt0LrNyBCs+Vf+vuDyi/4lQYWp90CZOc0r94800QKePiXT35phIo8h1VPOJ5dnWWU6ZXr4WsxiJMvCB76GoP1WJclRuzqPF9RoezEfNszHYe7JsLpF3kS8x5Om26hBxU6CpK8KpXMH0FlXNg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795971; c=relaxed/simple; bh=jBaTX53Phst+hHnS5w1wtky5QWcWytquKVGEZ5GX7ts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j+H28fkFmagPj5FyubZkCQoZdlGk3NDdxtk/ELSmS6zHsKJ0MP4aqI9228u/UHqByglhtGqyXQUK5EwJCYlkymFG2bQfqtn2LTOMo1vLLbKy7c2uxd8NGyZ9NLbLrfEDqCLzpnZnXUc0aZMDZdtXDugodVPC9ZkYzs/+iH7pHyg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=WlbQKWE1; arc=none smtp.client-ip=209.85.208.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="WlbQKWE1" Received: by mail-lj1-f171.google.com with SMTP id 38308e7fff4ca-2ef2cce8be8so19075431fa.1 for ; Fri, 16 Aug 2024 01:12:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723795968; x=1724400768; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=deaZPEiz8FHu9sPVP9I3mxBXKzoXXYxNuh+Xqkh0+pc=; b=WlbQKWE1ECF9a0Oq4oTv8vaDkSwmUWz82D8fx7FEsO42fESsU+HKoGE52n4qirXJeg OFG9UFqX22FtlDgNuW3BfoM87toWBtgmXh8LolCgbWJwS65DbaYUQEOKNPW7iPF0s5kc KzVDwibweDCcP+pvDBa8klv1s9Yv0dIZgkoM3BajCS2ThgOSOM8lbNMmhz/huM2iuzhe B+aC6OEk0KMFY//6C5Gaxqm7Sg7Tl4iXS+ckxxnZSIS5gtKB74ZcxbAo668ta97gQWnp HQv5bDwEfzPLZQbzpLu4WKljo0e33jus6AeCs38dMOOA3n5yXQaTrifjwVjReO+gdsMC PdwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723795968; x=1724400768; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=deaZPEiz8FHu9sPVP9I3mxBXKzoXXYxNuh+Xqkh0+pc=; b=Y9px8xvvBNb5X75aumatPaCflCao1EDGZ/Nr2XuDs6VH+1D+ZlHbytIYbJNNBA9BOu iv3o9e3PQ+gcz+RFpUtujQwj/AQfDh910+4bjawTO++8I0JeG4iTHgOd57hUEq9yjUYP DzTL+bcq20Cr0hAIiN+504/SlfWAIywM9kohQD9HINmTvfRb6DLtxA5zdYIc7W6V4/rh x8lToRg1GoHvQYsICknpTekl1w00JEct8VRb0o6G8x9vYRM+dAQ5pNDiCPoSMjMABKnD T9tAPWZgnKTTp9jklH9Vu1tVJS/rdVxuPedvhWCiRu8jdVTAAel5kxwEbvw7yc5/5DXt m73Q== X-Gm-Message-State: AOJu0YzYK5jHVfpq3NTo4oOoh/1TdaTZURrOi1EDyfkvZW3bKaLZz35P RJERQkoBLcFni+8qnLFFNpg9q/3eRMw5fI5FGCzwepsaklO5oM6ICTNjb67uIa4/X1cqlhyLZme tuIk= X-Google-Smtp-Source: AGHT+IHcO0hz1OM/X0LRknRDFQT/LCo8CrbGPbOl/NjVvg/n3iOjAnbbWI8CzCWuv8DqyOtlZGwzvA== X-Received: by 2002:a2e:515a:0:b0:2ef:5d1d:773f with SMTP id 38308e7fff4ca-2f3be5a8c4amr15414921fa.24.1723795967679; Fri, 16 Aug 2024 01:12:47 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ed6593casm16021205e9.28.2024.08.16.01.12.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 01:12:47 -0700 (PDT) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-pm@vger.kernel.org, lukasz.luba@arm.com, quic_manafm@quicinc.com Subject: [PATCH v2 5/7] tools/lib/thermal: Make more generic the command encoding function Date: Fri, 16 Aug 2024 10:12:36 +0200 Message-ID: <20240816081241.1925221-6-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240816081241.1925221-1-daniel.lezcano@linaro.org> References: <20240816081241.1925221-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The thermal netlink has been extended with more commands which require an encoding with more information. The generic encoding function puts the thermal zone id with the command name. It is the unique parameters. The next changes will provide more parameters to the command. Set the scene for those new parameters by making the encoding function more generic. Signed-off-by: Daniel Lezcano --- tools/lib/thermal/commands.c | 41 ++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c index 73d4d4e8d6ec..a9223df91dcf 100644 --- a/tools/lib/thermal/commands.c +++ b/tools/lib/thermal/commands.c @@ -261,8 +261,23 @@ static struct genl_ops thermal_cmd_ops = { .o_ncmds = ARRAY_SIZE(thermal_cmds), }; -static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd, - int flags, void *arg) +struct cmd_param { + int tz_id; +}; + +typedef int (*cmd_cb_t)(struct nl_msg *, struct cmd_param *); + +static int thermal_genl_tz_id_encode(struct nl_msg *msg, struct cmd_param *p) +{ + if (p->tz_id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) + return -1; + + return 0; +} + +static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cmd_cb, + struct cmd_param *param, + int cmd, int flags, void *arg) { struct nl_msg *msg; void *hdr; @@ -276,7 +291,7 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int if (!hdr) return THERMAL_ERROR; - if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id)) + if (cmd_cb && cmd_cb(msg, param)) return THERMAL_ERROR; if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg)) @@ -289,30 +304,38 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz) { - return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID, + return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_TZ_GET_ID, NLM_F_DUMP | NLM_F_ACK, tz); } thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc) { - return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET, + return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_CDEV_GET, NLM_F_DUMP | NLM_F_ACK, tc); } thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz) { - return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP, - 0, tz); + struct cmd_param p = { .tz_id = tz->id }; + + return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, + THERMAL_GENL_CMD_TZ_GET_TRIP, 0, tz); } thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz) { - return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz); + struct cmd_param p = { .tz_id = tz->id }; + + return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, + THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz); } thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz) { - return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz); + struct cmd_param p = { .tz_id = tz->id }; + + return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, + THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz); } thermal_error_t thermal_cmd_exit(struct thermal_handler *th) From patchwork Fri Aug 16 08:12:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 819958 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49B6812D74F for ; Fri, 16 Aug 2024 08:12:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795973; cv=none; b=Jr8/V3mi8aCfI62298k6L6bW3SwqjRU7z4bHbf4LYUNM8mwkYEQ8rNoaUg7ywvat681vd6JEWkLJ1dw7vmWtctogvuU7hbK8yQFcrjzPTWxfV2knlYbFcKMVf0ae59KDYUdPomaSRDLdjMvyDiMn2bSWiWbJ9vyu3odwAPp7K8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723795973; c=relaxed/simple; bh=ky6JEARCdxFnnRF1CRBNkrrQSuzdjffn6C61+FscHu8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JiT9TqkQSlda6ENOLuMEUnGFhFLchHUS5DBE41CfN8T2AQmofYrN6KhzmQH6uTJIDWkg1HH7WrAQ5gT+8HLvk6U4HPwnrEPJsRBdg6l0hXXlPt2NL6+pVH+bNd5H83uep0K6TEJ79rpjXzU8p0GUkJj0idGQ09RdtSZzSr1vCYU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=kaZTLUiJ; arc=none smtp.client-ip=209.85.128.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="kaZTLUiJ" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4281c164408so11798545e9.1 for ; Fri, 16 Aug 2024 01:12:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723795969; x=1724400769; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SeBSJLjzblBwDv/f5H0VYLzrS3n0MDRjLVWkG4LDN9U=; b=kaZTLUiJ3/b7D/RBZDUTJTMbbch5G3MyeZ2OwNcFslZNNmgSQ2g7RjSULmo9US4ett suz9U6N5zVlttOlf4ZnUp3cMMkb3WVEOziywOZc5W5N+y6fi7YNRa3w8BZfi/e8usC1X IElgjwcl6SWcIJzBWL1v/VBYz6VVyhOxFI6wUfskfsy1gmj8mYq41OE7mW8Ml2mE039W lspVj1mufa+yCCs7JZoIxJNMt0JauolgYRXThDL0CIK2b26rRcwOnmqdkzcYDteiHJfY WU4SW1pifdHrE/lcGiElZzezX8cEdPe2CYzXm+/a6TNZ2hEgBntdp5/J7ZqyVmNE/H5v 0ieg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723795969; x=1724400769; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SeBSJLjzblBwDv/f5H0VYLzrS3n0MDRjLVWkG4LDN9U=; b=SMaPVfgqZ/aF79InARdJTTMrXGHBEa7Cy6utejLkhogxXDyFDzfD1AsnwY6FNKiiBS 5QKmwvWlL0uvd6/+sa1/0dzGGg/2fjZ/R0Q9TIR3bC09wuici969lqLpfVVJuoBMdz3w JoyOSJD3hyGXJ8f6j8bXF9QKPoubvWkmK4MKwOZKtTC6JhlFmPj7yIoPk+zx07dvGNS3 w83qQEQvdos8HBE/BTyMkEbgAqki+87rq2MPeFcPOKmXpRLzoMt8wwJKOnDHtp180GSp HD5BrfdXJyebaaFNzSo8Upo1A62ZR8uw4nIezeye7a0FtnloyEy789De1wV0r1PgKirP fzoA== X-Gm-Message-State: AOJu0YywLuDEzTmHtu9SacY/+KYAN41XTeF0INRKm2/BMFQYRM91l8IO qihRHhzyeiihRA2zRoK1gNVzGvqQv0e35Zaz6vhmDTVQy302lwxbbAGhx2NSRnDI0dxEc5eUCFT 3gUE= X-Google-Smtp-Source: AGHT+IEcFUpF4dK5sJM0SASYxFYhaCZF3rTBwGU1mb454T9JCdmb1bBkmfii0fT/R1mZ/tMrUlkHYg== X-Received: by 2002:a05:600c:5108:b0:426:6618:146a with SMTP id 5b1f17b1804b1-429ed777266mr11866535e9.2.1723795969097; Fri, 16 Aug 2024 01:12:49 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ed6593casm16021205e9.28.2024.08.16.01.12.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 01:12:48 -0700 (PDT) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-pm@vger.kernel.org, lukasz.luba@arm.com, quic_manafm@quicinc.com Subject: [PATCH v2 7/7] tools/thermal/thermal-engine: Take into account the thresholds API Date: Fri, 16 Aug 2024 10:12:38 +0200 Message-ID: <20240816081241.1925221-8-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240816081241.1925221-1-daniel.lezcano@linaro.org> References: <20240816081241.1925221-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Enhance the thermal-engine skeleton with the thresholds added in the kernel and use the API exported by the thermal library. Signed-off-by: Daniel Lezcano --- tools/thermal/thermal-engine/thermal-engine.c | 109 +++++++++++++++--- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/tools/thermal/thermal-engine/thermal-engine.c b/tools/thermal/thermal-engine/thermal-engine.c index 9b1476a2680f..ddc30a27acda 100644 --- a/tools/thermal/thermal-engine/thermal-engine.c +++ b/tools/thermal/thermal-engine/thermal-engine.c @@ -38,6 +38,14 @@ struct thermal_data { struct thermal_handler *th; }; +static int show_threshold(struct thermal_threshold *th, __maybe_unused void *arg) +{ + INFO("threshold temp=%d, direction=%d\n", + th->temperature, th->direction); + + return 0; +} + static int show_trip(struct thermal_trip *tt, __maybe_unused void *arg) { INFO("trip id=%d, type=%d, temp=%d, hyst=%d\n", @@ -70,6 +78,8 @@ static int show_tz(struct thermal_zone *tz, __maybe_unused void *arg) for_each_thermal_trip(tz->trip, show_trip, NULL); + for_each_thermal_threshold(tz->thresholds, show_threshold, NULL); + show_temp(tz, arg); show_governor(tz, arg); @@ -77,6 +87,30 @@ static int show_tz(struct thermal_zone *tz, __maybe_unused void *arg) return 0; } +static int set_threshold(struct thermal_zone *tz, __maybe_unused void *arg) +{ + struct thermal_handler *th = arg; + int thresholds[] = { 43000, 65000, 49000, 55000, 57000 }; + size_t i; + + INFO("Setting threshold for thermal zone '%s', id=%d\n", tz->name, tz->id); + + if (thermal_cmd_threshold_flush(th, tz)) { + ERROR("Failed to flush all previous thresholds\n"); + return -1; + } + + for (i = 0; i < sizeof(thresholds) / sizeof(thresholds[0]); i++) + if (thermal_cmd_threshold_add(th, tz, thresholds[i], + THERMAL_THRESHOLD_WAY_UP | + THERMAL_THRESHOLD_WAY_DOWN)) { + ERROR("Failed to set threshold\n"); + return -1; + } + + return 0; +} + static int tz_create(const char *name, int tz_id, __maybe_unused void *arg) { INFO("Thermal zone '%s'/%d created\n", name, tz_id); @@ -197,20 +231,66 @@ static int gov_change(int tz_id, const char *name, __maybe_unused void *arg) return 0; } +static int threshold_add(int tz_id, int temp, int direction, + pid_t pid, __maybe_unused void *arg) +{ + INFO("Threshold added by pid=%d, tz_id=%d: temp=%d, direction=%d\n", + pid, tz_id, temp, direction); + + return 0; +} + +static int threshold_delete(int tz_id, int temp, int direction, + pid_t pid, __maybe_unused void *arg) +{ + INFO("Threshold deleted by pid=%d, tz_id=%d: temp=%d, direction=%d\n", + pid, tz_id, temp, direction); + + return 0; +} + +static int threshold_flush(int tz_id, pid_t pid, __maybe_unused void *arg) +{ + INFO("Thresholds flushed by pid=%d, tz_id=%d\n", pid, tz_id); + + return 0; +} + +static int threshold_up(int tz_id, int temp, int last_temp, __maybe_unused void *arg) +{ + INFO("Threshold crossed way up tz_id=%d: temp=%d, last_temp=%d\n", + tz_id, temp, last_temp); + + return 0; +} + +static int threshold_down(int tz_id, int temp, int last_temp, __maybe_unused void *arg) +{ + INFO("Threshold crossed way down tz_id=%d: temp=%d, last_temp=%d\n", + tz_id, temp, last_temp); + + return 0; +} + static struct thermal_ops ops = { - .events.tz_create = tz_create, - .events.tz_delete = tz_delete, - .events.tz_disable = tz_disable, - .events.tz_enable = tz_enable, - .events.trip_high = trip_high, - .events.trip_low = trip_low, - .events.trip_add = trip_add, - .events.trip_delete = trip_delete, - .events.trip_change = trip_change, - .events.cdev_add = cdev_add, - .events.cdev_delete = cdev_delete, - .events.cdev_update = cdev_update, - .events.gov_change = gov_change + .events.tz_create = tz_create, + .events.tz_delete = tz_delete, + .events.tz_disable = tz_disable, + .events.tz_enable = tz_enable, + .events.trip_high = trip_high, + .events.trip_low = trip_low, + .events.trip_add = trip_add, + .events.trip_delete = trip_delete, + .events.trip_change = trip_change, + .events.cdev_add = cdev_add, + .events.cdev_delete = cdev_delete, + .events.cdev_update = cdev_update, + .events.gov_change = gov_change, + .events.threshold_add = threshold_add, + .events.threshold_delete = threshold_delete, + .events.threshold_flush = threshold_flush, + .events.threshold_up = threshold_up, + .events.threshold_down = threshold_down, }; static int thermal_event(__maybe_unused int fd, __maybe_unused void *arg) @@ -280,6 +360,7 @@ enum { THERMAL_ENGINE_DAEMON_ERROR, THERMAL_ENGINE_LOG_ERROR, THERMAL_ENGINE_THERMAL_ERROR, + THERMAL_ENGINE_THRESHOLD_ERROR, THERMAL_ENGINE_MAINLOOP_ERROR, }; @@ -318,6 +399,8 @@ int main(int argc, char *argv[]) return THERMAL_ENGINE_THERMAL_ERROR; } + for_each_thermal_zone(td.tz, set_threshold, td.th); + for_each_thermal_zone(td.tz, show_tz, td.th); if (mainloop_init()) {