From patchwork Mon Jul 29 15:02:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815948 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) (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 F279F155A39 for ; Mon, 29 Jul 2024 15:03:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265417; cv=none; b=s7gt2qiMnLCtqJuiixnhEFLb90P3xcBeW1W6ytUxgJLVhsJNQllnJB5dGuAQOyRSC7KRjTJqb1UjtcIa1QJDnn2t3mFnQpCgBSbvCwJDSnC0Bmdz5+cpMP81aEpyPxzd/sFzGUis5umnGU+Kq9KhxbKnrDa69PkAf8aU3bUuuDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265417; c=relaxed/simple; bh=7LXIWhTFm6GfmS9Iv05xdMKiiBD3dYnnr6onqC+/POU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mCq1DbBgwEMTZ6TaftUB7RSxZpuXoAjbsSC/b2ln2+Sj8DpXtm3Q4459uyMABpgA/A7nuBNbNFcukWr6XVUu2Zbqf1cbWLABigQOeELvGwbUVTdyqt4DmjNEGj+JPYND2dbKbtaYOQtokv7YA4+7X3jT3iesIOnVfGl0P2ZUHwg= 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=CqFknS4k; arc=none smtp.client-ip=209.85.128.43 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="CqFknS4k" Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-428119da952so17342115e9.0 for ; Mon, 29 Jul 2024 08:03:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265414; x=1722870214; 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=0m5Inhdd//pDP4jvzaIA3RP1dMT0kGuSI0wQZgb4n7k=; b=CqFknS4kTAYe6pxQuH/YtYQw3Ak/58hNaoIPaj/1gNLD6RAAVc3X0PENdcfgwUYErM hXipeIPB5TF1ntAlJG9Q/fHAfXvywVn8HELYqfdvR5pk9UwzbxytigFeT4xns8zu9oXg v2J1pLNntTBGm3iO9TXeMlIrDqvFbVVvLTFY6RJq5oyoQZRGQ0Pjen0o7fsXn55GmQJO QXImWbaVcbcNidr5NSWSLnfF6ulWd5CObVfrF5rhtWvPmFFHjozDzDt6MjXSgoVei8/6 EZSySdwMkDLjX0Di862v+bZOqzIQF7qgV+OslN29euRiLojy/EMydgapYAVUfekFuzFo L16w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265414; x=1722870214; 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=0m5Inhdd//pDP4jvzaIA3RP1dMT0kGuSI0wQZgb4n7k=; b=sO4mWK8DJmeC36OGuzckiWCL1l8TQcdDItEuW7pfrHVSGxKo6qbqZiZefWB00Lt1Sj cofSDBRgaegtaS/hbPuSLDZ5K+Kf2txhzOUqRPJ1HF9drILJ/NEOU60/JEChqsj2nR0R 5aD0pWpROdJQdT+OUcRXUpwdgqRJ+No9YVz7b80z9a3hdP2xAR7PUtl23BOnCcr2bbR7 jCazsclU2kozwfFyxrNbGaAAG45FJAnPX6AaYM3e3f5QEAMOptrOzjeHC2LdSjTlNAb5 y3+izGlc6Zuc1jxz7u50BKcX/p6PxIBGFngMMQzfw2RBfnYHsK75maffgzc4s1tip54B 08VA== X-Gm-Message-State: AOJu0Yw6rC2UKiZeQJqTDae0Zz+uXM8kPiA93BLTWwzRzrtLeT4kmnCG WZDuK2hShYMEuTI3XTVdqFXPfd3i6P3uWRji0G8askUg9RHI+CdJTks/hubVqn0= X-Google-Smtp-Source: AGHT+IEDyiEoHwGgYkmOe2Bf/G87Pgo3Dyh5koW5qh80LjWF34ZSMZl26t599p6kgFbWT6MIB35eyg== X-Received: by 2002:a05:600c:458f:b0:428:16a0:1c3d with SMTP id 5b1f17b1804b1-42816a07e88mr46166695e9.19.1722265396720; Mon, 29 Jul 2024 08:03:16 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:16 -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 v1 1/7] thermal/core: Encapsulate more handle_thermal_trip Date: Mon, 29 Jul 2024 17:02:50 +0200 Message-ID: <20240729150259.1089814-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 value the incoming thresholds routine. Instead of looping in the trip descriptors in thermal_zone_device_update(), we move the loop in the handle_thermal_trip() function and use it to set the low and high values. As these variables can be set directly in the handle_thermal_trip(), we can get rid of a descriptors loop found in the thermal_set_trips() function as low and high are set in handle_thermal_trip(). Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 104 +++++++++++++++++++-------------- drivers/thermal/thermal_core.h | 2 +- drivers/thermal/thermal_trip.c | 12 +--- 3 files changed, 62 insertions(+), 56 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 95c399f94744..5cfa2a706e96 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -425,59 +425,74 @@ static void handle_critical_trips(struct thermal_zone_device *tz, } static void handle_thermal_trip(struct thermal_zone_device *tz, - struct thermal_trip_desc *td, struct list_head *way_up_list, - struct list_head *way_down_list) + struct list_head *way_down_list, + int *low, int *high) { - const struct thermal_trip *trip = &td->trip; + struct thermal_trip_desc *td; int old_threshold; - if (trip->temperature == THERMAL_TEMP_INVALID) - return; + for_each_trip_desc(tz, td) { - /* - * If the trip temperature or hysteresis has been updated recently, - * the threshold needs to be computed again using the new values. - * However, its initial value still reflects the old ones and that - * is what needs to be compared with the previous zone temperature - * to decide which action to take. - */ - old_threshold = td->threshold; - td->threshold = trip->temperature; + const struct thermal_trip *trip = &td->trip; + + if (trip->temperature == THERMAL_TEMP_INVALID) + continue; + + if (tz->last_temperature < old_threshold || + tz->last_temperature == THERMAL_TEMP_INIT) + continue; - if (tz->last_temperature >= old_threshold && - tz->last_temperature != THERMAL_TEMP_INIT) { /* - * Mitigation is under way, so it needs to stop if the zone - * temperature falls below the low temperature of the trip. - * In that case, the trip temperature becomes the new threshold. + * If the trip temperature or hysteresis has been updated recently, + * the threshold needs to be computed again using the new values. + * However, its initial value still reflects the old ones and that + * is what needs to be compared with the previous zone temperature + * to decide which action to take. */ - if (tz->temperature < trip->temperature - trip->hysteresis) { - list_add(&td->notify_list_node, way_down_list); - td->notify_temp = trip->temperature - trip->hysteresis; + old_threshold = td->threshold; + td->threshold = trip->temperature; - if (trip->type == THERMAL_TRIP_PASSIVE) { - tz->passive--; - WARN_ON(tz->passive < 0); + if (tz->last_temperature >= old_threshold && + tz->last_temperature != THERMAL_TEMP_INVALID) { + /* + * Mitigation is under way, so it needs to stop if the zone + * temperature falls below the low temperature of the trip. + * In that case, the trip temperature becomes the new threshold. + */ + if (tz->temperature < trip->temperature - trip->hysteresis) { + list_add(&td->notify_list_node, way_down_list); + td->notify_temp = trip->temperature - trip->hysteresis; + + if (trip->type == THERMAL_TRIP_PASSIVE) { + tz->passive--; + WARN_ON(tz->passive < 0); + } + } else { + td->threshold -= trip->hysteresis; } - } else { + } else if (tz->temperature >= trip->temperature) { + /* + * There is no mitigation under way, so it needs to be started + * if the zone temperature exceeds the trip one. The new + * threshold is then set to the low temperature of the trip. + */ + list_add_tail(&td->notify_list_node, way_up_list); + td->notify_temp = trip->temperature; td->threshold -= trip->hysteresis; + + if (trip->type == THERMAL_TRIP_PASSIVE) + tz->passive++; + else if (trip->type == THERMAL_TRIP_CRITICAL || + trip->type == THERMAL_TRIP_HOT) + handle_critical_trips(tz, trip); } - } else if (tz->temperature >= trip->temperature) { - /* - * There is no mitigation under way, so it needs to be started - * if the zone temperature exceeds the trip one. The new - * threshold is then set to the low temperature of the trip. - */ - list_add_tail(&td->notify_list_node, way_up_list); - td->notify_temp = trip->temperature; - td->threshold -= trip->hysteresis; - - if (trip->type == THERMAL_TRIP_PASSIVE) - tz->passive++; - else if (trip->type == THERMAL_TRIP_CRITICAL || - trip->type == THERMAL_TRIP_HOT) - handle_critical_trips(tz, trip); + + if (td->threshold < tz->temperature && td->threshold > *low) + *low = td->threshold; + + if (td->threshold > tz->temperature && td->threshold < *high) + *high = td->threshold; } } @@ -545,6 +560,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, { struct thermal_governor *governor = thermal_get_tz_governor(tz); struct thermal_trip_desc *td; + int low = -INT_MAX, high = INT_MAX; + LIST_HEAD(way_down_list); LIST_HEAD(way_up_list); int temp, ret; @@ -580,10 +597,9 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, tz->notify_event = event; - for_each_trip_desc(tz, td) - handle_thermal_trip(tz, td, &way_up_list, &way_down_list); + handle_thermal_trip(tz, &way_up_list, &way_down_list, &low, &high); - thermal_zone_set_trips(tz); + 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 c0b679b846b3..af0f9f5ae0de 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -76,10 +76,8 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips); * * 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 +85,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 Mon Jul 29 15:02:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815947 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) (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 393F315666D for ; Mon, 29 Jul 2024 15:03:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265419; cv=none; b=kk3m1QiO4uUTj0RIY2JVSNm/SX4Qmpm+4td/mNzEKqr/JEa3skDnCSWnRsDw/L0LGjQtSZRpQm7S5sl8vksZOelgabre0VhZoshRc7IYL3I9DIkWfnL9/MHsMdpeunI/9GBswbdtJkcSInW5rW2+yT3j3F4oo9z73RxoyJ3f8y0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265419; c=relaxed/simple; bh=V3Jv5lQ349hQFm3CIxs/YTGx4CZG3dm7HF9MHFBfhSI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MolxQNLUhA/EyOSf78+4bXeBWTXHCMMEXI4z6ZqtsSL4mcGU41wg9Y5upVdOtt7lEwKHL39Ac3whHu71JCCxB4/zSI7zZG8vKWO6yPrKjHyH47ZrK1PSIv/fOSo1R2k4uWRcBUBTa3XDRqtsH+rWv7qsuqtRuSm0Hq9m4CQFi/s= 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=kXdBn19D; arc=none smtp.client-ip=209.85.208.179 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="kXdBn19D" Received: by mail-lj1-f179.google.com with SMTP id 38308e7fff4ca-2ef23d04541so44929381fa.2 for ; Mon, 29 Jul 2024 08:03:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265415; x=1722870215; 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=D7k+J4GKlvNWueEcnY3YKZZwOsvS3fdyymDdUlp7zrk=; b=kXdBn19DN5E++EVJUgx0Fgt8ZVKEFQCjEYiHFzqqlwgu7dO7JDYcOVjkUvpUI428Jj eV7QjGTJqlfizB59KzOZgrNbXvXoYe0zhks+8dP91VSJ70uYD2peMYm87+ViI6CzJQ+e T0uUXzskx/LqYlqtDRd0rBXQ6Fzgym2iwsjarGP5IHePCV1TdXBn7jI7UkB1P6UufBEB VYkYJRcX976NcfssdPqQRN+PhlchXYGJIcV6C6mZdnftZfpGTvUfotGHKX1cvtOg9Mnu OMTXDl+8aQuNhe9t+X+XGm5NUrXHLcx7j96aJhOgNJjfFzaHxOf8ZQIPqGQly/bQ31Eb RyoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265415; x=1722870215; 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=D7k+J4GKlvNWueEcnY3YKZZwOsvS3fdyymDdUlp7zrk=; b=isRb4+9Lr1KSkCEvpjZ24nMvZlU2qSSwkfOdj/ijLV+pCPR2Wl641f3qL5QkLBexy/ iyyaK3ba1XRU8mZ9EIRfpKg96QOKfyXbva3n2tDxzR8yoZBlonsZ8VlN26K4Ej4LDJk1 00I7ZnpgB3Nw4YWj6xyzCKAiYKQMTRY8EXgAJNhTeQfAM01eoOelSwOVy1JWIWzq+a0N 9vQiosBxmOq8hu5vkjAtSVTnpl/RVoMIqQJMC36vl0L/oZuon/YQkYvzM2f1woHoFYdc zgyqlzegiVj52Biybkfyi9x3E3/iqNBEY6eDVRbg0Y+8r9EGdyELCAGtgNDHo0j2iXwD v47A== X-Gm-Message-State: AOJu0Yzf3zOunBklTkS9USMUH3TXeFFfu9M60Jjfj/qUSIewZZk2M5Am mOZZHIaRJ6eCoRX4b0y7D5cNYAyhwK1RQatsT115M0fpRZri55AUltat72CN6+w= X-Google-Smtp-Source: AGHT+IGuFf0bMWlNWRD7NCduCQbPGdXdjVTg4Y9BayFBYL3dxpT9oRev9mXgnlhMRC9HytFyESxQEw== X-Received: by 2002:a2e:800f:0:b0:2f0:27e4:3a43 with SMTP id 38308e7fff4ca-2f12edfd2d2mr49185011fa.11.1722265415093; Mon, 29 Jul 2024 08:03:35 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:34 -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 v1 2/7] thermal/core: Add thresholds support Date: Mon, 29 Jul 2024 17:02:51 +0200 Message-ID: <20240729150259.1089814-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 | 240 +++++++++++++++++++++++++++ drivers/thermal/thermal_thresholds.h | 57 +++++++ include/linux/thermal.h | 3 + 6 files changed, 322 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..7506684cca58 --- /dev/null +++ b/drivers/thermal/thermal_thresholds.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2024 Linaro Limited + * + * Author: Daniel Lezcano + * + * Thermal thresholds + */ +#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 Mon Jul 29 15:02:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815201 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (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 A87BD156864 for ; Mon, 29 Jul 2024 15:03:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265419; cv=none; b=PhqzkDXX5H/DlRWYG+kavXBuaNw5UU2TUpIxpjbKHaKZCGhOdJsFLgp/8BI/uF7sZHhqPNzZvL8oC8g4/nCDu1Rv/6SQut68ow4pelB+xoV2N85jZ/BjUT0CtrPHRx1u632fhzLEIfHHRTYJsdLlkmfbTRK4czf2WI7OAE5Vhmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265419; c=relaxed/simple; bh=Luu89QxJ9UUx/pMETY8/+y9F7kJjSWoxhcq37rD9X/4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NZb1lLgacE+F+m56JKE4leQTKSVoohYO2U/K72St5I4i9EAOQeul+wTCLafKS1LHfsOjrGT04pb/hB6V4BfrRmcxVvqOVTAOi6UaqV560BPHl/qKF5Jrc3laiS13DI89klqsjI0sejs6oQAtjlzLZbV5P/PLSC6IFT6Vbe9m4X4= 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=UfhArtS+; arc=none smtp.client-ip=209.85.128.50 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="UfhArtS+" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4281faefea9so5432395e9.2 for ; Mon, 29 Jul 2024 08:03:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265416; x=1722870216; 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=fvNWqKnvrqIzR2L2p9oPRLbv9hLOEbE07wjBN2Aeug4=; b=UfhArtS+Hi+VSJ/vjXQAsp2cGl2Vbc89Oofv5HcIJHxeTMXh1TA83CTgQ0q1y4/nOJ nOqziaQZqMgIulthsvyewumrGQJH2bqNE3meni3r2Eo2VCgj0WNm4OiNRXL5at3pfkQQ XQB4Tj+bCZIqkGNbLTxm+8XiCtk4XS817jnQmZTjZS7djDVfax72wRXp62EGhYDGMOF6 /f6mMXxl6oDO+XrNQ8AGC/zOonoItMIx1JN+Pudxfjib9DkQr+HYp5BihjTv3WfYLp8f tsHscCTIhfqINOT/bwF8tOEWVdlJuZcQvJjif+mNMSDY67CHQjnnzwbqhS4DiWjBKk31 xfqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265416; x=1722870216; 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=fvNWqKnvrqIzR2L2p9oPRLbv9hLOEbE07wjBN2Aeug4=; b=rDQg+gYODwl26fots/MEHQWF3ohoSajzxff24E12vQpyZYW1XhU+1c+/8BMGYyEFwx RgD529XJHoZDCPyjEeuftNy/ykAbTmA5Xc5Gqk5kktMvIAr1DxixUGxI3UEoXAz92ett rv5w1vXZtEKkEFDV3/ezxGAuulSbUaAXCbryu/wP1uBllopwWE0DGOdxTnkdZ3ojDdFc gTGeA2Zzs2xQWh6ii7lusBfDjw3Y4NAY7BeK3HAeQ77YKgR3c4h5BHW81cAWN8cukBkx ACDMzyovJSARxXv4Xd0zw4fBt9wJwf7MHwL63r0CnObBeoiatdfQP6NwdluhNl8lVQFu obbQ== X-Gm-Message-State: AOJu0YyPKF/Fq//RQad49/EUuuFdE7D5a2N1Q7Pg986UAWLPsTsf8sH8 dzIqjjYcZoqbw8XIVbUkUgKeoolRl35rbs6HOq4l3oAepefgzVrc0h7OyKogA/Y= X-Google-Smtp-Source: AGHT+IE4AjIWNU/ddobgDHZC/WypkJsZhyEFA7I6jLUfPSURrbhofhvqMu9IYGrhpAjeRMvlH1P8Cg== X-Received: by 2002:a5d:40cb:0:b0:368:445e:91cc with SMTP id ffacd0b85a97d-36b5cf0aa8cmr5376222f8f.21.1722265415868; Mon, 29 Jul 2024 08:03:35 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:35 -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 v1 3/7] thermal/core: Connect the threshold with the core Date: Mon, 29 Jul 2024 17:02:52 +0200 Message-ID: <20240729150259.1089814-4-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 Initialize, de-initialize and handle the threshold in the same place than the trip points. Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 5cfa2a706e96..7d35815b56b8 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -599,6 +599,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, handle_thermal_trip(tz, &way_up_list, &way_down_list, &low, &high); + thermal_thresholds_handle(tz, &low, &high); + thermal_zone_set_trips(tz, low, high); list_sort(NULL, &way_up_list, thermal_trip_notify_cmp); @@ -1569,6 +1571,10 @@ thermal_zone_device_register_with_trips(const char *type, goto unregister; } + result = thermal_thresholds_init(tz); + if (result) + goto remove_hwmon; + mutex_lock(&thermal_list_lock); mutex_lock(&tz->lock); list_add_tail(&tz->node, &thermal_tz_list); @@ -1589,6 +1595,8 @@ thermal_zone_device_register_with_trips(const char *type, return tz; +remove_hwmon: + thermal_remove_hwmon_sysfs(tz); unregister: device_del(&tz->device); release_device: @@ -1677,6 +1685,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_set_governor(tz, NULL); + thermal_thresholds_exit(tz); thermal_remove_hwmon_sysfs(tz); ida_free(&thermal_tz_ida, tz->id); ida_destroy(&tz->ida); From patchwork Mon Jul 29 15:02:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815946 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.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 996E8154C17 for ; Mon, 29 Jul 2024 15:03:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265421; cv=none; b=EOZQM8pl9Cke5HKNl6dIBGajL6PxSGk9Pv/0oebNh3YyDPvITAr2kHhfUnFKj/85dTLAngb6N0gd74za5iZr1cJpdfiXK6qKcwENbfANhrD07TiUpflK9+Y+LA3Y1THtuxEvMZkQ1lsuIMECDyERnhStdLySAfodoqmLS/mZIr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265421; c=relaxed/simple; bh=h+EE2Gqfp7GjvYl2R4KpliU+Iyr4vMitp6ZAJFHNsKg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BE0L+i58p8GRibMkkKW2imolYh349q4KWX0uOesbs5hq/hr7f20yRgFdRK743/FP5M29kSbkOxzI/4ciiOuHT7Bw3VYKSYweO/NQKjbsrJzSWQq1R92/F1Kr6aF5Z4Bcr72exzXdC0+7041TUPcIZpZ0u3TVwui+fUTnHdG4Hi8= 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=PS25eFar; arc=none smtp.client-ip=209.85.221.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="PS25eFar" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-367990aaef3so1636084f8f.0 for ; Mon, 29 Jul 2024 08:03:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265417; x=1722870217; 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=yCE6cI7Q2VTpE6v0Ag8CvQq77Igsepgge8qMIZzbipw=; b=PS25eFarfBBPtUtqH/EV3DK4GuFs91xBq40f9zXjbUcdaxsEN7F4IoC40eLbu/m2yb 6I6i3mUKMgKNjW3fWRfUfs1dYb+WEE8b7UXwYQ0WueMMSSL7vH8I4BnytCiwg3kC6V1V UgosHm5GCMH24F9mnUgbUx/jTRdI9WNFyqvdfTeSi/CMGt90eRBu6ROvCGIG/DV+T1au 3wqsCWtfYIdTz72Hp3gHSKS+SEL8aO8GrgVNWuKk88enuQ4OSQwP7oDIYCzSO0qBXIWH BIzYH9BCrL1AeGjF4ALXOCBAWksjQYV79Sy0TwzFqz9cWdWotOKTnC4DFlP8WMd87NEB N97Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265417; x=1722870217; 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=yCE6cI7Q2VTpE6v0Ag8CvQq77Igsepgge8qMIZzbipw=; b=NZrl+lC2Tm5esm8pAH4LULguDkfmrovHGViZYn6Qtz/Ol/XACztNAMXd+k5lfbJomr keK/l9+lDXcUmwNWJMQSbBo8OnAgqwiLktNy1hx4OmEY+Rvgd1Vot4/VGzO3/6fgvH6F Ppsg96wyPzljctbVTXVFcadEMSCqKQrYIYLE96amwcXK9f2aaBkJgNtBaL+gJONeTvKq MPkQfLKuqB2ih2ck1h+8SSjTruAlcqWuMBbRTryb8C48HugT1n+mc2NQ/hxAI/hywmx9 HpEDe++ETAxVD7IqzLsdN0lQ0hH+AbEC4QZppm15XFQJUg0LR8WY3jgBh0n+kcCRRRyJ xadQ== X-Gm-Message-State: AOJu0Yz9rDmnduQDRqvqk3MXLyNgXJ7zedH5xsN5grbQP3i68yHvlw5F SB6d1Ebjs1/+Lt3djHZx+nELsjJT5puTRwKFnzoAAJpraWVeLGIZFGPKkCZVZE0= X-Google-Smtp-Source: AGHT+IFtpqTjJ1gxXBuzmWQix1COUvbzHyxlC0R1jbrBkvohDzqZOK5tdfQihD5ywQlXTmOWVj/gSQ== X-Received: by 2002:adf:f412:0:b0:367:94a7:12cb with SMTP id ffacd0b85a97d-36b5d0ae56dmr5710406f8f.43.1722265416727; Mon, 29 Jul 2024 08:03:36 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:36 -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 v1 4/7] thermal/netlink: Add the commands and the events for the thresholds Date: Mon, 29 Jul 2024 17:02:53 +0200 Message-ID: <20240729150259.1089814-5-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 thresholds exist but there is no notification neither action code related to them yet. These changes implement the netlink for the notifications when the thresholds are crossed, added, deleted or flushed as well as the commands which allows to get the list of the thresholds, flush them, add and delete. As different processes in userspace can interact with the thresholds, the process id responsible of the action (add, delete or flush) will be added in the notification. This way a thermal engine is able to detect if another process is interfering with the thresholds. A process id of zero is the kernel as it is by convention usually. Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_netlink.c | 239 ++++++++++++++++++++++++++- drivers/thermal/thermal_netlink.h | 7 + drivers/thermal/thermal_thresholds.c | 36 ++-- drivers/thermal/thermal_thresholds.h | 15 +- include/uapi/linux/thermal.h | 30 +++- 5 files changed, 290 insertions(+), 37 deletions(-) diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index 97157c453630..3febb119a7f0 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -49,12 +50,19 @@ static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = [THERMAL_GENL_ATTR_CPU_CAPABILITY_ID] = { .type = NLA_U32 }, [THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE] = { .type = NLA_U32 }, [THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY] = { .type = NLA_U32 }, + + /* Thresholds */ + [THERMAL_GENL_ATTR_THRESHOLD] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_THRESHOLD_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_THRESHOLD_WAY] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_THRESHOLD_PID] = { .type = NLA_U32 }, }; struct param { struct nlattr **attrs; struct sk_buff *msg; const char *name; + pid_t pid; int tz_id; int cdev_id; int trip_id; @@ -62,6 +70,8 @@ struct param { int trip_type; int trip_hyst; int temp; + int last_temp; + int direction; int cdev_state; int cdev_max_state; struct thermal_genl_cpu_caps *cpu_capabilities; @@ -234,6 +244,36 @@ static int thermal_genl_event_cpu_capability_change(struct param *p) return -EMSGSIZE; } +static int thermal_genl_event_threshold_add(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, p->temp) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_WAY, p->direction) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_PID, p->pid)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_threshold_flush(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id), + nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_PID, p->pid)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_threshold_up(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_LAST_TEMP, p->last_temp) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TEMP, p->temp)) + return -EMSGSIZE; + + return 0; +} + int thermal_genl_event_tz_delete(struct param *p) __attribute__((alias("thermal_genl_event_tz"))); @@ -246,6 +286,12 @@ int thermal_genl_event_tz_disable(struct param *p) int thermal_genl_event_tz_trip_down(struct param *p) __attribute__((alias("thermal_genl_event_tz_trip_up"))); +int thermal_genl_event_threshold_delete(struct param *p) + __attribute__((alias("thermal_genl_event_threshold_add"))); + +int thermal_genl_event_threshold_down(struct param *p) + __attribute__((alias("thermal_genl_event_threshold_up"))); + static cb_t event_cb[] = { [THERMAL_GENL_EVENT_TZ_CREATE] = thermal_genl_event_tz_create, [THERMAL_GENL_EVENT_TZ_DELETE] = thermal_genl_event_tz_delete, @@ -259,6 +305,11 @@ static cb_t event_cb[] = { [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = thermal_genl_event_cdev_state_update, [THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = thermal_genl_event_gov_change, [THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE] = thermal_genl_event_cpu_capability_change, + [THERMAL_GENL_EVENT_THRESHOLD_ADD] = thermal_genl_event_threshold_add, + [THERMAL_GENL_EVENT_THRESHOLD_DELETE] = thermal_genl_event_threshold_delete, + [THERMAL_GENL_EVENT_THRESHOLD_FLUSH] = thermal_genl_event_threshold_flush, + [THERMAL_GENL_EVENT_THRESHOLD_DOWN] = thermal_genl_event_threshold_down, + [THERMAL_GENL_EVENT_THRESHOLD_UP] = thermal_genl_event_threshold_up, }; /* @@ -401,6 +452,43 @@ int thermal_genl_cpu_capability_event(int count, } EXPORT_SYMBOL_GPL(thermal_genl_cpu_capability_event); +int thermal_notify_threshold_add(const struct thermal_zone_device *tz, + int temperature, int direction, int pid) +{ + struct param p = { .tz_id = tz->id, .temp = temperature, .direction = direction, .pid = pid }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_ADD, &p); +} + +int thermal_notify_threshold_delete(const struct thermal_zone_device *tz, + int temperature, int direction, int pid) +{ + struct param p = { .tz_id = tz->id, .temp = temperature, .direction = direction, .pid = pid }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_DELETE, &p); +} + +int thermal_notify_threshold_flush(const struct thermal_zone_device *tz, int pid) +{ + struct param p = { .tz_id = tz->id, .pid = pid }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_FLUSH, &p); +} + +int thermal_notify_threshold_down(const struct thermal_zone_device *tz) +{ + struct param p = { .tz_id = tz->id, .temp = tz->temperature, .last_temp = tz->last_temperature }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_DOWN, &p); +} + +int thermal_notify_threshold_up(const struct thermal_zone_device *tz) +{ + struct param p = { .tz_id = tz->id, .temp = tz->temperature, .last_temp = tz->last_temperature }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_UP, &p); +} + /*************************** Command encoding ********************************/ static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz, @@ -575,12 +663,130 @@ static int thermal_genl_cmd_cdev_get(struct param *p) return ret; } +static int __thermal_genl_cmd_threshold_get(struct threshold *threshold, void *arg) +{ + struct sk_buff *msg = arg; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, threshold->temperature) || + nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_WAY, threshold->direction)) + return -1; + + return 0; +} + +static int thermal_genl_cmd_threshold_get(struct param *p) +{ + struct thermal_zone_device *tz; + struct sk_buff *msg = p->msg; + struct nlattr *start_trip; + int id, ret; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_THRESHOLD); + if (!start_trip) + return -EMSGSIZE; + + mutex_lock(&tz->lock); + ret = thermal_thresholds_for_each(tz, __thermal_genl_cmd_threshold_get, msg); + mutex_unlock(&tz->lock); + + if (ret) + return -EMSGSIZE; + + nla_nest_end(msg, start_trip); + + return 0; +} + +static int thermal_genl_cmd_threshold_add(struct param *p) +{ + struct thermal_zone_device *tz; + int id, temp, direction, ret = 0; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID] || + !p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP] || + !p->attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + temp = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]); + direction = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + mutex_lock(&tz->lock); + ret = thermal_thresholds_add(tz, temp, direction, p->pid); + mutex_unlock(&tz->lock); + + return ret; +} + +static int thermal_genl_cmd_threshold_delete(struct param *p) +{ + struct thermal_zone_device *tz; + int id, temp, direction, ret = 0; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID] || + !p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP] || + !p->attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + temp = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]); + direction = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + mutex_lock(&tz->lock); + ret = thermal_thresholds_delete(tz, temp, direction, p->pid); + mutex_unlock(&tz->lock); + + return ret; +} + +static int thermal_genl_cmd_threshold_flush(struct param *p) +{ + struct thermal_zone_device *tz; + int id; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + mutex_lock(&tz->lock); + thermal_thresholds_flush(tz, p->pid); + mutex_unlock(&tz->lock); + + return 0; +} + static cb_t cmd_cb[] = { - [THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id, - [THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip, - [THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp, - [THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov, - [THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get, + [THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id, + [THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip, + [THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp, + [THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov, + [THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get, + [THERMAL_GENL_CMD_THRESHOLD_GET] = thermal_genl_cmd_threshold_get, + [THERMAL_GENL_CMD_THRESHOLD_ADD] = thermal_genl_cmd_threshold_add, + [THERMAL_GENL_CMD_THRESHOLD_DELETE] = thermal_genl_cmd_threshold_delete, + [THERMAL_GENL_CMD_THRESHOLD_FLUSH] = thermal_genl_cmd_threshold_flush, }; static int thermal_genl_cmd_dumpit(struct sk_buff *skb, @@ -623,6 +829,7 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb, if (!msg) return -ENOMEM; p.msg = msg; + p.pid = task_tgid_vnr(current); hdr = genlmsg_put_reply(msg, info, &thermal_genl_family, 0, cmd); if (!hdr) @@ -691,6 +898,26 @@ static const struct genl_small_ops thermal_genl_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .dumpit = thermal_genl_cmd_dumpit, }, + { + .cmd = THERMAL_GENL_CMD_THRESHOLD_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_THRESHOLD_ADD, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_THRESHOLD_DELETE, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_THRESHOLD_FLUSH, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, }; static struct genl_family thermal_genl_family __ro_after_init = { @@ -703,7 +930,7 @@ static struct genl_family thermal_genl_family __ro_after_init = { .unbind = thermal_genl_unbind, .small_ops = thermal_genl_ops, .n_small_ops = ARRAY_SIZE(thermal_genl_ops), - .resv_start_op = THERMAL_GENL_CMD_CDEV_GET + 1, + .resv_start_op = __THERMAL_GENL_CMD_MAX, .mcgrps = thermal_genl_mcgrps, .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps), }; diff --git a/drivers/thermal/thermal_netlink.h b/drivers/thermal/thermal_netlink.h index e01221e8816b..715acee04f31 100644 --- a/drivers/thermal/thermal_netlink.h +++ b/drivers/thermal/thermal_netlink.h @@ -53,6 +53,13 @@ int thermal_notify_tz_gov_change(const struct thermal_zone_device *tz, int thermal_genl_sampling_temp(int id, int temp); int thermal_genl_cpu_capability_event(int count, struct thermal_genl_cpu_caps *caps); +int thermal_notify_threshold_add(const struct thermal_zone_device *tz, + int temperature, int direction, pid_t pid); +int thermal_notify_threshold_delete(const struct thermal_zone_device *tz, + int temperature, int direction, pid_t pid); +int thermal_notify_threshold_flush(const struct thermal_zone_device *tz, pid_t pid); +int thermal_notify_threshold_down(const struct thermal_zone_device *tz); +int thermal_notify_threshold_up(const struct thermal_zone_device *tz); #else static inline int thermal_netlink_init(void) { diff --git a/drivers/thermal/thermal_thresholds.c b/drivers/thermal/thermal_thresholds.c index 7506684cca58..0b87a8322fb3 100644 --- a/drivers/thermal/thermal_thresholds.c +++ b/drivers/thermal/thermal_thresholds.c @@ -31,7 +31,7 @@ int thermal_thresholds_init(struct thermal_zone_device *tz) void thermal_thresholds_exit(struct thermal_zone_device *tz) { - thermal_thresholds_flush(tz); + thermal_thresholds_flush(tz, 0); kfree(tz->thresholds); tz->thresholds = NULL; } @@ -110,7 +110,7 @@ static bool thermal_thresholds_handle_dropping(struct thresholds *thresholds, in return false; } -void thermal_thresholds_flush(struct thermal_zone_device *tz) +void thermal_thresholds_flush(struct thermal_zone_device *tz, pid_t pid) { struct thresholds *thresholds = tz->thresholds; struct threshold *entry, *tmp; @@ -122,6 +122,8 @@ void thermal_thresholds_flush(struct thermal_zone_device *tz) kfree(entry); } + thermal_notify_threshold_flush(tz, pid); + __thermal_zone_device_update(tz, THERMAL_THRESHOLD_FLUSHED); } @@ -131,7 +133,6 @@ int thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hig int temperature = tz->temperature; int last_temperature = tz->last_temperature; - bool notify; lockdep_assert_held(&tz->lock); @@ -153,21 +154,21 @@ int thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hig * - 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); + if (temperature > last_temperature) { + if (thermal_thresholds_handle_raising(thresholds, temperature, + last_temperature, low, high)) + thermal_notify_threshold_up(tz); + } else { + if (thermal_thresholds_handle_dropping(thresholds, temperature, + last_temperature, low, high)) + thermal_notify_threshold_down(tz); + } return 0; } -int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction) +int thermal_thresholds_add(struct thermal_zone_device *tz, + int temperature, int direction, pid_t pid) { struct thresholds *thresholds = tz->thresholds; struct threshold *t; @@ -193,12 +194,15 @@ int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int list_sort(NULL, &thresholds->list, __thermal_thresholds_cmp); } + thermal_notify_threshold_add(tz, temperature, direction, pid); + __thermal_zone_device_update(tz, THERMAL_THRESHOLD_ADDED); return 0; } -int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction) +int thermal_thresholds_delete(struct thermal_zone_device *tz, + int temperature, int direction, pid_t pid) { struct thresholds *thresholds = tz->thresholds; struct threshold *t; @@ -218,6 +222,8 @@ int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, i __thermal_zone_device_update(tz, THERMAL_THRESHOLD_DELETED); + thermal_notify_threshold_delete(tz, temperature, direction, pid); + return 0; } diff --git a/drivers/thermal/thermal_thresholds.h b/drivers/thermal/thermal_thresholds.h index 7c8ce150d6d0..b7a149b3400c 100644 --- a/drivers/thermal/thermal_thresholds.h +++ b/drivers/thermal/thermal_thresholds.h @@ -1,8 +1,5 @@ /* 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; @@ -12,9 +9,9 @@ struct threshold { #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); +void thermal_thresholds_flush(struct thermal_zone_device *tz, pid_t pid); +int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction, pid_t pid); +int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction, pid_t pid); 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); @@ -29,17 +26,17 @@ static inline void thermal_thresholds_exit(struct thermal_zone_device *tz) ; } -static inline void thermal_thresholds_flush(struct thermal_zone_device *tz) +static inline void thermal_thresholds_flush(struct thermal_zone_device *tz, pid_t pid) { ; } -static inline int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction) +static inline int thermal_thresholds_add(struct thermal_zone_device *tz, int temperature, int direction, pid_t pid) { return 0; } -static inline int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction) +static inline int thermal_thresholds_delete(struct thermal_zone_device *tz, int temperature, int direction, pid_t pid) { return 0; } diff --git a/include/uapi/linux/thermal.h b/include/uapi/linux/thermal.h index fc78bf3aead7..bcbaf62a1727 100644 --- a/include/uapi/linux/thermal.h +++ b/include/uapi/linux/thermal.h @@ -3,6 +3,8 @@ #define _UAPI_LINUX_THERMAL_H #define THERMAL_NAME_LENGTH 20 +#define THERMAL_THRESHOLD_WAY_UP 0x1 +#define THERMAL_THRESHOLD_WAY_DOWN 0x2 enum thermal_device_mode { THERMAL_DEVICE_DISABLED = 0, @@ -18,7 +20,7 @@ enum thermal_trip_type { /* Adding event notification support elements */ #define THERMAL_GENL_FAMILY_NAME "thermal" -#define THERMAL_GENL_VERSION 0x01 +#define THERMAL_GENL_VERSION 0x02 #define THERMAL_GENL_SAMPLING_GROUP_NAME "sampling" #define THERMAL_GENL_EVENT_GROUP_NAME "event" @@ -28,6 +30,7 @@ enum thermal_genl_attr { THERMAL_GENL_ATTR_TZ, THERMAL_GENL_ATTR_TZ_ID, THERMAL_GENL_ATTR_TZ_TEMP, + THERMAL_GENL_ATTR_TZ_LAST_TEMP, THERMAL_GENL_ATTR_TZ_TRIP, THERMAL_GENL_ATTR_TZ_TRIP_ID, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, @@ -48,6 +51,10 @@ enum thermal_genl_attr { THERMAL_GENL_ATTR_CPU_CAPABILITY_ID, THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE, THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY, + THERMAL_GENL_ATTR_THRESHOLD, + THERMAL_GENL_ATTR_THRESHOLD_TEMP, + THERMAL_GENL_ATTR_THRESHOLD_WAY, + THERMAL_GENL_ATTR_THRESHOLD_PID, __THERMAL_GENL_ATTR_MAX, }; #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) @@ -75,6 +82,11 @@ enum thermal_genl_event { THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, /* Cdev state updated */ THERMAL_GENL_EVENT_TZ_GOV_CHANGE, /* Governor policy changed */ THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE, /* CPU capability changed */ + THERMAL_GENL_EVENT_THRESHOLD_ADD, /* A thresold has been added */ + THERMAL_GENL_EVENT_THRESHOLD_DELETE, /* A thresold has been deleted */ + THERMAL_GENL_EVENT_THRESHOLD_FLUSH, /* All thresolds have been deleted */ + THERMAL_GENL_EVENT_THRESHOLD_UP, /* A thresold has been crossed the way up */ + THERMAL_GENL_EVENT_THRESHOLD_DOWN, /* A thresold has been crossed the way down */ __THERMAL_GENL_EVENT_MAX, }; #define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1) @@ -82,12 +94,16 @@ enum thermal_genl_event { /* Commands supported by the thermal_genl_family */ enum thermal_genl_cmd { THERMAL_GENL_CMD_UNSPEC, - THERMAL_GENL_CMD_TZ_GET_ID, /* List of thermal zones id */ - THERMAL_GENL_CMD_TZ_GET_TRIP, /* List of thermal trips */ - THERMAL_GENL_CMD_TZ_GET_TEMP, /* Get the thermal zone temperature */ - THERMAL_GENL_CMD_TZ_GET_GOV, /* Get the thermal zone governor */ - THERMAL_GENL_CMD_TZ_GET_MODE, /* Get the thermal zone mode */ - THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ + THERMAL_GENL_CMD_TZ_GET_ID, /* List of thermal zones id */ + THERMAL_GENL_CMD_TZ_GET_TRIP, /* List of thermal trips */ + THERMAL_GENL_CMD_TZ_GET_TEMP, /* Get the thermal zone temperature */ + THERMAL_GENL_CMD_TZ_GET_GOV, /* Get the thermal zone governor */ + THERMAL_GENL_CMD_TZ_GET_MODE, /* Get the thermal zone mode */ + THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ + THERMAL_GENL_CMD_THRESHOLD_GET, /* List of thresholds */ + THERMAL_GENL_CMD_THRESHOLD_ADD, /* Add a threshold */ + THERMAL_GENL_CMD_THRESHOLD_DELETE, /* Delete a threshold */ + THERMAL_GENL_CMD_THRESHOLD_FLUSH, /* Flush all the thresholds */ __THERMAL_GENL_CMD_MAX, }; #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) From patchwork Mon Jul 29 15:02:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815200 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (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 19B94155A39 for ; Mon, 29 Jul 2024 15:03:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265420; cv=none; b=Ha+X430TULtuKpkTIiSvxdNSAysD/zkNnx5FUOQdxBaT3R0itHdB38+DRsgFAOktZvPEKpZv1bpvCKdzF+b89jzwkMexSlJBmuBgobOa8tJ4Z1xToeZOyD2OsyTjEft+7Z7wiU6QwQ0fWDZ9noZmJYJJYtRHn/c+aO8emhxr/OQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265420; c=relaxed/simple; bh=jBaTX53Phst+hHnS5w1wtky5QWcWytquKVGEZ5GX7ts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KLV63mFK3RIGWUeeXC9cn40NG4pKT4dAxC9EKbmMSVCM53Lyra9Nc35xc+B94rLNOFoPM5zeOuDH3okXzE6v9ZxZMDxHMncu9rvDmaVd0h+9WdIy5+MuKelHsU2FIRgnZtr4PnrOpcTogVjEdX9K0qAJYeLwijJ2ZOZIv0xly0M= 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=AJJf0WDJ; arc=none smtp.client-ip=209.85.221.49 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="AJJf0WDJ" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-368440b073bso1234125f8f.0 for ; Mon, 29 Jul 2024 08:03:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265417; x=1722870217; 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=AJJf0WDJD1JdV/phTN3tjO/w/kQHH8qG9Ctws7eo4+2XmodRw5hjrQwxylCYNHTmK9 QVEb+7/bsYYFMJ9ahQyNBEJW/DMHTOOj4lFcFWrei8NbjQZ9p8Mww+a8IIvlcchYf8Qa Oro70n6txLO0fC3toYzK+epwVlSv8PfnW4UuBfof+rCZVRW4AMOqIlIKaacasmvQcl6s tZNyjCGb8sOrZAxRNlOavQplQykFwWTu4Ga8xMZJUgXMGkdAsbL5ue4LBsVO6mjPruqk 4718Z0QC7TKpbAqNU3Yr5fKxmwc0qvHFA70uqNcE7epgAc0EzUlseFkEkk6CxZHQTBar 3xqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265417; x=1722870217; 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=SliUrXmnIbNtDQM6d/uCpPNeu1hW5tGf447f3pMOpE8BLO2b/N6wSz9erC/opt1ADK 21DaU11xg4fm3pyW1TIU11cPRb0gr0jfI5DeHdT465TkG7L7OaZGC0M/189HA2fBqcVl /p94fAi6aZ4funFek05uNiOkO7tuTqBAOGuNwd4dIK2Exxq4M1Fzm0ZlRVnSbDSb/rw7 WAbDjks685OBldH82/Gk1ZeYzdzZO9un/pWksJssZzelBE3uzlqlHVgpp2kbsOIpAM7m mygaVDetcG7SiKHBO9OpNCW+/ZTyIlztHVXiSdq4A8Y+tNY6ucsttKGrjN3NhzWjEyMY zvdQ== X-Gm-Message-State: AOJu0YxXoebZjvmXYwD4ye1s+rgdfAyEDesIQjme8thRmgCkcwsYj5D/ 0jav2U9uVxXkroE3Ubo1tJz7xuJ1El51UobWlOvmLwmwcEVVrn7fV+uipqQRtBUqybSS/VaPXHV t X-Google-Smtp-Source: AGHT+IHShRMAWa6spcCLlwXE7Fb6x1EzSLqLAqjsL0bp2ZDSmqkM/HJ9kNrGjNEJXx4T5pc8fFaPaQ== X-Received: by 2002:a5d:6181:0:b0:362:d7ac:ae70 with SMTP id ffacd0b85a97d-36b5d7bda53mr4702533f8f.5.1722265417450; Mon, 29 Jul 2024 08:03:37 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:37 -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 v1 5/7] tools/lib/thermal: Make more generic the command encoding function Date: Mon, 29 Jul 2024 17:02:54 +0200 Message-ID: <20240729150259.1089814-6-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 Mon Jul 29 15:02:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815199 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) (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 35B0D15666D for ; Mon, 29 Jul 2024 15:03:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265422; cv=none; b=f/VDGAKyqt894R5a/M0jHK4f11hmnd8dGGg9sIS4moeI1oQdBkH7IeHMjZKBbEQKnOxsLPPGgFqG8PGaGVowMTMDsI9PqOU3cdac7eYylGKmjvgGP1jA0wyjOeV2Thdu2Inr1w2y0XlUAsR7XRaymv+xOqd256Dw5URvGGAhf+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265422; c=relaxed/simple; bh=OnYyHrw0OVCt42yLMry7RBzmbTCZJWDc505lUeqSeus=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qh6rOc3bn3NtIkh30EI452tcTWEOSwUVh1nl24fiicpKXaYVyol00HdtUAEKZI9t7ck3dWQVtoTObdEMJAhsAnCYDglQDZQr3EPtiGfSS3UdozCMNMsDsv9Hkfy67w+p8Hk/dUIpXGWt66b1j56+aWFdZvLYvAjriSHJYuMo4RE= 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=o58yCNiE; arc=none smtp.client-ip=209.85.208.179 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="o58yCNiE" Received: by mail-lj1-f179.google.com with SMTP id 38308e7fff4ca-2eeb1ba040aso61793901fa.1 for ; Mon, 29 Jul 2024 08:03:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265418; x=1722870218; 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=AaMSbRq616CiKnWW4VcljfAj49EnVXHHRWjN6wlUnNw=; b=o58yCNiEecTg9fhWSfvshrImLqF65kgHeLfwV1Zcqk1xV/FBidMZdqav6Y/38T7BUS mSiJfBPah5u0Ih8DSXO/mAUI10RmdSZeXXJX8bTEmDYf2WpI+Xr+i+IYhtS+6RH2f+4k TjuoZr+PY6XHbKK6jE1H1r2jsD9bnTehqz07A6VchkaXN15MqoHIStevmp0BTNF9W8PU wQ7C+Kom1P7Jvqi4Sk63lIwFgc1oRp+urp94tjzM585KGwowQCzFixkIOn7mGH3xCmx5 ll6wmExPZC50JoWK0zlNIOhVpqXfJMkAYaa6czIcySxYlCtTVSMO3m1XHj9C2ScsPOlk axZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265418; x=1722870218; 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=AaMSbRq616CiKnWW4VcljfAj49EnVXHHRWjN6wlUnNw=; b=DDU61ZKsGAOnBumJ4RMXJD92qyYD8VUO+iMrlNpRYb7jKhVVf9ciD8GEpiNBbKtDhh oWWF9KLRM2qa+cwepXl0HC3AfFHVaQnAnRVAJGtqR2AQgviD2rr8D1dkeyqAAlE8kMJ+ WNrNdL9SZjIcnMsDFtBfSm8qtmRpeOewBMlycAZSi3wxuY3BAIWqdmMZ4OcAIm5uHfzZ GG4yZC1Sz0dvC7LB+jRfK5E5veC2mt7oBXeU8279gZgxrx34fzaPEstw6cI9hJ6yRVnc Pv2/6iz2grHGs/rQY7/NixOd8qtDLfv1NKSMf7/b1NJ1wMQvaLTjPXlGKEOfDgVZ2frb KpAg== X-Gm-Message-State: AOJu0YyhOnrNmpZESjWXp51OchRP71i1I8VPrneO7b0a+f8MvKPKgsjK Fx0Q9i4n3ZW4nrzLKSMXXFkWWt9/g8mTeNX6e1qjg1667N8dXI9ysRvCP69Sb7U= X-Google-Smtp-Source: AGHT+IFvWKHWKcJzWWnhCUNEUKiUDxwC6S7ePKL5LPsCbVh8nJwbtUMimsr5kZNNU0/i9ocNEaasCA== X-Received: by 2002:a2e:904f:0:b0:2ef:2ee3:6e75 with SMTP id 38308e7fff4ca-2f12ee16004mr53307861fa.17.1722265418297; Mon, 29 Jul 2024 08:03:38 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:37 -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 v1 6/7] tools/lib/thermal: Add the threshold netlink ABI Date: Mon, 29 Jul 2024 17:02:55 +0200 Message-ID: <20240729150259.1089814-7-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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 framework supports the thresholds and allows the userspace to create, delete, flush, get the list of the thresholds as well as getting the list of the thresholds set for a specific thermal zone. Add the netlink abstraction in the thermal library to take full advantage of thresholds for the userspace program. Signed-off-by: Daniel Lezcano --- tools/lib/thermal/commands.c | 128 +++++++++++++++++++++++++++- tools/lib/thermal/events.c | 58 ++++++++++--- tools/lib/thermal/include/thermal.h | 40 +++++++++ tools/lib/thermal/libthermal.map | 5 ++ tools/lib/thermal/thermal.c | 17 ++++ tools/thermal/lib/Makefile | 2 +- 6 files changed, 235 insertions(+), 15 deletions(-) diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c index a9223df91dcf..12539a519b81 100644 --- a/tools/lib/thermal/commands.c +++ b/tools/lib/thermal/commands.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "thermal_nl.h" @@ -33,6 +34,11 @@ static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 }, [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 }, [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING }, + + /* Thresholds */ + [THERMAL_GENL_ATTR_THRESHOLD] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_THRESHOLD_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_THRESHOLD_WAY] = { .type = NLA_U32 }, }; static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz) @@ -182,6 +188,38 @@ static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz) return THERMAL_SUCCESS; } +static int parse_threshold_get(struct genl_info *info, struct thermal_zone *tz) +{ + struct nlattr *attr; + struct thermal_threshold *__tt = NULL; + size_t size = 0; + int rem; + + nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_THRESHOLD], rem) { + + if (nla_type(attr) == THERMAL_GENL_ATTR_THRESHOLD_TEMP) { + + size++; + + __tt = realloc(__tt, sizeof(*__tt) * (size + 2)); + if (!__tt) + return THERMAL_ERROR; + + __tt[size - 1].temperature = nla_get_u32(attr); + } + + if (nla_type(attr) == THERMAL_GENL_ATTR_THRESHOLD_WAY) + __tt[size - 1].direction = nla_get_u32(attr); + } + + if (__tt) + __tt[size].temperature = INT_MAX; + + tz->thresholds = __tt; + + return THERMAL_SUCCESS; +} + static int handle_netlink(struct nl_cache_ops *unused, struct genl_cmd *cmd, struct genl_info *info, void *arg) @@ -210,6 +248,10 @@ static int handle_netlink(struct nl_cache_ops *unused, ret = parse_tz_get_gov(info, arg); break; + case THERMAL_GENL_CMD_THRESHOLD_GET: + ret = parse_threshold_get(info, arg); + break; + default: return THERMAL_ERROR; } @@ -253,6 +295,34 @@ static struct genl_cmd thermal_cmds[] = { .c_maxattr = THERMAL_GENL_ATTR_MAX, .c_attr_policy = thermal_genl_policy, }, + { + .c_id = THERMAL_GENL_CMD_THRESHOLD_GET, + .c_name = (char *)"Get thresholds list", + .c_msg_parser = handle_netlink, + .c_maxattr = THERMAL_GENL_ATTR_MAX, + .c_attr_policy = thermal_genl_policy, + }, + { + .c_id = THERMAL_GENL_CMD_THRESHOLD_ADD, + .c_name = (char *)"Add a threshold", + .c_msg_parser = handle_netlink, + .c_maxattr = THERMAL_GENL_ATTR_MAX, + .c_attr_policy = thermal_genl_policy, + }, + { + .c_id = THERMAL_GENL_CMD_THRESHOLD_DELETE, + .c_name = (char *)"Delete a threshold", + .c_msg_parser = handle_netlink, + .c_maxattr = THERMAL_GENL_ATTR_MAX, + .c_attr_policy = thermal_genl_policy, + }, + { + .c_id = THERMAL_GENL_CMD_THRESHOLD_FLUSH, + .c_name = (char *)"Flush the thresholds", + .c_msg_parser = handle_netlink, + .c_maxattr = THERMAL_GENL_ATTR_MAX, + .c_attr_policy = thermal_genl_policy, + }, }; static struct genl_ops thermal_cmd_ops = { @@ -263,13 +333,29 @@ static struct genl_ops thermal_cmd_ops = { struct cmd_param { int tz_id; + int temp; + int direction; }; 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)) + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) + return -1; + + return 0; +} + +static int thermal_genl_threshold_encode(struct nl_msg *msg, struct cmd_param *p) +{ + if (thermal_genl_tz_id_encode(msg, p)) + return -1; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, p->temp)) + return -1; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_WAY, p->direction)) return -1; return 0; @@ -338,6 +424,46 @@ thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_ THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz); } +thermal_error_t thermal_cmd_threshold_get(struct thermal_handler *th, + struct thermal_zone *tz) +{ + struct cmd_param p = { .tz_id = tz->id }; + + return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, + THERMAL_GENL_CMD_THRESHOLD_GET, 0, tz); +} + +thermal_error_t thermal_cmd_threshold_add(struct thermal_handler *th, + struct thermal_zone *tz, + int temperature, + int direction) +{ + struct cmd_param p = { .tz_id = tz->id, .temp = temperature, .direction = direction }; + + return thermal_genl_auto(th, thermal_genl_threshold_encode, &p, + THERMAL_GENL_CMD_THRESHOLD_ADD, 0, tz); +} + +thermal_error_t thermal_cmd_threshold_delete(struct thermal_handler *th, + struct thermal_zone *tz, + int temperature, + int direction) +{ + struct cmd_param p = { .tz_id = tz->id, .temp = temperature, .direction = direction }; + + return thermal_genl_auto(th, thermal_genl_threshold_encode, &p, + THERMAL_GENL_CMD_THRESHOLD_DELETE, 0, tz); +} + +thermal_error_t thermal_cmd_threshold_flush(struct thermal_handler *th, + struct thermal_zone *tz) +{ + struct cmd_param p = { .tz_id = tz->id }; + + return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p, + THERMAL_GENL_CMD_THRESHOLD_FLUSH, 0, tz); +} + thermal_error_t thermal_cmd_exit(struct thermal_handler *th) { if (genl_unregister_family(&thermal_cmd_ops)) diff --git a/tools/lib/thermal/events.c b/tools/lib/thermal/events.c index a7a55d1a0c4c..a009381b30ec 100644 --- a/tools/lib/thermal/events.c +++ b/tools/lib/thermal/events.c @@ -94,6 +94,33 @@ static int handle_thermal_event(struct nl_msg *n, void *arg) case THERMAL_GENL_EVENT_TZ_GOV_CHANGE: return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg); + + case THERMAL_GENL_EVENT_THRESHOLD_ADD: + return ops->threshold_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_PID]), arg); + + case THERMAL_GENL_EVENT_THRESHOLD_DELETE: + return ops->threshold_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_WAY]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_PID]), arg); + + case THERMAL_GENL_EVENT_THRESHOLD_FLUSH: + return ops->threshold_flush(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_PID]), arg); + + case THERMAL_GENL_EVENT_THRESHOLD_UP: + return ops->threshold_up(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_LAST_TEMP]), arg); + + case THERMAL_GENL_EVENT_THRESHOLD_DOWN: + return ops->threshold_down(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), + nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_LAST_TEMP]), arg); + default: return -1; } @@ -101,19 +128,24 @@ static int handle_thermal_event(struct nl_msg *n, void *arg) static void thermal_events_ops_init(struct thermal_events_ops *ops) { - enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create; - enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete; - enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable; - enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable; - enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high; - enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low; - enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change; - enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add; - enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete; - enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add; - enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete; - enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update; - enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change; + enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create; + enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete; + enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable; + enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable; + enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high; + enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low; + enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change; + enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add; + enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete; + enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add; + enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete; + enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update; + enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change; + enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_ADD] = !!ops->threshold_add; + enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DELETE] = !!ops->threshold_delete; + enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_FLUSH] = !!ops->threshold_flush; + enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_UP] = !!ops->threshold_up; + enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DOWN] = !!ops->threshold_down; } thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg) diff --git a/tools/lib/thermal/include/thermal.h b/tools/lib/thermal/include/thermal.h index 1abc560602cf..0571ec0bf438 100644 --- a/tools/lib/thermal/include/thermal.h +++ b/tools/lib/thermal/include/thermal.h @@ -4,11 +4,20 @@ #define __LIBTHERMAL_H #include +#include #ifndef LIBTHERMAL_API #define LIBTHERMAL_API __attribute__((visibility("default"))) #endif +#ifndef THERMAL_THRESHOLD_WAY_UP +#define THERMAL_THRESHOLD_WAY_UP 0x1 +#endif + +#ifndef THERMAL_THRESHOLD_WAY_DOWN +#define THERMAL_THRESHOLD_WAY_DOWN 0x2 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -31,6 +40,11 @@ struct thermal_events_ops { int (*cdev_delete)(int cdev_id, void *arg); int (*cdev_update)(int cdev_id, int cur_state, void *arg); int (*gov_change)(int tz_id, const char *gov_name, void *arg); + int (*threshold_add)(int tz_id, int temperature, int direction, pid_t pid, void *arg); + int (*threshold_delete)(int tz_id, int temperature, int direction, pid_t pid, void *arg); + int (*threshold_flush)(int tz_id, pid_t pid, void *arg); + int (*threshold_up)(int tz_id, int temp, int last_temp, void *arg); + int (*threshold_down)(int tz_id, int temp, int last_temp, void *arg); }; struct thermal_ops { @@ -45,12 +59,18 @@ struct thermal_trip { int hyst; }; +struct thermal_threshold { + int temperature; + int direction; +}; + struct thermal_zone { int id; int temp; char name[THERMAL_NAME_LENGTH]; char governor[THERMAL_NAME_LENGTH]; struct thermal_trip *trip; + struct thermal_threshold *thresholds; }; struct thermal_cdev { @@ -74,12 +94,16 @@ typedef int (*cb_tt_t)(struct thermal_trip *, void *); typedef int (*cb_tc_t)(struct thermal_cdev *, void *); +typedef int (*cb_th_t)(struct thermal_threshold *, void *); + LIBTHERMAL_API int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg); LIBTHERMAL_API int for_each_thermal_trip(struct thermal_trip *tt, cb_tt_t cb, void *arg); LIBTHERMAL_API int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg); +LIBTHERMAL_API int for_each_thermal_threshold(struct thermal_threshold *th, cb_th_t cb, void *arg); + LIBTHERMAL_API struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz, const char *name); @@ -124,6 +148,22 @@ LIBTHERMAL_API thermal_error_t thermal_cmd_get_governor(struct thermal_handler * LIBTHERMAL_API thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz); +LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_get(struct thermal_handler *th, + struct thermal_zone *tz); + +LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_add(struct thermal_handler *th, + struct thermal_zone *tz, + int temperature, + int direction); + +LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_delete(struct thermal_handler *th, + struct thermal_zone *tz, + int temperature, + int direction); + +LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_flush(struct thermal_handler *th, + struct thermal_zone *tz); + /* * Netlink thermal samples */ diff --git a/tools/lib/thermal/libthermal.map b/tools/lib/thermal/libthermal.map index d5e77738c7a4..d657176aa47f 100644 --- a/tools/lib/thermal/libthermal.map +++ b/tools/lib/thermal/libthermal.map @@ -4,6 +4,7 @@ LIBTHERMAL_0.0.1 { for_each_thermal_zone; for_each_thermal_trip; for_each_thermal_cdev; + for_each_thermal_threshold; thermal_zone_find_by_name; thermal_zone_find_by_id; thermal_zone_discover; @@ -17,6 +18,10 @@ LIBTHERMAL_0.0.1 { thermal_cmd_get_trip; thermal_cmd_get_governor; thermal_cmd_get_temp; + thermal_cmd_threshold_get; + thermal_cmd_threshold_add; + thermal_cmd_threshold_delete; + thermal_cmd_threshold_flush; thermal_sampling_init; thermal_sampling_handle; thermal_sampling_fd; diff --git a/tools/lib/thermal/thermal.c b/tools/lib/thermal/thermal.c index 72a76dc205bc..4851744d482e 100644 --- a/tools/lib/thermal/thermal.c +++ b/tools/lib/thermal/thermal.c @@ -1,10 +1,24 @@ // SPDX-License-Identifier: LGPL-2.1+ // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano #include +#include #include #include "thermal_nl.h" +int for_each_thermal_threshold(struct thermal_threshold *th, cb_th_t cb, void *arg) +{ + int i, ret = 0; + + if (!th) + return 0; + + for (i = 0; th[i].temperature != INT_MAX; i++) + ret |= cb(&th[i], arg); + + return ret; +} + int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg) { int i, ret = 0; @@ -80,6 +94,9 @@ static int __thermal_zone_discover(struct thermal_zone *tz, void *th) if (thermal_cmd_get_trip(th, tz) < 0) return -1; + if (thermal_cmd_threshold_get(th, tz) < 0) + return -1; + if (thermal_cmd_get_governor(th, tz)) return -1; diff --git a/tools/thermal/lib/Makefile b/tools/thermal/lib/Makefile index 82db451935c5..f2552f73a64c 100644 --- a/tools/thermal/lib/Makefile +++ b/tools/thermal/lib/Makefile @@ -3,7 +3,7 @@ LIBTHERMAL_TOOLS_VERSION = 0 LIBTHERMAL_TOOLS_PATCHLEVEL = 0 -LIBTHERMAL_TOOLS_EXTRAVERSION = 1 +LIBTHERMAL_TOOLS_EXTRAVERSION = 2 MAKEFLAGS += --no-print-directory From patchwork Mon Jul 29 15:02:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 815945 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (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 C7DF5155342 for ; Mon, 29 Jul 2024 15:03:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265422; cv=none; b=DCPFxxo7sdh1sZfdeQPFDeZFExdt2q8SUZIzJS9sPEvY1VIGEUcOUluxUSf/QH8An/WiH6j85vr7djbH2VDRGg6tWz9zzGI0TQ4On3T/8oRAzox7KwQxrGxKDbUmHF7CjVlZ9TT9ejQMhMDhD8fT6alqir+MnQQjr8nDYSq1QC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722265422; c=relaxed/simple; bh=ky6JEARCdxFnnRF1CRBNkrrQSuzdjffn6C61+FscHu8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DUxf48T34EBVRd0C/9pdiedbA0KSGnXjqPA3A5tPkuP5bGkBwLizOd3lMSBQlNLmUwA/GZM4KRQD4XegqgQm8Aao5yLzHzYLC42Yje5C8NGraa2GRK9qy5oeOpGZmyXA1dttfh78cwqV10aomr9ZaQhbNzv4DPlkqmMUyTUzf0s= 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=hm9C/hYL; arc=none smtp.client-ip=209.85.221.47 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="hm9C/hYL" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-3685a564bafso1491618f8f.3 for ; Mon, 29 Jul 2024 08:03:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722265419; x=1722870219; 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=hm9C/hYLAGj0XthrtISQsl5bmVc42QpoL4zTEegjObsfakaf0vTHq0mDfONlhj7xLR 0zKgszwv0pBJL5oGVR2+iqD6ZT2LdqBkvvViSSRylfgSmZH56EiRHZ2LvIPnxV5qsNvp 3InhCq6JDGk36z2sADRYJqLhZqneM6IAGpPifJlpK3BPJt5Akssd1IAHClNEyIjdvznk aZHu1yXa5IzdX68YPTv4qZ7TSk+u9R/i8xJfQeOmFcWZ3ZSqwBXMxpnbHfZBB1pfVrif wniqJp+2G1PuNl3mQ5L2Tps/4gzzM5bRNKNWKfwtgNzeaAhnc/xyDYMwhfcQGekgcDdx fs4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722265419; x=1722870219; 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=O8D6DWAnIZx37RoaN928nJbeaGmamiMnmEqslM14EH4hEyjZjrKN0l1dTgRPd1NEcc NGrk8a0AZslQPimSyWHz7x7Dv3BVKq7p/ij52tCD/aOB/ZNFo1THAugKFn0xgYn1ddx1 79qvYLogcBCpQFle7fnr7Y2dCbmf3Flylahfo+LzhoTlq/NvngOX68FWrQvKBUgJVcvn 0nJEfkPuZhPWIqMrrhl+P87pvOo6IlVgrnA7V8YN16uHjKG3C5ltUvy2MaJKP2jDhn4Q 8JmuTEKGTWrjjbMaOGtdaAZU3uukM1XjLUYwJncKiAF60cHUknTjkpH3vfAb1a/HrzwP xm7w== X-Gm-Message-State: AOJu0YwOX1IgdXiDFG2aO1msx9rXugeT2WsO1/2pOeoMiEGu+dBc0kp7 LPaKkWojmHXprb2RA0vmledeHA6X4/i6j0ZOyE2sBVCXjlMC2MnKTDz/zlVc9TGlDTcLAfMVvV+ m X-Google-Smtp-Source: AGHT+IHqIJgjk3jL9V4RDISPZydZ+xvjHDq1sce1iOjDz57vMSmA8TBzY8lWzxl4+fvgWJ8XzoxBKw== X-Received: by 2002:a5d:45cb:0:b0:368:4634:c419 with SMTP id ffacd0b85a97d-36b5d09e40emr4715993f8f.58.1722265419085; Mon, 29 Jul 2024 08:03:39 -0700 (PDT) Received: from mai.box.freepro.com (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36b36863b45sm12652803f8f.107.2024.07.29.08.03.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Jul 2024 08:03:38 -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 v1 7/7] tools/thermal/thermal-engine: Take into account the thresholds API Date: Mon, 29 Jul 2024 17:02:56 +0200 Message-ID: <20240729150259.1089814-8-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240729150259.1089814-1-daniel.lezcano@linaro.org> References: <20240729150259.1089814-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()) {