All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] Thermal: generic thermal layer enhancement
@ 2012-07-19  6:31 Zhang Rui
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
                   ` (16 more replies)
  0 siblings, 17 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

Hi, all,

these are the patches that I want to push to linux-next.

it contains two patches from Durga, one patch for documentation update,
and 13 patches to fix the problems discussed in
http://marc.info/?l=linux-acpi&m=133836783425764&w=2

please kindly review.

1) patch 1, 2, introduce the writeable trip point,
   and introduce hysterisis information for each trip point.
2) patch 3 is a Documentation update.
3) patch 4, 5, 6, introduce the multiple cooling states support
   for both active and passive trip points.
4) patch 7, 8, remove passive specific requirement, aka, tc1/tc2, and
   introduce .get_trend() instead, for both active and passive cooling
   algorithm.
5) patch 9 introduces new function thermal_zone_trip_update(),
   which contains the code for general cooling algorithm.
6) patch 10, 11, 12, 13 rename some thermal structures to make them more accurate.
7) patch 14 introduces a simple cooling state arbitrator.
8) patch 15 unifies the code for both passive and active cooling.
9) patch 16 converts an internal list to plist, which is more efficient.

Any comments are welcome.

thanks,
rui

---------------------------------------------------------------------------
Durgadoss R (2):
      Thermal: Make Thermal trip points writeable
      Thermal: Add Hysteresis attributes

Zhang Rui (14):
      Thermal: Documentation update
      Thermal: Introduce multiple cooling states support
      Thermal: Introduce cooling states range support
      Thermal: set upper and lower limits
      Thermal: Introduce .get_trend() callback.
      Thermal: Remove tc1/tc2 in generic thermal layer.
      Thermal: Introduce thermal_zone_trip_update()
      Thermal: rename structure thermal_cooling_device_instance to thermal_instance
      Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances
      Thermal: Rename thermal_instance.node to thermal_instance.tz_node.
      Thermal: List thermal_instance in thermal_cooling_device.
      Thermal: Introduce simple arbitrator for setting device cooling state
      Thermal: Unify the code for both active and passive cooling
      Thermal: use plist instead of list

---------------------------------------------------------------------------
 Documentation/thermal/sysfs-api.txt      |   36 +-
 drivers/acpi/thermal.c                   |   99 ++++--
 drivers/platform/x86/acerhdf.c           |    6 +-
 drivers/platform/x86/intel_mid_thermal.c |    2 +-
 drivers/thermal/spear_thermal.c          |    4 +-
 drivers/thermal/thermal_sys.c            |  543 +++++++++++++++++++++---------
 include/linux/thermal.h                  |   43 ++-
 7 files changed, 521 insertions(+), 212 deletions(-)


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 10:35   ` R, Durgadoss
                     ` (2 more replies)
  2012-07-19  6:31 ` [PATCH 02/16] Thermal: Add Hysteresis attributes Zhang Rui
                   ` (15 subsequent siblings)
  16 siblings, 3 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

From: Durgadoss R <dugardoss.r@intel.com>

Some of the thermal drivers using the Generic Thermal Framework
require (all/some) trip points to be writeable. This patch makes
the trip point temperatures writeable on a per-trip point basis,
and modifies the required function call in thermal.c. This patch
also updates the Documentation to reflect the new change.

Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 Documentation/thermal/sysfs-api.txt      |    4 +-
 drivers/acpi/thermal.c                   |    4 +-
 drivers/platform/x86/acerhdf.c           |    2 +-
 drivers/platform/x86/intel_mid_thermal.c |    2 +-
 drivers/thermal/spear_thermal.c          |    2 +-
 drivers/thermal/thermal_sys.c            |  147 +++++++++++++++++++++---------
 include/linux/thermal.h                  |   15 ++-
 7 files changed, 125 insertions(+), 51 deletions(-)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 1733ab9..0c7c423 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -32,7 +32,8 @@ temperature) and throttle appropriate devices.
 
 1.1 thermal zone device interface
 1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name,
-		int trips, void *devdata, struct thermal_zone_device_ops *ops)
+		int trips, int flag, void *devdata,
+		struct thermal_zone_device_ops *ops)
 
     This interface function adds a new thermal zone device (sensor) to
     /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
@@ -40,6 +41,7 @@ temperature) and throttle appropriate devices.
 
     name: the thermal zone name.
     trips: the total number of trip points this thermal zone supports.
+    flag: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
     devdata: device private data
     ops: thermal zone device call-backs.
 	.bind: bind the thermal zone device with a thermal cooling device.
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 7dbebea..2107d1b 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -845,7 +845,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 
 	if (tz->trips.passive.flags.valid)
 		tz->thermal_zone =
-			thermal_zone_device_register("acpitz", trips, tz,
+			thermal_zone_device_register("acpitz", trips, 0, tz,
 						     &acpi_thermal_zone_ops,
 						     tz->trips.passive.tc1,
 						     tz->trips.passive.tc2,
@@ -853,7 +853,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 						     tz->polling_frequency*100);
 	else
 		tz->thermal_zone =
-			thermal_zone_device_register("acpitz", trips, tz,
+			thermal_zone_device_register("acpitz", trips, 0, tz,
 						     &acpi_thermal_zone_ops,
 						     0, 0, 0,
 						     tz->polling_frequency*100);
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 2fd9d36..39abb15 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -660,7 +660,7 @@ static int acerhdf_register_thermal(void)
 	if (IS_ERR(cl_dev))
 		return -EINVAL;
 
-	thz_dev = thermal_zone_device_register("acerhdf", 1, NULL,
+	thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
 					      &acerhdf_dev_ops, 0, 0, 0,
 					      (kernelmode) ? interval*1000 : 0);
 	if (IS_ERR(thz_dev))
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 5ae9cd9..2b2c212 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -499,7 +499,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
 			goto err;
 		}
 		pinfo->tzd[i] = thermal_zone_device_register(name[i],
-				0, td_info, &tzd_ops, 0, 0, 0, 0);
+				0, 0, td_info, &tzd_ops, 0, 0, 0, 0);
 		if (IS_ERR(pinfo->tzd[i])) {
 			kfree(td_info);
 			ret = PTR_ERR(pinfo->tzd[i]);
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index c2e32df..69a55d4 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
 	stdev->flags = pdata->thermal_flags;
 	writel_relaxed(stdev->flags, stdev->thermal_base);
 
-	spear_thermal = thermal_zone_device_register("spear_thermal", 0,
+	spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
 				stdev, &ops, 0, 0, 0, 0);
 	if (IS_ERR(spear_thermal)) {
 		dev_err(&pdev->dev, "thermal zone device is NULL\n");
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 022bacb..a590d57 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -196,6 +196,28 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
+trip_point_temp_store(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	int trip, ret;
+	unsigned long temperature;
+
+	if (!tz->ops->set_trip_temp)
+		return -EPERM;
+
+	if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
+		return -EINVAL;
+
+	if (kstrtoul(buf, 10, &temperature))
+		return -EINVAL;
+
+	ret = tz->ops->set_trip_temp(tz, trip, temperature);
+
+	return ret ? ret : count;
+}
+
+static ssize_t
 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 		     char *buf)
 {
@@ -283,33 +305,6 @@ static DEVICE_ATTR(temp, 0444, temp_show, NULL);
 static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 
-static struct device_attribute trip_point_attrs[] = {
-	__ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
-	__ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
-	__ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
-};
-
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)	\
 	container_of(_dev, struct thermal_cooling_device, device)
@@ -1089,9 +1084,83 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 EXPORT_SYMBOL(thermal_zone_device_update);
 
 /**
+ * create_trip_attrs - create attributes for trip points
+ * @tz:		the thermal zone device
+ * @flag:	Writeable trip point bitmap.
+ */
+static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
+{
+	int indx;
+	int writeable;
+
+	tz->trip_type_attrs =
+		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
+	if (!tz->trip_type_attrs)
+		return -ENOMEM;
+
+	tz->trip_temp_attrs =
+		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
+	if (!tz->trip_temp_attrs) {
+		kfree(tz->trip_type_attrs);
+		return -ENOMEM;
+	}
+
+	for (indx = 0; indx < tz->trips; indx++) {
+
+		/* create trip type attribute */
+		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
+			 "trip_point_%d_type", indx);
+
+		sysfs_attr_init(&tz->trip_type_attrs[count].attr.attr);
+		tz->trip_type_attrs[indx].attr.attr.name =
+						tz->trip_type_attrs[indx].name;
+		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
+		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
+
+		device_create_file(&tz->device,
+				   &tz->trip_type_attrs[indx].attr);
+
+		/* create trip temp attribute */
+		writeable = flag & (1 << indx);
+		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
+			 "trip_point_%d_temp", indx);
+
+		sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
+		tz->trip_temp_attrs[indx].attr.attr.name =
+						tz->trip_temp_attrs[indx].name;
+		tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
+		tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
+		if (writeable) {
+			tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
+			tz->trip_temp_attrs[indx].attr.store =
+							trip_point_temp_store;
+		}
+
+		device_create_file(&tz->device,
+				   &tz->trip_temp_attrs[indx].attr);
+	}
+	return 0;
+}
+
+static void remove_trip_attrs(struct thermal_zone_device *tz)
+{
+	int indx;
+
+	for (indx = 0; indx < tz->trips; indx++) {
+		device_remove_file(&tz->device,
+				   &tz->trip_type_attrs[indx].attr);
+		device_remove_file(&tz->device,
+				   &tz->trip_temp_attrs[indx].attr);
+	}
+	kfree(tz->trip_type_attrs);
+	kfree(tz->trip_temp_attrs);
+}
+
+/**
  * thermal_zone_device_register - register a new thermal zone device
  * @type:	the thermal zone device type
  * @trips:	the number of trip points the thermal zone support
+ * @flag:	a bit string indicating the writeablility of trip points
  * @devdata:	private device data
  * @ops:	standard thermal zone device callbacks
  * @tc1:	thermal coefficient 1 for passive calculations
@@ -1107,7 +1176,7 @@ EXPORT_SYMBOL(thermal_zone_device_update);
  * section 11.1.5.1 of the ACPI specification 3.0.
  */
 struct thermal_zone_device *thermal_zone_device_register(char *type,
-	int trips, void *devdata,
+	int trips, int flag, void *devdata,
 	const struct thermal_zone_device_ops *ops,
 	int tc1, int tc2, int passive_delay, int polling_delay)
 {
@@ -1124,6 +1193,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	if (trips > THERMAL_MAX_TRIPS || trips < 0)
 		return ERR_PTR(-EINVAL);
 
+	if (flag >> trips)
+		return ERR_PTR(-EINVAL);
+
 	if (!ops || !ops->get_temp)
 		return ERR_PTR(-EINVAL);
 
@@ -1175,15 +1247,11 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 			goto unregister;
 	}
 
+	result = create_trip_attrs(tz, flag);
+	if (result)
+		goto unregister;
+
 	for (count = 0; count < trips; count++) {
-		result = device_create_file(&tz->device,
-					    &trip_point_attrs[count * 2]);
-		if (result)
-			break;
-		result = device_create_file(&tz->device,
-					    &trip_point_attrs[count * 2 + 1]);
-		if (result)
-			goto unregister;
 		tz->ops->get_trip_type(tz, count, &trip_type);
 		if (trip_type == THERMAL_TRIP_PASSIVE)
 			passive = 1;
@@ -1259,13 +1327,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 	device_remove_file(&tz->device, &dev_attr_temp);
 	if (tz->ops->get_mode)
 		device_remove_file(&tz->device, &dev_attr_mode);
+	remove_trip_attrs(tz);
 
-	for (count = 0; count < tz->trips; count++) {
-		device_remove_file(&tz->device,
-				   &trip_point_attrs[count * 2]);
-		device_remove_file(&tz->device,
-				   &trip_point_attrs[count * 2 + 1]);
-	}
 	thermal_remove_hwmon_sysfs(tz);
 	release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
 	idr_destroy(&tz->idr);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 796f1ff..6eaf914 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -58,6 +58,8 @@ struct thermal_zone_device_ops {
 		enum thermal_trip_type *);
 	int (*get_trip_temp) (struct thermal_zone_device *, int,
 			      unsigned long *);
+	int (*set_trip_temp) (struct thermal_zone_device *, int,
+			      unsigned long);
 	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
@@ -85,10 +87,17 @@ struct thermal_cooling_device {
 				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
 #define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
 
+struct thermal_attr {
+	struct device_attribute attr;
+	char name[THERMAL_NAME_LENGTH];
+};
+
 struct thermal_zone_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
 	struct device device;
+	struct thermal_attr *trip_temp_attrs;
+	struct thermal_attr *trip_type_attrs;
 	void *devdata;
 	int trips;
 	int tc1;
@@ -137,9 +146,9 @@ enum {
 };
 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
 
-struct thermal_zone_device *thermal_zone_device_register(char *, int, void *,
-		const struct thermal_zone_device_ops *, int tc1, int tc2,
-		int passive_freq, int polling_freq);
+struct thermal_zone_device *thermal_zone_device_register(char *, int, int,
+		void *, const struct thermal_zone_device_ops *, int tc1,
+		int tc2, int passive_freq, int polling_freq);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 02/16] Thermal: Add Hysteresis attributes
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 10:40   ` R, Durgadoss
  2012-07-19  6:31 ` [PATCH 03/16] Thermal: Documentation update Zhang Rui
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

From: Durgadoss R <dugardoss.r@intel.com>

The Linux Thermal Framework does not support hysteresis
attributes. Most thermal sensors, today, have a
hysteresis value associated with trip points.

This patch adds hysteresis attributes on a per-trip-point
basis, to the Thermal Framework. These attributes are
optionally writable.

Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 Documentation/thermal/sysfs-api.txt |    6 +++
 drivers/thermal/thermal_sys.c       |   89 ++++++++++++++++++++++++++++++++---
 include/linux/thermal.h             |    5 ++
 3 files changed, 94 insertions(+), 6 deletions(-)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 0c7c423..3c8c2f8 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -121,6 +121,7 @@ if hwmon is compiled in or built as a module.
     |---mode:			Working mode of the thermal zone
     |---trip_point_[0-*]_temp:	Trip point temperature
     |---trip_point_[0-*]_type:	Trip point type
+    |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
 
 Thermal cooling device sys I/F, created once it's registered:
 /sys/class/thermal/cooling_device[0-*]:
@@ -190,6 +191,11 @@ trip_point_[0-*]_type
 	thermal zone.
 	RO, Optional
 
+trip_point_[0-*]_hyst
+	The hysteresis value for a trip point, represented as an integer
+	Unit: Celsius
+	RW, Optional
+
 cdev[0-*]
 	Sysfs link to the thermal cooling device node where the sys I/F
 	for cooling device throttling control represents.
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index a590d57..95e0d63 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -240,6 +240,52 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
+trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	int trip, ret;
+	unsigned long temperature;
+
+	if (!tz->ops->set_trip_hyst)
+		return -EPERM;
+
+	if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+		return -EINVAL;
+
+	if (kstrtoul(buf, 10, &temperature))
+		return -EINVAL;
+
+	/*
+	 * We are not doing any check on the 'temperature' value
+	 * here. The driver implementing 'set_trip_hyst' has to
+	 * take care of this.
+	 */
+	ret = tz->ops->set_trip_hyst(tz, trip, temperature);
+
+	return ret ? ret : count;
+}
+
+static ssize_t
+trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	int trip, ret;
+	unsigned long temperature;
+
+	if (!tz->ops->get_trip_hyst)
+		return -EPERM;
+
+	if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+		return -EINVAL;
+
+	ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+
+	return ret ? ret : sprintf(buf, "%ld\n", temperature);
+}
+
+static ssize_t
 passive_store(struct device *dev, struct device_attribute *attr,
 		    const char *buf, size_t count)
 {
@@ -1092,21 +1138,29 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
 {
 	int indx;
 	int writeable;
+	int size = sizeof(struct thermal_attr) * tz->trips;
 
-	tz->trip_type_attrs =
-		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
+	tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
 	if (!tz->trip_type_attrs)
 		return -ENOMEM;
 
-	tz->trip_temp_attrs =
-		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
+	tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
 	if (!tz->trip_temp_attrs) {
 		kfree(tz->trip_type_attrs);
 		return -ENOMEM;
 	}
 
-	for (indx = 0; indx < tz->trips; indx++) {
+	if (tz->ops->get_trip_hyst) {
+		tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
+		if (!tz->trip_hyst_attrs) {
+			kfree(tz->trip_type_attrs);
+			kfree(tz->trip_temp_attrs);
+			return -ENOMEM;
+		}
+	}
+
 
+	for (indx = 0; indx < tz->trips; indx++) {
 		/* create trip type attribute */
 		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
 			 "trip_point_%d_type", indx);
@@ -1138,6 +1192,26 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
 
 		device_create_file(&tz->device,
 				   &tz->trip_temp_attrs[indx].attr);
+
+		/* create Optional trip hyst attribute */
+		if (!tz->ops->get_trip_hyst)
+			continue;
+		snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
+			 "trip_point_%d_hyst", indx);
+
+		sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
+		tz->trip_hyst_attrs[indx].attr.attr.name =
+					tz->trip_hyst_attrs[indx].name;
+		tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
+		tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
+		if (tz->ops->set_trip_hyst) {
+			tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
+			tz->trip_hyst_attrs[indx].attr.store =
+					trip_point_hyst_store;
+		}
+
+		device_create_file(&tz->device,
+				   &tz->trip_hyst_attrs[indx].attr);
 	}
 	return 0;
 }
@@ -1151,9 +1225,13 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
 				   &tz->trip_type_attrs[indx].attr);
 		device_remove_file(&tz->device,
 				   &tz->trip_temp_attrs[indx].attr);
+		if (tz->ops->get_trip_hyst)
+			device_remove_file(&tz->device,
+				  &tz->trip_hyst_attrs[indx].attr);
 	}
 	kfree(tz->trip_type_attrs);
 	kfree(tz->trip_temp_attrs);
+	kfree(tz->trip_hyst_attrs);
 }
 
 /**
@@ -1300,7 +1378,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 {
 	struct thermal_cooling_device *cdev;
 	struct thermal_zone_device *pos = NULL;
-	int count;
 
 	if (!tz)
 		return;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 6eaf914..cfc8d90 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -60,6 +60,10 @@ struct thermal_zone_device_ops {
 			      unsigned long *);
 	int (*set_trip_temp) (struct thermal_zone_device *, int,
 			      unsigned long);
+	int (*get_trip_hyst) (struct thermal_zone_device *, int,
+			      unsigned long *);
+	int (*set_trip_hyst) (struct thermal_zone_device *, int,
+			      unsigned long);
 	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
@@ -98,6 +102,7 @@ struct thermal_zone_device {
 	struct device device;
 	struct thermal_attr *trip_temp_attrs;
 	struct thermal_attr *trip_type_attrs;
+	struct thermal_attr *trip_hyst_attrs;
 	void *devdata;
 	int trips;
 	int tc1;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 03/16] Thermal: Documentation update
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
  2012-07-19  6:31 ` [PATCH 02/16] Thermal: Add Hysteresis attributes Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 10:51   ` R, Durgadoss
  2012-07-19  6:31 ` [PATCH 04/16] Thermal: Introduce multiple cooling states support Zhang Rui
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

With commit 6503e5df08008b9a47022b5e9ebba658c8fa69af,
the value of /sys/class/thermal/thermal_zoneX/mode has been changed
from user/kernel to enabled/disabled.
Update the documentation so that users won't be confused.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 Documentation/thermal/sysfs-api.txt |   20 ++++++++++----------
 drivers/acpi/thermal.c              |    6 ++----
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 3c8c2f8..b7b3609 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -47,11 +47,11 @@ temperature) and throttle appropriate devices.
 	.bind: bind the thermal zone device with a thermal cooling device.
 	.unbind: unbind the thermal zone device with a thermal cooling device.
 	.get_temp: get the current temperature of the thermal zone.
-	.get_mode: get the current mode (user/kernel) of the thermal zone.
-	    - "kernel" means thermal management is done in kernel.
-	    - "user" will prevent kernel thermal driver actions upon trip points
+	.get_mode: get the current mode (enabled/disabled) of the thermal zone.
+	    - "enabled" means the kernel thermal management is enabled.
+	    - "disable" will prevent kernel thermal driver actions upon trip points
 	      so that user applications can take charge of thermal management.
-	.set_mode: set the mode (user/kernel) of the thermal zone.
+	.set_mode: set the mode (enabled/disabled) of the thermal zone.
 	.get_trip_type: get the type of certain trip point.
 	.get_trip_temp: get the temperature above which the certain trip point
 			will be fired.
@@ -170,14 +170,14 @@ temp
 	RO, Required
 
 mode
-	One of the predefined values in [kernel, user].
+	One of the predefined values in [enabled, disableed].
 	This file gives information about the algorithm that is currently
 	managing the thermal zone. It can be either default kernel based
 	algorithm or user space application.
-	kernel	= Thermal management in kernel thermal zone driver.
-	user	= Preventing kernel thermal zone driver actions upon
-		  trip points so that user application can take full
-		  charge of the thermal management.
+	enabled		= enable Kernel Thermal management.
+	disabled	= Preventing kernel thermal zone driver actions upon
+			  trip points so that user application can take full
+			  charge of the thermal management.
 	RW, Optional
 
 trip_point_[0-*]_temp
@@ -256,7 +256,7 @@ If the processor is listed in _PSL method, and the fan is listed in _AL0
 |thermal_zone1:
     |---type:			acpitz
     |---temp:			37000
-    |---mode:			kernel
+    |---mode:			enabled
     |---trip_point_0_temp:	100000
     |---trip_point_0_type:	critical
     |---trip_point_1_temp:	80000
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 2107d1b..8275e7b 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -550,8 +550,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static const char enabled[] = "kernel";
-static const char disabled[] = "user";
 static int thermal_get_mode(struct thermal_zone_device *thermal,
 				enum thermal_device_mode *mode)
 {
@@ -588,8 +586,8 @@ static int thermal_set_mode(struct thermal_zone_device *thermal,
 	if (enable != tz->tz_enabled) {
 		tz->tz_enabled = enable;
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			"%s ACPI thermal control\n",
-			tz->tz_enabled ? enabled : disabled));
+			"%s kernel ACPI thermal control\n",
+			tz->tz_enabled ? "Enable" : "Disable"));
 		acpi_thermal_check(tz);
 	}
 	return 0;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 04/16] Thermal: Introduce multiple cooling states support
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (2 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 03/16] Thermal: Documentation update Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 05/16] Thermal: Introduce cooling states range support Zhang Rui
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

This is because general active cooling devices, like fans,
may have multiple speeds, which can be mapped to different cooling states.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 95e0d63..63927e3 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1059,6 +1059,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 	enum thermal_trip_type trip_type;
 	struct thermal_cooling_device_instance *instance;
 	struct thermal_cooling_device *cdev;
+	unsigned long cur_state, max_state;
 
 	mutex_lock(&tz->lock);
 
@@ -1098,10 +1099,17 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 
 				cdev = instance->cdev;
 
+				cdev->ops->get_cur_state(cdev, &cur_state);
+				cdev->ops->get_max_state(cdev, &max_state);
+
 				if (temp >= trip_temp)
-					cdev->ops->set_cur_state(cdev, 1);
+					cur_state = cur_state < max_state ?
+						(cur_state + 1) : max_state;
 				else
-					cdev->ops->set_cur_state(cdev, 0);
+					cur_state = cur_state > 0 ?
+						(cur_state - 1) : 0;
+
+				cdev->ops->set_cur_state(cdev, cur_state);
 			}
 			break;
 		case THERMAL_TRIP_PASSIVE:
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 05/16] Thermal: Introduce cooling states range support
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (3 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 04/16] Thermal: Introduce multiple cooling states support Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 06/16] Thermal: set upper and lower limits Zhang Rui
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

As the active cooling devices can have multiple cooling states,
we may want only several cooling states for a certain trip point,
and other cooling states for other active trip points.

To do this, we should be able to describe the cooling device
behavior for a certain trip point, rather than for the entire thermal zone.
And when updating thermal zone, we need to check the upper and lower limit
to make sure the cooling device is set to the proper cooling state.

Note that this patch will not bring any different behavior as
upper limit is set to max_state and lower limit is set to 0
in this patch, for now.

Next patch will set these to real values.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 63927e3..4267a49 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -41,12 +41,19 @@ MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 
+/*
+ * This structure is used to describe the behavior of
+ * a certain cooling device on a certain trip point
+ * in a certain thermal zone
+ */
 struct thermal_cooling_device_instance {
 	int id;
 	char name[THERMAL_NAME_LENGTH];
 	struct thermal_zone_device *tz;
 	struct thermal_cooling_device *cdev;
 	int trip;
+	unsigned long upper;	/* Highest cooling state for this trip point */
+	unsigned long lower;	/* Lowest cooling state for this trip point */
 	char attr_name[THERMAL_NAME_LENGTH];
 	struct device_attribute attr;
 	struct list_head node;
@@ -800,6 +807,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	struct thermal_cooling_device_instance *pos;
 	struct thermal_zone_device *pos1;
 	struct thermal_cooling_device *pos2;
+	unsigned long max_state;
 	int result;
 
 	if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
@@ -824,6 +832,11 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	dev->tz = tz;
 	dev->cdev = cdev;
 	dev->trip = trip;
+
+	cdev->ops->get_max_state(dev, &max_state);
+	dev->upper = max_state;
+	dev->lower = 0;
+
 	result = get_idr(&tz->idr, &tz->lock, &dev->id);
 	if (result)
 		goto free_mem;
@@ -1103,11 +1116,15 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 				cdev->ops->get_max_state(cdev, &max_state);
 
 				if (temp >= trip_temp)
-					cur_state = cur_state < max_state ?
-						(cur_state + 1) : max_state;
+					cur_state =
+						cur_state < instance->upper ?
+						(cur_state + 1) :
+						instance->upper;
 				else
-					cur_state = cur_state > 0 ?
-						(cur_state - 1) : 0;
+					cur_state =
+						cur_state > instance->lower ?
+						(cur_state - 1) :
+						instance->lower;
 
 				cdev->ops->set_cur_state(cdev, cur_state);
 			}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 06/16] Thermal: set upper and lower limits
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (4 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 05/16] Thermal: Introduce cooling states range support Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 20:55   ` Rafael J. Wysocki
  2012-07-19  6:31 ` [PATCH 07/16] Thermal: Introduce .get_trend() callback Zhang Rui
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

set upper and lower limits when binding
a thermal cooling device to a thermal zone device.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 Documentation/thermal/sysfs-api.txt |    6 ++++-
 drivers/acpi/thermal.c              |   49 ++++++++++++++++++++++-------------
 drivers/platform/x86/acerhdf.c      |    2 +-
 drivers/thermal/thermal_sys.c       |   20 +++++++++-----
 include/linux/thermal.h             |    3 ++-
 5 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index b7b3609..f169821 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -84,7 +84,7 @@ temperature) and throttle appropriate devices.
 
 1.3 interface for binding a thermal zone device with a thermal cooling device
 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
-		int trip, struct thermal_cooling_device *cdev);
+	int trip, struct thermal_cooling_device *cdev, long upper, long lower);
 
     This interface function bind a thermal cooling device to the certain trip
     point of a thermal zone device.
@@ -93,6 +93,10 @@ temperature) and throttle appropriate devices.
     cdev: thermal cooling device
     trip: indicates which trip point the cooling devices is associated with
 	  in this thermal zone.
+    upper:the Maximum cooling state for this trip point.
+          -1 means no upper limit, and the cooling device can be in max_state.
+    lower:the Minimum cooling state can be used for this trip point.
+          -1 means no lower limit, and the cooling device can be in cooling state 0.
 
 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 		int trip, struct thermal_cooling_device *cdev);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 8275e7b..a7c97f5 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -727,11 +727,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 	return 0;
 }
 
-typedef int (*cb)(struct thermal_zone_device *, int,
-		  struct thermal_cooling_device *);
 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev,
-					cb action)
+					int bind)
 {
 	struct acpi_device *device = cdev->devdata;
 	struct acpi_thermal *tz = thermal->devdata;
@@ -755,11 +753,18 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		    i++) {
 			handle = tz->trips.passive.devices.handles[i];
 			status = acpi_bus_get_device(handle, &dev);
-			if (ACPI_SUCCESS(status) && (dev == device)) {
-				result = action(thermal, trip, cdev);
-				if (result)
-					goto failed;
-			}
+			if (ACPI_FAILURE(status) || dev != device)
+				continue;
+			if (bind)
+				result =
+					thermal_zone_bind_cooling_device
+					(thermal, trip, cdev, -1, -1);
+			else
+				result =
+					thermal_zone_unbind_cooling_device
+					(thermal, trip, cdev);
+			if (result)
+				goto failed;
 		}
 	}
 
@@ -772,11 +777,16 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		    j++) {
 			handle = tz->trips.active[i].devices.handles[j];
 			status = acpi_bus_get_device(handle, &dev);
-			if (ACPI_SUCCESS(status) && (dev == device)) {
-				result = action(thermal, trip, cdev);
-				if (result)
-					goto failed;
-			}
+			if (ACPI_FAILURE(status) || dev != device)
+				continue;
+			if (bind)
+				result = thermal_zone_bind_cooling_device
+					(thermal, trip, cdev, -1, -1);
+			else
+				result = thermal_zone_unbind_cooling_device
+					(thermal, trip, cdev);
+			if (result)
+				goto failed;
 		}
 	}
 
@@ -784,7 +794,12 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		handle = tz->devices.handles[i];
 		status = acpi_bus_get_device(handle, &dev);
 		if (ACPI_SUCCESS(status) && (dev == device)) {
-			result = action(thermal, -1, cdev);
+			if (bind)
+				result = thermal_zone_bind_cooling_device
+						(thermal, -1, cdev, -1, -1);
+			else
+				result = thermal_zone_unbind_cooling_device
+						(thermal, -1, cdev);
 			if (result)
 				goto failed;
 		}
@@ -798,16 +813,14 @@ static int
 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev)
 {
-	return acpi_thermal_cooling_device_cb(thermal, cdev,
-				thermal_zone_bind_cooling_device);
+	return acpi_thermal_cooling_device_cb(thermal, cdev, 1);
 }
 
 static int
 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev)
 {
-	return acpi_thermal_cooling_device_cb(thermal, cdev,
-				thermal_zone_unbind_cooling_device);
+	return acpi_thermal_cooling_device_cb(thermal, cdev, 0);
 }
 
 static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 39abb15..278aa0e 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -329,7 +329,7 @@ static int acerhdf_bind(struct thermal_zone_device *thermal,
 	if (cdev != cl_dev)
 		return 0;
 
-	if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) {
+	if (thermal_zone_bind_cooling_device(thermal, 0, cdev, -1, -1)) {
 		pr_err("error binding cooling dev\n");
 		return -EINVAL;
 	}
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 4267a49..db35300 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -316,7 +316,7 @@ passive_store(struct device *dev, struct device_attribute *attr,
 				     sizeof("Processor")))
 				thermal_zone_bind_cooling_device(tz,
 								 THERMAL_TRIPS_NONE,
-								 cdev);
+								 cdev, -1, -1);
 		}
 		mutex_unlock(&thermal_list_lock);
 		if (!tz->passive_delay)
@@ -801,7 +801,8 @@ static void thermal_zone_device_check(struct work_struct *work)
  */
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 				     int trip,
-				     struct thermal_cooling_device *cdev)
+				     struct thermal_cooling_device *cdev,
+				     long upper, long lower)
 {
 	struct thermal_cooling_device_instance *dev;
 	struct thermal_cooling_device_instance *pos;
@@ -825,6 +826,15 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	if (tz != pos1 || cdev != pos2)
 		return -EINVAL;
 
+	cdev->ops->get_max_state(cdev, &max_state);
+
+	/* lower default 0, upper default max_state */
+	lower = lower < 0 ? 0 : lower;
+	upper = upper < 0 ? max_state : upper;
+
+	if (lower > upper || upper > max_state)
+		return -EINVAL;
+
 	dev =
 	    kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
 	if (!dev)
@@ -832,10 +842,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	dev->tz = tz;
 	dev->cdev = cdev;
 	dev->trip = trip;
-
-	cdev->ops->get_max_state(dev, &max_state);
-	dev->upper = max_state;
-	dev->lower = 0;
+	dev->upper = upper;
+	dev->lower = lower;
 
 	result = get_idr(&tz->idr, &tz->lock, &dev->id);
 	if (result)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index cfc8d90..b355c62 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -157,7 +157,8 @@ struct thermal_zone_device *thermal_zone_device_register(char *, int, int,
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
-				     struct thermal_cooling_device *);
+				     struct thermal_cooling_device *,
+				     long, long);
 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
 				       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (5 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 06/16] Thermal: set upper and lower limits Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:13   ` Rafael J. Wysocki
  2012-07-19 22:09   ` Jacob Pan
  2012-07-19  6:31 ` [PATCH 08/16] Thermal: Remove tc1/tc2 in generic thermal layer Zhang Rui
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

tc1 and tc2 are used by OSPM to anticipate the temperature trends.
But they are ACPI platform specific concepts.

Introduce .get_trend() as a more general solution.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
 drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
 include/linux/thermal.h       |    9 +++++++++
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index a7c97f5..b345646 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 		return -EINVAL;
 }
 
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+				int trip, enum thermal_trend *trend)
+{
+	struct acpi_thermal *tz = thermal->devdata;
+	enum thermal_trip_type type;
+	unsigned long trip_temp;
+	int i;
+
+	if (thermal_get_trip_type(thermal, trip, &type))
+		return -EINVAL;
+
+	/* Only PASSIVE trip points need TREND */
+	if (type != THERMAL_TRIP_PASSIVE)
+		return -EINVAL;
+
+	/*
+	 * tz->temperature has already been updated by generic thermal layer,
+	 * before this callback being invoked
+	 */
+	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
+		+ (tz->trips.passive.tc2
+		* (tz->temperature - tz->trips.passive.temperature));
+
+	*trend = i > 0 ? THERMAL_TREND_RAISING :
+		(i < 0 ? THERMAL_TREND_DROPPING : THERMAL_TREND_STABLE);
+	return 0;
+}
+
+
 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 			   enum thermal_trip_type trip_type)
 {
@@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
 	.get_trip_type = thermal_get_trip_type,
 	.get_trip_temp = thermal_get_trip_temp,
 	.get_crit_temp = thermal_get_crit_temp,
+	.get_trend = thermal_get_trend,
 	.notify = thermal_notify,
 };
 
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index db35300..29b6dba 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 }
 #endif
 
+static void thermal_get_trend(struct thermal_zone_device *tz,
+		int trip, enum thermal_trend *trend)
+{
+	if (tz->ops->get_trend)
+		if (!tz->ops->get_trend(tz, trip, trend))
+			return;
+
+	*trend = tz->temperature >= tz->last_temperature ?
+		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
+	return;
+}
+
 static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
 					    int delay)
 {
@@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 	if (temp >= trip_temp) {
 		tz->passive = true;
 
+		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);
+
 		trend = (tz->tc1 * (temp - tz->last_temperature)) +
 			(tz->tc2 * (temp - trip_temp));
 
@@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 		goto leave;
 	}
 
+	tz->last_temperature = tz->temperature;
+	tz->temperature = temp;
+
 	for (count = 0; count < tz->trips; count++) {
 		tz->ops->get_trip_type(tz, count, &trip_type);
 		tz->ops->get_trip_temp(tz, count, &trip_temp);
@@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 		thermal_zone_device_passive(tz, temp, tz->forced_passive,
 					    THERMAL_TRIPS_NONE);
 
-	tz->last_temperature = temp;
-
 leave:
 	if (tz->passive)
 		thermal_zone_device_set_polling(tz, tz->passive_delay);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index b355c62..ab656d6 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -44,6 +44,12 @@ enum thermal_trip_type {
 	THERMAL_TRIP_CRITICAL,
 };
 
+enum thermal_trend {
+	THERMAL_TREND_STABLE, /* temperature is stable */
+	THERMAL_TREND_RAISING, /* temperature is raising */
+	THERMAL_TREND_DROPPING, /* temperature is dropping */
+};
+
 struct thermal_zone_device_ops {
 	int (*bind) (struct thermal_zone_device *,
 		     struct thermal_cooling_device *);
@@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
 	int (*set_trip_hyst) (struct thermal_zone_device *, int,
 			      unsigned long);
 	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
+	int (*get_trend) (struct thermal_zone_device *, int,
+			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
 };
@@ -109,6 +117,7 @@ struct thermal_zone_device {
 	int tc2;
 	int passive_delay;
 	int polling_delay;
+	int temperature;
 	int last_temperature;
 	bool passive;
 	unsigned int forced_passive;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 08/16] Thermal: Remove tc1/tc2 in generic thermal layer.
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (6 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 07/16] Thermal: Introduce .get_trend() callback Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update() Zhang Rui
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/acpi/thermal.c                   |    5 +----
 drivers/platform/x86/acerhdf.c           |    2 +-
 drivers/platform/x86/intel_mid_thermal.c |    2 +-
 drivers/thermal/spear_thermal.c          |    2 +-
 drivers/thermal/thermal_sys.c            |   15 ++-------------
 include/linux/thermal.h                  |    5 +----
 6 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index b345646..73e335f 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -888,15 +888,12 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
 						     &acpi_thermal_zone_ops,
-						     tz->trips.passive.tc1,
-						     tz->trips.passive.tc2,
 						     tz->trips.passive.tsp*100,
 						     tz->polling_frequency*100);
 	else
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     &acpi_thermal_zone_ops,
-						     0, 0, 0,
+						     &acpi_thermal_zone_ops, 0,
 						     tz->polling_frequency*100);
 	if (IS_ERR(tz->thermal_zone))
 		return -ENODEV;
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 278aa0e..e215771 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -661,7 +661,7 @@ static int acerhdf_register_thermal(void)
 		return -EINVAL;
 
 	thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
-					      &acerhdf_dev_ops, 0, 0, 0,
+					      &acerhdf_dev_ops, 0,
 					      (kernelmode) ? interval*1000 : 0);
 	if (IS_ERR(thz_dev))
 		return -EINVAL;
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index 2b2c212..6e309dd 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -499,7 +499,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
 			goto err;
 		}
 		pinfo->tzd[i] = thermal_zone_device_register(name[i],
-				0, 0, td_info, &tzd_ops, 0, 0, 0, 0);
+				0, 0, td_info, &tzd_ops, 0, 0);
 		if (IS_ERR(pinfo->tzd[i])) {
 			kfree(td_info);
 			ret = PTR_ERR(pinfo->tzd[i]);
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 69a55d4..b55840a 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -148,7 +148,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
 	writel_relaxed(stdev->flags, stdev->thermal_base);
 
 	spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
-				stdev, &ops, 0, 0, 0, 0);
+				stdev, &ops, 0, 0);
 	if (IS_ERR(spear_thermal)) {
 		dev_err(&pdev->dev, "thermal zone device is NULL\n");
 		ret = PTR_ERR(spear_thermal);
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 29b6dba..59af3b8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -334,9 +334,6 @@ passive_store(struct device *dev, struct device_attribute *attr,
 		tz->passive_delay = 0;
 	}
 
-	tz->tc1 = 1;
-	tz->tc2 = 1;
-
 	tz->forced_passive = state;
 
 	thermal_zone_device_update(tz);
@@ -746,9 +743,6 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 
 		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);
 
-		trend = (tz->tc1 * (temp - tz->last_temperature)) +
-			(tz->tc2 * (temp - trip_temp));
-
 		/* Heating up? */
 		if (trend > 0) {
 			list_for_each_entry(instance, &tz->cooling_devices,
@@ -1289,8 +1283,6 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
  * @flag:	a bit string indicating the writeablility of trip points
  * @devdata:	private device data
  * @ops:	standard thermal zone device callbacks
- * @tc1:	thermal coefficient 1 for passive calculations
- * @tc2:	thermal coefficient 2 for passive calculations
  * @passive_delay: number of milliseconds to wait between polls when
  *		   performing passive cooling
  * @polling_delay: number of milliseconds to wait between polls when checking
@@ -1298,13 +1290,12 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
  *		   driven systems)
  *
  * thermal_zone_device_unregister() must be called when the device is no
- * longer needed. The passive cooling formula uses tc1 and tc2 as described in
- * section 11.1.5.1 of the ACPI specification 3.0.
+ * longer needed. The passive cooling depends on the .get_trend() return value.
  */
 struct thermal_zone_device *thermal_zone_device_register(char *type,
 	int trips, int flag, void *devdata,
 	const struct thermal_zone_device_ops *ops,
-	int tc1, int tc2, int passive_delay, int polling_delay)
+	int passive_delay, int polling_delay)
 {
 	struct thermal_zone_device *tz;
 	struct thermal_cooling_device *pos;
@@ -1343,8 +1334,6 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	tz->device.class = &thermal_class;
 	tz->devdata = devdata;
 	tz->trips = trips;
-	tz->tc1 = tc1;
-	tz->tc2 = tc2;
 	tz->passive_delay = passive_delay;
 	tz->polling_delay = polling_delay;
 
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ab656d6..44d7fc3 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -113,8 +113,6 @@ struct thermal_zone_device {
 	struct thermal_attr *trip_hyst_attrs;
 	void *devdata;
 	int trips;
-	int tc1;
-	int tc2;
 	int passive_delay;
 	int polling_delay;
 	int temperature;
@@ -161,8 +159,7 @@ enum {
 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
 
 struct thermal_zone_device *thermal_zone_device_register(char *, int, int,
-		void *, const struct thermal_zone_device_ops *, int tc1,
-		int tc2, int passive_freq, int polling_freq);
+		void *, const struct thermal_zone_device_ops *, int, int);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (7 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 08/16] Thermal: Remove tc1/tc2 in generic thermal layer Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:19   ` Rafael J. Wysocki
                     ` (2 more replies)
  2012-07-19  6:31 ` [PATCH 10/16] Thermal: rename structure thermal_cooling_device_instance to thermal_instance Zhang Rui
                   ` (7 subsequent siblings)
  16 siblings, 3 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

This function is used to update the cooling state of
all the cooling devices that are binded to an active trip point.

This will be used for passive cooling as well, in the future patches.
as both active and passive cooling can share the same algorithm,
which is

1. if the temperature is higher than a trip point,
   a. if the trend is THERMAL_TREND_RAISING, use higher cooling
      state for this trip point
   b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
      state for this trip point

2. if the temperature is lower than a trip point, use lower
   cooling state for this trip point.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/acpi/thermal.c        |    7 +++-
 drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
 2 files changed, 71 insertions(+), 27 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 73e335f..14c4879 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
 	if (thermal_get_trip_type(thermal, trip, &type))
 		return -EINVAL;
 
-	/* Only PASSIVE trip points need TREND */
+	if (type == THERMAL_TRIP_ACTIVE) {
+		/* aggressive active cooling */
+		*trend = THERMAL_TREND_RAISING;
+		return 0;
+	}
+
 	if (type != THERMAL_TRIP_PASSIVE)
 		return -EINVAL;
 
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 59af3b8..011faba 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1076,6 +1076,70 @@ void thermal_cooling_device_unregister(struct
 }
 EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
+/*
+ * Cooling algorithm for active trip points
+ *
+ * 1. if the temperature is higher than a trip point,
+ *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
+ *       state for this trip point
+ *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
+ *       state for this trip point
+ *
+ * 2. if the temperature is lower than a trip point, use lower
+ *    cooling state for this trip point
+ *
+ * Note that this behaves the same as the previous passive cooling
+ * algorithm.
+ */
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz,
+				     int trip, long temp)
+{
+	struct thermal_cooling_device_instance *instance;
+	struct thermal_cooling_device *cdev = NULL;
+	unsigned long cur_state, max_state;
+	long trip_temp;
+	enum thermal_trend trend;
+
+	tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+	if (temp >= trip_temp) {
+		thermal_get_trend(tz, trip, &trend);
+
+		list_for_each_entry(instance, &tz->cooling_devices, node) {
+			if (instance->trip != trip)
+				continue;
+
+			cdev = instance->cdev;
+
+			cdev->ops->get_cur_state(cdev, &cur_state);
+			cdev->ops->get_max_state(cdev, &max_state);
+
+			if (trend == THERMAL_TREND_RAISING) {
+				cur_state = cur_state < instance->upper ?
+					    (cur_state + 1) : instance->upper;
+			} else if (trend == THERMAL_TREND_DROPPING) {
+				cur_state = cur_state > instance->lower ?
+				    (cur_state - 1) : instance->lower;
+			}
+			cdev->ops->set_cur_state(cdev, cur_state);
+		}
+	} else {	/* below trip */
+		list_for_each_entry(instance, &tz->cooling_devices, node) {
+			if (instance->trip != trip)
+				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);
+		}
+	}
+
+	return;
+}
 /**
  * thermal_zone_device_update - force an update of a thermal zone's state
  * @ttz:	the thermal zone to update
@@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 	int count, ret = 0;
 	long temp, trip_temp;
 	enum thermal_trip_type trip_type;
-	struct thermal_cooling_device_instance *instance;
-	struct thermal_cooling_device *cdev;
-	unsigned long cur_state, max_state;
 
 	mutex_lock(&tz->lock);
 
@@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 					tz->ops->notify(tz, count, trip_type);
 			break;
 		case THERMAL_TRIP_ACTIVE:
-			list_for_each_entry(instance, &tz->cooling_devices,
-					    node) {
-				if (instance->trip != count)
-					continue;
-
-				cdev = instance->cdev;
-
-				cdev->ops->get_cur_state(cdev, &cur_state);
-				cdev->ops->get_max_state(cdev, &max_state);
-
-				if (temp >= trip_temp)
-					cur_state =
-						cur_state < instance->upper ?
-						(cur_state + 1) :
-						instance->upper;
-				else
-					cur_state =
-						cur_state > instance->lower ?
-						(cur_state - 1) :
-						instance->lower;
-
-				cdev->ops->set_cur_state(cdev, cur_state);
-			}
+			thermal_zone_trip_update(tz, count, temp);
 			break;
 		case THERMAL_TRIP_PASSIVE:
 			if (temp >= trip_temp || tz->passive)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 10/16] Thermal: rename structure thermal_cooling_device_instance to thermal_instance
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (8 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update() Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances Zhang Rui
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

This struct is used to describe the behavior for a thermal
cooling device on a certain trip point for a certain thremal zone.

thermal_cooling_device_instance is not accurate, as a cooling device
can be used for more than one trip point in one thermal zone device.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 011faba..867fced 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
  * a certain cooling device on a certain trip point
  * in a certain thermal zone
  */
-struct thermal_cooling_device_instance {
+struct thermal_instance {
 	int id;
 	char name[THERMAL_NAME_LENGTH];
 	struct thermal_zone_device *tz;
@@ -429,10 +429,10 @@ static ssize_t
 thermal_cooling_device_trip_point_show(struct device *dev,
 				       struct device_attribute *attr, char *buf)
 {
-	struct thermal_cooling_device_instance *instance;
+	struct thermal_instance *instance;
 
 	instance =
-	    container_of(attr, struct thermal_cooling_device_instance, attr);
+	    container_of(attr, struct thermal_instance, attr);
 
 	if (instance->trip == THERMAL_TRIPS_NONE)
 		return sprintf(buf, "-1\n");
@@ -727,7 +727,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 					int temp, int trip_temp, int trip)
 {
 	int trend = 0;
-	struct thermal_cooling_device_instance *instance;
+	struct thermal_instance *instance;
 	struct thermal_cooling_device *cdev;
 	long state, max_state;
 
@@ -812,8 +812,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 				     struct thermal_cooling_device *cdev,
 				     long upper, long lower)
 {
-	struct thermal_cooling_device_instance *dev;
-	struct thermal_cooling_device_instance *pos;
+	struct thermal_instance *dev;
+	struct thermal_instance *pos;
 	struct thermal_zone_device *pos1;
 	struct thermal_cooling_device *pos2;
 	unsigned long max_state;
@@ -844,7 +844,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 		return -EINVAL;
 
 	dev =
-	    kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
+	    kzalloc(sizeof(struct thermal_instance), GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
 	dev->tz = tz;
@@ -909,7 +909,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 				       int trip,
 				       struct thermal_cooling_device *cdev)
 {
-	struct thermal_cooling_device_instance *pos, *next;
+	struct thermal_instance *pos, *next;
 
 	mutex_lock(&tz->lock);
 	list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
@@ -1095,7 +1095,7 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
 static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 				     int trip, long temp)
 {
-	struct thermal_cooling_device_instance *instance;
+	struct thermal_instance *instance;
 	struct thermal_cooling_device *cdev = NULL;
 	unsigned long cur_state, max_state;
 	long trip_temp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (9 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 10/16] Thermal: rename structure thermal_cooling_device_instance to thermal_instance Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:22   ` Rafael J. Wysocki
  2012-07-19  6:31 ` [PATCH 12/16] Thermal: Rename thermal_instance.node to thermal_instance.tz_node Zhang Rui
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

thermal_zone_device.cooling_devices is not accurate
as this is a list for thermal instances, rather than cooling devices.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   18 +++++++++---------
 include/linux/thermal.h       |    4 ++--
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 867fced..1836039 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -745,7 +745,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 
 		/* Heating up? */
 		if (trend > 0) {
-			list_for_each_entry(instance, &tz->cooling_devices,
+			list_for_each_entry(instance, &tz->instances,
 					    node) {
 				if (instance->trip != trip)
 					continue;
@@ -756,7 +756,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 					cdev->ops->set_cur_state(cdev, state);
 			}
 		} else if (trend < 0) { /* Cooling off? */
-			list_for_each_entry(instance, &tz->cooling_devices,
+			list_for_each_entry(instance, &tz->instances,
 					    node) {
 				if (instance->trip != trip)
 					continue;
@@ -777,7 +777,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 	 * and avoid thrashing around the passive trip point.  Note that we
 	 * assume symmetry.
 	 */
-	list_for_each_entry(instance, &tz->cooling_devices, node) {
+	list_for_each_entry(instance, &tz->instances, node) {
 		if (instance->trip != trip)
 			continue;
 		cdev = instance->cdev;
@@ -873,13 +873,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 		goto remove_symbol_link;
 
 	mutex_lock(&tz->lock);
-	list_for_each_entry(pos, &tz->cooling_devices, node)
+	list_for_each_entry(pos, &tz->instances, node)
 	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 		result = -EEXIST;
 		break;
 	}
 	if (!result)
-		list_add_tail(&dev->node, &tz->cooling_devices);
+		list_add_tail(&dev->node, &tz->instances);
 	mutex_unlock(&tz->lock);
 
 	if (!result)
@@ -912,7 +912,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 	struct thermal_instance *pos, *next;
 
 	mutex_lock(&tz->lock);
-	list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
+	list_for_each_entry_safe(pos, next, &tz->instances, node) {
 		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 			list_del(&pos->node);
 			mutex_unlock(&tz->lock);
@@ -1106,7 +1106,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 	if (temp >= trip_temp) {
 		thermal_get_trend(tz, trip, &trend);
 
-		list_for_each_entry(instance, &tz->cooling_devices, node) {
+		list_for_each_entry(instance, &tz->instances, node) {
 			if (instance->trip != trip)
 				continue;
 
@@ -1125,7 +1125,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 			cdev->ops->set_cur_state(cdev, cur_state);
 		}
 	} else {	/* below trip */
-		list_for_each_entry(instance, &tz->cooling_devices, node) {
+		list_for_each_entry(instance, &tz->instances, node) {
 			if (instance->trip != trip)
 				continue;
 
@@ -1359,7 +1359,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	if (!tz)
 		return ERR_PTR(-ENOMEM);
 
-	INIT_LIST_HEAD(&tz->cooling_devices);
+	INIT_LIST_HEAD(&tz->instances);
 	idr_init(&tz->idr);
 	mutex_init(&tz->lock);
 	result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 44d7fc3..a15b83c 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -120,9 +120,9 @@ struct thermal_zone_device {
 	bool passive;
 	unsigned int forced_passive;
 	const struct thermal_zone_device_ops *ops;
-	struct list_head cooling_devices;
+	struct list_head instances;
 	struct idr idr;
-	struct mutex lock;	/* protect cooling devices list */
+	struct mutex lock;	/* protect instances list */
 	struct list_head node;
 	struct delayed_work poll_queue;
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 12/16] Thermal: Rename thermal_instance.node to thermal_instance.tz_node.
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (10 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device Zhang Rui
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

thermal_instance should be referenced by both thermal zone devices
and thermal cooling devices.

Rename thermal_instance.node to thermal_instance.tz_node in this patch
and thermal_instanace.cdev_node will be introduced in next patch.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 1836039..5a5f916 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -56,7 +56,7 @@ struct thermal_instance {
 	unsigned long lower;	/* Lowest cooling state for this trip point */
 	char attr_name[THERMAL_NAME_LENGTH];
 	struct device_attribute attr;
-	struct list_head node;
+	struct list_head tz_node; /* node in tz->instances */
 };
 
 static DEFINE_IDR(thermal_tz_idr);
@@ -746,7 +746,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 		/* Heating up? */
 		if (trend > 0) {
 			list_for_each_entry(instance, &tz->instances,
-					    node) {
+					    tz_node) {
 				if (instance->trip != trip)
 					continue;
 				cdev = instance->cdev;
@@ -757,7 +757,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 			}
 		} else if (trend < 0) { /* Cooling off? */
 			list_for_each_entry(instance, &tz->instances,
-					    node) {
+					    tz_node) {
 				if (instance->trip != trip)
 					continue;
 				cdev = instance->cdev;
@@ -777,7 +777,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 	 * and avoid thrashing around the passive trip point.  Note that we
 	 * assume symmetry.
 	 */
-	list_for_each_entry(instance, &tz->instances, node) {
+	list_for_each_entry(instance, &tz->instances, tz_node) {
 		if (instance->trip != trip)
 			continue;
 		cdev = instance->cdev;
@@ -873,13 +873,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 		goto remove_symbol_link;
 
 	mutex_lock(&tz->lock);
-	list_for_each_entry(pos, &tz->instances, node)
+	list_for_each_entry(pos, &tz->instances, tz_node)
 	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 		result = -EEXIST;
 		break;
 	}
 	if (!result)
-		list_add_tail(&dev->node, &tz->instances);
+		list_add_tail(&dev->tz_node, &tz->instances);
 	mutex_unlock(&tz->lock);
 
 	if (!result)
@@ -912,9 +912,9 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 	struct thermal_instance *pos, *next;
 
 	mutex_lock(&tz->lock);
-	list_for_each_entry_safe(pos, next, &tz->instances, node) {
+	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
 		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
-			list_del(&pos->node);
+			list_del(&pos->tz_node);
 			mutex_unlock(&tz->lock);
 			goto unbind;
 		}
@@ -1106,7 +1106,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 	if (temp >= trip_temp) {
 		thermal_get_trend(tz, trip, &trend);
 
-		list_for_each_entry(instance, &tz->instances, node) {
+		list_for_each_entry(instance, &tz->instances, tz_node) {
 			if (instance->trip != trip)
 				continue;
 
@@ -1125,7 +1125,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 			cdev->ops->set_cur_state(cdev, cur_state);
 		}
 	} else {	/* below trip */
-		list_for_each_entry(instance, &tz->instances, node) {
+		list_for_each_entry(instance, &tz->instances, tz_node) {
 			if (instance->trip != trip)
 				continue;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device.
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (11 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 12/16] Thermal: Rename thermal_instance.node to thermal_instance.tz_node Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:25   ` Rafael J. Wysocki
  2012-07-19  6:31 ` [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state Zhang Rui
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

so that cooling device can know the cooling state requirement
of all the thermal instances.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |    7 ++++++-
 include/linux/thermal.h       |    1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 5a5f916..48b2668 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -57,6 +57,7 @@ struct thermal_instance {
 	char attr_name[THERMAL_NAME_LENGTH];
 	struct device_attribute attr;
 	struct list_head tz_node; /* node in tz->instances */
+	struct list_head cdev_node; /* node in cdev->instances */
 };
 
 static DEFINE_IDR(thermal_tz_idr);
@@ -878,8 +879,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 		result = -EEXIST;
 		break;
 	}
-	if (!result)
+	if (!result) {
 		list_add_tail(&dev->tz_node, &tz->instances);
+		list_add_tail(&dev->cdev_node, &cdev->instances);
+	}
 	mutex_unlock(&tz->lock);
 
 	if (!result)
@@ -915,6 +918,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
 		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 			list_del(&pos->tz_node);
+			list_del(&pos->cdev_node);
 			mutex_unlock(&tz->lock);
 			goto unbind;
 		}
@@ -984,6 +988,7 @@ thermal_cooling_device_register(char *type, void *devdata,
 	}
 
 	strcpy(cdev->type, type);
+	INIT_LIST_HEAD(&cdev->instances);
 	cdev->ops = ops;
 	cdev->device.class = &thermal_class;
 	cdev->devdata = devdata;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index a15b83c..d8e069e 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -92,6 +92,7 @@ struct thermal_cooling_device {
 	struct device device;
 	void *devdata;
 	const struct thermal_cooling_device_ops *ops;
+	struct list_head instances;
 	struct list_head node;
 };
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (12 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:39   ` Rafael J. Wysocki
  2012-07-19  6:31 ` [PATCH 15/16] Thermal: Unify the code for both active and passive cooling Zhang Rui
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

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>
---
 drivers/thermal/thermal_sys.c |   41 ++++++++++++++++++++++++++++++++++++++---
 include/linux/thermal.h       |    1 +
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 48b2668..803ce94 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -54,6 +54,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->instances */
@@ -853,6 +854,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	dev->trip = trip;
 	dev->upper = upper;
 	dev->lower = lower;
+	dev->target = -1;
 
 	result = get_idr(&tz->idr, &tz->lock, &dev->id);
 	if (result)
@@ -990,6 +992,7 @@ thermal_cooling_device_register(char *type, void *devdata,
 	strcpy(cdev->type, type);
 	INIT_LIST_HEAD(&cdev->instances);
 	cdev->ops = ops;
+	cdev->updated = 1;
 	cdev->device.class = &thermal_class;
 	cdev->devdata = devdata;
 	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1081,6 +1084,32 @@ void thermal_cooling_device_unregister(struct
 }
 EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
+static void thermal_zone_do_update(struct thermal_zone_device *tz)
+{
+	struct thermal_instance *instance1, *instance2;
+	struct thermal_cooling_device *cdev;
+	int target;
+
+	list_for_each_entry(instance1, &tz->instances, tz_node) {
+		cdev = instance1->cdev;
+
+		/* cooling device has already been updated*/
+		if (cdev->updated)
+			continue;
+
+		target = 0;
+		/* Make sure cdev enters the deepest cooling state */
+		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
+			if (instance2->target == -1)
+				continue;
+			if (instance2->target > target)
+				target = instance2->target;
+		}
+		cdev->ops->set_cur_state(cdev, target);
+		cdev->updated = 1;
+	}
+}
+
 /*
  * Cooling algorithm for active trip points
  *
@@ -1127,19 +1156,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 = 0; /* cooling device needs update */
 		}
 	} else {	/* below trip */
 		list_for_each_entry(instance, &tz->instances, tz_node) {
 			if (instance->trip != trip)
 				continue;
 
+			/* Do not use the deacitve thermal instance */
+			if (instance->target == -1)
+				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) : -1;
+			instance->target = cur_state;
+			cdev->updated = 0; /* cooling device needs update */
 		}
 	}
 
@@ -1200,6 +1234,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 d8e069e..604c0f0 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -92,6 +92,7 @@ struct thermal_cooling_device {
 	struct device device;
 	void *devdata;
 	const struct thermal_cooling_device_ops *ops;
+	int updated; /* 1 if the cooling device does not need update */
 	struct list_head instances;
 	struct list_head node;
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 15/16] Thermal: Unify the code for both active and passive cooling
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (13 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19  6:31 ` [PATCH 16/16] Thermal: use plist instead of list Zhang Rui
  2012-07-19  6:37 ` [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

Remove thermal_zone_device_passive(). And use
thermal_zone_trip_update() and thermal_zone_do_update()
for both active and passive cooling.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   97 ++++++++++-------------------------------
 include/linux/thermal.h       |    2 +-
 2 files changed, 24 insertions(+), 75 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 803ce94..a40dda1 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -725,73 +725,6 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
 				      msecs_to_jiffies(delay));
 }
 
-static void thermal_zone_device_passive(struct thermal_zone_device *tz,
-					int temp, int trip_temp, int trip)
-{
-	int trend = 0;
-	struct thermal_instance *instance;
-	struct thermal_cooling_device *cdev;
-	long state, max_state;
-
-	/*
-	 * Above Trip?
-	 * -----------
-	 * Calculate the thermal trend (using the passive cooling equation)
-	 * and modify the performance limit for all passive cooling devices
-	 * accordingly.  Note that we assume symmetry.
-	 */
-	if (temp >= trip_temp) {
-		tz->passive = true;
-
-		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);
-
-		/* Heating up? */
-		if (trend > 0) {
-			list_for_each_entry(instance, &tz->instances,
-					    tz_node) {
-				if (instance->trip != trip)
-					continue;
-				cdev = instance->cdev;
-				cdev->ops->get_cur_state(cdev, &state);
-				cdev->ops->get_max_state(cdev, &max_state);
-				if (state++ < max_state)
-					cdev->ops->set_cur_state(cdev, state);
-			}
-		} else if (trend < 0) { /* Cooling off? */
-			list_for_each_entry(instance, &tz->instances,
-					    tz_node) {
-				if (instance->trip != trip)
-					continue;
-				cdev = instance->cdev;
-				cdev->ops->get_cur_state(cdev, &state);
-				cdev->ops->get_max_state(cdev, &max_state);
-				if (state > 0)
-					cdev->ops->set_cur_state(cdev, --state);
-			}
-		}
-		return;
-	}
-
-	/*
-	 * Below Trip?
-	 * -----------
-	 * Implement passive cooling hysteresis to slowly increase performance
-	 * and avoid thrashing around the passive trip point.  Note that we
-	 * assume symmetry.
-	 */
-	list_for_each_entry(instance, &tz->instances, tz_node) {
-		if (instance->trip != trip)
-			continue;
-		cdev = instance->cdev;
-		cdev->ops->get_cur_state(cdev, &state);
-		cdev->ops->get_max_state(cdev, &max_state);
-		if (state > 0)
-			cdev->ops->set_cur_state(cdev, --state);
-		if (state == 0)
-			tz->passive = false;
-	}
-}
-
 static void thermal_zone_device_check(struct work_struct *work)
 {
 	struct thermal_zone_device *tz = container_of(work, struct
@@ -1111,7 +1044,7 @@ static void thermal_zone_do_update(struct thermal_zone_device *tz)
 }
 
 /*
- * Cooling algorithm for active trip points
+ * Cooling algorithm for both active and passive cooling
  *
  * 1. if the temperature is higher than a trip point,
  *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
@@ -1133,9 +1066,16 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 	struct thermal_cooling_device *cdev = NULL;
 	unsigned long cur_state, max_state;
 	long trip_temp;
+	enum thermal_trip_type trip_type;
 	enum thermal_trend trend;
 
-	tz->ops->get_trip_temp(tz, trip, &trip_temp);
+	if (trip == THERMAL_TRIPS_NONE) {
+		trip_temp = tz->forced_passive;
+		trip_type = THERMAL_TRIPS_NONE;
+	} else {
+		tz->ops->get_trip_temp(tz, trip, &trip_temp);
+		tz->ops->get_trip_type(tz, trip, &trip_type);
+	}
 
 	if (temp >= trip_temp) {
 		thermal_get_trend(tz, trip, &trend);
@@ -1156,6 +1096,12 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 				cur_state = cur_state > instance->lower ?
 				    (cur_state - 1) : instance->lower;
 			}
+
+			/* activate a passive thermal instance */
+			if (trip_type == THERMAL_TRIP_PASSIVE &&
+			    instance->target == -1)
+				tz->passive++;
+
 			instance->target = cur_state;
 			cdev->updated = 0; /* cooling device needs update */
 		}
@@ -1172,6 +1118,11 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 
 			cur_state = cur_state > instance->lower ?
 				    (cur_state - 1) : -1;
+
+			/* deactivate a passive thermal instance */
+			if (trip_type == THERMAL_TRIP_PASSIVE &&
+			    cur_state == -1)
+				tz->passive--;
 			instance->target = cur_state;
 			cdev->updated = 0; /* cooling device needs update */
 		}
@@ -1228,16 +1179,14 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 			break;
 		case THERMAL_TRIP_PASSIVE:
 			if (temp >= trip_temp || tz->passive)
-				thermal_zone_device_passive(tz, temp,
-							    trip_temp, count);
+				thermal_zone_trip_update(tz, count, temp);
 			break;
 		}
 	}
 
-	thermal_zone_do_update(tz);
 	if (tz->forced_passive)
-		thermal_zone_device_passive(tz, temp, tz->forced_passive,
-					    THERMAL_TRIPS_NONE);
+		thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
+	thermal_zone_do_update(tz);
 
 leave:
 	if (tz->passive)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 604c0f0..f725eb9 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -119,7 +119,7 @@ struct thermal_zone_device {
 	int polling_delay;
 	int temperature;
 	int last_temperature;
-	bool passive;
+	int passive;
 	unsigned int forced_passive;
 	const struct thermal_zone_device_ops *ops;
 	struct list_head instances;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 16/16] Thermal: use plist instead of list
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (14 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 15/16] Thermal: Unify the code for both active and passive cooling Zhang Rui
@ 2012-07-19  6:31 ` Zhang Rui
  2012-07-19 21:45   ` Rafael J. Wysocki
  2012-07-19  6:37 ` [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
  16 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:31 UTC (permalink / raw)
  To: linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni, Zhang Rui

so that the thermal manager can easily find out
the deepest cooling state request for a cooling device.

cdev->lock is also introduced in this patch to protect this plist.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_sys.c |   84 ++++++++++++++++++++++++++---------------
 include/linux/thermal.h       |    4 +-
 2 files changed, 57 insertions(+), 31 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index a40dda1..9f56250 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -54,11 +54,10 @@ 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->instances */
-	struct list_head cdev_node; /* node in cdev->instances */
+	struct plist_node cdev_node; /* node in cdev->instances */
 };
 
 static DEFINE_IDR(thermal_tz_idr);
@@ -787,7 +786,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	dev->trip = trip;
 	dev->upper = upper;
 	dev->lower = lower;
-	dev->target = -1;
+	plist_node_init(&dev->cdev_node, -1);
 
 	result = get_idr(&tz->idr, &tz->lock, &dev->id);
 	if (result)
@@ -809,6 +808,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 		goto remove_symbol_link;
 
 	mutex_lock(&tz->lock);
+	mutex_lock(&cdev->lock);
 	list_for_each_entry(pos, &tz->instances, tz_node)
 	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 		result = -EEXIST;
@@ -816,8 +816,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	}
 	if (!result) {
 		list_add_tail(&dev->tz_node, &tz->instances);
-		list_add_tail(&dev->cdev_node, &cdev->instances);
+		plist_add(&dev->cdev_node, &cdev->instances);
 	}
+	mutex_unlock(&cdev->lock);
 	mutex_unlock(&tz->lock);
 
 	if (!result)
@@ -850,14 +851,17 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 	struct thermal_instance *pos, *next;
 
 	mutex_lock(&tz->lock);
+	mutex_lock(&cdev->lock);
 	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
 		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 			list_del(&pos->tz_node);
-			list_del(&pos->cdev_node);
+			plist_del(&pos->cdev_node, &pos->cdev->instances);
+			mutex_unlock(&cdev->lock);
 			mutex_unlock(&tz->lock);
 			goto unbind;
 		}
 	}
+	mutex_unlock(&cdev->lock);
 	mutex_unlock(&tz->lock);
 
 	return -ENODEV;
@@ -923,7 +927,8 @@ thermal_cooling_device_register(char *type, void *devdata,
 	}
 
 	strcpy(cdev->type, type);
-	INIT_LIST_HEAD(&cdev->instances);
+	plist_head_init(&cdev->instances);
+	mutex_init(&cdev->lock);
 	cdev->ops = ops;
 	cdev->updated = 1;
 	cdev->device.class = &thermal_class;
@@ -1019,26 +1024,21 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
 static void thermal_zone_do_update(struct thermal_zone_device *tz)
 {
-	struct thermal_instance *instance1, *instance2;
+	struct thermal_instance *instance;
+	struct plist_node *node;
 	struct thermal_cooling_device *cdev;
-	int target;
 
-	list_for_each_entry(instance1, &tz->instances, tz_node) {
-		cdev = instance1->cdev;
+	list_for_each_entry(instance, &tz->instances, tz_node) {
+		cdev = instance->cdev;
 
 		/* cooling device has already been updated*/
 		if (cdev->updated)
 			continue;
 
-		target = 0;
-		/* Make sure cdev enters the deepest cooling state */
-		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
-			if (instance2->target == -1)
-				continue;
-			if (instance2->target > target)
-				target = instance2->target;
-		}
-		cdev->ops->set_cur_state(cdev, target);
+		/* Deepest cooling state required */
+		node = plist_last(&cdev->instances);
+
+		cdev->ops->set_cur_state(cdev, node->prio < 0 ? 0 : node->prio);
 		cdev->updated = 1;
 	}
 }
@@ -1064,7 +1064,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 {
 	struct thermal_instance *instance;
 	struct thermal_cooling_device *cdev = NULL;
-	unsigned long cur_state, max_state;
+	unsigned long cur_state, max_state, target_state;
 	long trip_temp;
 	enum thermal_trip_type trip_type;
 	enum thermal_trend trend;
@@ -1088,21 +1088,29 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 
 			cdev->ops->get_cur_state(cdev, &cur_state);
 			cdev->ops->get_max_state(cdev, &max_state);
-
+			target_state = cur_state;
 			if (trend == THERMAL_TREND_RAISING) {
-				cur_state = cur_state < instance->upper ?
+				target_state = cur_state < instance->upper ?
 					    (cur_state + 1) : instance->upper;
 			} else if (trend == THERMAL_TREND_DROPPING) {
-				cur_state = cur_state > instance->lower ?
+				target_state = cur_state > instance->lower ?
 				    (cur_state - 1) : instance->lower;
 			}
 
+			if (target_state == cur_state)
+				continue;
+
 			/* activate a passive thermal instance */
 			if (trip_type == THERMAL_TRIP_PASSIVE &&
-			    instance->target == -1)
+			    instance->cdev_node.prio == -1)
 				tz->passive++;
 
-			instance->target = cur_state;
+			mutex_lock(&cdev->lock);
+			plist_del(&instance->cdev_node, &cdev->instances);
+			plist_node_init(&instance->cdev_node, target_state);
+			plist_add(&instance->cdev_node, &cdev->instances);
+			mutex_unlock(&cdev->lock);
+
 			cdev->updated = 0; /* cooling device needs update */
 		}
 	} else {	/* below trip */
@@ -1111,20 +1119,36 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
 				continue;
 
 			/* Do not use the deacitve thermal instance */
-			if (instance->target == -1)
+			if (instance->cdev_node.prio == -1)
 				continue;
 			cdev = instance->cdev;
 			cdev->ops->get_cur_state(cdev, &cur_state);
 
-			cur_state = cur_state > instance->lower ?
+			target_state = cur_state > instance->lower ?
 				    (cur_state - 1) : -1;
 
+			if (target_state == cur_state)
+				continue;
+
 			/* deactivate a passive thermal instance */
 			if (trip_type == THERMAL_TRIP_PASSIVE &&
-			    cur_state == -1)
+			    target_state == -1)
 				tz->passive--;
-			instance->target = cur_state;
-			cdev->updated = 0; /* cooling device needs update */
+
+			mutex_lock(&cdev->lock);
+			plist_del(&instance->cdev_node, &cdev->instances);
+			plist_node_init(&instance->cdev_node, target_state);
+			plist_add(&instance->cdev_node, &cdev->instances);
+			mutex_unlock(&cdev->lock);
+
+			/*
+			 * cooling device needs update.
+			 * But if the target_state is -1, it means that
+			 * the cooling device is already in cooling state 0,
+			 * thus we do not need update
+			 */
+			if (target_state != -1)
+				cdev->updated = 0;
 		}
 	}
 
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f725eb9..376a59e 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -28,6 +28,7 @@
 #include <linux/idr.h>
 #include <linux/device.h>
 #include <linux/workqueue.h>
+#include <linux/plist.h>
 
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -93,7 +94,8 @@ struct thermal_cooling_device {
 	void *devdata;
 	const struct thermal_cooling_device_ops *ops;
 	int updated; /* 1 if the cooling device does not need update */
-	struct list_head instances;
+	struct mutex lock;
+	struct plist_head instances;
 	struct list_head node;
 };
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 00/16] Thermal: generic thermal layer enhancement
  2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
                   ` (15 preceding siblings ...)
  2012-07-19  6:31 ` [PATCH 16/16] Thermal: use plist instead of list Zhang Rui
@ 2012-07-19  6:37 ` Zhang Rui
  16 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-19  6:37 UTC (permalink / raw)
  To: linux-acpi
  Cc: linux-pm, Rafael J. Wysocki, Matthew Garrett, Len Brown,
	R Durgadoss, Eduardo Valentin, Amit Kachhap, Wei Ni

oops, wrong email address for Eduardo...
sorry about that.

On Thu, 2012-07-19 at 14:31 +0800, Zhang Rui wrote:
> Hi, all,
> 
> these are the patches that I want to push to linux-next.
> 
> it contains two patches from Durga, one patch for documentation update,
> and 13 patches to fix the problems discussed in
> http://marc.info/?l=linux-acpi&m=133836783425764&w=2
> 
> please kindly review.
> 
> 1) patch 1, 2, introduce the writeable trip point,
>    and introduce hysterisis information for each trip point.
> 2) patch 3 is a Documentation update.
> 3) patch 4, 5, 6, introduce the multiple cooling states support
>    for both active and passive trip points.
> 4) patch 7, 8, remove passive specific requirement, aka, tc1/tc2, and
>    introduce .get_trend() instead, for both active and passive cooling
>    algorithm.
> 5) patch 9 introduces new function thermal_zone_trip_update(),
>    which contains the code for general cooling algorithm.
> 6) patch 10, 11, 12, 13 rename some thermal structures to make them more accurate.
> 7) patch 14 introduces a simple cooling state arbitrator.
> 8) patch 15 unifies the code for both passive and active cooling.
> 9) patch 16 converts an internal list to plist, which is more efficient.
> 
> Any comments are welcome.
> 
> thanks,
> rui
> 
> ---------------------------------------------------------------------------
> Durgadoss R (2):
>       Thermal: Make Thermal trip points writeable
>       Thermal: Add Hysteresis attributes
> 
> Zhang Rui (14):
>       Thermal: Documentation update
>       Thermal: Introduce multiple cooling states support
>       Thermal: Introduce cooling states range support
>       Thermal: set upper and lower limits
>       Thermal: Introduce .get_trend() callback.
>       Thermal: Remove tc1/tc2 in generic thermal layer.
>       Thermal: Introduce thermal_zone_trip_update()
>       Thermal: rename structure thermal_cooling_device_instance to thermal_instance
>       Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances
>       Thermal: Rename thermal_instance.node to thermal_instance.tz_node.
>       Thermal: List thermal_instance in thermal_cooling_device.
>       Thermal: Introduce simple arbitrator for setting device cooling state
>       Thermal: Unify the code for both active and passive cooling
>       Thermal: use plist instead of list
> 
> ---------------------------------------------------------------------------
>  Documentation/thermal/sysfs-api.txt      |   36 +-
>  drivers/acpi/thermal.c                   |   99 ++++--
>  drivers/platform/x86/acerhdf.c           |    6 +-
>  drivers/platform/x86/intel_mid_thermal.c |    2 +-
>  drivers/thermal/spear_thermal.c          |    4 +-
>  drivers/thermal/thermal_sys.c            |  543 +++++++++++++++++++++---------
>  include/linux/thermal.h                  |   43 ++-
>  7 files changed, 521 insertions(+), 212 deletions(-)
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
@ 2012-07-19 10:35   ` R, Durgadoss
  2012-07-19 19:38   ` Rafael J. Wysocki
  2012-07-19 20:27   ` Rafael J. Wysocki
  2 siblings, 0 replies; 56+ messages in thread
From: R, Durgadoss @ 2012-07-19 10:35 UTC (permalink / raw)
  To: Zhang, Rui, linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, Eduardo Valentin,
	Amit Kachhap, Wei Ni

Hi Rui,


> -----Original Message-----
> From: Zhang, Rui
> Sent: Thursday, July 19, 2012 12:01 PM
> To: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org
> Cc: Rafael J. Wysocki; Matthew Garrett; Len Brown; R, Durgadoss; Eduardo
> Valentin; Amit Kachhap; Wei Ni; Zhang, Rui
> Subject: [PATCH 01/16] Thermal: Make Thermal trip points writeable
> 
> From: Durgadoss R <dugardoss.r@intel.com>

[cut.]

> 
>  static ssize_t
> +trip_point_temp_store(struct device *dev, struct device_attribute *attr,
> +		     const char *buf, size_t count)
> +{
> +	struct thermal_zone_device *tz = to_thermal_zone(dev);
> +	int trip, ret;
> +	unsigned long temperature;
> +
> +	if (!tz->ops->set_trip_temp)
> +		return -EPERM;
> +
> +	if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
> +		return -EINVAL;
> +
> +	if (kstrtoul(buf, 10, &temperature))
> +		return -EINVAL;
> +
> +	ret = tz->ops->set_trip_temp(tz, trip, temperature);
> +
> +	return ret ? ret : count;
> +}
> +
> +static ssize_t
>  trip_point_temp_show(struct device *dev, struct device_attribute *attr,
>  		     char *buf)
>  {
> @@ -283,33 +305,6 @@ static DEVICE_ATTR(temp, 0444, temp_show, NULL);
>  static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
>  static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show,
> passive_store);
> 
> -static struct device_attribute trip_point_attrs[] = {
> -	__ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
> -};
> -
>  /* sys I/F for cooling device */
>  #define to_cooling_device(_dev)	\
>  	container_of(_dev, struct thermal_cooling_device, device)
> @@ -1089,9 +1084,83 @@ void thermal_zone_device_update(struct
> thermal_zone_device *tz)
>  EXPORT_SYMBOL(thermal_zone_device_update);
> 
>  /**
> + * create_trip_attrs - create attributes for trip points
> + * @tz:		the thermal zone device
> + * @flag:	Writeable trip point bitmap.
> + */
> +static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
> +{
> +	int indx;
> +	int writeable;
> +
> +	tz->trip_type_attrs =
> +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> +	if (!tz->trip_type_attrs)
> +		return -ENOMEM;
> +
> +	tz->trip_temp_attrs =
> +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> +	if (!tz->trip_temp_attrs) {
> +		kfree(tz->trip_type_attrs);
> +		return -ENOMEM;
> +	}
> +
> +	for (indx = 0; indx < tz->trips; indx++) {
> +
> +		/* create trip type attribute */
> +		snprintf(tz->trip_type_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> +			 "trip_point_%d_type", indx);
> +
> +		sysfs_attr_init(&tz->trip_type_attrs[count].attr.attr);

Shouldn't the 'count' be 'indx' ?

> +		tz->trip_type_attrs[indx].attr.attr.name =

Thanks,
Durga

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: [PATCH 02/16] Thermal: Add Hysteresis attributes
  2012-07-19  6:31 ` [PATCH 02/16] Thermal: Add Hysteresis attributes Zhang Rui
@ 2012-07-19 10:40   ` R, Durgadoss
  2012-07-19 20:00     ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: R, Durgadoss @ 2012-07-19 10:40 UTC (permalink / raw)
  To: Zhang, Rui, linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, Eduardo Valentin,
	Amit Kachhap, Wei Ni

Hi Rui,

> -----Original Message-----
> From: Zhang, Rui
> Sent: Thursday, July 19, 2012 12:01 PM
> To: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org
> Cc: Rafael J. Wysocki; Matthew Garrett; Len Brown; R, Durgadoss; Eduardo
> Valentin; Amit Kachhap; Wei Ni; Zhang, Rui
> Subject: [PATCH 02/16] Thermal: Add Hysteresis attributes
> 
> From: Durgadoss R <dugardoss.r@intel.com>
> 
> The Linux Thermal Framework does not support hysteresis
> attributes. Most thermal sensors, today, have a
> hysteresis value associated with trip points.
> 
> This patch adds hysteresis attributes on a per-trip-point
> basis, to the Thermal Framework. These attributes are
> optionally writable.
> 
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  Documentation/thermal/sysfs-api.txt |    6 +++
>  drivers/thermal/thermal_sys.c       |   89
> ++++++++++++++++++++++++++++++++---
>  include/linux/thermal.h             |    5 ++
>  3 files changed, 94 insertions(+), 6 deletions(-)
> 
> diff --git a/Documentation/thermal/sysfs-api.txt
> b/Documentation/thermal/sysfs-api.txt
> index 0c7c423..3c8c2f8 100644
> --- a/Documentation/thermal/sysfs-api.txt
> +++ b/Documentation/thermal/sysfs-api.txt
> @@ -121,6 +121,7 @@ if hwmon is compiled in or built as a module.
>      |---mode:			Working mode of the thermal zone
>      |---trip_point_[0-*]_temp:	Trip point temperature
>      |---trip_point_[0-*]_type:	Trip point type
> +    |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
> 
>  Thermal cooling device sys I/F, created once it's registered:
>  /sys/class/thermal/cooling_device[0-*]:
> @@ -190,6 +191,11 @@ trip_point_[0-*]_type
>  	thermal zone.
>  	RO, Optional
> 
[cut.]

> +		/* create Optional trip hyst attribute */
> +		if (!tz->ops->get_trip_hyst)
> +			continue;
> +		snprintf(tz->trip_hyst_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> +			 "trip_point_%d_hyst", indx);
> +
> +		sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
> +		tz->trip_hyst_attrs[indx].attr.attr.name =
> +					tz->trip_hyst_attrs[indx].name;
> +		tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
> +		tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
> +		if (tz->ops->set_trip_hyst) {
> +			tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
> +			tz->trip_hyst_attrs[indx].attr.store =
> +					trip_point_hyst_store;
> +		}
> +
> +		device_create_file(&tz->device,
> +				   &tz->trip_hyst_attrs[indx].attr);
>  	}
>  	return 0;
>  }
> @@ -1151,9 +1225,13 @@ static void remove_trip_attrs(struct
> thermal_zone_device *tz)
>  				   &tz->trip_type_attrs[indx].attr);
>  		device_remove_file(&tz->device,
>  				   &tz->trip_temp_attrs[indx].attr);
> +		if (tz->ops->get_trip_hyst)
> +			device_remove_file(&tz->device,
> +				  &tz->trip_hyst_attrs[indx].attr);
>  	}
>  	kfree(tz->trip_type_attrs);
>  	kfree(tz->trip_temp_attrs);

I believe we should have a check here for 'if (tz->ops->get_trip_hyst)' and then
only free this, if required.

> +	kfree(tz->trip_hyst_attrs);
>  }
> 

Thanks,
Durga

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: [PATCH 03/16] Thermal: Documentation update
  2012-07-19  6:31 ` [PATCH 03/16] Thermal: Documentation update Zhang Rui
@ 2012-07-19 10:51   ` R, Durgadoss
  2012-07-23  8:36     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: R, Durgadoss @ 2012-07-19 10:51 UTC (permalink / raw)
  To: Zhang, Rui, linux-acpi, linux-pm
  Cc: Rafael J. Wysocki, Matthew Garrett, Len Brown, Eduardo Valentin,
	Amit Kachhap, Wei Ni

Hi Rui,

No major comments. Just some spell checks.

> -----Original Message-----
> From: Zhang, Rui
> Sent: Thursday, July 19, 2012 12:01 PM
> To: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org
> Cc: Rafael J. Wysocki; Matthew Garrett; Len Brown; R, Durgadoss; Eduardo
> Valentin; Amit Kachhap; Wei Ni; Zhang, Rui
> Subject: [PATCH 03/16] Thermal: Documentation update
> 
> With commit 6503e5df08008b9a47022b5e9ebba658c8fa69af,
> the value of /sys/class/thermal/thermal_zoneX/mode has been changed
> from user/kernel to enabled/disabled.
> Update the documentation so that users won't be confused.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  Documentation/thermal/sysfs-api.txt |   20 ++++++++++----------
>  drivers/acpi/thermal.c              |    6 ++----
>  2 files changed, 12 insertions(+), 14 deletions(-)
> 
> diff --git a/Documentation/thermal/sysfs-api.txt
> b/Documentation/thermal/sysfs-api.txt
> index 3c8c2f8..b7b3609 100644
> --- a/Documentation/thermal/sysfs-api.txt
> +++ b/Documentation/thermal/sysfs-api.txt
> @@ -47,11 +47,11 @@ temperature) and throttle appropriate devices.
>  	.bind: bind the thermal zone device with a thermal cooling device.
>  	.unbind: unbind the thermal zone device with a thermal cooling device.
>  	.get_temp: get the current temperature of the thermal zone.
> -	.get_mode: get the current mode (user/kernel) of the thermal zone.
> -	    - "kernel" means thermal management is done in kernel.
> -	    - "user" will prevent kernel thermal driver actions upon trip points
> +	.get_mode: get the current mode (enabled/disabled) of the thermal
> zone.
> +	    - "enabled" means the kernel thermal management is enabled.
> +	    - "disable" will prevent kernel thermal driver actions upon trip points

/s/disable/disabled

>  	      so that user applications can take charge of thermal management.
> -	.set_mode: set the mode (user/kernel) of the thermal zone.
> +	.set_mode: set the mode (enabled/disabled) of the thermal zone.
>  	.get_trip_type: get the type of certain trip point.
>  	.get_trip_temp: get the temperature above which the certain trip point
>  			will be fired.
> @@ -170,14 +170,14 @@ temp
>  	RO, Required
> 
>  mode
> -	One of the predefined values in [kernel, user].
> +	One of the predefined values in [enabled, disableed].

/s/disableed/disabled

Thanks,
Durga

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
  2012-07-19 10:35   ` R, Durgadoss
@ 2012-07-19 19:38   ` Rafael J. Wysocki
  2012-07-23  8:11     ` Zhang Rui
  2012-07-19 20:27   ` Rafael J. Wysocki
  2 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 19:38 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> From: Durgadoss R <dugardoss.r@intel.com>
> 
> Some of the thermal drivers using the Generic Thermal Framework
> require (all/some) trip points to be writeable. This patch makes
> the trip point temperatures writeable on a per-trip point basis,
> and modifies the required function call in thermal.c. This patch
> also updates the Documentation to reflect the new change.
> 
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  Documentation/thermal/sysfs-api.txt      |    4 +-
>  drivers/acpi/thermal.c                   |    4 +-
>  drivers/platform/x86/acerhdf.c           |    2 +-
>  drivers/platform/x86/intel_mid_thermal.c |    2 +-
>  drivers/thermal/spear_thermal.c          |    2 +-
>  drivers/thermal/thermal_sys.c            |  147 +++++++++++++++++++++---------
>  include/linux/thermal.h                  |   15 ++-
>  7 files changed, 125 insertions(+), 51 deletions(-)
> 
> diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> index 1733ab9..0c7c423 100644
> --- a/Documentation/thermal/sysfs-api.txt
> +++ b/Documentation/thermal/sysfs-api.txt
> @@ -32,7 +32,8 @@ temperature) and throttle appropriate devices.
>  
>  1.1 thermal zone device interface
>  1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name,
> -		int trips, void *devdata, struct thermal_zone_device_ops *ops)
> +		int trips, int flag, void *devdata,
> +		struct thermal_zone_device_ops *ops)
>  
>      This interface function adds a new thermal zone device (sensor) to
>      /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
> @@ -40,6 +41,7 @@ temperature) and throttle appropriate devices.
>  
>      name: the thermal zone name.
>      trips: the total number of trip points this thermal zone supports.
> +    flag: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
>      devdata: device private data
>      ops: thermal zone device call-backs.
>  	.bind: bind the thermal zone device with a thermal cooling device.

I wonder.  What is the maximum number of trip points currently passed to this
function in one call?

Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 02/16] Thermal: Add Hysteresis attributes
  2012-07-19 10:40   ` R, Durgadoss
@ 2012-07-19 20:00     ` Rafael J. Wysocki
  0 siblings, 0 replies; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 20:00 UTC (permalink / raw)
  To: R, Durgadoss
  Cc: Zhang, Rui, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Thursday, July 19, 2012, R, Durgadoss wrote:
> Hi Rui,
> 
> > -----Original Message-----
> > From: Zhang, Rui
> > Sent: Thursday, July 19, 2012 12:01 PM
> > To: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org
> > Cc: Rafael J. Wysocki; Matthew Garrett; Len Brown; R, Durgadoss; Eduardo
> > Valentin; Amit Kachhap; Wei Ni; Zhang, Rui
> > Subject: [PATCH 02/16] Thermal: Add Hysteresis attributes
> > 
> > From: Durgadoss R <dugardoss.r@intel.com>
> > 
> > The Linux Thermal Framework does not support hysteresis
> > attributes. Most thermal sensors, today, have a
> > hysteresis value associated with trip points.
> > 
> > This patch adds hysteresis attributes on a per-trip-point
> > basis, to the Thermal Framework. These attributes are
> > optionally writable.
> > 
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  Documentation/thermal/sysfs-api.txt |    6 +++
> >  drivers/thermal/thermal_sys.c       |   89
> > ++++++++++++++++++++++++++++++++---
> >  include/linux/thermal.h             |    5 ++
> >  3 files changed, 94 insertions(+), 6 deletions(-)
> > 
> > diff --git a/Documentation/thermal/sysfs-api.txt
> > b/Documentation/thermal/sysfs-api.txt
> > index 0c7c423..3c8c2f8 100644
> > --- a/Documentation/thermal/sysfs-api.txt
> > +++ b/Documentation/thermal/sysfs-api.txt
> > @@ -121,6 +121,7 @@ if hwmon is compiled in or built as a module.
> >      |---mode:			Working mode of the thermal zone
> >      |---trip_point_[0-*]_temp:	Trip point temperature
> >      |---trip_point_[0-*]_type:	Trip point type
> > +    |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
> > 
> >  Thermal cooling device sys I/F, created once it's registered:
> >  /sys/class/thermal/cooling_device[0-*]:
> > @@ -190,6 +191,11 @@ trip_point_[0-*]_type
> >  	thermal zone.
> >  	RO, Optional
> > 
> [cut.]
> 
> > +		/* create Optional trip hyst attribute */
> > +		if (!tz->ops->get_trip_hyst)
> > +			continue;
> > +		snprintf(tz->trip_hyst_attrs[indx].name,
> > THERMAL_NAME_LENGTH,
> > +			 "trip_point_%d_hyst", indx);
> > +
> > +		sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
> > +		tz->trip_hyst_attrs[indx].attr.attr.name =
> > +					tz->trip_hyst_attrs[indx].name;
> > +		tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
> > +		tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
> > +		if (tz->ops->set_trip_hyst) {
> > +			tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
> > +			tz->trip_hyst_attrs[indx].attr.store =
> > +					trip_point_hyst_store;
> > +		}
> > +
> > +		device_create_file(&tz->device,
> > +				   &tz->trip_hyst_attrs[indx].attr);
> >  	}
> >  	return 0;
> >  }
> > @@ -1151,9 +1225,13 @@ static void remove_trip_attrs(struct
> > thermal_zone_device *tz)
> >  				   &tz->trip_type_attrs[indx].attr);
> >  		device_remove_file(&tz->device,
> >  				   &tz->trip_temp_attrs[indx].attr);
> > +		if (tz->ops->get_trip_hyst)
> > +			device_remove_file(&tz->device,
> > +				  &tz->trip_hyst_attrs[indx].attr);
> >  	}
> >  	kfree(tz->trip_type_attrs);
> >  	kfree(tz->trip_temp_attrs);
> 
> I believe we should have a check here for 'if (tz->ops->get_trip_hyst)' and then
> only free this, if required.
> 
> > +	kfree(tz->trip_hyst_attrs);
> >  }

No, we don't have to, kfree() checks for NULL pointers.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
  2012-07-19 10:35   ` R, Durgadoss
  2012-07-19 19:38   ` Rafael J. Wysocki
@ 2012-07-19 20:27   ` Rafael J. Wysocki
  2012-07-23  8:22     ` Zhang Rui
  2 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 20:27 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> From: Durgadoss R <dugardoss.r@intel.com>
> 
> Some of the thermal drivers using the Generic Thermal Framework
> require (all/some) trip points to be writeable. This patch makes
> the trip point temperatures writeable on a per-trip point basis,
> and modifies the required function call in thermal.c. This patch
> also updates the Documentation to reflect the new change.
> 
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  Documentation/thermal/sysfs-api.txt      |    4 +-
>  drivers/acpi/thermal.c                   |    4 +-
>  drivers/platform/x86/acerhdf.c           |    2 +-
>  drivers/platform/x86/intel_mid_thermal.c |    2 +-
>  drivers/thermal/spear_thermal.c          |    2 +-
>  drivers/thermal/thermal_sys.c            |  147 +++++++++++++++++++++---------
>  include/linux/thermal.h                  |   15 ++-
>  7 files changed, 125 insertions(+), 51 deletions(-)
> 
> diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> index 1733ab9..0c7c423 100644
> --- a/Documentation/thermal/sysfs-api.txt
> +++ b/Documentation/thermal/sysfs-api.txt
> @@ -32,7 +32,8 @@ temperature) and throttle appropriate devices.
>  
>  1.1 thermal zone device interface
>  1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name,
> -		int trips, void *devdata, struct thermal_zone_device_ops *ops)
> +		int trips, int flag, void *devdata,

The 'flags' argument should rather be called 'mask', or even 'writable_mask'.

> +		struct thermal_zone_device_ops *ops)
>  
>      This interface function adds a new thermal zone device (sensor) to
>      /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
> @@ -40,6 +41,7 @@ temperature) and throttle appropriate devices.
>  
>      name: the thermal zone name.
>      trips: the total number of trip points this thermal zone supports.
> +    flag: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
>      devdata: device private data
>      ops: thermal zone device call-backs.
>  	.bind: bind the thermal zone device with a thermal cooling device.
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 7dbebea..2107d1b 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -845,7 +845,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
>  
>  	if (tz->trips.passive.flags.valid)
>  		tz->thermal_zone =
> -			thermal_zone_device_register("acpitz", trips, tz,
> +			thermal_zone_device_register("acpitz", trips, 0, tz,
>  						     &acpi_thermal_zone_ops,
>  						     tz->trips.passive.tc1,
>  						     tz->trips.passive.tc2,
> @@ -853,7 +853,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
>  						     tz->polling_frequency*100);
>  	else
>  		tz->thermal_zone =
> -			thermal_zone_device_register("acpitz", trips, tz,
> +			thermal_zone_device_register("acpitz", trips, 0, tz,
>  						     &acpi_thermal_zone_ops,
>  						     0, 0, 0,
>  						     tz->polling_frequency*100);
> diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
> index 2fd9d36..39abb15 100644
> --- a/drivers/platform/x86/acerhdf.c
> +++ b/drivers/platform/x86/acerhdf.c
> @@ -660,7 +660,7 @@ static int acerhdf_register_thermal(void)
>  	if (IS_ERR(cl_dev))
>  		return -EINVAL;
>  
> -	thz_dev = thermal_zone_device_register("acerhdf", 1, NULL,
> +	thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
>  					      &acerhdf_dev_ops, 0, 0, 0,
>  					      (kernelmode) ? interval*1000 : 0);
>  	if (IS_ERR(thz_dev))
> diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
> index 5ae9cd9..2b2c212 100644
> --- a/drivers/platform/x86/intel_mid_thermal.c
> +++ b/drivers/platform/x86/intel_mid_thermal.c
> @@ -499,7 +499,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
>  			goto err;
>  		}
>  		pinfo->tzd[i] = thermal_zone_device_register(name[i],
> -				0, td_info, &tzd_ops, 0, 0, 0, 0);
> +				0, 0, td_info, &tzd_ops, 0, 0, 0, 0);
>  		if (IS_ERR(pinfo->tzd[i])) {
>  			kfree(td_info);
>  			ret = PTR_ERR(pinfo->tzd[i]);
> diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
> index c2e32df..69a55d4 100644
> --- a/drivers/thermal/spear_thermal.c
> +++ b/drivers/thermal/spear_thermal.c
> @@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
>  	stdev->flags = pdata->thermal_flags;
>  	writel_relaxed(stdev->flags, stdev->thermal_base);
>  
> -	spear_thermal = thermal_zone_device_register("spear_thermal", 0,
> +	spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
>  				stdev, &ops, 0, 0, 0, 0);
>  	if (IS_ERR(spear_thermal)) {
>  		dev_err(&pdev->dev, "thermal zone device is NULL\n");
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 022bacb..a590d57 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -196,6 +196,28 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
>  }
>  
>  static ssize_t
> +trip_point_temp_store(struct device *dev, struct device_attribute *attr,
> +		     const char *buf, size_t count)
> +{
> +	struct thermal_zone_device *tz = to_thermal_zone(dev);
> +	int trip, ret;
> +	unsigned long temperature;
> +
> +	if (!tz->ops->set_trip_temp)
> +		return -EPERM;
> +
> +	if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
> +		return -EINVAL;
> +
> +	if (kstrtoul(buf, 10, &temperature))
> +		return -EINVAL;
> +
> +	ret = tz->ops->set_trip_temp(tz, trip, temperature);
> +
> +	return ret ? ret : count;
> +}
> +
> +static ssize_t
>  trip_point_temp_show(struct device *dev, struct device_attribute *attr,
>  		     char *buf)
>  {
> @@ -283,33 +305,6 @@ static DEVICE_ATTR(temp, 0444, temp_show, NULL);
>  static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
>  static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
>  
> -static struct device_attribute trip_point_attrs[] = {
> -	__ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
> -	__ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
> -	__ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
> -};
> -
>  /* sys I/F for cooling device */
>  #define to_cooling_device(_dev)	\
>  	container_of(_dev, struct thermal_cooling_device, device)
> @@ -1089,9 +1084,83 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  EXPORT_SYMBOL(thermal_zone_device_update);
>  
>  /**
> + * create_trip_attrs - create attributes for trip points
> + * @tz:		the thermal zone device
> + * @flag:	Writeable trip point bitmap.
> + */
> +static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
> +{
> +	int indx;
> +	int writeable;
> +
> +	tz->trip_type_attrs =
> +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> +	if (!tz->trip_type_attrs)
> +		return -ENOMEM;
> +
> +	tz->trip_temp_attrs =
> +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> +	if (!tz->trip_temp_attrs) {
> +		kfree(tz->trip_type_attrs);
> +		return -ENOMEM;
> +	}
> +
> +	for (indx = 0; indx < tz->trips; indx++) {
> +
> +		/* create trip type attribute */
> +		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
> +			 "trip_point_%d_type", indx);

If this really truncates the name, we'll run into problems in _show() and _store().
Is there any solution to that?

> +
> +		sysfs_attr_init(&tz->trip_type_attrs[count].attr.attr);
> +		tz->trip_type_attrs[indx].attr.attr.name =
> +						tz->trip_type_attrs[indx].name;
> +		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
> +		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
> +
> +		device_create_file(&tz->device,
> +				   &tz->trip_type_attrs[indx].attr);
> +
> +		/* create trip temp attribute */
> +		writeable = flag & (1 << indx);
> +		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
> +			 "trip_point_%d_temp", indx);
> +
> +		sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
> +		tz->trip_temp_attrs[indx].attr.attr.name =
> +						tz->trip_temp_attrs[indx].name;
> +		tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
> +		tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
> +		if (writeable) {

Why don't you put the "flag & (1 << indx)" here directly instead of 'writable'?

> +			tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
> +			tz->trip_temp_attrs[indx].attr.store =
> +							trip_point_temp_store;
> +		}
> +
> +		device_create_file(&tz->device,
> +				   &tz->trip_temp_attrs[indx].attr);
> +	}
> +	return 0;
> +}
> +
> +static void remove_trip_attrs(struct thermal_zone_device *tz)
> +{
> +	int indx;
> +
> +	for (indx = 0; indx < tz->trips; indx++) {
> +		device_remove_file(&tz->device,
> +				   &tz->trip_type_attrs[indx].attr);
> +		device_remove_file(&tz->device,
> +				   &tz->trip_temp_attrs[indx].attr);
> +	}
> +	kfree(tz->trip_type_attrs);
> +	kfree(tz->trip_temp_attrs);
> +}
> +
> +/**
>   * thermal_zone_device_register - register a new thermal zone device
>   * @type:	the thermal zone device type
>   * @trips:	the number of trip points the thermal zone support
> + * @flag:	a bit string indicating the writeablility of trip points
>   * @devdata:	private device data
>   * @ops:	standard thermal zone device callbacks
>   * @tc1:	thermal coefficient 1 for passive calculations
> @@ -1107,7 +1176,7 @@ EXPORT_SYMBOL(thermal_zone_device_update);
>   * section 11.1.5.1 of the ACPI specification 3.0.
>   */
>  struct thermal_zone_device *thermal_zone_device_register(char *type,
> -	int trips, void *devdata,
> +	int trips, int flag, void *devdata,
>  	const struct thermal_zone_device_ops *ops,
>  	int tc1, int tc2, int passive_delay, int polling_delay)
>  {
> @@ -1124,6 +1193,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
>  	if (trips > THERMAL_MAX_TRIPS || trips < 0)
>  		return ERR_PTR(-EINVAL);
>  
> +	if (flag >> trips)
> +		return ERR_PTR(-EINVAL);

I'm not sure if this check is necessary.  Does it actually matter is someone
passes ones in the unused bit positions?

> +
>  	if (!ops || !ops->get_temp)
>  		return ERR_PTR(-EINVAL);
>  
> @@ -1175,15 +1247,11 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
>  			goto unregister;
>  	}
>  
> +	result = create_trip_attrs(tz, flag);
> +	if (result)
> +		goto unregister;
> +
>  	for (count = 0; count < trips; count++) {
> -		result = device_create_file(&tz->device,
> -					    &trip_point_attrs[count * 2]);
> -		if (result)
> -			break;
> -		result = device_create_file(&tz->device,
> -					    &trip_point_attrs[count * 2 + 1]);
> -		if (result)
> -			goto unregister;
>  		tz->ops->get_trip_type(tz, count, &trip_type);
>  		if (trip_type == THERMAL_TRIP_PASSIVE)
>  			passive = 1;
> @@ -1259,13 +1327,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
>  	device_remove_file(&tz->device, &dev_attr_temp);
>  	if (tz->ops->get_mode)
>  		device_remove_file(&tz->device, &dev_attr_mode);
> +	remove_trip_attrs(tz);
>  
> -	for (count = 0; count < tz->trips; count++) {
> -		device_remove_file(&tz->device,
> -				   &trip_point_attrs[count * 2]);
> -		device_remove_file(&tz->device,
> -				   &trip_point_attrs[count * 2 + 1]);
> -	}
>  	thermal_remove_hwmon_sysfs(tz);
>  	release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
>  	idr_destroy(&tz->idr);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 796f1ff..6eaf914 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -58,6 +58,8 @@ struct thermal_zone_device_ops {
>  		enum thermal_trip_type *);
>  	int (*get_trip_temp) (struct thermal_zone_device *, int,
>  			      unsigned long *);
> +	int (*set_trip_temp) (struct thermal_zone_device *, int,
> +			      unsigned long);
>  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
>  	int (*notify) (struct thermal_zone_device *, int,
>  		       enum thermal_trip_type);
> @@ -85,10 +87,17 @@ struct thermal_cooling_device {
>  				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
>  #define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
>  
> +struct thermal_attr {
> +	struct device_attribute attr;
> +	char name[THERMAL_NAME_LENGTH];
> +};
> +
>  struct thermal_zone_device {
>  	int id;
>  	char type[THERMAL_NAME_LENGTH];
>  	struct device device;
> +	struct thermal_attr *trip_temp_attrs;
> +	struct thermal_attr *trip_type_attrs;
>  	void *devdata;
>  	int trips;
>  	int tc1;
> @@ -137,9 +146,9 @@ enum {
>  };
>  #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
>  
> -struct thermal_zone_device *thermal_zone_device_register(char *, int, void *,
> -		const struct thermal_zone_device_ops *, int tc1, int tc2,
> -		int passive_freq, int polling_freq);
> +struct thermal_zone_device *thermal_zone_device_register(char *, int, int,
> +		void *, const struct thermal_zone_device_ops *, int tc1,
> +		int tc2, int passive_freq, int polling_freq);
>  void thermal_zone_device_unregister(struct thermal_zone_device *);
>  
>  int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 06/16] Thermal: set upper and lower limits
  2012-07-19  6:31 ` [PATCH 06/16] Thermal: set upper and lower limits Zhang Rui
@ 2012-07-19 20:55   ` Rafael J. Wysocki
  2012-07-23  8:45     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 20:55 UTC (permalink / raw)
  To: Zhang Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> set upper and lower limits when binding
> a thermal cooling device to a thermal zone device.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  Documentation/thermal/sysfs-api.txt |    6 ++++-
>  drivers/acpi/thermal.c              |   49 ++++++++++++++++++++++-------------
>  drivers/platform/x86/acerhdf.c      |    2 +-
>  drivers/thermal/thermal_sys.c       |   20 +++++++++-----
>  include/linux/thermal.h             |    3 ++-
>  5 files changed, 53 insertions(+), 27 deletions(-)
> 
> diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> index b7b3609..f169821 100644
> --- a/Documentation/thermal/sysfs-api.txt
> +++ b/Documentation/thermal/sysfs-api.txt
> @@ -84,7 +84,7 @@ temperature) and throttle appropriate devices.
>  
>  1.3 interface for binding a thermal zone device with a thermal cooling device
>  1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> -		int trip, struct thermal_cooling_device *cdev);
> +	int trip, struct thermal_cooling_device *cdev, long upper, long lower);
>  
>      This interface function bind a thermal cooling device to the certain trip
>      point of a thermal zone device.
> @@ -93,6 +93,10 @@ temperature) and throttle appropriate devices.
>      cdev: thermal cooling device
>      trip: indicates which trip point the cooling devices is associated with
>  	  in this thermal zone.
> +    upper:the Maximum cooling state for this trip point.
> +          -1 means no upper limit, and the cooling device can be in max_state.
> +    lower:the Minimum cooling state can be used for this trip point.
> +          -1 means no lower limit, and the cooling device can be in cooling state 0.

If we have to use -1 (or all ones for unsigned long), I'd suggest to define a
constant called CS_NO_LIMIT or something like that and use it instead of the
plain numbers.

And perhaps change the name of the above to
thermal_zone_bind_cooling_device_limits() and define
thermal_zone_bind_cooling_device() as a static inline that will not take the
extra two arguments and make it call thermal_zone_bind_cooling_device_limits()
with the CS_NO_LIMIT values in there.

>  1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
>  		int trip, struct thermal_cooling_device *cdev);
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 8275e7b..a7c97f5 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -727,11 +727,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
>  	return 0;
>  }
>  
> -typedef int (*cb)(struct thermal_zone_device *, int,
> -		  struct thermal_cooling_device *);
>  static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>  					struct thermal_cooling_device *cdev,
> -					cb action)
> +					int bind)

Should 'bind' be a bool?

>  {
>  	struct acpi_device *device = cdev->devdata;
>  	struct acpi_thermal *tz = thermal->devdata;
> @@ -755,11 +753,18 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>  		    i++) {
>  			handle = tz->trips.passive.devices.handles[i];
>  			status = acpi_bus_get_device(handle, &dev);
> -			if (ACPI_SUCCESS(status) && (dev == device)) {
> -				result = action(thermal, trip, cdev);
> -				if (result)
> -					goto failed;
> -			}
> +			if (ACPI_FAILURE(status) || dev != device)
> +				continue;
> +			if (bind)
> +				result =
> +					thermal_zone_bind_cooling_device
> +					(thermal, trip, cdev, -1, -1);
> +			else
> +				result =
> +					thermal_zone_unbind_cooling_device
> +					(thermal, trip, cdev);
> +			if (result)
> +				goto failed;
>  		}
>  	}
>  
> @@ -772,11 +777,16 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>  		    j++) {
>  			handle = tz->trips.active[i].devices.handles[j];
>  			status = acpi_bus_get_device(handle, &dev);
> -			if (ACPI_SUCCESS(status) && (dev == device)) {
> -				result = action(thermal, trip, cdev);
> -				if (result)
> -					goto failed;
> -			}
> +			if (ACPI_FAILURE(status) || dev != device)
> +				continue;
> +			if (bind)
> +				result = thermal_zone_bind_cooling_device
> +					(thermal, trip, cdev, -1, -1);
> +			else
> +				result = thermal_zone_unbind_cooling_device
> +					(thermal, trip, cdev);
> +			if (result)
> +				goto failed;
>  		}
>  	}
>  
> @@ -784,7 +794,12 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
>  		handle = tz->devices.handles[i];
>  		status = acpi_bus_get_device(handle, &dev);
>  		if (ACPI_SUCCESS(status) && (dev == device)) {
> -			result = action(thermal, -1, cdev);
> +			if (bind)
> +				result = thermal_zone_bind_cooling_device
> +						(thermal, -1, cdev, -1, -1);
> +			else
> +				result = thermal_zone_unbind_cooling_device
> +						(thermal, -1, cdev);
>  			if (result)
>  				goto failed;
>  		}
> @@ -798,16 +813,14 @@ static int
>  acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
>  					struct thermal_cooling_device *cdev)
>  {
> -	return acpi_thermal_cooling_device_cb(thermal, cdev,
> -				thermal_zone_bind_cooling_device);
> +	return acpi_thermal_cooling_device_cb(thermal, cdev, 1);
>  }
>  
>  static int
>  acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
>  					struct thermal_cooling_device *cdev)
>  {
> -	return acpi_thermal_cooling_device_cb(thermal, cdev,
> -				thermal_zone_unbind_cooling_device);
> +	return acpi_thermal_cooling_device_cb(thermal, cdev, 0);
>  }
>  
>  static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
> diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
> index 39abb15..278aa0e 100644
> --- a/drivers/platform/x86/acerhdf.c
> +++ b/drivers/platform/x86/acerhdf.c
> @@ -329,7 +329,7 @@ static int acerhdf_bind(struct thermal_zone_device *thermal,
>  	if (cdev != cl_dev)
>  		return 0;
>  
> -	if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) {
> +	if (thermal_zone_bind_cooling_device(thermal, 0, cdev, -1, -1)) {
>  		pr_err("error binding cooling dev\n");
>  		return -EINVAL;
>  	}
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 4267a49..db35300 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -316,7 +316,7 @@ passive_store(struct device *dev, struct device_attribute *attr,
>  				     sizeof("Processor")))
>  				thermal_zone_bind_cooling_device(tz,
>  								 THERMAL_TRIPS_NONE,
> -								 cdev);
> +								 cdev, -1, -1);
>  		}
>  		mutex_unlock(&thermal_list_lock);
>  		if (!tz->passive_delay)
> @@ -801,7 +801,8 @@ static void thermal_zone_device_check(struct work_struct *work)
>   */
>  int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  				     int trip,
> -				     struct thermal_cooling_device *cdev)
> +				     struct thermal_cooling_device *cdev,
> +				     long upper, long lower)

upper and lower were unsigned long in the previous patch.  Can we please
use the same data type for them everywhere?

>  {
>  	struct thermal_cooling_device_instance *dev;
>  	struct thermal_cooling_device_instance *pos;
> @@ -825,6 +826,15 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  	if (tz != pos1 || cdev != pos2)
>  		return -EINVAL;
>  
> +	cdev->ops->get_max_state(cdev, &max_state);
> +
> +	/* lower default 0, upper default max_state */
> +	lower = lower < 0 ? 0 : lower;
> +	upper = upper < 0 ? max_state : upper;
> +
> +	if (lower > upper || upper > max_state)
> +		return -EINVAL;
> +
>  	dev =
>  	    kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
>  	if (!dev)
> @@ -832,10 +842,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  	dev->tz = tz;
>  	dev->cdev = cdev;
>  	dev->trip = trip;
> -
> -	cdev->ops->get_max_state(dev, &max_state);
> -	dev->upper = max_state;
> -	dev->lower = 0;
> +	dev->upper = upper;
> +	dev->lower = lower;
>  
>  	result = get_idr(&tz->idr, &tz->lock, &dev->id);
>  	if (result)
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index cfc8d90..b355c62 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -157,7 +157,8 @@ struct thermal_zone_device *thermal_zone_device_register(char *, int, int,
>  void thermal_zone_device_unregister(struct thermal_zone_device *);
>  
>  int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
> -				     struct thermal_cooling_device *);
> +				     struct thermal_cooling_device *,
> +				     long, long);
>  int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
>  				       struct thermal_cooling_device *);
>  void thermal_zone_device_update(struct thermal_zone_device *);
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-19  6:31 ` [PATCH 07/16] Thermal: Introduce .get_trend() callback Zhang Rui
@ 2012-07-19 21:13   ` Rafael J. Wysocki
  2012-07-24  1:42     ` Zhang Rui
  2012-07-19 22:09   ` Jacob Pan
  1 sibling, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:13 UTC (permalink / raw)
  To: Zhang Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> But they are ACPI platform specific concepts.
> 
> Introduce .get_trend() as a more general solution.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
>  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
>  include/linux/thermal.h       |    9 +++++++++
>  3 files changed, 56 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index a7c97f5..b345646 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
>  		return -EINVAL;
>  }
>  
> +static int thermal_get_trend(struct thermal_zone_device *thermal,
> +				int trip, enum thermal_trend *trend)
> +{
> +	struct acpi_thermal *tz = thermal->devdata;
> +	enum thermal_trip_type type;
> +	unsigned long trip_temp;
> +	int i;
> +
> +	if (thermal_get_trip_type(thermal, trip, &type))
> +		return -EINVAL;
> +
> +	/* Only PASSIVE trip points need TREND */
> +	if (type != THERMAL_TRIP_PASSIVE)
> +		return -EINVAL;
> +
> +	/*
> +	 * tz->temperature has already been updated by generic thermal layer,
> +	 * before this callback being invoked
> +	 */
> +	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> +		+ (tz->trips.passive.tc2
> +		* (tz->temperature - tz->trips.passive.temperature));
> +
> +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> +		(i < 0 ? THERMAL_TREND_DROPPING : THERMAL_TREND_STABLE);

I'd use if (...) / else if (...) / else here.  It would be _way_ more readable.

> +	return 0;
> +}
> +
> +
>  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
>  			   enum thermal_trip_type trip_type)
>  {
> @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
>  	.get_trip_type = thermal_get_trip_type,
>  	.get_trip_temp = thermal_get_trip_temp,
>  	.get_crit_temp = thermal_get_crit_temp,
> +	.get_trend = thermal_get_trend,
>  	.notify = thermal_notify,
>  };
>  
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index db35300..29b6dba 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
>  }
>  #endif
>  
> +static void thermal_get_trend(struct thermal_zone_device *tz,
> +		int trip, enum thermal_trend *trend)

The fact that this function has the same name as the ACPI one above is kind of
disturbing.  Any chance to call it differently?

> +{
> +	if (tz->ops->get_trend)
> +		if (!tz->ops->get_trend(tz, trip, trend))
> +			return;

What about:

+	if (tz->ops->get_trend && !tz->ops->get_trend(tz, trip, trend))
+		return;

And since the error code returned by .get_trend() apparently doesn't matter,
shouldn't it return a bool?

> +
> +	*trend = tz->temperature >= tz->last_temperature ?
> +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
> +	return;
> +}
> +
>  static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
>  					    int delay)
>  {
> @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>  	if (temp >= trip_temp) {
>  		tz->passive = true;
>  
> +		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);

What's wrong with the data type of 'trend' here?

> +
>  		trend = (tz->tc1 * (temp - tz->last_temperature)) +
>  			(tz->tc2 * (temp - trip_temp));
>  
> @@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  		goto leave;
>  	}
>  
> +	tz->last_temperature = tz->temperature;
> +	tz->temperature = temp;
> +
>  	for (count = 0; count < tz->trips; count++) {
>  		tz->ops->get_trip_type(tz, count, &trip_type);
>  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> @@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  		thermal_zone_device_passive(tz, temp, tz->forced_passive,
>  					    THERMAL_TRIPS_NONE);
>  
> -	tz->last_temperature = temp;
> -

I'm not sure if this is correct.  It seems to change the behavior of
thermal_zone_device_passive() in a subtle way, but I'm not sure that really
matters.  Does it?

>  leave:
>  	if (tz->passive)
>  		thermal_zone_device_set_polling(tz, tz->passive_delay);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index b355c62..ab656d6 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -44,6 +44,12 @@ enum thermal_trip_type {
>  	THERMAL_TRIP_CRITICAL,
>  };
>  
> +enum thermal_trend {
> +	THERMAL_TREND_STABLE, /* temperature is stable */
> +	THERMAL_TREND_RAISING, /* temperature is raising */
> +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> +};
> +
>  struct thermal_zone_device_ops {
>  	int (*bind) (struct thermal_zone_device *,
>  		     struct thermal_cooling_device *);
> @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
>  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
>  			      unsigned long);
>  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
> +	int (*get_trend) (struct thermal_zone_device *, int,
> +			  enum thermal_trend *);
>  	int (*notify) (struct thermal_zone_device *, int,
>  		       enum thermal_trip_type);
>  };
> @@ -109,6 +117,7 @@ struct thermal_zone_device {
>  	int tc2;
>  	int passive_delay;
>  	int polling_delay;
> +	int temperature;
>  	int last_temperature;
>  	bool passive;
>  	unsigned int forced_passive;
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-19  6:31 ` [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update() Zhang Rui
@ 2012-07-19 21:19   ` Rafael J. Wysocki
  2012-07-24  1:47     ` Zhang Rui
       [not found]   ` <CAK44p21hNYGH4YkH5E+XK-pM2upingQbvm77WkJbttCRp6ZamQ@mail.gmail.com>
  2012-07-24  7:57   ` Amit Kachhap
  2 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:19 UTC (permalink / raw)
  To: Zhang Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> This function is used to update the cooling state of
> all the cooling devices that are binded to an active trip point.

s/binded/bound/

> This will be used for passive cooling as well, in the future patches.
> as both active and passive cooling can share the same algorithm,
> which is
> 
> 1. if the temperature is higher than a trip point,
>    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
>       state for this trip point
>    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
>       state for this trip point
> 
> 2. if the temperature is lower than a trip point, use lower
>    cooling state for this trip point.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/acpi/thermal.c        |    7 +++-
>  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
>  2 files changed, 71 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 73e335f..14c4879 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
>  	if (thermal_get_trip_type(thermal, trip, &type))
>  		return -EINVAL;
>  
> -	/* Only PASSIVE trip points need TREND */
> +	if (type == THERMAL_TRIP_ACTIVE) {
> +		/* aggressive active cooling */
> +		*trend = THERMAL_TREND_RAISING;
> +		return 0;

Please move that into thermal_zone_trip_update() directly, unless you
need it elsewhere.

> +	}
> +
>  	if (type != THERMAL_TRIP_PASSIVE)
>  		return -EINVAL;
>  
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 59af3b8..011faba 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -1076,6 +1076,70 @@ void thermal_cooling_device_unregister(struct
>  }
>  EXPORT_SYMBOL(thermal_cooling_device_unregister);
>  
> +/*
> + * Cooling algorithm for active trip points
> + *
> + * 1. if the temperature is higher than a trip point,
> + *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> + *       state for this trip point
> + *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> + *       state for this trip point
> + *
> + * 2. if the temperature is lower than a trip point, use lower
> + *    cooling state for this trip point
> + *
> + * Note that this behaves the same as the previous passive cooling
> + * algorithm.
> + */
> +
> +static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> +				     int trip, long temp)
> +{
> +	struct thermal_cooling_device_instance *instance;
> +	struct thermal_cooling_device *cdev = NULL;
> +	unsigned long cur_state, max_state;
> +	long trip_temp;
> +	enum thermal_trend trend;
> +
> +	tz->ops->get_trip_temp(tz, trip, &trip_temp);
> +
> +	if (temp >= trip_temp) {
> +		thermal_get_trend(tz, trip, &trend);
> +
> +		list_for_each_entry(instance, &tz->cooling_devices, node) {
> +			if (instance->trip != trip)
> +				continue;
> +
> +			cdev = instance->cdev;
> +
> +			cdev->ops->get_cur_state(cdev, &cur_state);
> +			cdev->ops->get_max_state(cdev, &max_state);
> +
> +			if (trend == THERMAL_TREND_RAISING) {
> +				cur_state = cur_state < instance->upper ?
> +					    (cur_state + 1) : instance->upper;
> +			} else if (trend == THERMAL_TREND_DROPPING) {
> +				cur_state = cur_state > instance->lower ?
> +				    (cur_state - 1) : instance->lower;
> +			}
> +			cdev->ops->set_cur_state(cdev, cur_state);
> +		}
> +	} else {	/* below trip */
> +		list_for_each_entry(instance, &tz->cooling_devices, node) {
> +			if (instance->trip != trip)
> +				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);
> +		}
> +	}
> +
> +	return;
> +}
>  /**
>   * thermal_zone_device_update - force an update of a thermal zone's state
>   * @ttz:	the thermal zone to update
> @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  	int count, ret = 0;
>  	long temp, trip_temp;
>  	enum thermal_trip_type trip_type;
> -	struct thermal_cooling_device_instance *instance;
> -	struct thermal_cooling_device *cdev;
> -	unsigned long cur_state, max_state;
>  
>  	mutex_lock(&tz->lock);
>  
> @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  					tz->ops->notify(tz, count, trip_type);
>  			break;
>  		case THERMAL_TRIP_ACTIVE:
> -			list_for_each_entry(instance, &tz->cooling_devices,
> -					    node) {
> -				if (instance->trip != count)
> -					continue;
> -
> -				cdev = instance->cdev;
> -
> -				cdev->ops->get_cur_state(cdev, &cur_state);
> -				cdev->ops->get_max_state(cdev, &max_state);
> -
> -				if (temp >= trip_temp)
> -					cur_state =
> -						cur_state < instance->upper ?
> -						(cur_state + 1) :
> -						instance->upper;
> -				else
> -					cur_state =
> -						cur_state > instance->lower ?
> -						(cur_state - 1) :
> -						instance->lower;
> -
> -				cdev->ops->set_cur_state(cdev, cur_state);
> -			}
> +			thermal_zone_trip_update(tz, count, temp);
>  			break;
>  		case THERMAL_TRIP_PASSIVE:
>  			if (temp >= trip_temp || tz->passive)
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances
  2012-07-19  6:31 ` [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances Zhang Rui
@ 2012-07-19 21:22   ` Rafael J. Wysocki
  2012-07-24  1:48     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:22 UTC (permalink / raw)
  To: Zhang Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> thermal_zone_device.cooling_devices is not accurate
> as this is a list for thermal instances, rather than cooling devices.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/thermal/thermal_sys.c |   18 +++++++++---------
>  include/linux/thermal.h       |    4 ++--
>  2 files changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 867fced..1836039 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -745,7 +745,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>  
>  		/* Heating up? */
>  		if (trend > 0) {
> -			list_for_each_entry(instance, &tz->cooling_devices,
> +			list_for_each_entry(instance, &tz->instances,
>  					    node) {
>  				if (instance->trip != trip)
>  					continue;
> @@ -756,7 +756,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>  					cdev->ops->set_cur_state(cdev, state);
>  			}
>  		} else if (trend < 0) { /* Cooling off? */
> -			list_for_each_entry(instance, &tz->cooling_devices,
> +			list_for_each_entry(instance, &tz->instances,
>  					    node) {
>  				if (instance->trip != trip)
>  					continue;
> @@ -777,7 +777,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>  	 * and avoid thrashing around the passive trip point.  Note that we
>  	 * assume symmetry.
>  	 */
> -	list_for_each_entry(instance, &tz->cooling_devices, node) {
> +	list_for_each_entry(instance, &tz->instances, node) {
>  		if (instance->trip != trip)
>  			continue;
>  		cdev = instance->cdev;
> @@ -873,13 +873,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  		goto remove_symbol_link;
>  
>  	mutex_lock(&tz->lock);
> -	list_for_each_entry(pos, &tz->cooling_devices, node)
> +	list_for_each_entry(pos, &tz->instances, node)
>  	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
>  		result = -EEXIST;
>  		break;
>  	}
>  	if (!result)
> -		list_add_tail(&dev->node, &tz->cooling_devices);
> +		list_add_tail(&dev->node, &tz->instances);
>  	mutex_unlock(&tz->lock);
>  
>  	if (!result)
> @@ -912,7 +912,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
>  	struct thermal_instance *pos, *next;
>  
>  	mutex_lock(&tz->lock);
> -	list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
> +	list_for_each_entry_safe(pos, next, &tz->instances, node) {
>  		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
>  			list_del(&pos->node);
>  			mutex_unlock(&tz->lock);
> @@ -1106,7 +1106,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
>  	if (temp >= trip_temp) {
>  		thermal_get_trend(tz, trip, &trend);
>  
> -		list_for_each_entry(instance, &tz->cooling_devices, node) {
> +		list_for_each_entry(instance, &tz->instances, node) {
>  			if (instance->trip != trip)
>  				continue;
>  
> @@ -1125,7 +1125,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
>  			cdev->ops->set_cur_state(cdev, cur_state);
>  		}
>  	} else {	/* below trip */
> -		list_for_each_entry(instance, &tz->cooling_devices, node) {
> +		list_for_each_entry(instance, &tz->instances, node) {
>  			if (instance->trip != trip)
>  				continue;
>  
> @@ -1359,7 +1359,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
>  	if (!tz)
>  		return ERR_PTR(-ENOMEM);
>  
> -	INIT_LIST_HEAD(&tz->cooling_devices);
> +	INIT_LIST_HEAD(&tz->instances);
>  	idr_init(&tz->idr);
>  	mutex_init(&tz->lock);
>  	result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 44d7fc3..a15b83c 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -120,9 +120,9 @@ struct thermal_zone_device {
>  	bool passive;
>  	unsigned int forced_passive;
>  	const struct thermal_zone_device_ops *ops;
> -	struct list_head cooling_devices;
> +	struct list_head instances;

What about calling that 'thermal_instances'?  As is, it isn't really obvious
the instances of what exactly they are.

>  	struct idr idr;
> -	struct mutex lock;	/* protect cooling devices list */
> +	struct mutex lock;	/* protect instances list */
>  	struct list_head node;
>  	struct delayed_work poll_queue;
>  };
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device.
  2012-07-19  6:31 ` [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device Zhang Rui
@ 2012-07-19 21:25   ` Rafael J. Wysocki
  2012-07-24  1:48     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:25 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> so that cooling device can know the cooling state requirement
> of all the thermal instances.

The changelog looks odd in this form.  Please start the sentence in a sensible
way.

> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/thermal/thermal_sys.c |    7 ++++++-
>  include/linux/thermal.h       |    1 +
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 5a5f916..48b2668 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -57,6 +57,7 @@ struct thermal_instance {
>  	char attr_name[THERMAL_NAME_LENGTH];
>  	struct device_attribute attr;
>  	struct list_head tz_node; /* node in tz->instances */
> +	struct list_head cdev_node; /* node in cdev->instances */
>  };
>  
>  static DEFINE_IDR(thermal_tz_idr);
> @@ -878,8 +879,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  		result = -EEXIST;
>  		break;
>  	}
> -	if (!result)
> +	if (!result) {
>  		list_add_tail(&dev->tz_node, &tz->instances);
> +		list_add_tail(&dev->cdev_node, &cdev->instances);
> +	}
>  	mutex_unlock(&tz->lock);
>  
>  	if (!result)
> @@ -915,6 +918,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
>  	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
>  		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
>  			list_del(&pos->tz_node);
> +			list_del(&pos->cdev_node);
>  			mutex_unlock(&tz->lock);
>  			goto unbind;
>  		}
> @@ -984,6 +988,7 @@ thermal_cooling_device_register(char *type, void *devdata,
>  	}
>  
>  	strcpy(cdev->type, type);
> +	INIT_LIST_HEAD(&cdev->instances);
>  	cdev->ops = ops;
>  	cdev->device.class = &thermal_class;
>  	cdev->devdata = devdata;
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index a15b83c..d8e069e 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -92,6 +92,7 @@ struct thermal_cooling_device {
>  	struct device device;
>  	void *devdata;
>  	const struct thermal_cooling_device_ops *ops;
> +	struct list_head instances;
>  	struct list_head node;
>  };
>  
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state
  2012-07-19  6:31 ` [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state Zhang Rui
@ 2012-07-19 21:39   ` Rafael J. Wysocki
  2012-07-24  1:49     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:39 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> 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>
> ---
>  drivers/thermal/thermal_sys.c |   41 ++++++++++++++++++++++++++++++++++++++---
>  include/linux/thermal.h       |    1 +
>  2 files changed, 39 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 48b2668..803ce94 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -54,6 +54,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->instances */
> @@ -853,6 +854,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  	dev->trip = trip;
>  	dev->upper = upper;
>  	dev->lower = lower;
> +	dev->target = -1;

Please define THERMAL_NO_TARGET and use that instead of plain -1.

>  
>  	result = get_idr(&tz->idr, &tz->lock, &dev->id);
>  	if (result)
> @@ -990,6 +992,7 @@ thermal_cooling_device_register(char *type, void *devdata,
>  	strcpy(cdev->type, type);
>  	INIT_LIST_HEAD(&cdev->instances);
>  	cdev->ops = ops;
> +	cdev->updated = 1;
>  	cdev->device.class = &thermal_class;
>  	cdev->devdata = devdata;
>  	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
> @@ -1081,6 +1084,32 @@ void thermal_cooling_device_unregister(struct
>  }
>  EXPORT_SYMBOL(thermal_cooling_device_unregister);
>  
> +static void thermal_zone_do_update(struct thermal_zone_device *tz)
> +{
> +	struct thermal_instance *instance1, *instance2;
> +	struct thermal_cooling_device *cdev;
> +	int target;

The 'target' field in the structure is unsigned long.  It'd be better to use
the same data type here.

It would be good to use 'true' and 'false' as the values of 'updated' too.

> +
> +	list_for_each_entry(instance1, &tz->instances, tz_node) {
> +		cdev = instance1->cdev;
> +
> +		/* cooling device has already been updated*/
> +		if (cdev->updated)
> +			continue;
> +
> +		target = 0;
> +		/* Make sure cdev enters the deepest cooling state */
> +		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
> +			if (instance2->target == -1)
> +				continue;
> +			if (instance2->target > target)
> +				target = instance2->target;
> +		}
> +		cdev->ops->set_cur_state(cdev, target);
> +		cdev->updated = 1;
> +	}
> +}

I would split the function above into two, one that would walk all
instances of the thermal zone and the other, that would walk the
instances for a given device.  It would look much cleaner, then.

> +
>  /*
>   * Cooling algorithm for active trip points
>   *
> @@ -1127,19 +1156,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 = 0; /* cooling device needs update */
>  		}
>  	} else {	/* below trip */
>  		list_for_each_entry(instance, &tz->instances, tz_node) {
>  			if (instance->trip != trip)
>  				continue;
>  
> +			/* Do not use the deacitve thermal instance */
> +			if (instance->target == -1)
> +				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) : -1;
> +			instance->target = cur_state;
> +			cdev->updated = 0; /* cooling device needs update */
>  		}
>  	}
>  
> @@ -1200,6 +1234,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 d8e069e..604c0f0 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -92,6 +92,7 @@ struct thermal_cooling_device {
>  	struct device device;
>  	void *devdata;
>  	const struct thermal_cooling_device_ops *ops;
> +	int updated; /* 1 if the cooling device does not need update */

+	bool updated;

>  	struct list_head instances;
>  	struct list_head node;
>  };
> 

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/16] Thermal: use plist instead of list
  2012-07-19  6:31 ` [PATCH 16/16] Thermal: use plist instead of list Zhang Rui
@ 2012-07-19 21:45   ` Rafael J. Wysocki
  2012-07-24  2:13     ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-19 21:45 UTC (permalink / raw)
  To: Zhang Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss, Wei Ni

On Thursday, July 19, 2012, Zhang Rui wrote:
> so that the thermal manager can easily find out
> the deepest cooling state request for a cooling device.
> 
> cdev->lock is also introduced in this patch to protect this plist.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>

I'm not sure if this is actually better than without the plist.

The plist manipulations in thermal_zone_trip_update() look like they
can add quite some overhead in some situations.

Do you have any quantitative justification for this change?

Rafael


> ---
>  drivers/thermal/thermal_sys.c |   84 ++++++++++++++++++++++++++---------------
>  include/linux/thermal.h       |    4 +-
>  2 files changed, 57 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index a40dda1..9f56250 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -54,11 +54,10 @@ 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->instances */
> -	struct list_head cdev_node; /* node in cdev->instances */
> +	struct plist_node cdev_node; /* node in cdev->instances */
>  };
>  
>  static DEFINE_IDR(thermal_tz_idr);
> @@ -787,7 +786,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  	dev->trip = trip;
>  	dev->upper = upper;
>  	dev->lower = lower;
> -	dev->target = -1;
> +	plist_node_init(&dev->cdev_node, -1);
>  
>  	result = get_idr(&tz->idr, &tz->lock, &dev->id);
>  	if (result)
> @@ -809,6 +808,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  		goto remove_symbol_link;
>  
>  	mutex_lock(&tz->lock);
> +	mutex_lock(&cdev->lock);
>  	list_for_each_entry(pos, &tz->instances, tz_node)
>  	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
>  		result = -EEXIST;
> @@ -816,8 +816,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
>  	}
>  	if (!result) {
>  		list_add_tail(&dev->tz_node, &tz->instances);
> -		list_add_tail(&dev->cdev_node, &cdev->instances);
> +		plist_add(&dev->cdev_node, &cdev->instances);
>  	}
> +	mutex_unlock(&cdev->lock);
>  	mutex_unlock(&tz->lock);
>  
>  	if (!result)
> @@ -850,14 +851,17 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
>  	struct thermal_instance *pos, *next;
>  
>  	mutex_lock(&tz->lock);
> +	mutex_lock(&cdev->lock);
>  	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
>  		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
>  			list_del(&pos->tz_node);
> -			list_del(&pos->cdev_node);
> +			plist_del(&pos->cdev_node, &pos->cdev->instances);
> +			mutex_unlock(&cdev->lock);
>  			mutex_unlock(&tz->lock);
>  			goto unbind;
>  		}
>  	}
> +	mutex_unlock(&cdev->lock);
>  	mutex_unlock(&tz->lock);
>  
>  	return -ENODEV;
> @@ -923,7 +927,8 @@ thermal_cooling_device_register(char *type, void *devdata,
>  	}
>  
>  	strcpy(cdev->type, type);
> -	INIT_LIST_HEAD(&cdev->instances);
> +	plist_head_init(&cdev->instances);
> +	mutex_init(&cdev->lock);
>  	cdev->ops = ops;
>  	cdev->updated = 1;
>  	cdev->device.class = &thermal_class;
> @@ -1019,26 +1024,21 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
>  
>  static void thermal_zone_do_update(struct thermal_zone_device *tz)
>  {
> -	struct thermal_instance *instance1, *instance2;
> +	struct thermal_instance *instance;
> +	struct plist_node *node;
>  	struct thermal_cooling_device *cdev;
> -	int target;
>  
> -	list_for_each_entry(instance1, &tz->instances, tz_node) {
> -		cdev = instance1->cdev;
> +	list_for_each_entry(instance, &tz->instances, tz_node) {
> +		cdev = instance->cdev;
>  
>  		/* cooling device has already been updated*/
>  		if (cdev->updated)
>  			continue;
>  
> -		target = 0;
> -		/* Make sure cdev enters the deepest cooling state */
> -		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
> -			if (instance2->target == -1)
> -				continue;
> -			if (instance2->target > target)
> -				target = instance2->target;
> -		}
> -		cdev->ops->set_cur_state(cdev, target);
> +		/* Deepest cooling state required */
> +		node = plist_last(&cdev->instances);
> +
> +		cdev->ops->set_cur_state(cdev, node->prio < 0 ? 0 : node->prio);
>  		cdev->updated = 1;
>  	}
>  }
> @@ -1064,7 +1064,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
>  {
>  	struct thermal_instance *instance;
>  	struct thermal_cooling_device *cdev = NULL;
> -	unsigned long cur_state, max_state;
> +	unsigned long cur_state, max_state, target_state;
>  	long trip_temp;
>  	enum thermal_trip_type trip_type;
>  	enum thermal_trend trend;
> @@ -1088,21 +1088,29 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
>  
>  			cdev->ops->get_cur_state(cdev, &cur_state);
>  			cdev->ops->get_max_state(cdev, &max_state);
> -
> +			target_state = cur_state;
>  			if (trend == THERMAL_TREND_RAISING) {
> -				cur_state = cur_state < instance->upper ?
> +				target_state = cur_state < instance->upper ?
>  					    (cur_state + 1) : instance->upper;
>  			} else if (trend == THERMAL_TREND_DROPPING) {
> -				cur_state = cur_state > instance->lower ?
> +				target_state = cur_state > instance->lower ?
>  				    (cur_state - 1) : instance->lower;
>  			}
>  
> +			if (target_state == cur_state)
> +				continue;
> +
>  			/* activate a passive thermal instance */
>  			if (trip_type == THERMAL_TRIP_PASSIVE &&
> -			    instance->target == -1)
> +			    instance->cdev_node.prio == -1)
>  				tz->passive++;
>  
> -			instance->target = cur_state;
> +			mutex_lock(&cdev->lock);
> +			plist_del(&instance->cdev_node, &cdev->instances);
> +			plist_node_init(&instance->cdev_node, target_state);
> +			plist_add(&instance->cdev_node, &cdev->instances);
> +			mutex_unlock(&cdev->lock);
> +
>  			cdev->updated = 0; /* cooling device needs update */
>  		}
>  	} else {	/* below trip */
> @@ -1111,20 +1119,36 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
>  				continue;
>  
>  			/* Do not use the deacitve thermal instance */
> -			if (instance->target == -1)
> +			if (instance->cdev_node.prio == -1)
>  				continue;
>  			cdev = instance->cdev;
>  			cdev->ops->get_cur_state(cdev, &cur_state);
>  
> -			cur_state = cur_state > instance->lower ?
> +			target_state = cur_state > instance->lower ?
>  				    (cur_state - 1) : -1;
>  
> +			if (target_state == cur_state)
> +				continue;
> +
>  			/* deactivate a passive thermal instance */
>  			if (trip_type == THERMAL_TRIP_PASSIVE &&
> -			    cur_state == -1)
> +			    target_state == -1)
>  				tz->passive--;
> -			instance->target = cur_state;
> -			cdev->updated = 0; /* cooling device needs update */
> +
> +			mutex_lock(&cdev->lock);
> +			plist_del(&instance->cdev_node, &cdev->instances);
> +			plist_node_init(&instance->cdev_node, target_state);
> +			plist_add(&instance->cdev_node, &cdev->instances);
> +			mutex_unlock(&cdev->lock);
> +
> +			/*
> +			 * cooling device needs update.
> +			 * But if the target_state is -1, it means that
> +			 * the cooling device is already in cooling state 0,
> +			 * thus we do not need update
> +			 */
> +			if (target_state != -1)
> +				cdev->updated = 0;
>  		}
>  	}
>  
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index f725eb9..376a59e 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -28,6 +28,7 @@
>  #include <linux/idr.h>
>  #include <linux/device.h>
>  #include <linux/workqueue.h>
> +#include <linux/plist.h>
>  
>  struct thermal_zone_device;
>  struct thermal_cooling_device;
> @@ -93,7 +94,8 @@ struct thermal_cooling_device {
>  	void *devdata;
>  	const struct thermal_cooling_device_ops *ops;
>  	int updated; /* 1 if the cooling device does not need update */
> -	struct list_head instances;
> +	struct mutex lock;
> +	struct plist_head instances;
>  	struct list_head node;
>  };
>  
> 


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-19  6:31 ` [PATCH 07/16] Thermal: Introduce .get_trend() callback Zhang Rui
  2012-07-19 21:13   ` Rafael J. Wysocki
@ 2012-07-19 22:09   ` Jacob Pan
  2012-07-20  9:53     ` Rafael J. Wysocki
  1 sibling, 1 reply; 56+ messages in thread
From: Jacob Pan @ 2012-07-19 22:09 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, R Durgadoss, Eduardo Valentin, Amit Kachhap, Wei Ni

On Thu, 19 Jul 2012 14:31:11 +0800
Zhang Rui <rui.zhang@intel.com> wrote:

> tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> But they are ACPI platform specific concepts.
> 
> Introduce .get_trend() as a more general solution.
> 
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
>  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
>  include/linux/thermal.h       |    9 +++++++++
>  3 files changed, 56 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index a7c97f5..b345646 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct
> thermal_zone_device *thermal, return -EINVAL;
>  }
>  
> +static int thermal_get_trend(struct thermal_zone_device *thermal,
> +				int trip, enum thermal_trend *trend)
> +{
> +	struct acpi_thermal *tz = thermal->devdata;
> +	enum thermal_trip_type type;
> +	unsigned long trip_temp;
> +	int i;
> +
> +	if (thermal_get_trip_type(thermal, trip, &type))
> +		return -EINVAL;
> +
> +	/* Only PASSIVE trip points need TREND */
> +	if (type != THERMAL_TRIP_PASSIVE)
> +		return -EINVAL;
> +
> +	/*
> +	 * tz->temperature has already been updated by generic
> thermal layer,
> +	 * before this callback being invoked
> +	 */
> +	i = (tz->trips.passive.tc1 * (tz->temperature -
> tz->last_temperature))
> +		+ (tz->trips.passive.tc2
> +		* (tz->temperature - tz->trips.passive.temperature));
> +
> +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> +		(i < 0 ? THERMAL_TREND_DROPPING :
> THERMAL_TREND_STABLE);
> +	return 0;
> +}
> +
> +
>  static int thermal_notify(struct thermal_zone_device *thermal, int
> trip, enum thermal_trip_type trip_type)
>  {
> @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops
> acpi_thermal_zone_ops = { .get_trip_type = thermal_get_trip_type,
>  	.get_trip_temp = thermal_get_trip_temp,
>  	.get_crit_temp = thermal_get_crit_temp,
> +	.get_trend = thermal_get_trend,
>  	.notify = thermal_notify,
>  };
>  
> diff --git a/drivers/thermal/thermal_sys.c
> b/drivers/thermal/thermal_sys.c index db35300..29b6dba 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct
> thermal_zone_device *tz) }
>  #endif
>  
> +static void thermal_get_trend(struct thermal_zone_device *tz,
> +		int trip, enum thermal_trend *trend)
> +{
> +	if (tz->ops->get_trend)
> +		if (!tz->ops->get_trend(tz, trip, trend))
> +			return;
> +
> +	*trend = tz->temperature >= tz->last_temperature ?
> +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
I think you are mixing things a little here. ACPI passive cooling
formula generates a performance trend to guide thermal management,
which is not a simple temperature trend.

In case of no .get_trend() present, caller can easily figure out
temperature trend explicitly instead of getting uninformed information.

> +	return;
> +}
> +
>  static void thermal_zone_device_set_polling(struct
> thermal_zone_device *tz, int delay)
>  {
> @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct
> thermal_zone_device *tz, if (temp >= trip_temp) {
>  		tz->passive = true;
>  
> +		thermal_get_trend(tz, trip, (enum thermal_trend
> *)&trend); +
>  		trend = (tz->tc1 * (temp - tz->last_temperature)) +
>  			(tz->tc2 * (temp - trip_temp));
>  
> @@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct
> thermal_zone_device *tz) goto leave;
>  	}
>  
> +	tz->last_temperature = tz->temperature;
> +	tz->temperature = temp;
> +
>  	for (count = 0; count < tz->trips; count++) {
>  		tz->ops->get_trip_type(tz, count, &trip_type);
>  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> @@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct
> thermal_zone_device *tz) thermal_zone_device_passive(tz, temp,
> tz->forced_passive, THERMAL_TRIPS_NONE);
>  
> -	tz->last_temperature = temp;
> -
>  leave:
>  	if (tz->passive)
>  		thermal_zone_device_set_polling(tz,
> tz->passive_delay); diff --git a/include/linux/thermal.h
> b/include/linux/thermal.h index b355c62..ab656d6 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -44,6 +44,12 @@ enum thermal_trip_type {
>  	THERMAL_TRIP_CRITICAL,
>  };
>  
> +enum thermal_trend {
> +	THERMAL_TREND_STABLE, /* temperature is stable */
> +	THERMAL_TREND_RAISING, /* temperature is raising */
> +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> +};
> +
>  struct thermal_zone_device_ops {
>  	int (*bind) (struct thermal_zone_device *,
>  		     struct thermal_cooling_device *);
> @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
>  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
>  			      unsigned long);
>  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned
> long *);
> +	int (*get_trend) (struct thermal_zone_device *, int,
> +			  enum thermal_trend *);
>  	int (*notify) (struct thermal_zone_device *, int,
>  		       enum thermal_trip_type);
>  };
> @@ -109,6 +117,7 @@ struct thermal_zone_device {
>  	int tc2;
>  	int passive_delay;
>  	int polling_delay;
> +	int temperature;
>  	int last_temperature;
>  	bool passive;
>  	unsigned int forced_passive;



-- 
Thanks,

Jacob

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-19 22:09   ` Jacob Pan
@ 2012-07-20  9:53     ` Rafael J. Wysocki
  2012-07-20 16:12       ` Jacob Pan
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-20  9:53 UTC (permalink / raw)
  To: Jacob Pan, Amit Kachhap
  Cc: Zhang Rui, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On Friday, July 20, 2012, Jacob Pan wrote:
> On Thu, 19 Jul 2012 14:31:11 +0800
> Zhang Rui <rui.zhang@intel.com> wrote:
> 
> > tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> > But they are ACPI platform specific concepts.
> > 
> > Introduce .get_trend() as a more general solution.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
> >  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
> >  include/linux/thermal.h       |    9 +++++++++
> >  3 files changed, 56 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > index a7c97f5..b345646 100644
> > --- a/drivers/acpi/thermal.c
> > +++ b/drivers/acpi/thermal.c
> > @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct
> > thermal_zone_device *thermal, return -EINVAL;
> >  }
> >  
> > +static int thermal_get_trend(struct thermal_zone_device *thermal,
> > +				int trip, enum thermal_trend *trend)
> > +{
> > +	struct acpi_thermal *tz = thermal->devdata;
> > +	enum thermal_trip_type type;
> > +	unsigned long trip_temp;
> > +	int i;
> > +
> > +	if (thermal_get_trip_type(thermal, trip, &type))
> > +		return -EINVAL;
> > +
> > +	/* Only PASSIVE trip points need TREND */
> > +	if (type != THERMAL_TRIP_PASSIVE)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * tz->temperature has already been updated by generic
> > thermal layer,
> > +	 * before this callback being invoked
> > +	 */
> > +	i = (tz->trips.passive.tc1 * (tz->temperature -
> > tz->last_temperature))
> > +		+ (tz->trips.passive.tc2
> > +		* (tz->temperature - tz->trips.passive.temperature));
> > +
> > +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> > +		(i < 0 ? THERMAL_TREND_DROPPING :
> > THERMAL_TREND_STABLE);
> > +	return 0;
> > +}
> > +
> > +
> >  static int thermal_notify(struct thermal_zone_device *thermal, int
> > trip, enum thermal_trip_type trip_type)
> >  {
> > @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops
> > acpi_thermal_zone_ops = { .get_trip_type = thermal_get_trip_type,
> >  	.get_trip_temp = thermal_get_trip_temp,
> >  	.get_crit_temp = thermal_get_crit_temp,
> > +	.get_trend = thermal_get_trend,
> >  	.notify = thermal_notify,
> >  };
> >  
> > diff --git a/drivers/thermal/thermal_sys.c
> > b/drivers/thermal/thermal_sys.c index db35300..29b6dba 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct
> > thermal_zone_device *tz) }
> >  #endif
> >  
> > +static void thermal_get_trend(struct thermal_zone_device *tz,
> > +		int trip, enum thermal_trend *trend)
> > +{
> > +	if (tz->ops->get_trend)
> > +		if (!tz->ops->get_trend(tz, trip, trend))
> > +			return;
> > +
> > +	*trend = tz->temperature >= tz->last_temperature ?
> > +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
> I think you are mixing things a little here. ACPI passive cooling
> formula generates a performance trend to guide thermal management,
> which is not a simple temperature trend.
> 
> In case of no .get_trend() present, caller can easily figure out
> temperature trend explicitly instead of getting uninformed information.

thermal_zone_device_passive() (below) is the caller and I don't think it
can really do that.

That said, since thermal_zone_device_passive() seems to me the only caller of
thermal_get_trend(), it might be better to move the code to that function
directly.

Thanks,
Rafael


> > +	return;
> > +}
> > +
> >  static void thermal_zone_device_set_polling(struct
> > thermal_zone_device *tz, int delay)
> >  {
> > @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct
> > thermal_zone_device *tz, if (temp >= trip_temp) {
> >  		tz->passive = true;
> >  
> > +		thermal_get_trend(tz, trip, (enum thermal_trend
> > *)&trend); +
> >  		trend = (tz->tc1 * (temp - tz->last_temperature)) +
> >  			(tz->tc2 * (temp - trip_temp));
> >  
> > @@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct
> > thermal_zone_device *tz) goto leave;
> >  	}
> >  
> > +	tz->last_temperature = tz->temperature;
> > +	tz->temperature = temp;
> > +
> >  	for (count = 0; count < tz->trips; count++) {
> >  		tz->ops->get_trip_type(tz, count, &trip_type);
> >  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> > @@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct
> > thermal_zone_device *tz) thermal_zone_device_passive(tz, temp,
> > tz->forced_passive, THERMAL_TRIPS_NONE);
> >  
> > -	tz->last_temperature = temp;
> > -
> >  leave:
> >  	if (tz->passive)
> >  		thermal_zone_device_set_polling(tz,
> > tz->passive_delay); diff --git a/include/linux/thermal.h
> > b/include/linux/thermal.h index b355c62..ab656d6 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -44,6 +44,12 @@ enum thermal_trip_type {
> >  	THERMAL_TRIP_CRITICAL,
> >  };
> >  
> > +enum thermal_trend {
> > +	THERMAL_TREND_STABLE, /* temperature is stable */
> > +	THERMAL_TREND_RAISING, /* temperature is raising */
> > +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> > +};
> > +
> >  struct thermal_zone_device_ops {
> >  	int (*bind) (struct thermal_zone_device *,
> >  		     struct thermal_cooling_device *);
> > @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
> >  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
> >  			      unsigned long);
> >  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned
> > long *);
> > +	int (*get_trend) (struct thermal_zone_device *, int,
> > +			  enum thermal_trend *);
> >  	int (*notify) (struct thermal_zone_device *, int,
> >  		       enum thermal_trip_type);
> >  };
> > @@ -109,6 +117,7 @@ struct thermal_zone_device {
> >  	int tc2;
> >  	int passive_delay;
> >  	int polling_delay;
> > +	int temperature;
> >  	int last_temperature;
> >  	bool passive;
> >  	unsigned int forced_passive;
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-20  9:53     ` Rafael J. Wysocki
@ 2012-07-20 16:12       ` Jacob Pan
  0 siblings, 0 replies; 56+ messages in thread
From: Jacob Pan @ 2012-07-20 16:12 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, Zhang Rui, linux-acpi, linux-pm, Matthew Garrett,
	Len Brown, R Durgadoss, Wei Ni

On Fri, 20 Jul 2012 11:53:41 +0200
"Rafael J. Wysocki" <rjw@sisk.pl> wrote:

> On Friday, July 20, 2012, Jacob Pan wrote:
> > On Thu, 19 Jul 2012 14:31:11 +0800
> > Zhang Rui <rui.zhang@intel.com> wrote:
> > 
> > > tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> > > But they are ACPI platform specific concepts.
> > > 
> > > Introduce .get_trend() as a more general solution.
> > > 
> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > ---
> > >  drivers/acpi/thermal.c        |   30
> > > ++++++++++++++++++++++++++++++ drivers/thermal/thermal_sys.c |
> > > 19 +++++++++++++++++-- include/linux/thermal.h       |    9
> > > +++++++++ 3 files changed, 56 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > index a7c97f5..b345646 100644
> > > --- a/drivers/acpi/thermal.c
> > > +++ b/drivers/acpi/thermal.c
> > > @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct
> > > thermal_zone_device *thermal, return -EINVAL;
> > >  }
> > >  
> > > +static int thermal_get_trend(struct thermal_zone_device *thermal,
> > > +				int trip, enum thermal_trend
> > > *trend) +{
> > > +	struct acpi_thermal *tz = thermal->devdata;
> > > +	enum thermal_trip_type type;
> > > +	unsigned long trip_temp;
> > > +	int i;
> > > +
> > > +	if (thermal_get_trip_type(thermal, trip, &type))
> > > +		return -EINVAL;
> > > +
> > > +	/* Only PASSIVE trip points need TREND */
> > > +	if (type != THERMAL_TRIP_PASSIVE)
> > > +		return -EINVAL;
> > > +
> > > +	/*
> > > +	 * tz->temperature has already been updated by generic
> > > thermal layer,
> > > +	 * before this callback being invoked
> > > +	 */
> > > +	i = (tz->trips.passive.tc1 * (tz->temperature -
> > > tz->last_temperature))
> > > +		+ (tz->trips.passive.tc2
> > > +		* (tz->temperature -
> > > tz->trips.passive.temperature)); +
> > > +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> > > +		(i < 0 ? THERMAL_TREND_DROPPING :
> > > THERMAL_TREND_STABLE);
> > > +	return 0;
> > > +}
> > > +
> > > +
> > >  static int thermal_notify(struct thermal_zone_device *thermal,
> > > int trip, enum thermal_trip_type trip_type)
> > >  {
> > > @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops
> > > acpi_thermal_zone_ops = { .get_trip_type = thermal_get_trip_type,
> > >  	.get_trip_temp = thermal_get_trip_temp,
> > >  	.get_crit_temp = thermal_get_crit_temp,
> > > +	.get_trend = thermal_get_trend,
> > >  	.notify = thermal_notify,
> > >  };
> > >  
> > > diff --git a/drivers/thermal/thermal_sys.c
> > > b/drivers/thermal/thermal_sys.c index db35300..29b6dba 100644
> > > --- a/drivers/thermal/thermal_sys.c
> > > +++ b/drivers/thermal/thermal_sys.c
> > > @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct
> > > thermal_zone_device *tz) }
> > >  #endif
> > >  
> > > +static void thermal_get_trend(struct thermal_zone_device *tz,
> > > +		int trip, enum thermal_trend *trend)
> > > +{
> > > +	if (tz->ops->get_trend)
> > > +		if (!tz->ops->get_trend(tz, trip, trend))
> > > +			return;
> > > +
> > > +	*trend = tz->temperature >= tz->last_temperature ?
> > > +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
> > I think you are mixing things a little here. ACPI passive cooling
> > formula generates a performance trend to guide thermal management,
> > which is not a simple temperature trend.
> > 
> > In case of no .get_trend() present, caller can easily figure out
> > temperature trend explicitly instead of getting uninformed
> > information.
> 
> thermal_zone_device_passive() (below) is the caller and I don't think
> it can really do that.
> 
perhaps i did not make it clear, i meant in case caller wants to know
the simple temperature trend, it can keep the last reading and
timestamp to figure out trend.

Going back to the original point, even though TC1 TC2 are ACPI specific
time constants but they represents a generic characteristic of the
platform thermal dynamics. These are useful for userspace or governors
to do thermal control in general. perhaps, we can generalize TCx
paramenters instead. i.e. allow a set of thermal constants exposed from
ACPI/BIOS and treat ACPI passive formular as a simple governor. In the
future, more constants can be added to have a better control logic.
e.g. I have written a PID controller (userspace) to manage passive
cooling, it shows better result than the ACPI passive formula in terms
of responsiveness, overshoot etc. In case of PID, we need three
constants which i have to tune manually at this point.

> That said, since thermal_zone_device_passive() seems to me the only
> caller of thermal_get_trend(), it might be better to move the code to
> that function directly.
> 
> Thanks,
> Rafael
> 
> 
> > > +	return;
> > > +}
> > > +
> > >  static void thermal_zone_device_set_polling(struct
> > > thermal_zone_device *tz, int delay)
> > >  {
> > > @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct
> > > thermal_zone_device *tz, if (temp >= trip_temp) {
> > >  		tz->passive = true;
> > >  
> > > +		thermal_get_trend(tz, trip, (enum thermal_trend
> > > *)&trend); +
> > >  		trend = (tz->tc1 * (temp -
> > > tz->last_temperature)) + (tz->tc2 * (temp - trip_temp));
> > >  
> > > @@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct
> > > thermal_zone_device *tz) goto leave;
> > >  	}
> > >  
> > > +	tz->last_temperature = tz->temperature;
> > > +	tz->temperature = temp;
> > > +
> > >  	for (count = 0; count < tz->trips; count++) {
> > >  		tz->ops->get_trip_type(tz, count, &trip_type);
> > >  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> > > @@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct
> > > thermal_zone_device *tz) thermal_zone_device_passive(tz, temp,
> > > tz->forced_passive, THERMAL_TRIPS_NONE);
> > >  
> > > -	tz->last_temperature = temp;
> > > -
> > >  leave:
> > >  	if (tz->passive)
> > >  		thermal_zone_device_set_polling(tz,
> > > tz->passive_delay); diff --git a/include/linux/thermal.h
> > > b/include/linux/thermal.h index b355c62..ab656d6 100644
> > > --- a/include/linux/thermal.h
> > > +++ b/include/linux/thermal.h
> > > @@ -44,6 +44,12 @@ enum thermal_trip_type {
> > >  	THERMAL_TRIP_CRITICAL,
> > >  };
> > >  
> > > +enum thermal_trend {
> > > +	THERMAL_TREND_STABLE, /* temperature is stable */
> > > +	THERMAL_TREND_RAISING, /* temperature is raising */
> > > +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> > > +};
> > > +
> > >  struct thermal_zone_device_ops {
> > >  	int (*bind) (struct thermal_zone_device *,
> > >  		     struct thermal_cooling_device *);
> > > @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
> > >  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
> > >  			      unsigned long);
> > >  	int (*get_crit_temp) (struct thermal_zone_device *,
> > > unsigned long *);
> > > +	int (*get_trend) (struct thermal_zone_device *, int,
> > > +			  enum thermal_trend *);
> > >  	int (*notify) (struct thermal_zone_device *, int,
> > >  		       enum thermal_trip_type);
> > >  };
> > > @@ -109,6 +117,7 @@ struct thermal_zone_device {
> > >  	int tc2;
> > >  	int passive_delay;
> > >  	int polling_delay;
> > > +	int temperature;
> > >  	int last_temperature;
> > >  	bool passive;
> > >  	unsigned int forced_passive;
> > 
> > 
> > 
> > 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi"
> in the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Thanks,

Jacob

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19 19:38   ` Rafael J. Wysocki
@ 2012-07-23  8:11     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-23  8:11 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

Hi, Rafael,

thanks for reviewing this patch set.

On 四, 2012-07-19 at 21:38 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > From: Durgadoss R <dugardoss.r@intel.com>
> > 
> > Some of the thermal drivers using the Generic Thermal Framework
> > require (all/some) trip points to be writeable. This patch makes
> > the trip point temperatures writeable on a per-trip point basis,
> > and modifies the required function call in thermal.c. This patch
> > also updates the Documentation to reflect the new change.
> > 
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  Documentation/thermal/sysfs-api.txt      |    4 +-
> >  drivers/acpi/thermal.c                   |    4 +-
> >  drivers/platform/x86/acerhdf.c           |    2 +-
> >  drivers/platform/x86/intel_mid_thermal.c |    2 +-
> >  drivers/thermal/spear_thermal.c          |    2 +-
> >  drivers/thermal/thermal_sys.c            |  147 +++++++++++++++++++++---------
> >  include/linux/thermal.h                  |   15 ++-
> >  7 files changed, 125 insertions(+), 51 deletions(-)
> > 
> > diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> > index 1733ab9..0c7c423 100644
> > --- a/Documentation/thermal/sysfs-api.txt
> > +++ b/Documentation/thermal/sysfs-api.txt
> > @@ -32,7 +32,8 @@ temperature) and throttle appropriate devices.
> >  
> >  1.1 thermal zone device interface
> >  1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name,
> > -		int trips, void *devdata, struct thermal_zone_device_ops *ops)
> > +		int trips, int flag, void *devdata,
> > +		struct thermal_zone_device_ops *ops)
> >  
> >      This interface function adds a new thermal zone device (sensor) to
> >      /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
> > @@ -40,6 +41,7 @@ temperature) and throttle appropriate devices.
> >  
> >      name: the thermal zone name.
> >      trips: the total number of trip points this thermal zone supports.
> > +    flag: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
> >      devdata: device private data
> >      ops: thermal zone device call-backs.
> >  	.bind: bind the thermal zone device with a thermal cooling device.
> 
> I wonder.  What is the maximum number of trip points currently passed to this
> function in one call?
> 
in include/linux/thermal.h
#define THERMAL_MAX_TRIPS 12

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-19 20:27   ` Rafael J. Wysocki
@ 2012-07-23  8:22     ` Zhang Rui
  2012-07-23 10:25       ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-23  8:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On 四, 2012-07-19 at 22:27 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > From: Durgadoss R <dugardoss.r@intel.com>
> > 
> > Some of the thermal drivers using the Generic Thermal Framework
> > require (all/some) trip points to be writeable. This patch makes
> > the trip point temperatures writeable on a per-trip point basis,
> > and modifies the required function call in thermal.c. This patch
> > also updates the Documentation to reflect the new change.
> > 
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  Documentation/thermal/sysfs-api.txt      |    4 +-
> >  drivers/acpi/thermal.c                   |    4 +-
> >  drivers/platform/x86/acerhdf.c           |    2 +-
> >  drivers/platform/x86/intel_mid_thermal.c |    2 +-
> >  drivers/thermal/spear_thermal.c          |    2 +-
> >  drivers/thermal/thermal_sys.c            |  147 +++++++++++++++++++++---------
> >  include/linux/thermal.h                  |   15 ++-
> >  7 files changed, 125 insertions(+), 51 deletions(-)
> > 
> > diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> > index 1733ab9..0c7c423 100644
> > --- a/Documentation/thermal/sysfs-api.txt
> > +++ b/Documentation/thermal/sysfs-api.txt
> > @@ -32,7 +32,8 @@ temperature) and throttle appropriate devices.
> >  
> >  1.1 thermal zone device interface
> >  1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name,
> > -		int trips, void *devdata, struct thermal_zone_device_ops *ops)
> > +		int trips, int flag, void *devdata,
> 
> The 'flags' argument should rather be called 'mask', or even 'writable_mask'.
> 
Agreed.

> >  #define to_cooling_device(_dev)	\
> >  	container_of(_dev, struct thermal_cooling_device, device)
> > @@ -1089,9 +1084,83 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> >  EXPORT_SYMBOL(thermal_zone_device_update);
> >  >  /**
> > + * create_trip_attrs - create attributes for trip points
> > + * @tz:		the thermal zone device
> > + * @flag:	Writeable trip point bitmap.
> > + */
> > +static int create_trip_attrs(struct thermal_zone_device *tz, int flag)
> > +{
> > +	int indx;
> > +	int writeable;
> > +
> > +	tz->trip_type_attrs =
> > +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> > +	if (!tz->trip_type_attrs)
> > +		return -ENOMEM;
> > +
> > +	tz->trip_temp_attrs =
> > +		kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
> > +	if (!tz->trip_temp_attrs) {
> > +		kfree(tz->trip_type_attrs);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	for (indx = 0; indx < tz->trips; indx++) {
> > +
> > +		/* create trip type attribute */
> > +		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
> > +			 "trip_point_%d_type", indx);
> 
> If this really truncates the name, we'll run into problems in _show() and _store().
> Is there any solution to that?
> 
as THERMAL_MAX_TRIP is smaller than 100, so the answer is no.

> > +
> > +		sysfs_attr_init(&tz->trip_type_attrs[count].attr.attr);
> > +		tz->trip_type_attrs[indx].attr.attr.name =
> > +						tz->trip_type_attrs[indx].name;
> > +		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
> > +		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
> > +
> > +		device_create_file(&tz->device,
> > +				   &tz->trip_type_attrs[indx].attr);
> > +
> > +		/* create trip temp attribute */
> > +		writeable = flag & (1 << indx);
> > +		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
> > +			 "trip_point_%d_temp", indx);
> > +
> > +		sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
> > +		tz->trip_temp_attrs[indx].attr.attr.name =
> > +						tz->trip_temp_attrs[indx].name;
> > +		tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
> > +		tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
> > +		if (writeable) {
> 
> Why don't you put the "flag & (1 << indx)" here directly instead of 'writable'?
> 
agreed.

> > +			tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
> > +			tz->trip_temp_attrs[indx].attr.store =
> > +							trip_point_temp_store;
> > +		}
> > +
> > +		device_create_file(&tz->device,
> > +				   &tz->trip_temp_attrs[indx].attr);
> > +	}
> > +	return 0;
> > +}
> > +
> > +static void remove_trip_attrs(struct thermal_zone_device *tz)
> > +{
> > +	int indx;
> > +
> > +	for (indx = 0; indx < tz->trips; indx++) {
> > +		device_remove_file(&tz->device,
> > +				   &tz->trip_type_attrs[indx].attr);
> > +		device_remove_file(&tz->device,
> > +				   &tz->trip_temp_attrs[indx].attr);
> > +	}
> > +	kfree(tz->trip_type_attrs);
> > +	kfree(tz->trip_temp_attrs);
> > +}
> > +
> > +/**
> >   * thermal_zone_device_register - register a new thermal zone device
> >   * @type:	the thermal zone device type
> >   * @trips:	the number of trip points the thermal zone support
> > + * @flag:	a bit string indicating the writeablility of trip points
> >   * @devdata:	private device data
> >   * @ops:	standard thermal zone device callbacks
> >   * @tc1:	thermal coefficient 1 for passive calculations
> > @@ -1107,7 +1176,7 @@ EXPORT_SYMBOL(thermal_zone_device_update);
> >   * section 11.1.5.1 of the ACPI specification 3.0.
> >   */
> >  struct thermal_zone_device *thermal_zone_device_register(char *type,
> > -	int trips, void *devdata,
> > +	int trips, int flag, void *devdata,
> >  	const struct thermal_zone_device_ops *ops,
> >  	int tc1, int tc2, int passive_delay, int polling_delay)
> >  {
> > @@ -1124,6 +1193,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
> >  	if (trips > THERMAL_MAX_TRIPS || trips < 0)
> >  		return ERR_PTR(-EINVAL);
> >  
> > +	if (flag >> trips)
> > +		return ERR_PTR(-EINVAL);
> 
> I'm not sure if this check is necessary.  Does it actually matter is someone
> passes ones in the unused bit positions?
> 
I do not think we can trust this value if the caller even wants to set
writable mask for a non-exist trip point.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: [PATCH 03/16] Thermal: Documentation update
  2012-07-19 10:51   ` R, Durgadoss
@ 2012-07-23  8:36     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-23  8:36 UTC (permalink / raw)
  To: R, Durgadoss
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, Eduardo Valentin, Amit Kachhap, Wei Ni

Hi, Durga,

thanks for review. :)

On 四, 2012-07-19 at 04:51 -0600, R, Durgadoss wrote:
> Hi Rui,
> 
> No major comments. Just some spell checks.
> 
> > -----Original Message-----
> > From: Zhang, Rui
> > Sent: Thursday, July 19, 2012 12:01 PM
> > To: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org
> > Cc: Rafael J. Wysocki; Matthew Garrett; Len Brown; R, Durgadoss; Eduardo
> > Valentin; Amit Kachhap; Wei Ni; Zhang, Rui
> > Subject: [PATCH 03/16] Thermal: Documentation update
> > 
> > With commit 6503e5df08008b9a47022b5e9ebba658c8fa69af,
> > the value of /sys/class/thermal/thermal_zoneX/mode has been changed
> > from user/kernel to enabled/disabled.
> > Update the documentation so that users won't be confused.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  Documentation/thermal/sysfs-api.txt |   20 ++++++++++----------
> >  drivers/acpi/thermal.c              |    6 ++----
> >  2 files changed, 12 insertions(+), 14 deletions(-)
> > 
> > diff --git a/Documentation/thermal/sysfs-api.txt
> > b/Documentation/thermal/sysfs-api.txt
> > index 3c8c2f8..b7b3609 100644
> > --- a/Documentation/thermal/sysfs-api.txt
> > +++ b/Documentation/thermal/sysfs-api.txt
> > @@ -47,11 +47,11 @@ temperature) and throttle appropriate devices.
> >  	.bind: bind the thermal zone device with a thermal cooling device.
> >  	.unbind: unbind the thermal zone device with a thermal cooling device.
> >  	.get_temp: get the current temperature of the thermal zone.
> > -	.get_mode: get the current mode (user/kernel) of the thermal zone.
> > -	    - "kernel" means thermal management is done in kernel.
> > -	    - "user" will prevent kernel thermal driver actions upon trip points
> > +	.get_mode: get the current mode (enabled/disabled) of the thermal
> > zone.
> > +	    - "enabled" means the kernel thermal management is enabled.
> > +	    - "disable" will prevent kernel thermal driver actions upon trip points
> 
> /s/disable/disabled
> 
fixed.

thanks,
rui
> >  	      so that user applications can take charge of thermal management.
> > -	.set_mode: set the mode (user/kernel) of the thermal zone.
> > +	.set_mode: set the mode (enabled/disabled) of the thermal zone.
> >  	.get_trip_type: get the type of certain trip point.
> >  	.get_trip_temp: get the temperature above which the certain trip point
> >  			will be fired.
> > @@ -170,14 +170,14 @@ temp
> >  	RO, Required
> > 
> >  mode
> > -	One of the predefined values in [kernel, user].
> > +	One of the predefined values in [enabled, disableed].
> 
> /s/disableed/disabled
> 
> Thanks,
> Durga


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 06/16] Thermal: set upper and lower limits
  2012-07-19 20:55   ` Rafael J. Wysocki
@ 2012-07-23  8:45     ` Zhang Rui
  2012-07-23 19:15       ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-23  8:45 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 四, 2012-07-19 at 22:55 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > set upper and lower limits when binding
> > a thermal cooling device to a thermal zone device.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  Documentation/thermal/sysfs-api.txt |    6 ++++-
> >  drivers/acpi/thermal.c              |   49 ++++++++++++++++++++++-------------
> >  drivers/platform/x86/acerhdf.c      |    2 +-
> >  drivers/thermal/thermal_sys.c       |   20 +++++++++-----
> >  include/linux/thermal.h             |    3 ++-
> >  5 files changed, 53 insertions(+), 27 deletions(-)
> > 
> > diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> > index b7b3609..f169821 100644
> > --- a/Documentation/thermal/sysfs-api.txt
> > +++ b/Documentation/thermal/sysfs-api.txt
> > @@ -84,7 +84,7 @@ temperature) and throttle appropriate devices.
> >  
> >  1.3 interface for binding a thermal zone device with a thermal cooling device
> >  1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> > -		int trip, struct thermal_cooling_device *cdev);
> > +	int trip, struct thermal_cooling_device *cdev, long upper, long lower);
> >  
> >      This interface function bind a thermal cooling device to the certain trip
> >      point of a thermal zone device.
> > @@ -93,6 +93,10 @@ temperature) and throttle appropriate devices.
> >      cdev: thermal cooling device
> >      trip: indicates which trip point the cooling devices is associated with
> >  	  in this thermal zone.
> > +    upper:the Maximum cooling state for this trip point.
> > +          -1 means no upper limit, and the cooling device can be in max_state.
> > +    lower:the Minimum cooling state can be used for this trip point.
> > +          -1 means no lower limit, and the cooling device can be in cooling state 0.
> 
> If we have to use -1 (or all ones for unsigned long), I'd suggest to define a
> constant called CS_NO_LIMIT or something like that and use it instead of the
> plain numbers.
> 
agreed.

> And perhaps change the name of the above to
> thermal_zone_bind_cooling_device_limits() and define
> thermal_zone_bind_cooling_device() as a static inline that will not take the
> extra two arguments and make it call thermal_zone_bind_cooling_device_limits()
> with the CS_NO_LIMIT values in there.
> 
then you mean there are two APIs for binding?
users can invoke thermal_zone_bind_cooling_device if they do not care
the limits?
Hmm, I do not think we need to do this. And further more, as there are
and there will be more and more parameters for binding, say, maybe
weight/influence in the near future, I'm thinking of using a struct
thermal_bind_params to pass the parameters instead.

> >  1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
> >  		int trip, struct thermal_cooling_device *cdev);
> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > index 8275e7b..a7c97f5 100644
> > --- a/drivers/acpi/thermal.c
> > +++ b/drivers/acpi/thermal.c
> > @@ -727,11 +727,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
> >  	return 0;
> >  }
> >  
> > -typedef int (*cb)(struct thermal_zone_device *, int,
> > -		  struct thermal_cooling_device *);
> >  static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
> >  					struct thermal_cooling_device *cdev,
> > -					cb action)
> > +					int bind)
> 
> Should 'bind' be a bool?
> 
yep.

> >  {
> >  	struct acpi_device *device = cdev->devdata;
> >  	struct acpi_thermal *tz = thermal->devdata;
> > @@ -755,11 +753,18 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
> >  		    i++) {
> >  			handle = tz->trips.passive.devices.handles[i];
> >  			status = acpi_bus_get_device(handle, &dev);
> > -			if (ACPI_SUCCESS(status) && (dev == device)) {
> > -				result = action(thermal, trip, cdev);
> > -				if (result)
> > -					goto failed;
> > -			}
> > +			if (ACPI_FAILURE(status) || dev != device)
> > +				continue;
> > +			if (bind)
> > +				result =
> > +					thermal_zone_bind_cooling_device
> > +					(thermal, trip, cdev, -1, -1);
> > +			else
> > +				result =
> > +					thermal_zone_unbind_cooling_device
> > +					(thermal, trip, cdev);
> > +			if (result)
> > +				goto failed;
> >  		}
> >  	}
> >  
> > @@ -772,11 +777,16 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
> >  		    j++) {
> >  			handle = tz->trips.active[i].devices.handles[j];
> >  			status = acpi_bus_get_device(handle, &dev);
> > -			if (ACPI_SUCCESS(status) && (dev == device)) {
> > -				result = action(thermal, trip, cdev);
> > -				if (result)
> > -					goto failed;
> > -			}
> > +			if (ACPI_FAILURE(status) || dev != device)
> > +				continue;
> > +			if (bind)
> > +				result = thermal_zone_bind_cooling_device
> > +					(thermal, trip, cdev, -1, -1);
> > +			else
> > +				result = thermal_zone_unbind_cooling_device
> > +					(thermal, trip, cdev);
> > +			if (result)
> > +				goto failed;
> >  		}
> >  	}
> >  
> > @@ -784,7 +794,12 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
> >  		handle = tz->devices.handles[i];
> >  		status = acpi_bus_get_device(handle, &dev);
> >  		if (ACPI_SUCCESS(status) && (dev == device)) {
> > -			result = action(thermal, -1, cdev);
> > +			if (bind)
> > +				result = thermal_zone_bind_cooling_device
> > +						(thermal, -1, cdev, -1, -1);
> > +			else
> > +				result = thermal_zone_unbind_cooling_device
> > +						(thermal, -1, cdev);
> >  			if (result)
> >  				goto failed;
> >  		}
> > @@ -798,16 +813,14 @@ static int
> >  acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
> >  					struct thermal_cooling_device *cdev)
> >  {
> > -	return acpi_thermal_cooling_device_cb(thermal, cdev,
> > -				thermal_zone_bind_cooling_device);
> > +	return acpi_thermal_cooling_device_cb(thermal, cdev, 1);
> >  }
> >  
> >  static int
> >  acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
> >  					struct thermal_cooling_device *cdev)
> >  {
> > -	return acpi_thermal_cooling_device_cb(thermal, cdev,
> > -				thermal_zone_unbind_cooling_device);
> > +	return acpi_thermal_cooling_device_cb(thermal, cdev, 0);
> >  }
> >  
> >  static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
> > diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
> > index 39abb15..278aa0e 100644
> > --- a/drivers/platform/x86/acerhdf.c
> > +++ b/drivers/platform/x86/acerhdf.c
> > @@ -329,7 +329,7 @@ static int acerhdf_bind(struct thermal_zone_device *thermal,
> >  	if (cdev != cl_dev)
> >  		return 0;
> >  
> > -	if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) {
> > +	if (thermal_zone_bind_cooling_device(thermal, 0, cdev, -1, -1)) {
> >  		pr_err("error binding cooling dev\n");
> >  		return -EINVAL;
> >  	}
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index 4267a49..db35300 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -316,7 +316,7 @@ passive_store(struct device *dev, struct device_attribute *attr,
> >  				     sizeof("Processor")))
> >  				thermal_zone_bind_cooling_device(tz,
> >  								 THERMAL_TRIPS_NONE,
> > -								 cdev);
> > +								 cdev, -1, -1);
> >  		}
> >  		mutex_unlock(&thermal_list_lock);
> >  		if (!tz->passive_delay)
> > @@ -801,7 +801,8 @@ static void thermal_zone_device_check(struct work_struct *work)
> >   */
> >  int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  				     int trip,
> > -				     struct thermal_cooling_device *cdev)
> > +				     struct thermal_cooling_device *cdev,
> > +				     long upper, long lower)
> 
> upper and lower were unsigned long in the previous patch.  Can we please
> use the same data type for them everywhere?
> 
yep.

thanks,
rui


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/16] Thermal: Make Thermal trip points writeable
  2012-07-23  8:22     ` Zhang Rui
@ 2012-07-23 10:25       ` Rafael J. Wysocki
  0 siblings, 0 replies; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-23 10:25 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On Monday, July 23, 2012, Zhang Rui wrote:
> On 四, 2012-07-19 at 22:27 +0200, Rafael J. Wysocki wrote:
> > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > From: Durgadoss R <dugardoss.r@intel.com>
[...]
> > >  	if (trips > THERMAL_MAX_TRIPS || trips < 0)
> > >  		return ERR_PTR(-EINVAL);
> > >  
> > > +	if (flag >> trips)
> > > +		return ERR_PTR(-EINVAL);
> > 
> > I'm not sure if this check is necessary.  Does it actually matter is someone
> > passes ones in the unused bit positions?
> > 
> I do not think we can trust this value if the caller even wants to set
> writable mask for a non-exist trip point.

OK, so perhaps we can merge the two conditionals into one?

Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 06/16] Thermal: set upper and lower limits
  2012-07-23  8:45     ` Zhang Rui
@ 2012-07-23 19:15       ` Rafael J. Wysocki
  0 siblings, 0 replies; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-23 19:15 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On Monday, July 23, 2012, Zhang Rui wrote:
> On 四, 2012-07-19 at 22:55 +0200, Rafael J. Wysocki wrote:
> > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > set upper and lower limits when binding
> > > a thermal cooling device to a thermal zone device.
> > > 
> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > ---
> > >  Documentation/thermal/sysfs-api.txt |    6 ++++-
> > >  drivers/acpi/thermal.c              |   49 ++++++++++++++++++++++-------------
> > >  drivers/platform/x86/acerhdf.c      |    2 +-
> > >  drivers/thermal/thermal_sys.c       |   20 +++++++++-----
> > >  include/linux/thermal.h             |    3 ++-
> > >  5 files changed, 53 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
> > > index b7b3609..f169821 100644
> > > --- a/Documentation/thermal/sysfs-api.txt
> > > +++ b/Documentation/thermal/sysfs-api.txt
> > > @@ -84,7 +84,7 @@ temperature) and throttle appropriate devices.
> > >  
> > >  1.3 interface for binding a thermal zone device with a thermal cooling device
> > >  1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> > > -		int trip, struct thermal_cooling_device *cdev);
> > > +	int trip, struct thermal_cooling_device *cdev, long upper, long lower);
> > >  
> > >      This interface function bind a thermal cooling device to the certain trip
> > >      point of a thermal zone device.
> > > @@ -93,6 +93,10 @@ temperature) and throttle appropriate devices.
> > >      cdev: thermal cooling device
> > >      trip: indicates which trip point the cooling devices is associated with
> > >  	  in this thermal zone.
> > > +    upper:the Maximum cooling state for this trip point.
> > > +          -1 means no upper limit, and the cooling device can be in max_state.
> > > +    lower:the Minimum cooling state can be used for this trip point.
> > > +          -1 means no lower limit, and the cooling device can be in cooling state 0.
> > 
> > If we have to use -1 (or all ones for unsigned long), I'd suggest to define a
> > constant called CS_NO_LIMIT or something like that and use it instead of the
> > plain numbers.
> > 
> agreed.
> 
> > And perhaps change the name of the above to
> > thermal_zone_bind_cooling_device_limits() and define
> > thermal_zone_bind_cooling_device() as a static inline that will not take the
> > extra two arguments and make it call thermal_zone_bind_cooling_device_limits()
> > with the CS_NO_LIMIT values in there.
> > 
> then you mean there are two APIs for binding?
> users can invoke thermal_zone_bind_cooling_device if they do not care
> the limits?

Yes.

> Hmm, I do not think we need to do this. And further more, as there are
> and there will be more and more parameters for binding, say, maybe
> weight/influence in the near future,

The majority of existing users don't care, it appears (as follows from
the rest of your patch).

> I'm thinking of using a struct thermal_bind_params to pass the parameters
> instead.

Yes, you can do that if you know already that more parameters will be
necessary.  Still, a wrapper passing NULL in there may be useful for some
users.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-19 21:13   ` Rafael J. Wysocki
@ 2012-07-24  1:42     ` Zhang Rui
  2012-07-24  9:22       ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  1:42 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 四, 2012-07-19 at 23:13 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> > But they are ACPI platform specific concepts.
> > 
> > Introduce .get_trend() as a more general solution.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
> >  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
> >  include/linux/thermal.h       |    9 +++++++++
> >  3 files changed, 56 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > index a7c97f5..b345646 100644
> > --- a/drivers/acpi/thermal.c
> > +++ b/drivers/acpi/thermal.c
> > @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
> >  		return -EINVAL;
> >  }
> >  
> > +static int thermal_get_trend(struct thermal_zone_device *thermal,
> > +				int trip, enum thermal_trend *trend)
> > +{
> > +	struct acpi_thermal *tz = thermal->devdata;
> > +	enum thermal_trip_type type;
> > +	unsigned long trip_temp;
> > +	int i;
> > +
> > +	if (thermal_get_trip_type(thermal, trip, &type))
> > +		return -EINVAL;
> > +
> > +	/* Only PASSIVE trip points need TREND */
> > +	if (type != THERMAL_TRIP_PASSIVE)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * tz->temperature has already been updated by generic thermal layer,
> > +	 * before this callback being invoked
> > +	 */
> > +	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> > +		+ (tz->trips.passive.tc2
> > +		* (tz->temperature - tz->trips.passive.temperature));
> > +
> > +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> > +		(i < 0 ? THERMAL_TREND_DROPPING : THERMAL_TREND_STABLE);
> 
> I'd use if (...) / else if (...) / else here.  It would be _way_ more readable.
> 
agreed.

> > +	return 0;
> > +}
> > +
> > +
> >  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
> >  			   enum thermal_trip_type trip_type)
> >  {
> > @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
> >  	.get_trip_type = thermal_get_trip_type,
> >  	.get_trip_temp = thermal_get_trip_temp,
> >  	.get_crit_temp = thermal_get_crit_temp,
> > +	.get_trend = thermal_get_trend,
> >  	.notify = thermal_notify,
> >  };
> >  
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index db35300..29b6dba 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
> >  }
> >  #endif
> >  
> > +static void thermal_get_trend(struct thermal_zone_device *tz,
> > +		int trip, enum thermal_trend *trend)
> 
> The fact that this function has the same name as the ACPI one above is kind of
> disturbing.  Any chance to call it differently?
> 
> > +{
> > +	if (tz->ops->get_trend)
> > +		if (!tz->ops->get_trend(tz, trip, trend))
> > +			return;
> 
> What about:
> 
> +	if (tz->ops->get_trend && !tz->ops->get_trend(tz, trip, trend))
> +		return;
> 
> And since the error code returned by .get_trend() apparently doesn't matter,
> shouldn't it return a bool?
> 
agreed.
> > +
> > +	*trend = tz->temperature >= tz->last_temperature ?
> > +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
> > +	return;
> > +}
> > +
> >  static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
> >  					    int delay)
> >  {
> > @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> >  	if (temp >= trip_temp) {
> >  		tz->passive = true;
> >  
> > +		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);
> 
> What's wrong with the data type of 'trend' here?
> 
this is no functional changes in this patch.
the trend value returned by thermal_get_trend first is overridden by
tc1/tc2 formula below, so trend is still an integer at this time.

But you remind me that I should redefine trend as enum thermal_trend in
the next patch.

> > +
> >  		trend = (tz->tc1 * (temp - tz->last_temperature)) +
> >  			(tz->tc2 * (temp - trip_temp));
> >  

> > @@ -1090,6 +1104,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> >  		goto leave;
> >  	}
> >  
Say, when the temperature is changed from 60C to 65C,

without this patch, tz->last_temperature is 60C because it is updated in
the previous thermal_zone_device_update() call.
with this patch, tz->temperature is 60C because it is the previous
"current" temperature.

> > +	tz->last_temperature = tz->temperature;
> > +	tz->temperature = temp;
> > +
we update here them to reflect the truth.

> >  	for (count = 0; count < tz->trips; count++) {
> >  		tz->ops->get_trip_type(tz, count, &trip_type);
> >  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> > @@ -1149,8 +1166,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> >  		thermal_zone_device_passive(tz, temp, tz->forced_passive,
> >  					    THERMAL_TRIPS_NONE);
> >  
> > -	tz->last_temperature = temp;
> > -
without this patch, tz->last_temperature is updated to 65C
with this patch, tz->last_temperature is still 60C and tz->temperature
is 65C.
that's why we need to update them in the beginning of
thermal_zone_device_update().
> 
> I'm not sure if this is correct.  It seems to change the behavior of
> thermal_zone_device_passive() in a subtle way, but I'm not sure that really
> matters.  Does it?
> 
so I think this will not change the behavior of
thermal_zone_device_passive.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-19 21:19   ` Rafael J. Wysocki
@ 2012-07-24  1:47     ` Zhang Rui
  2012-07-24  9:27       ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  1:47 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 四, 2012-07-19 at 23:19 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > This function is used to update the cooling state of
> > all the cooling devices that are binded to an active trip point.
> 
> s/binded/bound/
> 
got it.

> > This will be used for passive cooling as well, in the future patches.
> > as both active and passive cooling can share the same algorithm,
> > which is
> > 
> > 1. if the temperature is higher than a trip point,
> >    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> >       state for this trip point
> >    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> >       state for this trip point
> > 
> > 2. if the temperature is lower than a trip point, use lower
> >    cooling state for this trip point.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  drivers/acpi/thermal.c        |    7 +++-
> >  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
> >  2 files changed, 71 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > index 73e335f..14c4879 100644
> > --- a/drivers/acpi/thermal.c
> > +++ b/drivers/acpi/thermal.c
> > @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
> >  	if (thermal_get_trip_type(thermal, trip, &type))
> >  		return -EINVAL;
> >  
> > -	/* Only PASSIVE trip points need TREND */
> > +	if (type == THERMAL_TRIP_ACTIVE) {
> > +		/* aggressive active cooling */
> > +		*trend = THERMAL_TREND_RAISING;
> > +		return 0;
> 
> Please move that into thermal_zone_trip_update() directly, unless you
> need it elsewhere.
> 
IMO, I can say that ACPI thermal wants aggressive active cooling, as it
will never spin down the fan when the temperature is higher than the
trip point.

But I'm not sure if this is true for other platforms.
say if a fan have 5 speeds.
it may want to run at the maximum speed when the temperature is raising,
but if the temperature begins to drop, it may want to spin down the fan
a little for some reason, say, power, noise, etc.

so I want the platform thermal drivers to have the maximum flexibility.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances
  2012-07-19 21:22   ` Rafael J. Wysocki
@ 2012-07-24  1:48     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  1:48 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 四, 2012-07-19 at 23:22 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > thermal_zone_device.cooling_devices is not accurate
> > as this is a list for thermal instances, rather than cooling devices.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  drivers/thermal/thermal_sys.c |   18 +++++++++---------
> >  include/linux/thermal.h       |    4 ++--
> >  2 files changed, 11 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index 867fced..1836039 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -745,7 +745,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> >  
> >  		/* Heating up? */
> >  		if (trend > 0) {
> > -			list_for_each_entry(instance, &tz->cooling_devices,
> > +			list_for_each_entry(instance, &tz->instances,
> >  					    node) {
> >  				if (instance->trip != trip)
> >  					continue;
> > @@ -756,7 +756,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> >  					cdev->ops->set_cur_state(cdev, state);
> >  			}
> >  		} else if (trend < 0) { /* Cooling off? */
> > -			list_for_each_entry(instance, &tz->cooling_devices,
> > +			list_for_each_entry(instance, &tz->instances,
> >  					    node) {
> >  				if (instance->trip != trip)
> >  					continue;
> > @@ -777,7 +777,7 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> >  	 * and avoid thrashing around the passive trip point.  Note that we
> >  	 * assume symmetry.
> >  	 */
> > -	list_for_each_entry(instance, &tz->cooling_devices, node) {
> > +	list_for_each_entry(instance, &tz->instances, node) {
> >  		if (instance->trip != trip)
> >  			continue;
> >  		cdev = instance->cdev;
> > @@ -873,13 +873,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  		goto remove_symbol_link;
> >  
> >  	mutex_lock(&tz->lock);
> > -	list_for_each_entry(pos, &tz->cooling_devices, node)
> > +	list_for_each_entry(pos, &tz->instances, node)
> >  	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
> >  		result = -EEXIST;
> >  		break;
> >  	}
> >  	if (!result)
> > -		list_add_tail(&dev->node, &tz->cooling_devices);
> > +		list_add_tail(&dev->node, &tz->instances);
> >  	mutex_unlock(&tz->lock);
> >  
> >  	if (!result)
> > @@ -912,7 +912,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
> >  	struct thermal_instance *pos, *next;
> >  
> >  	mutex_lock(&tz->lock);
> > -	list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
> > +	list_for_each_entry_safe(pos, next, &tz->instances, node) {
> >  		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
> >  			list_del(&pos->node);
> >  			mutex_unlock(&tz->lock);
> > @@ -1106,7 +1106,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> >  	if (temp >= trip_temp) {
> >  		thermal_get_trend(tz, trip, &trend);
> >  
> > -		list_for_each_entry(instance, &tz->cooling_devices, node) {
> > +		list_for_each_entry(instance, &tz->instances, node) {
> >  			if (instance->trip != trip)
> >  				continue;
> >  
> > @@ -1125,7 +1125,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> >  			cdev->ops->set_cur_state(cdev, cur_state);
> >  		}
> >  	} else {	/* below trip */
> > -		list_for_each_entry(instance, &tz->cooling_devices, node) {
> > +		list_for_each_entry(instance, &tz->instances, node) {
> >  			if (instance->trip != trip)
> >  				continue;
> >  
> > @@ -1359,7 +1359,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
> >  	if (!tz)
> >  		return ERR_PTR(-ENOMEM);
> >  
> > -	INIT_LIST_HEAD(&tz->cooling_devices);
> > +	INIT_LIST_HEAD(&tz->instances);
> >  	idr_init(&tz->idr);
> >  	mutex_init(&tz->lock);
> >  	result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> > index 44d7fc3..a15b83c 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -120,9 +120,9 @@ struct thermal_zone_device {
> >  	bool passive;
> >  	unsigned int forced_passive;
> >  	const struct thermal_zone_device_ops *ops;
> > -	struct list_head cooling_devices;
> > +	struct list_head instances;
> 
> What about calling that 'thermal_instances'?  As is, it isn't really obvious
> the instances of what exactly they are.
> 
agreed.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device.
  2012-07-19 21:25   ` Rafael J. Wysocki
@ 2012-07-24  1:48     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  1:48 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On 四, 2012-07-19 at 23:25 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > so that cooling device can know the cooling state requirement
> > of all the thermal instances.
> 
> The changelog looks odd in this form.  Please start the sentence in a sensible
> way.
> 
agreed.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state
  2012-07-19 21:39   ` Rafael J. Wysocki
@ 2012-07-24  1:49     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  1:49 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-acpi, linux-pm, Matthew Garrett, Len Brown, R Durgadoss,
	Eduardo Valentin, Amit Kachhap, Wei Ni

On 四, 2012-07-19 at 23:39 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > 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>
> > ---
> >  drivers/thermal/thermal_sys.c |   41 ++++++++++++++++++++++++++++++++++++++---
> >  include/linux/thermal.h       |    1 +
> >  2 files changed, 39 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index 48b2668..803ce94 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -54,6 +54,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->instances */
> > @@ -853,6 +854,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  	dev->trip = trip;
> >  	dev->upper = upper;
> >  	dev->lower = lower;
> > +	dev->target = -1;
> 
> Please define THERMAL_NO_TARGET and use that instead of plain -1.
> 
agreed.

> >  
> >  	result = get_idr(&tz->idr, &tz->lock, &dev->id);
> >  	if (result)
> > @@ -990,6 +992,7 @@ thermal_cooling_device_register(char *type, void *devdata,
> >  	strcpy(cdev->type, type);
> >  	INIT_LIST_HEAD(&cdev->instances);
> >  	cdev->ops = ops;
> > +	cdev->updated = 1;
> >  	cdev->device.class = &thermal_class;
> >  	cdev->devdata = devdata;
> >  	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
> > @@ -1081,6 +1084,32 @@ void thermal_cooling_device_unregister(struct
> >  }
> >  EXPORT_SYMBOL(thermal_cooling_device_unregister);
> >  
> > +static void thermal_zone_do_update(struct thermal_zone_device *tz)
> > +{
> > +	struct thermal_instance *instance1, *instance2;
> > +	struct thermal_cooling_device *cdev;
> > +	int target;
> 
> The 'target' field in the structure is unsigned long.  It'd be better to use
> the same data type here.
> 
> It would be good to use 'true' and 'false' as the values of 'updated' too.
> 
agreed.

> > +
> > +	list_for_each_entry(instance1, &tz->instances, tz_node) {
> > +		cdev = instance1->cdev;
> > +
> > +		/* cooling device has already been updated*/
> > +		if (cdev->updated)
> > +			continue;
> > +
> > +		target = 0;
> > +		/* Make sure cdev enters the deepest cooling state */
> > +		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
> > +			if (instance2->target == -1)
> > +				continue;
> > +			if (instance2->target > target)
> > +				target = instance2->target;
> > +		}
> > +		cdev->ops->set_cur_state(cdev, target);
> > +		cdev->updated = 1;
> > +	}
> > +}
> 
> I would split the function above into two, one that would walk all
> instances of the thermal zone and the other, that would walk the
> instances for a given device.  It would look much cleaner, then.
> 
agreed.

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/16] Thermal: use plist instead of list
  2012-07-19 21:45   ` Rafael J. Wysocki
@ 2012-07-24  2:13     ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  2:13 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni, eduardo

On 四, 2012-07-19 at 23:45 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 19, 2012, Zhang Rui wrote:
> > so that the thermal manager can easily find out
> > the deepest cooling state request for a cooling device.
> > 
> > cdev->lock is also introduced in this patch to protect this plist.
> > 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> 
> I'm not sure if this is actually better than without the plist.
> 
> The plist manipulations in thermal_zone_trip_update() look like they
> can add quite some overhead in some situations.
> 
> Do you have any quantitative justification for this change?
> 
No.
I made this change based on Eduardo's suggestion.
currently, as there are not too many nodes in the list, I don't think we
can get any measurable benefit for now.

Eduardo, I guess you must have more to say on this. :p

thanks,
rui

> Rafael
> 
> 
> > ---
> >  drivers/thermal/thermal_sys.c |   84 ++++++++++++++++++++++++++---------------
> >  include/linux/thermal.h       |    4 +-
> >  2 files changed, 57 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index a40dda1..9f56250 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -54,11 +54,10 @@ 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->instances */
> > -	struct list_head cdev_node; /* node in cdev->instances */
> > +	struct plist_node cdev_node; /* node in cdev->instances */
> >  };
> >  
> >  static DEFINE_IDR(thermal_tz_idr);
> > @@ -787,7 +786,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  	dev->trip = trip;
> >  	dev->upper = upper;
> >  	dev->lower = lower;
> > -	dev->target = -1;
> > +	plist_node_init(&dev->cdev_node, -1);
> >  
> >  	result = get_idr(&tz->idr, &tz->lock, &dev->id);
> >  	if (result)
> > @@ -809,6 +808,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  		goto remove_symbol_link;
> >  
> >  	mutex_lock(&tz->lock);
> > +	mutex_lock(&cdev->lock);
> >  	list_for_each_entry(pos, &tz->instances, tz_node)
> >  	    if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
> >  		result = -EEXIST;
> > @@ -816,8 +816,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
> >  	}
> >  	if (!result) {
> >  		list_add_tail(&dev->tz_node, &tz->instances);
> > -		list_add_tail(&dev->cdev_node, &cdev->instances);
> > +		plist_add(&dev->cdev_node, &cdev->instances);
> >  	}
> > +	mutex_unlock(&cdev->lock);
> >  	mutex_unlock(&tz->lock);
> >  
> >  	if (!result)
> > @@ -850,14 +851,17 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
> >  	struct thermal_instance *pos, *next;
> >  
> >  	mutex_lock(&tz->lock);
> > +	mutex_lock(&cdev->lock);
> >  	list_for_each_entry_safe(pos, next, &tz->instances, tz_node) {
> >  		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
> >  			list_del(&pos->tz_node);
> > -			list_del(&pos->cdev_node);
> > +			plist_del(&pos->cdev_node, &pos->cdev->instances);
> > +			mutex_unlock(&cdev->lock);
> >  			mutex_unlock(&tz->lock);
> >  			goto unbind;
> >  		}
> >  	}
> > +	mutex_unlock(&cdev->lock);
> >  	mutex_unlock(&tz->lock);
> >  
> >  	return -ENODEV;
> > @@ -923,7 +927,8 @@ thermal_cooling_device_register(char *type, void *devdata,
> >  	}
> >  
> >  	strcpy(cdev->type, type);
> > -	INIT_LIST_HEAD(&cdev->instances);
> > +	plist_head_init(&cdev->instances);
> > +	mutex_init(&cdev->lock);
> >  	cdev->ops = ops;
> >  	cdev->updated = 1;
> >  	cdev->device.class = &thermal_class;
> > @@ -1019,26 +1024,21 @@ EXPORT_SYMBOL(thermal_cooling_device_unregister);
> >  
> >  static void thermal_zone_do_update(struct thermal_zone_device *tz)
> >  {
> > -	struct thermal_instance *instance1, *instance2;
> > +	struct thermal_instance *instance;
> > +	struct plist_node *node;
> >  	struct thermal_cooling_device *cdev;
> > -	int target;
> >  
> > -	list_for_each_entry(instance1, &tz->instances, tz_node) {
> > -		cdev = instance1->cdev;
> > +	list_for_each_entry(instance, &tz->instances, tz_node) {
> > +		cdev = instance->cdev;
> >  
> >  		/* cooling device has already been updated*/
> >  		if (cdev->updated)
> >  			continue;
> >  
> > -		target = 0;
> > -		/* Make sure cdev enters the deepest cooling state */
> > -		list_for_each_entry(instance2, &cdev->instances, cdev_node) {
> > -			if (instance2->target == -1)
> > -				continue;
> > -			if (instance2->target > target)
> > -				target = instance2->target;
> > -		}
> > -		cdev->ops->set_cur_state(cdev, target);
> > +		/* Deepest cooling state required */
> > +		node = plist_last(&cdev->instances);
> > +
> > +		cdev->ops->set_cur_state(cdev, node->prio < 0 ? 0 : node->prio);
> >  		cdev->updated = 1;
> >  	}
> >  }
> > @@ -1064,7 +1064,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> >  {
> >  	struct thermal_instance *instance;
> >  	struct thermal_cooling_device *cdev = NULL;
> > -	unsigned long cur_state, max_state;
> > +	unsigned long cur_state, max_state, target_state;
> >  	long trip_temp;
> >  	enum thermal_trip_type trip_type;
> >  	enum thermal_trend trend;
> > @@ -1088,21 +1088,29 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> >  
> >  			cdev->ops->get_cur_state(cdev, &cur_state);
> >  			cdev->ops->get_max_state(cdev, &max_state);
> > -
> > +			target_state = cur_state;
> >  			if (trend == THERMAL_TREND_RAISING) {
> > -				cur_state = cur_state < instance->upper ?
> > +				target_state = cur_state < instance->upper ?
> >  					    (cur_state + 1) : instance->upper;
> >  			} else if (trend == THERMAL_TREND_DROPPING) {
> > -				cur_state = cur_state > instance->lower ?
> > +				target_state = cur_state > instance->lower ?
> >  				    (cur_state - 1) : instance->lower;
> >  			}
> >  
> > +			if (target_state == cur_state)
> > +				continue;
> > +
> >  			/* activate a passive thermal instance */
> >  			if (trip_type == THERMAL_TRIP_PASSIVE &&
> > -			    instance->target == -1)
> > +			    instance->cdev_node.prio == -1)
> >  				tz->passive++;
> >  
> > -			instance->target = cur_state;
> > +			mutex_lock(&cdev->lock);
> > +			plist_del(&instance->cdev_node, &cdev->instances);
> > +			plist_node_init(&instance->cdev_node, target_state);
> > +			plist_add(&instance->cdev_node, &cdev->instances);
> > +			mutex_unlock(&cdev->lock);
> > +
> >  			cdev->updated = 0; /* cooling device needs update */
> >  		}
> >  	} else {	/* below trip */
> > @@ -1111,20 +1119,36 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> >  				continue;
> >  
> >  			/* Do not use the deacitve thermal instance */
> > -			if (instance->target == -1)
> > +			if (instance->cdev_node.prio == -1)
> >  				continue;
> >  			cdev = instance->cdev;
> >  			cdev->ops->get_cur_state(cdev, &cur_state);
> >  
> > -			cur_state = cur_state > instance->lower ?
> > +			target_state = cur_state > instance->lower ?
> >  				    (cur_state - 1) : -1;
> >  
> > +			if (target_state == cur_state)
> > +				continue;
> > +
> >  			/* deactivate a passive thermal instance */
> >  			if (trip_type == THERMAL_TRIP_PASSIVE &&
> > -			    cur_state == -1)
> > +			    target_state == -1)
> >  				tz->passive--;
> > -			instance->target = cur_state;
> > -			cdev->updated = 0; /* cooling device needs update */
> > +
> > +			mutex_lock(&cdev->lock);
> > +			plist_del(&instance->cdev_node, &cdev->instances);
> > +			plist_node_init(&instance->cdev_node, target_state);
> > +			plist_add(&instance->cdev_node, &cdev->instances);
> > +			mutex_unlock(&cdev->lock);
> > +
> > +			/*
> > +			 * cooling device needs update.
> > +			 * But if the target_state is -1, it means that
> > +			 * the cooling device is already in cooling state 0,
> > +			 * thus we do not need update
> > +			 */
> > +			if (target_state != -1)
> > +				cdev->updated = 0;
> >  		}
> >  	}
> >  
> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> > index f725eb9..376a59e 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -28,6 +28,7 @@
> >  #include <linux/idr.h>
> >  #include <linux/device.h>
> >  #include <linux/workqueue.h>
> > +#include <linux/plist.h>
> >  
> >  struct thermal_zone_device;
> >  struct thermal_cooling_device;
> > @@ -93,7 +94,8 @@ struct thermal_cooling_device {
> >  	void *devdata;
> >  	const struct thermal_cooling_device_ops *ops;
> >  	int updated; /* 1 if the cooling device does not need update */
> > -	struct list_head instances;
> > +	struct mutex lock;
> > +	struct plist_head instances;
> >  	struct list_head node;
> >  };
> >  
> > 
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
       [not found]   ` <CAK44p21hNYGH4YkH5E+XK-pM2upingQbvm77WkJbttCRp6ZamQ@mail.gmail.com>
@ 2012-07-24  7:11     ` Zhang Rui
  2012-07-24  8:06       ` Amit Kachhap
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-24  7:11 UTC (permalink / raw)
  To: Amit Kachhap
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, R Durgadoss, Eduardo Valentin, Wei Ni

On 二, 2012-07-24 at 12:27 +0530, Amit Kachhap wrote:
> 
> 
> On 19 July 2012 12:01, Zhang Rui <rui.zhang@intel.com> wrote:
>         This function is used to update the cooling state of
>         all the cooling devices that are binded to an active trip
>         point.
>         
>         This will be used for passive cooling as well, in the future
>         patches.
>         as both active and passive cooling can share the same
>         algorithm,
>         which is
>         
>         1. if the temperature is higher than a trip point,
>            a. if the trend is THERMAL_TREND_RAISING, use higher
>         cooling
>               state for this trip point
>            b. if the trend is THERMAL_TREND_DROPPING, use lower
>         cooling
>               state for this trip point
>         
>         2. if the temperature is lower than a trip point, use lower
>            cooling state for this trip point.
> 
> Hi Rui,
> 
> Your patches looks useful.
> For my platform I need to have get_trend called even in the case when
> current temp is less than the trip point and then use
> THERMAL_TREND_DROPPING to actually lower the cooling state.
> 
hmm, why?
in the current cooling algorithm, when the temperature is lower than the
trip point, the cooling state is decreased by 1 every time,
unconditionally, isn't this what you want?

thanks,
rui

> Thanks,
> Amit
>  
>         
>         Signed-off-by: Zhang Rui <rui.zhang@intel.com>
>         ---
>          drivers/acpi/thermal.c        |    7 +++-
>          drivers/thermal/thermal_sys.c |   91
>         +++++++++++++++++++++++++++++------------
>          2 files changed, 71 insertions(+), 27 deletions(-)
>         
>         diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
>         index 73e335f..14c4879 100644
>         --- a/drivers/acpi/thermal.c
>         +++ b/drivers/acpi/thermal.c
>         @@ -715,7 +715,12 @@ static int thermal_get_trend(struct
>         thermal_zone_device *thermal,
>                 if (thermal_get_trip_type(thermal, trip, &type))
>                         return -EINVAL;
>         
>         -       /* Only PASSIVE trip points need TREND */
>         +       if (type == THERMAL_TRIP_ACTIVE) {
>         +               /* aggressive active cooling */
>         +               *trend = THERMAL_TREND_RAISING;
>         +               return 0;
>         +       }
>         +
>                 if (type != THERMAL_TRIP_PASSIVE)
>                         return -EINVAL;
>         
>         diff --git a/drivers/thermal/thermal_sys.c
>         b/drivers/thermal/thermal_sys.c
>         index 59af3b8..011faba 100644
>         --- a/drivers/thermal/thermal_sys.c
>         +++ b/drivers/thermal/thermal_sys.c
>         @@ -1076,6 +1076,70 @@ void
>         thermal_cooling_device_unregister(struct
>          }
>          EXPORT_SYMBOL(thermal_cooling_device_unregister);
>         
>         +/*
>         + * Cooling algorithm for active trip points
>         + *
>         + * 1. if the temperature is higher than a trip point,
>         + *    a. if the trend is THERMAL_TREND_RAISING, use higher
>         cooling
>         + *       state for this trip point
>         + *    b. if the trend is THERMAL_TREND_DROPPING, use lower
>         cooling
>         + *       state for this trip point
>         + *
>         + * 2. if the temperature is lower than a trip point, use
>         lower
>         + *    cooling state for this trip point
>         + *
>         + * Note that this behaves the same as the previous passive
>         cooling
>         + * algorithm.
>         + */
>         +
>         +static void thermal_zone_trip_update(struct
>         thermal_zone_device *tz,
>         +                                    int trip, long temp)
>         +{
>         +       struct thermal_cooling_device_instance *instance;
>         +       struct thermal_cooling_device *cdev = NULL;
>         +       unsigned long cur_state, max_state;
>         +       long trip_temp;
>         +       enum thermal_trend trend;
>         +
>         +       tz->ops->get_trip_temp(tz, trip, &trip_temp);
>         +
>         +       if (temp >= trip_temp) {
>         +               thermal_get_trend(tz, trip, &trend);
>         +
>         +               list_for_each_entry(instance,
>         &tz->cooling_devices, node) {
>         +                       if (instance->trip != trip)
>         +                               continue;
>         +
>         +                       cdev = instance->cdev;
>         +
>         +                       cdev->ops->get_cur_state(cdev,
>         &cur_state);
>         +                       cdev->ops->get_max_state(cdev,
>         &max_state);
>         +
>         +                       if (trend == THERMAL_TREND_RAISING) {
>         +                               cur_state = cur_state <
>         instance->upper ?
>         +                                           (cur_state + 1) :
>         instance->upper;
>         +                       } else if (trend ==
>         THERMAL_TREND_DROPPING) {
>         +                               cur_state = cur_state >
>         instance->lower ?
>         +                                   (cur_state - 1) :
>         instance->lower;
>         +                       }
>         +                       cdev->ops->set_cur_state(cdev,
>         cur_state);
>         +               }
>         +       } else {        /* below trip */
>         +               list_for_each_entry(instance,
>         &tz->cooling_devices, node) {
>         +                       if (instance->trip != trip)
>         +                               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);
>         +               }
>         +       }
>         +
>         +       return;
>         +}
>          /**
>           * thermal_zone_device_update - force an update of a thermal
>         zone's state
>           * @ttz:       the thermal zone to update
>         @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct
>         thermal_zone_device *tz)
>                 int count, ret = 0;
>                 long temp, trip_temp;
>                 enum thermal_trip_type trip_type;
>         -       struct thermal_cooling_device_instance *instance;
>         -       struct thermal_cooling_device *cdev;
>         -       unsigned long cur_state, max_state;
>         
>                 mutex_lock(&tz->lock);
>         
>         @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct
>         thermal_zone_device *tz)
>                                                 tz->ops->notify(tz,
>         count, trip_type);
>                                 break;
>                         case THERMAL_TRIP_ACTIVE:
>         -                       list_for_each_entry(instance,
>         &tz->cooling_devices,
>         -                                           node) {
>         -                               if (instance->trip != count)
>         -                                       continue;
>         -
>         -                               cdev = instance->cdev;
>         -
>         -                               cdev->ops->get_cur_state(cdev,
>         &cur_state);
>         -                               cdev->ops->get_max_state(cdev,
>         &max_state);
>         -
>         -                               if (temp >= trip_temp)
>         -                                       cur_state =
>         -                                               cur_state <
>         instance->upper ?
>         -                                               (cur_state +
>         1) :
>         -
>         instance->upper;
>         -                               else
>         -                                       cur_state =
>         -                                               cur_state >
>         instance->lower ?
>         -                                               (cur_state -
>         1) :
>         -
>         instance->lower;
>         -
>         -                               cdev->ops->set_cur_state(cdev,
>         cur_state);
>         -                       }
>         +                       thermal_zone_trip_update(tz, count,
>         temp);
>                                 break;
>                         case THERMAL_TRIP_PASSIVE:
>                                 if (temp >= trip_temp || tz->passive)
>         --
>         1.7.9.5
>         
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-19  6:31 ` [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update() Zhang Rui
  2012-07-19 21:19   ` Rafael J. Wysocki
       [not found]   ` <CAK44p21hNYGH4YkH5E+XK-pM2upingQbvm77WkJbttCRp6ZamQ@mail.gmail.com>
@ 2012-07-24  7:57   ` Amit Kachhap
  2 siblings, 0 replies; 56+ messages in thread
From: Amit Kachhap @ 2012-07-24  7:57 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, R Durgadoss, Eduardo Valentin, Wei Ni

On 19 July 2012 12:01, Zhang Rui <rui.zhang@intel.com> wrote:
>
> This function is used to update the cooling state of
> all the cooling devices that are binded to an active trip point.
>
> This will be used for passive cooling as well, in the future patches.
> as both active and passive cooling can share the same algorithm,
> which is
>
> 1. if the temperature is higher than a trip point,
>    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
>       state for this trip point
>    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
>       state for this trip point
>
> 2. if the temperature is lower than a trip point, use lower
>    cooling state for this trip point.

Hi Rui,

Your patches looks useful.
For my platform I need to have get_trend called even in the case when
current temp is less than the trip point and then use
THERMAL_TREND_DROPPING to actually lower the cooling state.

Thanks,
Amit
>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/acpi/thermal.c        |    7 +++-
>  drivers/thermal/thermal_sys.c |   91
> +++++++++++++++++++++++++++++------------
>  2 files changed, 71 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 73e335f..14c4879 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -715,7 +715,12 @@ static int thermal_get_trend(struct
> thermal_zone_device *thermal,
>         if (thermal_get_trip_type(thermal, trip, &type))
>                 return -EINVAL;
>
> -       /* Only PASSIVE trip points need TREND */
> +       if (type == THERMAL_TRIP_ACTIVE) {
> +               /* aggressive active cooling */
> +               *trend = THERMAL_TREND_RAISING;
> +               return 0;
> +       }
> +
>         if (type != THERMAL_TRIP_PASSIVE)
>                 return -EINVAL;
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 59af3b8..011faba 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -1076,6 +1076,70 @@ void thermal_cooling_device_unregister(struct
>  }
>  EXPORT_SYMBOL(thermal_cooling_device_unregister);
>
> +/*
> + * Cooling algorithm for active trip points
> + *
> + * 1. if the temperature is higher than a trip point,
> + *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> + *       state for this trip point
> + *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> + *       state for this trip point
> + *
> + * 2. if the temperature is lower than a trip point, use lower
> + *    cooling state for this trip point
> + *
> + * Note that this behaves the same as the previous passive cooling
> + * algorithm.
> + */
> +
> +static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> +                                    int trip, long temp)
> +{
> +       struct thermal_cooling_device_instance *instance;
> +       struct thermal_cooling_device *cdev = NULL;
> +       unsigned long cur_state, max_state;
> +       long trip_temp;
> +       enum thermal_trend trend;
> +
> +       tz->ops->get_trip_temp(tz, trip, &trip_temp);
> +
> +       if (temp >= trip_temp) {
> +               thermal_get_trend(tz, trip, &trend);
> +
> +               list_for_each_entry(instance, &tz->cooling_devices, node)
> {
> +                       if (instance->trip != trip)
> +                               continue;
> +
> +                       cdev = instance->cdev;
> +
> +                       cdev->ops->get_cur_state(cdev, &cur_state);
> +                       cdev->ops->get_max_state(cdev, &max_state);
> +
> +                       if (trend == THERMAL_TREND_RAISING) {
> +                               cur_state = cur_state < instance->upper ?
> +                                           (cur_state + 1) :
> instance->upper;
> +                       } else if (trend == THERMAL_TREND_DROPPING) {
> +                               cur_state = cur_state > instance->lower ?
> +                                   (cur_state - 1) : instance->lower;
> +                       }
> +                       cdev->ops->set_cur_state(cdev, cur_state);
> +               }
> +       } else {        /* below trip */
> +               list_for_each_entry(instance, &tz->cooling_devices, node)
> {
> +                       if (instance->trip != trip)
> +                               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);
> +               }
> +       }
> +
> +       return;
> +}
>  /**
>   * thermal_zone_device_update - force an update of a thermal zone's state
>   * @ttz:       the thermal zone to update
> @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct
> thermal_zone_device *tz)
>         int count, ret = 0;
>         long temp, trip_temp;
>         enum thermal_trip_type trip_type;
> -       struct thermal_cooling_device_instance *instance;
> -       struct thermal_cooling_device *cdev;
> -       unsigned long cur_state, max_state;
>
>         mutex_lock(&tz->lock);
>
> @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct
> thermal_zone_device *tz)
>                                         tz->ops->notify(tz, count,
> trip_type);
>                         break;
>                 case THERMAL_TRIP_ACTIVE:
> -                       list_for_each_entry(instance,
> &tz->cooling_devices,
> -                                           node) {
> -                               if (instance->trip != count)
> -                                       continue;
> -
> -                               cdev = instance->cdev;
> -
> -                               cdev->ops->get_cur_state(cdev,
> &cur_state);
> -                               cdev->ops->get_max_state(cdev,
> &max_state);
> -
> -                               if (temp >= trip_temp)
> -                                       cur_state =
> -                                               cur_state <
> instance->upper ?
> -                                               (cur_state + 1) :
> -                                               instance->upper;
> -                               else
> -                                       cur_state =
> -                                               cur_state >
> instance->lower ?
> -                                               (cur_state - 1) :
> -                                               instance->lower;
> -
> -                               cdev->ops->set_cur_state(cdev, cur_state);
> -                       }
> +                       thermal_zone_trip_update(tz, count, temp);
>                         break;
>                 case THERMAL_TRIP_PASSIVE:
>                         if (temp >= trip_temp || tz->passive)
> --
> 1.7.9.5
>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-24  7:11     ` Zhang Rui
@ 2012-07-24  8:06       ` Amit Kachhap
  2012-07-26  5:08         ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Amit Kachhap @ 2012-07-24  8:06 UTC (permalink / raw)
  To: Zhang Rui
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, R Durgadoss, Eduardo Valentin, Wei Ni

On 24 July 2012 12:41, Zhang Rui <rui.zhang@intel.com> wrote:
> On 二, 2012-07-24 at 12:27 +0530, Amit Kachhap wrote:
>>
>>
>> On 19 July 2012 12:01, Zhang Rui <rui.zhang@intel.com> wrote:
>>         This function is used to update the cooling state of
>>         all the cooling devices that are binded to an active trip
>>         point.
>>
>>         This will be used for passive cooling as well, in the future
>>         patches.
>>         as both active and passive cooling can share the same
>>         algorithm,
>>         which is
>>
>>         1. if the temperature is higher than a trip point,
>>            a. if the trend is THERMAL_TREND_RAISING, use higher
>>         cooling
>>               state for this trip point
>>            b. if the trend is THERMAL_TREND_DROPPING, use lower
>>         cooling
>>               state for this trip point
>>
>>         2. if the temperature is lower than a trip point, use lower
>>            cooling state for this trip point.
>>
>> Hi Rui,
>>
>> Your patches looks useful.
>> For my platform I need to have get_trend called even in the case when
>> current temp is less than the trip point and then use
>> THERMAL_TREND_DROPPING to actually lower the cooling state.
>>
> hmm, why?
> in the current cooling algorithm, when the temperature is lower than the
> trip point, the cooling state is decreased by 1 every time,
> unconditionally, isn't this what you want?

Basically the requirement is that I do not want to remove the cooling
device when the temp just reaches below the trip point because this
causes many throttling in this trip point so say I will remove cooling
device when the temp is < (trip - 5) which can be done inside the new
platform get_trend call.

Thanks,
Amit D
>
> thanks,
> rui
>
>> Thanks,
>> Amit
>>
>>
>>         Signed-off-by: Zhang Rui <rui.zhang@intel.com>
>>         ---
>>          drivers/acpi/thermal.c        |    7 +++-
>>          drivers/thermal/thermal_sys.c |   91
>>         +++++++++++++++++++++++++++++------------
>>          2 files changed, 71 insertions(+), 27 deletions(-)
>>
>>         diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
>>         index 73e335f..14c4879 100644
>>         --- a/drivers/acpi/thermal.c
>>         +++ b/drivers/acpi/thermal.c
>>         @@ -715,7 +715,12 @@ static int thermal_get_trend(struct
>>         thermal_zone_device *thermal,
>>                 if (thermal_get_trip_type(thermal, trip, &type))
>>                         return -EINVAL;
>>
>>         -       /* Only PASSIVE trip points need TREND */
>>         +       if (type == THERMAL_TRIP_ACTIVE) {
>>         +               /* aggressive active cooling */
>>         +               *trend = THERMAL_TREND_RAISING;
>>         +               return 0;
>>         +       }
>>         +
>>                 if (type != THERMAL_TRIP_PASSIVE)
>>                         return -EINVAL;
>>
>>         diff --git a/drivers/thermal/thermal_sys.c
>>         b/drivers/thermal/thermal_sys.c
>>         index 59af3b8..011faba 100644
>>         --- a/drivers/thermal/thermal_sys.c
>>         +++ b/drivers/thermal/thermal_sys.c
>>         @@ -1076,6 +1076,70 @@ void
>>         thermal_cooling_device_unregister(struct
>>          }
>>          EXPORT_SYMBOL(thermal_cooling_device_unregister);
>>
>>         +/*
>>         + * Cooling algorithm for active trip points
>>         + *
>>         + * 1. if the temperature is higher than a trip point,
>>         + *    a. if the trend is THERMAL_TREND_RAISING, use higher
>>         cooling
>>         + *       state for this trip point
>>         + *    b. if the trend is THERMAL_TREND_DROPPING, use lower
>>         cooling
>>         + *       state for this trip point
>>         + *
>>         + * 2. if the temperature is lower than a trip point, use
>>         lower
>>         + *    cooling state for this trip point
>>         + *
>>         + * Note that this behaves the same as the previous passive
>>         cooling
>>         + * algorithm.
>>         + */
>>         +
>>         +static void thermal_zone_trip_update(struct
>>         thermal_zone_device *tz,
>>         +                                    int trip, long temp)
>>         +{
>>         +       struct thermal_cooling_device_instance *instance;
>>         +       struct thermal_cooling_device *cdev = NULL;
>>         +       unsigned long cur_state, max_state;
>>         +       long trip_temp;
>>         +       enum thermal_trend trend;
>>         +
>>         +       tz->ops->get_trip_temp(tz, trip, &trip_temp);
>>         +
>>         +       if (temp >= trip_temp) {
>>         +               thermal_get_trend(tz, trip, &trend);
>>         +
>>         +               list_for_each_entry(instance,
>>         &tz->cooling_devices, node) {
>>         +                       if (instance->trip != trip)
>>         +                               continue;
>>         +
>>         +                       cdev = instance->cdev;
>>         +
>>         +                       cdev->ops->get_cur_state(cdev,
>>         &cur_state);
>>         +                       cdev->ops->get_max_state(cdev,
>>         &max_state);
>>         +
>>         +                       if (trend == THERMAL_TREND_RAISING) {
>>         +                               cur_state = cur_state <
>>         instance->upper ?
>>         +                                           (cur_state + 1) :
>>         instance->upper;
>>         +                       } else if (trend ==
>>         THERMAL_TREND_DROPPING) {
>>         +                               cur_state = cur_state >
>>         instance->lower ?
>>         +                                   (cur_state - 1) :
>>         instance->lower;
>>         +                       }
>>         +                       cdev->ops->set_cur_state(cdev,
>>         cur_state);
>>         +               }
>>         +       } else {        /* below trip */
>>         +               list_for_each_entry(instance,
>>         &tz->cooling_devices, node) {
>>         +                       if (instance->trip != trip)
>>         +                               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);
>>         +               }
>>         +       }
>>         +
>>         +       return;
>>         +}
>>          /**
>>           * thermal_zone_device_update - force an update of a thermal
>>         zone's state
>>           * @ttz:       the thermal zone to update
>>         @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct
>>         thermal_zone_device *tz)
>>                 int count, ret = 0;
>>                 long temp, trip_temp;
>>                 enum thermal_trip_type trip_type;
>>         -       struct thermal_cooling_device_instance *instance;
>>         -       struct thermal_cooling_device *cdev;
>>         -       unsigned long cur_state, max_state;
>>
>>                 mutex_lock(&tz->lock);
>>
>>         @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct
>>         thermal_zone_device *tz)
>>                                                 tz->ops->notify(tz,
>>         count, trip_type);
>>                                 break;
>>                         case THERMAL_TRIP_ACTIVE:
>>         -                       list_for_each_entry(instance,
>>         &tz->cooling_devices,
>>         -                                           node) {
>>         -                               if (instance->trip != count)
>>         -                                       continue;
>>         -
>>         -                               cdev = instance->cdev;
>>         -
>>         -                               cdev->ops->get_cur_state(cdev,
>>         &cur_state);
>>         -                               cdev->ops->get_max_state(cdev,
>>         &max_state);
>>         -
>>         -                               if (temp >= trip_temp)
>>         -                                       cur_state =
>>         -                                               cur_state <
>>         instance->upper ?
>>         -                                               (cur_state +
>>         1) :
>>         -
>>         instance->upper;
>>         -                               else
>>         -                                       cur_state =
>>         -                                               cur_state >
>>         instance->lower ?
>>         -                                               (cur_state -
>>         1) :
>>         -
>>         instance->lower;
>>         -
>>         -                               cdev->ops->set_cur_state(cdev,
>>         cur_state);
>>         -                       }
>>         +                       thermal_zone_trip_update(tz, count,
>>         temp);
>>                                 break;
>>                         case THERMAL_TRIP_PASSIVE:
>>                                 if (temp >= trip_temp || tz->passive)
>>         --
>>         1.7.9.5
>>
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/16] Thermal: Introduce .get_trend() callback.
  2012-07-24  1:42     ` Zhang Rui
@ 2012-07-24  9:22       ` Rafael J. Wysocki
  0 siblings, 0 replies; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-24  9:22 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On Tuesday, July 24, 2012, Zhang Rui wrote:
> On 四, 2012-07-19 at 23:13 +0200, Rafael J. Wysocki wrote:
> > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > tc1 and tc2 are used by OSPM to anticipate the temperature trends.
> > > But they are ACPI platform specific concepts.
> > > 
> > > Introduce .get_trend() as a more general solution.
> > > 
> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > ---
> > >  drivers/acpi/thermal.c        |   30 ++++++++++++++++++++++++++++++
> > >  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
> > >  include/linux/thermal.h       |    9 +++++++++
> > >  3 files changed, 56 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > index a7c97f5..b345646 100644
> > > --- a/drivers/acpi/thermal.c
> > > +++ b/drivers/acpi/thermal.c
> > > @@ -704,6 +704,35 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
> > >  		return -EINVAL;
> > >  }
> > >  
> > > +static int thermal_get_trend(struct thermal_zone_device *thermal,
> > > +				int trip, enum thermal_trend *trend)
> > > +{
> > > +	struct acpi_thermal *tz = thermal->devdata;
> > > +	enum thermal_trip_type type;
> > > +	unsigned long trip_temp;
> > > +	int i;
> > > +
> > > +	if (thermal_get_trip_type(thermal, trip, &type))
> > > +		return -EINVAL;
> > > +
> > > +	/* Only PASSIVE trip points need TREND */
> > > +	if (type != THERMAL_TRIP_PASSIVE)
> > > +		return -EINVAL;
> > > +
> > > +	/*
> > > +	 * tz->temperature has already been updated by generic thermal layer,
> > > +	 * before this callback being invoked
> > > +	 */
> > > +	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> > > +		+ (tz->trips.passive.tc2
> > > +		* (tz->temperature - tz->trips.passive.temperature));
> > > +
> > > +	*trend = i > 0 ? THERMAL_TREND_RAISING :
> > > +		(i < 0 ? THERMAL_TREND_DROPPING : THERMAL_TREND_STABLE);
> > 
> > I'd use if (...) / else if (...) / else here.  It would be _way_ more readable.
> > 
> agreed.
> 
> > > +	return 0;
> > > +}
> > > +
> > > +
> > >  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
> > >  			   enum thermal_trip_type trip_type)
> > >  {
> > > @@ -832,6 +861,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
> > >  	.get_trip_type = thermal_get_trip_type,
> > >  	.get_trip_temp = thermal_get_trip_temp,
> > >  	.get_crit_temp = thermal_get_crit_temp,
> > > +	.get_trend = thermal_get_trend,
> > >  	.notify = thermal_notify,
> > >  };
> > >  
> > > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > > index db35300..29b6dba 100644
> > > --- a/drivers/thermal/thermal_sys.c
> > > +++ b/drivers/thermal/thermal_sys.c
> > > @@ -698,6 +698,18 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
> > >  }
> > >  #endif
> > >  
> > > +static void thermal_get_trend(struct thermal_zone_device *tz,
> > > +		int trip, enum thermal_trend *trend)
> > 
> > The fact that this function has the same name as the ACPI one above is kind of
> > disturbing.  Any chance to call it differently?
> > 
> > > +{
> > > +	if (tz->ops->get_trend)
> > > +		if (!tz->ops->get_trend(tz, trip, trend))
> > > +			return;
> > 
> > What about:
> > 
> > +	if (tz->ops->get_trend && !tz->ops->get_trend(tz, trip, trend))
> > +		return;
> > 
> > And since the error code returned by .get_trend() apparently doesn't matter,
> > shouldn't it return a bool?
> > 
> agreed.
> > > +
> > > +	*trend = tz->temperature >= tz->last_temperature ?
> > > +		 THERMAL_TREND_RAISING : THERMAL_TREND_DROPPING;
> > > +	return;
> > > +}
> > > +
> > >  static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
> > >  					    int delay)
> > >  {
> > > @@ -732,6 +744,8 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> > >  	if (temp >= trip_temp) {
> > >  		tz->passive = true;
> > >  
> > > +		thermal_get_trend(tz, trip, (enum thermal_trend *)&trend);
> > 
> > What's wrong with the data type of 'trend' here?
> > 
> this is no functional changes in this patch.

Sure.

I was wondering if the explicit cast could be avoided.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-24  1:47     ` Zhang Rui
@ 2012-07-24  9:27       ` Rafael J. Wysocki
  2012-07-25  1:38         ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-24  9:27 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On Tuesday, July 24, 2012, Zhang Rui wrote:
> On 四, 2012-07-19 at 23:19 +0200, Rafael J. Wysocki wrote:
> > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > This function is used to update the cooling state of
> > > all the cooling devices that are binded to an active trip point.
> > 
> > s/binded/bound/
> > 
> got it.
> 
> > > This will be used for passive cooling as well, in the future patches.
> > > as both active and passive cooling can share the same algorithm,
> > > which is
> > > 
> > > 1. if the temperature is higher than a trip point,
> > >    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > >       state for this trip point
> > >    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > >       state for this trip point
> > > 
> > > 2. if the temperature is lower than a trip point, use lower
> > >    cooling state for this trip point.
> > > 
> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > ---
> > >  drivers/acpi/thermal.c        |    7 +++-
> > >  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
> > >  2 files changed, 71 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > index 73e335f..14c4879 100644
> > > --- a/drivers/acpi/thermal.c
> > > +++ b/drivers/acpi/thermal.c
> > > @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
> > >  	if (thermal_get_trip_type(thermal, trip, &type))
> > >  		return -EINVAL;
> > >  
> > > -	/* Only PASSIVE trip points need TREND */
> > > +	if (type == THERMAL_TRIP_ACTIVE) {
> > > +		/* aggressive active cooling */
> > > +		*trend = THERMAL_TREND_RAISING;
> > > +		return 0;
> > 
> > Please move that into thermal_zone_trip_update() directly, unless you
> > need it elsewhere.
> > 
> IMO, I can say that ACPI thermal wants aggressive active cooling, as it
> will never spin down the fan when the temperature is higher than the
> trip point.

I meant the code organization, not the functionality. :-)

Since thermal_get_trend() is static, it is not used outside of this file,
so you can move the "if (type == THERMAL_TRIP_ACTIVE)" conditional from it
directly into the caller (unless there are more callers, which I'm not sure
about without reading the whole code again).

That would make the code cleaner, because right now the condition is
hidden in thermal_get_trend() and it may not be clear to the reader of
thermal_zone_trip_update() that it is actually checked.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-24  9:27       ` Rafael J. Wysocki
@ 2012-07-25  1:38         ` Zhang Rui
  2012-07-25 11:07           ` Rafael J. Wysocki
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-25  1:38 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 二, 2012-07-24 at 11:27 +0200, Rafael J. Wysocki wrote:
> On Tuesday, July 24, 2012, Zhang Rui wrote:
> > On 四, 2012-07-19 at 23:19 +0200, Rafael J. Wysocki wrote:
> > > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > > This function is used to update the cooling state of
> > > > all the cooling devices that are binded to an active trip point.
> > > 
> > > s/binded/bound/
> > > 
> > got it.
> > 
> > > > This will be used for passive cooling as well, in the future patches.
> > > > as both active and passive cooling can share the same algorithm,
> > > > which is
> > > > 
> > > > 1. if the temperature is higher than a trip point,
> > > >    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > > >       state for this trip point
> > > >    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > > >       state for this trip point
> > > > 
> > > > 2. if the temperature is lower than a trip point, use lower
> > > >    cooling state for this trip point.
> > > > 
> > > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > > ---
> > > >  drivers/acpi/thermal.c        |    7 +++-
> > > >  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
> > > >  2 files changed, 71 insertions(+), 27 deletions(-)
> > > > 
> > > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > > index 73e335f..14c4879 100644
> > > > --- a/drivers/acpi/thermal.c
> > > > +++ b/drivers/acpi/thermal.c
> > > > @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
> > > >  	if (thermal_get_trip_type(thermal, trip, &type))
> > > >  		return -EINVAL;
> > > >  
> > > > -	/* Only PASSIVE trip points need TREND */
> > > > +	if (type == THERMAL_TRIP_ACTIVE) {
> > > > +		/* aggressive active cooling */
> > > > +		*trend = THERMAL_TREND_RAISING;
> > > > +		return 0;
> > > 
> > > Please move that into thermal_zone_trip_update() directly, unless you
> > > need it elsewhere.
> > > 
> > IMO, I can say that ACPI thermal wants aggressive active cooling, as it
> > will never spin down the fan when the temperature is higher than the
> > trip point.
> 
> I meant the code organization, not the functionality. :-)
> 
sure.

> Since thermal_get_trend() is static, it is not used outside of this file,
> so you can move the "if (type == THERMAL_TRIP_ACTIVE)" conditional from it
> directly into the caller (unless there are more callers, which I'm not sure
> about without reading the whole code again).
> 
sorry I still do not get it.
the generic thermal layer is the caller of this callback.
so you mean in thermal_zone_trip_update(),
when updating an active trip point, we set the trend to
THERMAL_TREND_RAISING explicitly?
in this way, all the platform thermal drivers will spin up the fan step
by step when the temperature is higher than the trip point, even if the
temperature is dropping. (Note that, this is not a problem for ACPI, as
there is only two state for ACPI FAN, on/off, it must be always on when
the temperature is higher than the active trip point. but other platform
may want to spin down the fan a little even if the system is still warm)

> That would make the code cleaner, because right now the condition is
> hidden in thermal_get_trend() and it may not be clear to the reader of
> thermal_zone_trip_update() that it is actually checked.
> 
why?
Readers should trust the value returned by
drivers/thermal/thermal_sys.c:thermal_get_trend().
And platform thermal drivers should provide the proper trend for active
trip points as well. If they don't, we will use the default trend by
comparing the current temperature and last temperature.

thanks,
rui

> Thanks,
> Rafael


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-25  1:38         ` Zhang Rui
@ 2012-07-25 11:07           ` Rafael J. Wysocki
  2012-07-26  0:49             ` Zhang Rui
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2012-07-25 11:07 UTC (permalink / raw)
  To: Zhang Rui
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On Wednesday, July 25, 2012, Zhang Rui wrote:
> On 二, 2012-07-24 at 11:27 +0200, Rafael J. Wysocki wrote:
> > On Tuesday, July 24, 2012, Zhang Rui wrote:
> > > On 四, 2012-07-19 at 23:19 +0200, Rafael J. Wysocki wrote:
> > > > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > > > This function is used to update the cooling state of
> > > > > all the cooling devices that are binded to an active trip point.
> > > > 
> > > > s/binded/bound/
> > > > 
> > > got it.
> > > 
> > > > > This will be used for passive cooling as well, in the future patches.
> > > > > as both active and passive cooling can share the same algorithm,
> > > > > which is
> > > > > 
> > > > > 1. if the temperature is higher than a trip point,
> > > > >    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > > > >       state for this trip point
> > > > >    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > > > >       state for this trip point
> > > > > 
> > > > > 2. if the temperature is lower than a trip point, use lower
> > > > >    cooling state for this trip point.
> > > > > 
> > > > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > > > ---
> > > > >  drivers/acpi/thermal.c        |    7 +++-
> > > > >  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
> > > > >  2 files changed, 71 insertions(+), 27 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > > > index 73e335f..14c4879 100644
> > > > > --- a/drivers/acpi/thermal.c
> > > > > +++ b/drivers/acpi/thermal.c
> > > > > @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
> > > > >  	if (thermal_get_trip_type(thermal, trip, &type))
> > > > >  		return -EINVAL;
> > > > >  
> > > > > -	/* Only PASSIVE trip points need TREND */
> > > > > +	if (type == THERMAL_TRIP_ACTIVE) {
> > > > > +		/* aggressive active cooling */
> > > > > +		*trend = THERMAL_TREND_RAISING;
> > > > > +		return 0;
> > > > 
> > > > Please move that into thermal_zone_trip_update() directly, unless you
> > > > need it elsewhere.
> > > > 
> > > IMO, I can say that ACPI thermal wants aggressive active cooling, as it
> > > will never spin down the fan when the temperature is higher than the
> > > trip point.
> > 
> > I meant the code organization, not the functionality. :-)
> > 
> sure.
> 
> > Since thermal_get_trend() is static, it is not used outside of this file,
> > so you can move the "if (type == THERMAL_TRIP_ACTIVE)" conditional from it
> > directly into the caller (unless there are more callers, which I'm not sure
> > about without reading the whole code again).
> > 
> sorry I still do not get it.
> the generic thermal layer is the caller of this callback.

I'm not talking about the callback, but of the static function with the
same name you've introduced into drivers/thermal/thermal_sys.c in the
previous patch. :-)

The only caller of this function seems to be thermal_zone_device_passive()
and my point is that it would be better to simply put the code from that
function into thermal_zone_device_passive() directly, unless there are
more callers added by the subsequent patches, which I'm not sure about.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-25 11:07           ` Rafael J. Wysocki
@ 2012-07-26  0:49             ` Zhang Rui
  0 siblings, 0 replies; 56+ messages in thread
From: Zhang Rui @ 2012-07-26  0:49 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Amit Kachhap, linux-acpi, linux-pm, Matthew Garrett, Len Brown,
	R Durgadoss, Wei Ni

On 三, 2012-07-25 at 13:07 +0200, Rafael J. Wysocki wrote:
> On Wednesday, July 25, 2012, Zhang Rui wrote:
> > On 二, 2012-07-24 at 11:27 +0200, Rafael J. Wysocki wrote:
> > > On Tuesday, July 24, 2012, Zhang Rui wrote:
> > > > On 四, 2012-07-19 at 23:19 +0200, Rafael J. Wysocki wrote:
> > > > > On Thursday, July 19, 2012, Zhang Rui wrote:
> > > > > > This function is used to update the cooling state of
> > > > > > all the cooling devices that are binded to an active trip point.
> > > > > 
> > > > > s/binded/bound/
> > > > > 
> > > > got it.
> > > > 
> > > > > > This will be used for passive cooling as well, in the future patches.
> > > > > > as both active and passive cooling can share the same algorithm,
> > > > > > which is
> > > > > > 
> > > > > > 1. if the temperature is higher than a trip point,
> > > > > >    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > > > > >       state for this trip point
> > > > > >    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > > > > >       state for this trip point
> > > > > > 
> > > > > > 2. if the temperature is lower than a trip point, use lower
> > > > > >    cooling state for this trip point.
> > > > > > 
> > > > > > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > > > > > ---
> > > > > >  drivers/acpi/thermal.c        |    7 +++-
> > > > > >  drivers/thermal/thermal_sys.c |   91 +++++++++++++++++++++++++++++------------
> > > > > >  2 files changed, 71 insertions(+), 27 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > > > > > index 73e335f..14c4879 100644
> > > > > > --- a/drivers/acpi/thermal.c
> > > > > > +++ b/drivers/acpi/thermal.c
> > > > > > @@ -715,7 +715,12 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
> > > > > >  	if (thermal_get_trip_type(thermal, trip, &type))
> > > > > >  		return -EINVAL;
> > > > > >  
> > > > > > -	/* Only PASSIVE trip points need TREND */
> > > > > > +	if (type == THERMAL_TRIP_ACTIVE) {
> > > > > > +		/* aggressive active cooling */
> > > > > > +		*trend = THERMAL_TREND_RAISING;
> > > > > > +		return 0;
> > > > > 
> > > > > Please move that into thermal_zone_trip_update() directly, unless you
> > > > > need it elsewhere.
> > > > > 
> > > > IMO, I can say that ACPI thermal wants aggressive active cooling, as it
> > > > will never spin down the fan when the temperature is higher than the
> > > > trip point.
> > > 
> > > I meant the code organization, not the functionality. :-)
> > > 
> > sure.
> > 
> > > Since thermal_get_trend() is static, it is not used outside of this file,
> > > so you can move the "if (type == THERMAL_TRIP_ACTIVE)" conditional from it
> > > directly into the caller (unless there are more callers, which I'm not sure
> > > about without reading the whole code again).
> > > 
> > sorry I still do not get it.
> > the generic thermal layer is the caller of this callback.
> 
> I'm not talking about the callback, but of the static function with the
> same name you've introduced into drivers/thermal/thermal_sys.c in the
> previous patch. :-)
> 
> The only caller of this function seems to be thermal_zone_device_passive()
> and my point is that it would be better to simply put the code from that
> function into thermal_zone_device_passive() directly, unless there are
> more callers added by the subsequent patches, which I'm not sure about.

hah, I understand.
yes, I can move thermal_sys.c thermal_get_trend() in to
thermal_trip_update.
and there will be no such confusion (two functions share the same name)
any more. :)

thanks,
rui

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-24  8:06       ` Amit Kachhap
@ 2012-07-26  5:08         ` Zhang Rui
  2012-07-26  6:01           ` R, Durgadoss
  0 siblings, 1 reply; 56+ messages in thread
From: Zhang Rui @ 2012-07-26  5:08 UTC (permalink / raw)
  To: Amit Kachhap
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, R Durgadoss, Eduardo Valentin, Wei Ni

On 二, 2012-07-24 at 13:36 +0530, Amit Kachhap wrote:
> On 24 July 2012 12:41, Zhang Rui <rui.zhang@intel.com> wrote:
> > On 二, 2012-07-24 at 12:27 +0530, Amit Kachhap wrote:
> >>
> >>
> >> On 19 July 2012 12:01, Zhang Rui <rui.zhang@intel.com> wrote:
> >>         This function is used to update the cooling state of
> >>         all the cooling devices that are binded to an active trip
> >>         point.
> >>
> >>         This will be used for passive cooling as well, in the future
> >>         patches.
> >>         as both active and passive cooling can share the same
> >>         algorithm,
> >>         which is
> >>
> >>         1. if the temperature is higher than a trip point,
> >>            a. if the trend is THERMAL_TREND_RAISING, use higher
> >>         cooling
> >>               state for this trip point
> >>            b. if the trend is THERMAL_TREND_DROPPING, use lower
> >>         cooling
> >>               state for this trip point
> >>
> >>         2. if the temperature is lower than a trip point, use lower
> >>            cooling state for this trip point.
> >>
> >> Hi Rui,
> >>
> >> Your patches looks useful.
> >> For my platform I need to have get_trend called even in the case when
> >> current temp is less than the trip point and then use
> >> THERMAL_TREND_DROPPING to actually lower the cooling state.
> >>
> > hmm, why?
> > in the current cooling algorithm, when the temperature is lower than the
> > trip point, the cooling state is decreased by 1 every time,
> > unconditionally, isn't this what you want?
> 
> Basically the requirement is that I do not want to remove the cooling
> device when the temp just reaches below the trip point because this
> causes many throttling in this trip point so say I will remove cooling
> device when the temp is < (trip - 5) which can be done inside the new
> platform get_trend call.
> 
As Durga is working on the thermal governor patches, I think that one
can handle this, right?

Currently, as I do not want to change the behavior of the current
drivers, ACPI passive cooling, etc, I did not use trend when the
temperature is lower  than the trip point.
But anyway, if really needed, I can generate an incremental patch.
what do you think?

thanks,
rui

> Thanks,
> Amit D
> >
> > thanks,
> > rui
> >
> >> Thanks,
> >> Amit
> >>
> >>
> >>         Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> >>         ---
> >>          drivers/acpi/thermal.c        |    7 +++-
> >>          drivers/thermal/thermal_sys.c |   91
> >>         +++++++++++++++++++++++++++++------------
> >>          2 files changed, 71 insertions(+), 27 deletions(-)
> >>
> >>         diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> >>         index 73e335f..14c4879 100644
> >>         --- a/drivers/acpi/thermal.c
> >>         +++ b/drivers/acpi/thermal.c
> >>         @@ -715,7 +715,12 @@ static int thermal_get_trend(struct
> >>         thermal_zone_device *thermal,
> >>                 if (thermal_get_trip_type(thermal, trip, &type))
> >>                         return -EINVAL;
> >>
> >>         -       /* Only PASSIVE trip points need TREND */
> >>         +       if (type == THERMAL_TRIP_ACTIVE) {
> >>         +               /* aggressive active cooling */
> >>         +               *trend = THERMAL_TREND_RAISING;
> >>         +               return 0;
> >>         +       }
> >>         +
> >>                 if (type != THERMAL_TRIP_PASSIVE)
> >>                         return -EINVAL;
> >>
> >>         diff --git a/drivers/thermal/thermal_sys.c
> >>         b/drivers/thermal/thermal_sys.c
> >>         index 59af3b8..011faba 100644
> >>         --- a/drivers/thermal/thermal_sys.c
> >>         +++ b/drivers/thermal/thermal_sys.c
> >>         @@ -1076,6 +1076,70 @@ void
> >>         thermal_cooling_device_unregister(struct
> >>          }
> >>          EXPORT_SYMBOL(thermal_cooling_device_unregister);
> >>
> >>         +/*
> >>         + * Cooling algorithm for active trip points
> >>         + *
> >>         + * 1. if the temperature is higher than a trip point,
> >>         + *    a. if the trend is THERMAL_TREND_RAISING, use higher
> >>         cooling
> >>         + *       state for this trip point
> >>         + *    b. if the trend is THERMAL_TREND_DROPPING, use lower
> >>         cooling
> >>         + *       state for this trip point
> >>         + *
> >>         + * 2. if the temperature is lower than a trip point, use
> >>         lower
> >>         + *    cooling state for this trip point
> >>         + *
> >>         + * Note that this behaves the same as the previous passive
> >>         cooling
> >>         + * algorithm.
> >>         + */
> >>         +
> >>         +static void thermal_zone_trip_update(struct
> >>         thermal_zone_device *tz,
> >>         +                                    int trip, long temp)
> >>         +{
> >>         +       struct thermal_cooling_device_instance *instance;
> >>         +       struct thermal_cooling_device *cdev = NULL;
> >>         +       unsigned long cur_state, max_state;
> >>         +       long trip_temp;
> >>         +       enum thermal_trend trend;
> >>         +
> >>         +       tz->ops->get_trip_temp(tz, trip, &trip_temp);
> >>         +
> >>         +       if (temp >= trip_temp) {
> >>         +               thermal_get_trend(tz, trip, &trend);
> >>         +
> >>         +               list_for_each_entry(instance,
> >>         &tz->cooling_devices, node) {
> >>         +                       if (instance->trip != trip)
> >>         +                               continue;
> >>         +
> >>         +                       cdev = instance->cdev;
> >>         +
> >>         +                       cdev->ops->get_cur_state(cdev,
> >>         &cur_state);
> >>         +                       cdev->ops->get_max_state(cdev,
> >>         &max_state);
> >>         +
> >>         +                       if (trend == THERMAL_TREND_RAISING) {
> >>         +                               cur_state = cur_state <
> >>         instance->upper ?
> >>         +                                           (cur_state + 1) :
> >>         instance->upper;
> >>         +                       } else if (trend ==
> >>         THERMAL_TREND_DROPPING) {
> >>         +                               cur_state = cur_state >
> >>         instance->lower ?
> >>         +                                   (cur_state - 1) :
> >>         instance->lower;
> >>         +                       }
> >>         +                       cdev->ops->set_cur_state(cdev,
> >>         cur_state);
> >>         +               }
> >>         +       } else {        /* below trip */
> >>         +               list_for_each_entry(instance,
> >>         &tz->cooling_devices, node) {
> >>         +                       if (instance->trip != trip)
> >>         +                               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);
> >>         +               }
> >>         +       }
> >>         +
> >>         +       return;
> >>         +}
> >>          /**
> >>           * thermal_zone_device_update - force an update of a thermal
> >>         zone's state
> >>           * @ttz:       the thermal zone to update
> >>         @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct
> >>         thermal_zone_device *tz)
> >>                 int count, ret = 0;
> >>                 long temp, trip_temp;
> >>                 enum thermal_trip_type trip_type;
> >>         -       struct thermal_cooling_device_instance *instance;
> >>         -       struct thermal_cooling_device *cdev;
> >>         -       unsigned long cur_state, max_state;
> >>
> >>                 mutex_lock(&tz->lock);
> >>
> >>         @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct
> >>         thermal_zone_device *tz)
> >>                                                 tz->ops->notify(tz,
> >>         count, trip_type);
> >>                                 break;
> >>                         case THERMAL_TRIP_ACTIVE:
> >>         -                       list_for_each_entry(instance,
> >>         &tz->cooling_devices,
> >>         -                                           node) {
> >>         -                               if (instance->trip != count)
> >>         -                                       continue;
> >>         -
> >>         -                               cdev = instance->cdev;
> >>         -
> >>         -                               cdev->ops->get_cur_state(cdev,
> >>         &cur_state);
> >>         -                               cdev->ops->get_max_state(cdev,
> >>         &max_state);
> >>         -
> >>         -                               if (temp >= trip_temp)
> >>         -                                       cur_state =
> >>         -                                               cur_state <
> >>         instance->upper ?
> >>         -                                               (cur_state +
> >>         1) :
> >>         -
> >>         instance->upper;
> >>         -                               else
> >>         -                                       cur_state =
> >>         -                                               cur_state >
> >>         instance->lower ?
> >>         -                                               (cur_state -
> >>         1) :
> >>         -
> >>         instance->lower;
> >>         -
> >>         -                               cdev->ops->set_cur_state(cdev,
> >>         cur_state);
> >>         -                       }
> >>         +                       thermal_zone_trip_update(tz, count,
> >>         temp);
> >>                                 break;
> >>                         case THERMAL_TRIP_PASSIVE:
> >>                                 if (temp >= trip_temp || tz->passive)
> >>         --
> >>         1.7.9.5
> >>
> >>
> >
> >


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* RE: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
  2012-07-26  5:08         ` Zhang Rui
@ 2012-07-26  6:01           ` R, Durgadoss
  0 siblings, 0 replies; 56+ messages in thread
From: R, Durgadoss @ 2012-07-26  6:01 UTC (permalink / raw)
  To: Zhang, Rui, Amit Kachhap
  Cc: linux-acpi, linux-pm, Rafael J. Wysocki, Matthew Garrett,
	Len Brown, Eduardo Valentin, Wei Ni

Hi Rui/Amit,


> -----Original Message-----
> From: Zhang, Rui
> Sent: Thursday, July 26, 2012 10:38 AM
> To: Amit Kachhap
> Cc: linux-acpi@vger.kernel.org; linux-pm@vger.kernel.org; Rafael J. Wysocki;
> Matthew Garrett; Len Brown; R, Durgadoss; Eduardo Valentin; Wei Ni
> Subject: Re: [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update()
> 
> On 二, 2012-07-24 at 13:36 +0530, Amit Kachhap wrote:
> > On 24 July 2012 12:41, Zhang Rui <rui.zhang@intel.com> wrote:
> > > On 二, 2012-07-24 at 12:27 +0530, Amit Kachhap wrote:
> > >>
> > >>
> > >> On 19 July 2012 12:01, Zhang Rui <rui.zhang@intel.com> wrote:
> > >>         This function is used to update the cooling state of
> > >>         all the cooling devices that are binded to an active trip
> > >>         point.
> > >>
> > >>         This will be used for passive cooling as well, in the future
> > >>         patches.
> > >>         as both active and passive cooling can share the same
> > >>         algorithm,
> > >>         which is
> > >>
> > >>         1. if the temperature is higher than a trip point,
> > >>            a. if the trend is THERMAL_TREND_RAISING, use higher
> > >>         cooling
> > >>               state for this trip point
> > >>            b. if the trend is THERMAL_TREND_DROPPING, use lower
> > >>         cooling
> > >>               state for this trip point
> > >>
> > >>         2. if the temperature is lower than a trip point, use lower
> > >>            cooling state for this trip point.
> > >>
> > >> Hi Rui,
> > >>
> > >> Your patches looks useful.
> > >> For my platform I need to have get_trend called even in the case when
> > >> current temp is less than the trip point and then use
> > >> THERMAL_TREND_DROPPING to actually lower the cooling state.
> > >>
> > > hmm, why?
> > > in the current cooling algorithm, when the temperature is lower than the
> > > trip point, the cooling state is decreased by 1 every time,
> > > unconditionally, isn't this what you want?
> >
> > Basically the requirement is that I do not want to remove the cooling
> > device when the temp just reaches below the trip point because this
> > causes many throttling in this trip point so say I will remove cooling
> > device when the temp is < (trip - 5) which can be done inside the new
> > platform get_trend call.
> >
> As Durga is working on the thermal governor patches, I think that one
> can handle this, right?

I am fine with this..Since we anyway want all throttling logic to be moved to
the governor, I think it makes sense to put this there.

So, I will pick it up, when I submit the governor patches.
Amit, Please feel free to point out if I don’t pick this one in my patches.

Thanks,
Durga
> 
> Currently, as I do not want to change the behavior of the current
> drivers, ACPI passive cooling, etc, I did not use trend when the
> temperature is lower  than the trip point.
> But anyway, if really needed, I can generate an incremental patch.
> what do you think?
> 
> thanks,
> rui
> 
> > Thanks,
> > Amit D
> > >
> > > thanks,
> > > rui
> > >
> > >> Thanks,
> > >> Amit
> > >>
> > >>
> > >>         Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > >>         ---
> > >>          drivers/acpi/thermal.c        |    7 +++-
> > >>          drivers/thermal/thermal_sys.c |   91
> > >>         +++++++++++++++++++++++++++++------------
> > >>          2 files changed, 71 insertions(+), 27 deletions(-)
> > >>
> > >>         diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > >>         index 73e335f..14c4879 100644
> > >>         --- a/drivers/acpi/thermal.c
> > >>         +++ b/drivers/acpi/thermal.c
> > >>         @@ -715,7 +715,12 @@ static int thermal_get_trend(struct
> > >>         thermal_zone_device *thermal,
> > >>                 if (thermal_get_trip_type(thermal, trip, &type))
> > >>                         return -EINVAL;
> > >>
> > >>         -       /* Only PASSIVE trip points need TREND */
> > >>         +       if (type == THERMAL_TRIP_ACTIVE) {
> > >>         +               /* aggressive active cooling */
> > >>         +               *trend = THERMAL_TREND_RAISING;
> > >>         +               return 0;
> > >>         +       }
> > >>         +
> > >>                 if (type != THERMAL_TRIP_PASSIVE)
> > >>                         return -EINVAL;
> > >>
> > >>         diff --git a/drivers/thermal/thermal_sys.c
> > >>         b/drivers/thermal/thermal_sys.c
> > >>         index 59af3b8..011faba 100644
> > >>         --- a/drivers/thermal/thermal_sys.c
> > >>         +++ b/drivers/thermal/thermal_sys.c
> > >>         @@ -1076,6 +1076,70 @@ void
> > >>         thermal_cooling_device_unregister(struct
> > >>          }
> > >>          EXPORT_SYMBOL(thermal_cooling_device_unregister);
> > >>
> > >>         +/*
> > >>         + * Cooling algorithm for active trip points
> > >>         + *
> > >>         + * 1. if the temperature is higher than a trip point,
> > >>         + *    a. if the trend is THERMAL_TREND_RAISING, use higher
> > >>         cooling
> > >>         + *       state for this trip point
> > >>         + *    b. if the trend is THERMAL_TREND_DROPPING, use lower
> > >>         cooling
> > >>         + *       state for this trip point
> > >>         + *
> > >>         + * 2. if the temperature is lower than a trip point, use
> > >>         lower
> > >>         + *    cooling state for this trip point
> > >>         + *
> > >>         + * Note that this behaves the same as the previous passive
> > >>         cooling
> > >>         + * algorithm.
> > >>         + */
> > >>         +
> > >>         +static void thermal_zone_trip_update(struct
> > >>         thermal_zone_device *tz,
> > >>         +                                    int trip, long temp)
> > >>         +{
> > >>         +       struct thermal_cooling_device_instance *instance;
> > >>         +       struct thermal_cooling_device *cdev = NULL;
> > >>         +       unsigned long cur_state, max_state;
> > >>         +       long trip_temp;
> > >>         +       enum thermal_trend trend;
> > >>         +
> > >>         +       tz->ops->get_trip_temp(tz, trip, &trip_temp);
> > >>         +
> > >>         +       if (temp >= trip_temp) {
> > >>         +               thermal_get_trend(tz, trip, &trend);
> > >>         +
> > >>         +               list_for_each_entry(instance,
> > >>         &tz->cooling_devices, node) {
> > >>         +                       if (instance->trip != trip)
> > >>         +                               continue;
> > >>         +
> > >>         +                       cdev = instance->cdev;
> > >>         +
> > >>         +                       cdev->ops->get_cur_state(cdev,
> > >>         &cur_state);
> > >>         +                       cdev->ops->get_max_state(cdev,
> > >>         &max_state);
> > >>         +
> > >>         +                       if (trend == THERMAL_TREND_RAISING) {
> > >>         +                               cur_state = cur_state <
> > >>         instance->upper ?
> > >>         +                                           (cur_state + 1) :
> > >>         instance->upper;
> > >>         +                       } else if (trend ==
> > >>         THERMAL_TREND_DROPPING) {
> > >>         +                               cur_state = cur_state >
> > >>         instance->lower ?
> > >>         +                                   (cur_state - 1) :
> > >>         instance->lower;
> > >>         +                       }
> > >>         +                       cdev->ops->set_cur_state(cdev,
> > >>         cur_state);
> > >>         +               }
> > >>         +       } else {        /* below trip */
> > >>         +               list_for_each_entry(instance,
> > >>         &tz->cooling_devices, node) {
> > >>         +                       if (instance->trip != trip)
> > >>         +                               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);
> > >>         +               }
> > >>         +       }
> > >>         +
> > >>         +       return;
> > >>         +}
> > >>          /**
> > >>           * thermal_zone_device_update - force an update of a thermal
> > >>         zone's state
> > >>           * @ttz:       the thermal zone to update
> > >>         @@ -1086,9 +1150,6 @@ void thermal_zone_device_update(struct
> > >>         thermal_zone_device *tz)
> > >>                 int count, ret = 0;
> > >>                 long temp, trip_temp;
> > >>                 enum thermal_trip_type trip_type;
> > >>         -       struct thermal_cooling_device_instance *instance;
> > >>         -       struct thermal_cooling_device *cdev;
> > >>         -       unsigned long cur_state, max_state;
> > >>
> > >>                 mutex_lock(&tz->lock);
> > >>
> > >>         @@ -1124,29 +1185,7 @@ void thermal_zone_device_update(struct
> > >>         thermal_zone_device *tz)
> > >>                                                 tz->ops->notify(tz,
> > >>         count, trip_type);
> > >>                                 break;
> > >>                         case THERMAL_TRIP_ACTIVE:
> > >>         -                       list_for_each_entry(instance,
> > >>         &tz->cooling_devices,
> > >>         -                                           node) {
> > >>         -                               if (instance->trip != count)
> > >>         -                                       continue;
> > >>         -
> > >>         -                               cdev = instance->cdev;
> > >>         -
> > >>         -                               cdev->ops->get_cur_state(cdev,
> > >>         &cur_state);
> > >>         -                               cdev->ops->get_max_state(cdev,
> > >>         &max_state);
> > >>         -
> > >>         -                               if (temp >= trip_temp)
> > >>         -                                       cur_state =
> > >>         -                                               cur_state <
> > >>         instance->upper ?
> > >>         -                                               (cur_state +
> > >>         1) :
> > >>         -
> > >>         instance->upper;
> > >>         -                               else
> > >>         -                                       cur_state =
> > >>         -                                               cur_state >
> > >>         instance->lower ?
> > >>         -                                               (cur_state -
> > >>         1) :
> > >>         -
> > >>         instance->lower;
> > >>         -
> > >>         -                               cdev->ops->set_cur_state(cdev,
> > >>         cur_state);
> > >>         -                       }
> > >>         +                       thermal_zone_trip_update(tz, count,
> > >>         temp);
> > >>                                 break;
> > >>                         case THERMAL_TRIP_PASSIVE:
> > >>                                 if (temp >= trip_temp || tz->passive)
> > >>         --
> > >>         1.7.9.5
> > >>
> > >>
> > >
> > >
> 


^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2012-07-26  6:02 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-19  6:31 [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui
2012-07-19  6:31 ` [PATCH 01/16] Thermal: Make Thermal trip points writeable Zhang Rui
2012-07-19 10:35   ` R, Durgadoss
2012-07-19 19:38   ` Rafael J. Wysocki
2012-07-23  8:11     ` Zhang Rui
2012-07-19 20:27   ` Rafael J. Wysocki
2012-07-23  8:22     ` Zhang Rui
2012-07-23 10:25       ` Rafael J. Wysocki
2012-07-19  6:31 ` [PATCH 02/16] Thermal: Add Hysteresis attributes Zhang Rui
2012-07-19 10:40   ` R, Durgadoss
2012-07-19 20:00     ` Rafael J. Wysocki
2012-07-19  6:31 ` [PATCH 03/16] Thermal: Documentation update Zhang Rui
2012-07-19 10:51   ` R, Durgadoss
2012-07-23  8:36     ` Zhang Rui
2012-07-19  6:31 ` [PATCH 04/16] Thermal: Introduce multiple cooling states support Zhang Rui
2012-07-19  6:31 ` [PATCH 05/16] Thermal: Introduce cooling states range support Zhang Rui
2012-07-19  6:31 ` [PATCH 06/16] Thermal: set upper and lower limits Zhang Rui
2012-07-19 20:55   ` Rafael J. Wysocki
2012-07-23  8:45     ` Zhang Rui
2012-07-23 19:15       ` Rafael J. Wysocki
2012-07-19  6:31 ` [PATCH 07/16] Thermal: Introduce .get_trend() callback Zhang Rui
2012-07-19 21:13   ` Rafael J. Wysocki
2012-07-24  1:42     ` Zhang Rui
2012-07-24  9:22       ` Rafael J. Wysocki
2012-07-19 22:09   ` Jacob Pan
2012-07-20  9:53     ` Rafael J. Wysocki
2012-07-20 16:12       ` Jacob Pan
2012-07-19  6:31 ` [PATCH 08/16] Thermal: Remove tc1/tc2 in generic thermal layer Zhang Rui
2012-07-19  6:31 ` [PATCH 09/16] Thermal: Introduce thermal_zone_trip_update() Zhang Rui
2012-07-19 21:19   ` Rafael J. Wysocki
2012-07-24  1:47     ` Zhang Rui
2012-07-24  9:27       ` Rafael J. Wysocki
2012-07-25  1:38         ` Zhang Rui
2012-07-25 11:07           ` Rafael J. Wysocki
2012-07-26  0:49             ` Zhang Rui
     [not found]   ` <CAK44p21hNYGH4YkH5E+XK-pM2upingQbvm77WkJbttCRp6ZamQ@mail.gmail.com>
2012-07-24  7:11     ` Zhang Rui
2012-07-24  8:06       ` Amit Kachhap
2012-07-26  5:08         ` Zhang Rui
2012-07-26  6:01           ` R, Durgadoss
2012-07-24  7:57   ` Amit Kachhap
2012-07-19  6:31 ` [PATCH 10/16] Thermal: rename structure thermal_cooling_device_instance to thermal_instance Zhang Rui
2012-07-19  6:31 ` [PATCH 11/16] Thermal: Rename thermal_zone_device.cooling_devices to thermal_zone_device.instances Zhang Rui
2012-07-19 21:22   ` Rafael J. Wysocki
2012-07-24  1:48     ` Zhang Rui
2012-07-19  6:31 ` [PATCH 12/16] Thermal: Rename thermal_instance.node to thermal_instance.tz_node Zhang Rui
2012-07-19  6:31 ` [PATCH 13/16] Thermal: List thermal_instance in thermal_cooling_device Zhang Rui
2012-07-19 21:25   ` Rafael J. Wysocki
2012-07-24  1:48     ` Zhang Rui
2012-07-19  6:31 ` [PATCH 14/16] Thermal: Introduce simple arbitrator for setting device cooling state Zhang Rui
2012-07-19 21:39   ` Rafael J. Wysocki
2012-07-24  1:49     ` Zhang Rui
2012-07-19  6:31 ` [PATCH 15/16] Thermal: Unify the code for both active and passive cooling Zhang Rui
2012-07-19  6:31 ` [PATCH 16/16] Thermal: use plist instead of list Zhang Rui
2012-07-19 21:45   ` Rafael J. Wysocki
2012-07-24  2:13     ` Zhang Rui
2012-07-19  6:37 ` [PATCH 00/16] Thermal: generic thermal layer enhancement Zhang Rui

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.