mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: rjw@rjwysocki.net
Cc: daniel.lezcano@linaro.org, linux-acpi@vger.kernel.org,
	linux-pm@vger.kernel.org, "Rafael J. Wysocki" <rafael@kernel.org>,
	Zhang Rui <rui.zhang@intel.com>, Len Brown <lenb@kernel.org>,
	linux-kernel@vger.kernel.org (open list)
Subject: [PATCH v2 10/11] thermal/acpi: Rewrite the trip point intialization to use the generic thermal trip
Date: Fri,  3 Feb 2023 18:44:28 +0100	[thread overview]
Message-ID: <20230203174429.3375691-11-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <20230203174429.3375691-1-daniel.lezcano@linaro.org>

We can use the thermal trip points defined in the thermal.h.

Let's initialize them properly and when the code will be moved to the
generic thermal structure, we will be able to remove the specific acpi
trip points.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/acpi/thermal.c | 238 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 212 insertions(+), 26 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9122d1c44777..f89236cd4fcd 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -153,6 +153,8 @@ struct acpi_thermal {
 	struct acpi_thermal_trip trips[ACPI_THERMAL_TRIP_MAX];
 	struct acpi_handle_list devices;
 	struct thermal_zone_device *thermal_zone;
+	struct thermal_trip *_trips;
+	int num_trips;
 	int kelvin_offset;	/* in millidegrees */
 	struct work_struct thermal_check_work;
 	struct mutex thermal_check_lock;
@@ -244,6 +246,198 @@ do {	\
 		"Please report to linux-acpi@vger.kernel.org\n", str); \
 } while (0)
 
+static void acpi_thermal_trips_override(struct thermal_trip *trip, int temperature)
+{
+	if (temperature > trip->temperature)
+		pr_info("Overriding temperature %d->%d m°C\n",
+			trip->temperature, temperature);
+
+	trip->temperature = temperature;
+}
+
+static struct thermal_trip *acpi_thermal_trips_alloc_critical(struct acpi_thermal *tz,
+							      struct thermal_trip *trips,
+							      int *num_trips)
+{
+	acpi_status status = AE_OK;
+	unsigned long long temp;
+
+	/*
+	 * Module parameters disable the critical trip point
+	 */
+	if (crt < 0)
+		goto out;
+
+	status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &temp);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_debug(tz->device->handle, "No critical threshold\n");
+		goto out;
+	}
+
+	if (temp <= 2732) {
+		pr_info(FW_BUG "Invalid critical threshold (%llu)\n", temp);
+		goto out;
+	}
+
+	trips = krealloc(trips, sizeof(*trips) * (*num_trips + 1), GFP_KERNEL);
+	if (!trips)
+		goto out;
+
+	memset(&trips[*num_trips], 0, sizeof(*trips));
+
+	trips[*num_trips].temperature = deci_kelvin_to_millicelsius(temp);
+	trips[*num_trips].type = THERMAL_TRIP_CRITICAL;
+
+	if (crt > 0)
+		acpi_thermal_trips_override(&trips[*num_trips], crt * MILLI);
+	
+	(*num_trips)++;
+out:
+	return trips;
+}
+
+static struct thermal_trip *acpi_thermal_trips_alloc_hot(struct acpi_thermal *tz,
+							 struct thermal_trip *trips,
+							 int *num_trips)
+{
+	acpi_status status;
+	unsigned long long temp;
+
+	status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &temp);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_debug(tz->device->handle, "No hot threshold\n");
+		goto out;
+	}
+
+	trips = krealloc(trips, sizeof(*trips) * (*num_trips + 1), GFP_KERNEL);
+	if (!trips)
+		goto out;
+
+	memset(&trips[*num_trips], 0, sizeof(*trips));
+
+	trips[*num_trips].temperature = deci_kelvin_to_millicelsius(temp);
+	trips[*num_trips].type = THERMAL_TRIP_HOT;
+	
+	(*num_trips)++;
+out:
+	return trips;
+}
+
+static struct thermal_trip *acpi_thermal_trips_alloc_passive(struct acpi_thermal *tz,
+							     struct thermal_trip *trips,
+							     int *num_trips)
+{
+	struct acpi_handle_list devices;
+	acpi_status status;
+	unsigned long long temp;
+
+	/*
+	 * Module parameters disable all passive trip points
+	 */
+	if (psv < 0)
+		goto out;
+	
+	status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &temp);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_debug(tz->device->handle, "No passive threshold\n");
+		goto out;
+	}
+
+	status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_debug(tz->device->handle, "No passive device associated\n");
+		goto out;
+	}
+	
+	trips = krealloc(trips, sizeof(*trips) * (*num_trips + 1), GFP_KERNEL);
+	if (!trips)
+		goto out;
+
+	memset(&trips[*num_trips], 0, sizeof(*trips));
+
+	trips[*num_trips].temperature = deci_kelvin_to_millicelsius(temp);
+	trips[*num_trips].type = THERMAL_TRIP_PASSIVE;
+	
+	(*num_trips)++;
+out:
+	return trips;
+}
+
+static struct thermal_trip *acpi_thermal_trips_alloc_active(struct acpi_thermal *tz,
+							    struct thermal_trip *trips,
+							    int *num_trips)
+{
+	struct acpi_handle_list devices;
+	acpi_status status;
+	unsigned long long temp;
+	int i;
+
+	/*
+	 * Module parameters disable all active trip points
+	 */
+	if (act < 0)
+		return trips;
+
+	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+		char name[5];
+
+		sprintf(name, "_AC%d", i);
+
+		status = acpi_evaluate_integer(tz->device->handle, name, NULL, &temp);
+		if (ACPI_FAILURE(status))
+			break;
+
+		sprintf(name, "_AL%d", i);
+
+		status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_info(tz->device->handle, "No _AL%d defined for _AC%d\n", i, i);
+			break;
+		}
+
+		trips = krealloc(trips, sizeof(*trips) * (*num_trips + 1), GFP_KERNEL);
+		if (!trips)
+			break;
+
+		memset(&trips[*num_trips], 0, sizeof(*trips));
+
+		trips[*num_trips].temperature = deci_kelvin_to_millicelsius(temp);
+		trips[*num_trips].type = THERMAL_TRIP_ACTIVE;
+	
+		(*num_trips)++;
+	}
+
+	/*
+	 * We found at least one trip point and we have an override option
+	 */
+	if (i && act) {
+		/*
+		 * Regarding the ACPI specification AC0 is the highest active
+		 * temperature trip point. We will override this one.
+		 */
+		acpi_thermal_trips_override(&trips[*num_trips], act * MILLI);		
+	}
+
+	return trips;
+}
+
+static struct thermal_trip *acpi_thermal_trips_alloc(struct acpi_thermal *tz, int *num_trips)
+{
+	struct thermal_trip *trips = NULL;
+
+	*num_trips = 0;
+
+	trips = acpi_thermal_trips_alloc_critical(tz, trips, num_trips);
+
+	trips = acpi_thermal_trips_alloc_hot(tz, trips, num_trips);
+
+	trips = acpi_thermal_trips_alloc_passive(tz, trips, num_trips);
+
+	trips = acpi_thermal_trips_alloc_active(tz, trips, num_trips);
+
+	return trips;
+}
+
 static int acpi_thermal_trips_update_critical(struct acpi_thermal *tz, int flag)
 {
 	acpi_status status = AE_OK;
@@ -398,7 +592,7 @@ static int acpi_thermal_trips_update_active(struct acpi_thermal *tz, int flag)
 	int valid = 0;
 	int i;
 
-	for (i = ACPI_THERMAL_TRIP_ACTIVE; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
 		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
 
 		valid = tz->trips[i].flags.valid;
@@ -820,35 +1014,20 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
 
 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 {
-	int trips = 0;
 	int result;
 	acpi_status status;
-	int i;
-
-	if (tz->trips[ACPI_THERMAL_TRIP_CRITICAL].flags.valid)
-		trips++;
-
-	if (tz->trips[ACPI_THERMAL_TRIP_HOT].flags.valid)
-		trips++;
-
-	if (tz->trips[ACPI_THERMAL_TRIP_PASSIVE].flags.valid)
-		trips++;
-
-	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips[i].flags.valid;
-	     i++, trips++);
 
 	if (tz->trips[ACPI_THERMAL_TRIP_PASSIVE].flags.valid)
 		tz->thermal_zone =
-			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     		&acpi_thermal_zone_ops, NULL,
-						     		tz->trips[ACPI_THERMAL_TRIP_PASSIVE].tsp*100,
-						     		tz->polling_frequency*100);
+			thermal_zone_device_register_with_trips("acpitz", tz->_trips, tz->num_trips, 0, tz,
+								&acpi_thermal_zone_ops, NULL,
+								tz->trips[ACPI_THERMAL_TRIP_PASSIVE].tsp*100,
+								tz->polling_frequency*100);
 	else
 		tz->thermal_zone =
-			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     		&acpi_thermal_zone_ops, NULL,
-						     		0, tz->polling_frequency * 100);
-
+			thermal_zone_device_register_with_trips("acpitz", tz->_trips, tz->num_trips, 0, tz,
+								&acpi_thermal_zone_ops, NULL,
+								0, tz->polling_frequency*100);
 	if (IS_ERR(tz->thermal_zone))
 		return -ENODEV;
 
@@ -1051,8 +1230,8 @@ static void acpi_thermal_check_fn(struct work_struct *work)
 
 static int acpi_thermal_add(struct acpi_device *device)
 {
-	struct acpi_thermal *tz;
-	int result;
+	struct acpi_thermal *tz = NULL;
+	int result = 0;
 
 	if (!device)
 		return -EINVAL;
@@ -1073,9 +1252,13 @@ static int acpi_thermal_add(struct acpi_device *device)
 
 	acpi_thermal_guess_offset(tz);
 
+	tz->_trips = acpi_thermal_trips_alloc(tz, &tz->num_trips);
+	if (!tz->_trips)
+		goto free_trips;
+
 	result = acpi_thermal_register_thermal_zone(tz);
 	if (result)
-		goto free_memory;
+		goto free_trips;
 
 	refcount_set(&tz->thermal_check_count, 3);
 	mutex_init(&tz->thermal_check_lock);
@@ -1085,6 +1268,8 @@ static int acpi_thermal_add(struct acpi_device *device)
 		acpi_device_bid(device), tz->temperature);
 	goto end;
 
+free_trips:
+	kfree(tz->_trips);
 free_memory:
 	kfree(tz);
 end:
@@ -1101,6 +1286,7 @@ static void acpi_thermal_remove(struct acpi_device *device)
 	flush_workqueue(acpi_thermal_pm_queue);
 	tz = acpi_driver_data(device);
 
+	kfree(tz->trips);
 	acpi_thermal_unregister_thermal_zone(tz);
 	kfree(tz);
 }
-- 
2.34.1


  parent reply	other threads:[~2023-02-03 17:45 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20230203174429.3375691-1-daniel.lezcano@linaro.org>
2023-02-03 17:44 ` [PATCH v2 01/11] thermal/acpi: Remove the intermediate acpi_thermal_trip structure Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 02/11] thermal/acpi: Change to a common " Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 03/11] thermal/acpi: Convert the acpi thermal trips to an array Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 04/11] thermal/acpi: Move the active trip points to the same array Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 05/11] thermal/acpi: Optimize get_trip_points() Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 06/11] thermal/acpi: Encapsulate in functions the trip initialization Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 07/11] thermal/acpi: Simplifify the condition check Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 08/11] thermal/acpi: Remove active and enabled flags Daniel Lezcano
2023-02-03 17:44 ` [PATCH v2 09/11] thermal/acpi: Convert the units to milli Celsuis Daniel Lezcano
2023-02-03 17:44 ` Daniel Lezcano [this message]
2023-02-03 17:44 ` [PATCH v2 11/11] thermal/acpi: Use the thermal framework ACPI API Daniel Lezcano
2023-02-04  5:10   ` kernel test robot
2023-02-04  7:54   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230203174429.3375691-11-daniel.lezcano@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=rui.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®