mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Len Brown <lenb@kernel.org>
To: linux-acpi@vger.kernel.org, linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Zhang Rui <rui.zhang@intel.com>
Subject: [PATCH 11/30] Thermal: Introduce simple arbitrator for setting device cooling state
Date: Tue,  9 Oct 2012 01:54:01 -0400	[thread overview]
Message-ID: <ce119f83257aae29b84a5bfad0669e8348437b18.1349761836.git.len.brown@intel.com> (raw)
In-Reply-To: <1349762060-25334-1-git-send-email-lenb@kernel.org>
In-Reply-To: <e3f25e6e5836c4790fbe395ff42e241f372d859d.1349761836.git.len.brown@intel.com>

From: Zhang Rui <rui.zhang@intel.com>

This fixes the problem that a cooling device may be referenced by
by multiple trip points in multiple thermal zones.

With this patch, we have two stages for updating a thermal zone,
1. check if a thermal_instance needs to be updated or not
2. update the cooling device, based on the target cooling state
   of all its instances.

Note that, currently, the cooling device is set to the deepest
cooling state required.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/thermal/thermal_sys.c | 44 ++++++++++++++++++++++++++++++++++++++++---
 include/linux/thermal.h       |  1 +
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 70045c1..36ae2f4 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -41,6 +41,7 @@ MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 
+#define THERMAL_NO_TARGET -1UL
 /*
  * This structure is used to describe the behavior of
  * a certain cooling device on a certain trip point
@@ -54,6 +55,7 @@ struct thermal_instance {
 	int trip;
 	unsigned long upper;	/* Highest cooling state for this trip point */
 	unsigned long lower;	/* Lowest cooling state for this trip point */
+	unsigned long target;	/* expected cooling state */
 	char attr_name[THERMAL_NAME_LENGTH];
 	struct device_attribute attr;
 	struct list_head tz_node; /* node in tz->thermal_instances */
@@ -853,6 +855,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	dev->trip = trip;
 	dev->upper = upper;
 	dev->lower = lower;
+	dev->target = THERMAL_NO_TARGET;
 
 	result = get_idr(&tz->idr, &tz->lock, &dev->id);
 	if (result)
@@ -990,6 +993,7 @@ thermal_cooling_device_register(char *type, void *devdata,
 	strcpy(cdev->type, type);
 	INIT_LIST_HEAD(&cdev->thermal_instances);
 	cdev->ops = ops;
+	cdev->updated = true;
 	cdev->device.class = &thermal_class;
 	cdev->devdata = devdata;
 	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1081,6 +1085,34 @@ void thermal_cooling_device_unregister(struct
 }
 EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
+static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
+{
+	struct thermal_instance *instance;
+	unsigned long target = 0;
+
+	/* cooling device is updated*/
+	if (cdev->updated)
+		return;
+
+	/* Make sure cdev enters the deepest cooling state */
+	list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
+		if (instance->target == THERMAL_NO_TARGET)
+			continue;
+		if (instance->target > target)
+			target = instance->target;
+	}
+	cdev->ops->set_cur_state(cdev, target);
+	cdev->updated = true;
+}
+
+static void thermal_zone_do_update(struct thermal_zone_device *tz)
+{
+	struct thermal_instance *instance;
+
+	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+		thermal_cdev_do_update(instance->cdev);
+}
+
 /*
  * Cooling algorithm for active trip points
  *
@@ -1138,19 +1170,24 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 				cur_state = cur_state > instance->lower ?
 				    (cur_state - 1) : instance->lower;
 			}
-			cdev->ops->set_cur_state(cdev, cur_state);
+			instance->target = cur_state;
+			cdev->updated = false; /* cooling device needs update */
 		}
 	} else {	/* below trip */
 		list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
 			if (instance->trip != trip)
 				continue;
 
+			/* Do not use the inactive thermal instance */
+			if (instance->target == THERMAL_NO_TARGET)
+				continue;
 			cdev = instance->cdev;
 			cdev->ops->get_cur_state(cdev, &cur_state);
 
 			cur_state = cur_state > instance->lower ?
-				    (cur_state - 1) : instance->lower;
-			cdev->ops->set_cur_state(cdev, cur_state);
+				    (cur_state - 1) : THERMAL_NO_TARGET;
+			instance->target = cur_state;
+			cdev->updated = false; /* cooling device needs update */
 		}
 	}
 
@@ -1211,6 +1248,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 		}
 	}
 
+	thermal_zone_do_update(tz);
 	if (tz->forced_passive)
 		thermal_zone_device_passive(tz, temp, tz->forced_passive,
 					    THERMAL_TRIPS_NONE);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 9ae378a..de0515a 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -94,6 +94,7 @@ struct thermal_cooling_device {
 	struct device device;
 	void *devdata;
 	const struct thermal_cooling_device_ops *ops;
+	bool updated; /* true if the cooling device does not need update */
 	struct list_head thermal_instances;
 	struct list_head node;
 };
-- 
1.8.0.rc1


  parent reply	other threads:[~2012-10-09  6:03 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-09  5:53 ACPI & Thermal patches for Linux-3.7-merge Len Brown
2012-10-09  5:53 ` [PATCH 01/30] Thermal: Introduce multiple cooling states support Len Brown
2012-10-09  5:53   ` [PATCH 02/30] Thermal: Introduce cooling states range support Len Brown
2012-10-09  5:53   ` [PATCH 03/30] Thermal: set upper and lower limits Len Brown
2012-10-09  5:53   ` [PATCH 04/30] Thermal: Introduce .get_trend() callback Len Brown
2012-10-09  5:53   ` [PATCH 05/30] Thermal: Remove tc1/tc2 in generic thermal layer Len Brown
2012-10-09  5:53   ` [PATCH 06/30] Thermal: Introduce thermal_zone_trip_update() Len Brown
2012-10-09  5:53   ` [PATCH 07/30] Thermal: rename structure thermal_cooling_device_instance to thermal_instance Len Brown
2012-10-09  5:53   ` [PATCH 08/30] Thermal: Rename thermal_zone_device.cooling_devices Len Brown
2012-10-09  5:53   ` [PATCH 09/30] Thermal: Rename thermal_instance.node to thermal_instance.tz_node Len Brown
2012-10-09  5:54   ` [PATCH 10/30] Thermal: List thermal_instance in thermal_cooling_device Len Brown
2012-10-09  5:54   ` Len Brown [this message]
2012-10-09  5:54   ` [PATCH 12/30] Thermal: Unify the code for both active and passive cooling Len Brown
2012-10-09  5:54   ` [PATCH 13/30] Thermal: Introduce locking for cdev.thermal_instances list Len Brown
2012-10-09  5:54   ` [PATCH 14/30] thermal: fix potential out-of-bounds memory access Len Brown
2012-10-09  5:54   ` [PATCH 15/30] thermal: add Renesas R-Car thermal sensor support Len Brown
2012-10-09  5:54   ` [PATCH 16/30] thermal: Fix potential NULL pointer accesses Len Brown
2012-10-09  5:54   ` [PATCH 17/30] Fix a build error Len Brown
2012-10-09  5:54   ` [PATCH 18/30] thermal: add generic cpufreq cooling implementation Len Brown
2012-10-09  5:54   ` [PATCH 19/30] hwmon: exynos4: move thermal sensor driver to driver/thermal directory Len Brown
2012-10-09  5:54   ` [PATCH 20/30] thermal: exynos5: add exynos5250 thermal sensor driver support Len Brown
2012-10-09  5:54   ` [PATCH 21/30] thermal: exynos: register the tmu sensor with the kernel thermal layer Len Brown
2012-10-09  5:54   ` [PATCH 22/30] ARM: exynos: add thermal sensor driver platform data support Len Brown
2012-10-09  5:54   ` [PATCH 23/30] thermal: exynos: Use devm_* functions Len Brown
2012-10-09  5:54   ` [PATCH 24/30] Thermal: Fix bug on cpu_cooling, cooling device's id conflict problem Len Brown
2012-10-09  5:54   ` [PATCH 25/30] thermal: Exynos: Fix NULL pointer dereference in exynos_unregister_thermal() Len Brown
2012-10-09  5:54   ` [PATCH 26/30] ACPI: EC: Make the GPE storm threshold a module parameter Len Brown
2012-10-09  5:54   ` [PATCH 27/30] ACPI: EC: Add a quirk for CLEVO M720T/M730T laptop Len Brown
2012-10-09  6:16     ` Jonathan Nieder
2012-10-09  6:22       ` Feng Tang
2012-10-09  6:59         ` Jonathan Nieder
2012-10-09  7:19           ` Feng Tang
2012-10-09  5:54   ` [PATCH 28/30] cpuidle / ACPI: fix potential NULL pointer dereference Len Brown
2012-10-09  5:54   ` [PATCH 29/30] ACPI idle, CPU hotplug: Fix NULL pointer dereference during hotplug Len Brown
2012-10-09  5:54   ` [PATCH 30/30] tools/power/acpi/acpidump: remove duplicated include from acpidump.c Len Brown

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=ce119f83257aae29b84a5bfad0669e8348437b18.1349761836.git.len.brown@intel.com \
    --to=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --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®