[PATCHv5 RESEND 09/10] Thermal: Add ABI Documentation for sysfs interfaces

2014-01-17 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R 
---
 Documentation/ABI/testing/sysfs-class-thermal |  161 +
 1 file changed, 161 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..144efc1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,161 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Type of the cooling device
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/cur_state
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Current throttle state the cooling device is in
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/max_state
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Maximum number of throttle states the cooling device supports
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/zone_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor

[PATCHv5 RESEND 03/10] Thermal: Add cooling device APIs

2014-01-17 Thread Durgadoss R
This patch adds the cooling device APIs to the
new thermal framework. The register/unregister
APIs stay the same. Below are some minimal
changes:
 * Use DEVICE_ATTR_RO/RW macros
 * Add 'struct idr idr' to struct thermal_cooling_device
 * Tidy up the error handling paths in register API
 * Use thermal_cdev_register as API name, to keep
   THERMAL_V2 APIs along with the existing ones.
 * Use 'cdevX' as name for cooling_device so as
   to not collide with the existing ABI.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  184 
 include/linux/thermal.h|   12 +++
 2 files changed, 196 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index b369a6f..463165c 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -39,15 +39,21 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support v2");
 MODULE_LICENSE("GPL v2");
 
 static DEFINE_IDR(thermal_sensor_idr);
+static DEFINE_IDR(thermal_cdev_idr);
 
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_cdev_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
+#define to_cooling_device(_dev)\
+   container_of(_dev, struct thermal_cooling_device, device)
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -168,10 +174,69 @@ threshold_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+   return sprintf(buf, "%s\n", cdev->type);
+}
+
+static ssize_t
+max_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev->ops->get_max_state(cdev, );
+   if (ret)
+   return ret;
+   return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+cur_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev->ops->get_cur_state(cdev, );
+   if (ret)
+   return ret;
+   return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+cur_state_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = sscanf(buf, "%ld\n", );
+   if (!ret)
+   return -EINVAL;
+
+   if ((long)state < 0)
+   return -EINVAL;
+
+   ret = cdev->ops->set_cur_state(cdev, state);
+
+   return ret ? ret : count;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
 
+/* Thermal cooling device attributes */
+static DEVICE_ATTR_RO(type);
+static DEVICE_ATTR_RO(max_state);
+static DEVICE_ATTR_RW(cur_state);
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -365,3 +430,122 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
return;
 }
 EXPORT_SYMBOL_GPL(thermal_sensor_unregister);
+
+/**
+ * thermal_cdev_register() - register a new thermal cooling device
+ * @type:  the thermal cooling device type.
+ * @devdata:   device private data.
+ * @ops:   standard thermal cooling devices callbacks.
+ *
+ * This interface function adds a new thermal cooling device to
+ * /sys/class/thermal/ folder as cooling_device[0-*].
+ *
+ * Return: a pointer to the created struct thermal_cooling_device or an
+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
+ */
+struct thermal_cooling_device *thermal_cdev_register(char *type, void *devdata,
+   const struct thermal_cooling_device_ops *ops)
+{
+   struct thermal_cooling_device *cdev;
+   int result;
+
+   if (!type || (type && strlen(type) >= THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   if (!ops || !ops->get_max_state || !ops->get_cur_state ||
+   !ops->set_cur_state)
+   return ERR_PTR(-EINVAL);
+
+   cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+   if (!cdev)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(>idr);
+   result = get_idr(_cdev_idr, >id);
+   if (result)
+   goto exit_free;
+
+   strlcpy(cdev->type, type ? : "", sizeof(cdev->

[PATCHv5 RESEND 08/10] Thermal: Add Documentation to new APIs

2014-01-17 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  240 ++
 1 file changed, 240 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..1045dfc
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,240 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2014 Intel Corporation
+
+Created on: 15 January 2014
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information

[PATCHv5 RESEND 03/10] Thermal: Add cooling device APIs

2014-01-17 Thread Durgadoss R
This patch adds the cooling device APIs to the
new thermal framework. The register/unregister
APIs stay the same. Below are some minimal
changes:
 * Use DEVICE_ATTR_RO/RW macros
 * Add 'struct idr idr' to struct thermal_cooling_device
 * Tidy up the error handling paths in register API
 * Use thermal_cdev_register as API name, to keep
   THERMAL_V2 APIs along with the existing ones.
 * Use 'cdevX' as name for cooling_device so as
   to not collide with the existing ABI.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  184 
 include/linux/thermal.h|   12 +++
 2 files changed, 196 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index b369a6f..463165c 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -39,15 +39,21 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support v2);
 MODULE_LICENSE(GPL v2);
 
 static DEFINE_IDR(thermal_sensor_idr);
+static DEFINE_IDR(thermal_cdev_idr);
 
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_cdev_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
+#define to_cooling_device(_dev)\
+   container_of(_dev, struct thermal_cooling_device, device)
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -168,10 +174,69 @@ threshold_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+   return sprintf(buf, %s\n, cdev-type);
+}
+
+static ssize_t
+max_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev-ops-get_max_state(cdev, state);
+   if (ret)
+   return ret;
+   return sprintf(buf, %ld\n, state);
+}
+
+static ssize_t
+cur_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev-ops-get_cur_state(cdev, state);
+   if (ret)
+   return ret;
+   return sprintf(buf, %ld\n, state);
+}
+
+static ssize_t
+cur_state_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = sscanf(buf, %ld\n, state);
+   if (!ret)
+   return -EINVAL;
+
+   if ((long)state  0)
+   return -EINVAL;
+
+   ret = cdev-ops-set_cur_state(cdev, state);
+
+   return ret ? ret : count;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
 
+/* Thermal cooling device attributes */
+static DEVICE_ATTR_RO(type);
+static DEVICE_ATTR_RO(max_state);
+static DEVICE_ATTR_RW(cur_state);
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -365,3 +430,122 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
return;
 }
 EXPORT_SYMBOL_GPL(thermal_sensor_unregister);
+
+/**
+ * thermal_cdev_register() - register a new thermal cooling device
+ * @type:  the thermal cooling device type.
+ * @devdata:   device private data.
+ * @ops:   standard thermal cooling devices callbacks.
+ *
+ * This interface function adds a new thermal cooling device to
+ * /sys/class/thermal/ folder as cooling_device[0-*].
+ *
+ * Return: a pointer to the created struct thermal_cooling_device or an
+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
+ */
+struct thermal_cooling_device *thermal_cdev_register(char *type, void *devdata,
+   const struct thermal_cooling_device_ops *ops)
+{
+   struct thermal_cooling_device *cdev;
+   int result;
+
+   if (!type || (type  strlen(type) = THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   if (!ops || !ops-get_max_state || !ops-get_cur_state ||
+   !ops-set_cur_state)
+   return ERR_PTR(-EINVAL);
+
+   cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+   if (!cdev)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(cdev-idr);
+   result = get_idr(thermal_cdev_idr, cdev-id);
+   if (result)
+   goto exit_free;
+
+   strlcpy(cdev-type, type ? : , sizeof(cdev-type));
+   mutex_init(cdev-lock);
+   cdev-ops = ops;
+   cdev-updated = true;
+   cdev

[PATCHv5 RESEND 08/10] Thermal: Add Documentation to new APIs

2014-01-17 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/thermal/sysfs-api2.txt |  240 ++
 1 file changed, 240 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..1045dfc
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,240 @@
+Thermal Framework
+-
+
+Written by Durgadoss R durgados...@intel.com
+Copyright (c) 2014 Intel Corporation
+
+Created on: 15 January 2014
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides

[PATCHv5 RESEND 09/10] Thermal: Add ABI Documentation for sysfs interfaces

2014-01-17 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/ABI/testing/sysfs-class-thermal |  161 +
 1 file changed, 161 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..144efc1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,161 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Type of the cooling device
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/cur_state
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Current throttle state the cooling device is in
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/cdevX/max_state
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Maximum number of throttle states the cooling device supports
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/zone_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users

[PATCHv5 01/10] Thermal: Do kfree in _unregister functions

2014-01-16 Thread Durgadoss R
Currently the thermal_release function does
kfree for all devices when they call device_unregister.
This makes code scattering i.e whenever we add new
devices (to thermal class) we need to add its
corresponding kfree in thermal_release function.
And the if-else is also growing lengthy.

Instead, do all kfree() of devices in their own
_unregister functions. This makes the code look
clean and easy to maintain.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |   17 +
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 338a88b..165afc6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1042,18 +1042,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device);
 
 static void thermal_release(struct device *dev)
 {
-   struct thermal_zone_device *tz;
-   struct thermal_cooling_device *cdev;
-
-   if (!strncmp(dev_name(dev), "thermal_zone",
-sizeof("thermal_zone") - 1)) {
-   tz = to_thermal_zone(dev);
-   kfree(tz);
-   } else if(!strncmp(dev_name(dev), "cooling_device",
-   sizeof("cooling_device") - 1)){
-   cdev = to_cooling_device(dev);
-   kfree(cdev);
-   }
+   /* No-op since kfree(dev) is done in _unregister functions */
 }
 
 static struct class thermal_class = {
@@ -1146,6 +1135,7 @@ __thermal_cooling_device_register(struct device_node *np,
 unregister:
release_idr(_cdev_idr, _idr_lock, cdev->id);
device_unregister(>device);
+   kfree(cdev);
return ERR_PTR(result);
 }
 
@@ -1250,6 +1240,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
release_idr(_cdev_idr, _idr_lock, cdev->id);
device_unregister(>device);
+   kfree(cdev);
return;
 }
 EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
@@ -1563,6 +1554,7 @@ struct thermal_zone_device 
*thermal_zone_device_register(const char *type,
 unregister:
release_idr(_tz_idr, _idr_lock, tz->id);
device_unregister(>device);
+   kfree(tz);
return ERR_PTR(result);
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_register);
@@ -1630,6 +1622,7 @@ void thermal_zone_device_unregister(struct 
thermal_zone_device *tz)
idr_destroy(>idr);
mutex_destroy(>lock);
device_unregister(>device);
+   kfree(tz);
return;
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv5 02/10] Thermal: Create sensor level APIs

2014-01-16 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework, in a new file named
thermal_core_new.c. The thermal_class variable
is moved as extern to thermal_core.h to
facilitate co-existence of both the APIs.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|3 +
 drivers/thermal/Makefile   |1 +
 drivers/thermal/thermal_core.c |2 +-
 drivers/thermal/thermal_core.h |1 +
 drivers/thermal/thermal_core_new.c |  367 
 include/linux/thermal.h|   37 
 6 files changed, 410 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/thermal_core_new.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 35c0664..f6a8057 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,9 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_V2
+   bool
+
 config THERMAL_HWMON
bool
prompt "Expose thermal sensors as hwmon device"
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 54e4ec9..d9ae9ac 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_THERMAL)  += thermal_sys.o
 thermal_sys-y  += thermal_core.o
+thermal_sys-$(CONFIG_THERMAL_V2) += thermal_core_new.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 165afc6..a17702f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1045,7 +1045,7 @@ static void thermal_release(struct device *dev)
/* No-op since kfree(dev) is done in _unregister functions */
 }
 
-static struct class thermal_class = {
+struct class thermal_class = {
.name = "thermal",
.dev_release = thermal_release,
 };
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 3db339f..adf817c 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 
+extern struct class thermal_class;
 /* Initial state of a cooling device during binding */
 #define THERMAL_NO_TARGET -1UL
 
diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
new file mode 100644
index 000..b369a6f
--- /dev/null
+++ b/drivers/thermal/thermal_core_new.c
@@ -0,0 +1,367 @@
+/*
+ *  thermal_core_new.c - Generic Thermal Management Sysfs support.
+ *  Derived from the previous thermal_core.c
+ *  This adds multiple sensor per zone support along with various
+ *  options to provide platform data for Thermal management.
+ *
+ *  Copyright (C) 2014 Intel Corporation
+ *
+ *  ~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "thermal_core.h"
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("Generic thermal management sysfs support v2");
+MODULE_LICENSE("GPL v2");
+
+static DEFINE_IDR(thermal_sensor_idr);
+
+static LIST_HEAD(thermal_sensor_list);
+
+static DEFINE_MUTEX(thermal_idr_lock);
+static DEFINE_MUTEX(sensor_list_lock);
+
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static int get_idr(struct idr *idr, int *id)
+{
+   int ret;
+
+   mutex_lock(_idr_lock);
+   ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+   mutex_unlock(_idr_lock);
+
+   if (unlikely(ret < 0))
+   return ret;
+
+   *id = ret;
+   return 0;
+}
+
+static void release_idr(struct idr *idr, int id)
+{
+   mutex_lock(_idr_lock);
+   idr_remove(idr, id);
+   mutex_unlock(_idr_lock);
+}
+
+static ssize_t
+name_show(struct device *dev, struct device_attribute *attr

[PATCHv5 05/10] Thermal: Add APIs to bind cdev to new zone structure

2014-01-16 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the existing cooling device implementation.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  135 
 include/linux/thermal.h|8 +++
 2 files changed, 143 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index 4f84cb5..3134b1a 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -66,6 +66,9 @@ static DEFINE_MUTEX(zone_list_lock);
 #define for_each_thermal_zone(pos) \
list_for_each_entry(pos, _zone_list, node)
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, _cdev_list, node)
+
 #define GET_INDEX(tz, ptr, type)   \
 ({ \
int i, ret = -EINVAL;   \
@@ -301,6 +304,27 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
mutex_unlock(>lock);
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   mutex_lock(>lock);
+
+   /* Shift the entries in the tz->cdevs array */
+   for (j = indx; j < MAX_CDEVS_PER_ZONE - 1; j++)
+   tz->cdevs[j] = tz->cdevs[j + 1];
+
+   tz->cdev_indx--;
+   mutex_unlock(>lock);
+}
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -593,6 +617,7 @@ EXPORT_SYMBOL_GPL(thermal_cdev_register);
 void thermal_cdev_unregister(struct thermal_cooling_device *cdev)
 {
struct thermal_cooling_device *pos, *next;
+   struct thermal_zone *tz;
bool found = false;
 
if (!cdev)
@@ -610,6 +635,13 @@ void thermal_cdev_unregister(struct thermal_cooling_device 
*cdev)
if (!found)
return;
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tz)
+   remove_cdev_from_zone(tz, cdev);
+
+   mutex_unlock(_list_lock);
+
device_remove_file(>device, _attr_type);
device_remove_file(>device, _attr_max_state);
device_remove_file(>device, _attr_cur_state);
@@ -688,6 +720,7 @@ void thermal_remove_thermal_zone(struct thermal_zone *tz)
 {
struct thermal_zone *pos, *next;
struct thermal_sensor *ts;
+   struct thermal_cooling_device *cdev;
bool found = false;
 
if (!tz)
@@ -709,6 +742,9 @@ void thermal_remove_thermal_zone(struct thermal_zone *tz)
for_each_thermal_sensor(ts)
remove_sensor_from_zone(tz, ts);
 
+   for_each_cdev(cdev)
+   remove_cdev_from_zone(tz, cdev);
+
device_remove_file(>device, _attr_zone_name);
 
mutex_destroy(>lock);
@@ -817,3 +853,102 @@ exit_zone:
return ret;
 }
 EXPORT_SYMBOL_GPL(thermal_add_sensor_to_zone);
+
+/**
+ * thermal_get_cdev_by_name() - search for a cdev and returns its reference
+ * @name: cooling device name to fetch the reference
+ *
+ * On success returns a reference to an unique cdev with
+ * the name matching that of @name, an ERR_PTR otherwise:
+ * -EINVAL for invalid paramenters
+ * -ENODEV for cdev not found
+ * -EEXIST for multiple matches
+ */
+struct thermal_cooling_device *thermal_get_cdev_by_name(const char *name)
+{
+   int found = 0;
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = ERR_PTR(-EINVAL);
+
+   if (!name)
+   return cdev;
+
+   mutex_lock(_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos->type, name, THERMAL_NAME_LENGTH)) {
+   found++;
+   cdev = pos;
+   }
+   }
+   mutex_unlock(_list_lock);
+
+   /*
+* Nothing has been found; return an error code for it.
+* Return success only when an unique cdev is found.
+*/
+   if (found == 0)
+   cdev = ERR_PTR(-ENODEV);
+   else if (found > 1)
+   cdev = ERR_PTR(-EEXIST);
+
+   return cdev;
+}
+EXPORT_SYMBOL_GPL(thermal_get_cdev_by_name);
+
+/**
+ * thermal_add_cdev_to_zone - Add @cdev to thermal zone @tz
+ * @tz:Thermal zone reference
+ * @cdev:  Cooling device reference
+ *
+ * Returns 0 on success, otherwise
+ * -EINVAL for invalid paramenters
+ * -EINVAL when trying to add more cdevs than MAX_CDEVS_PER_ZONE
+ * -EEXIST when trying add existing cdev again
+ */
+int thermal_add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(_list

[PATCHv5 08/10] Thermal: Add Documentation to new APIs

2014-01-16 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  240 ++
 1 file changed, 240 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..dd03297
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,240 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2014 Intel Corporation
+
+Created on: 15 January 2014
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information

[PATCHv5 04/10] Thermal: Create zone level APIs

2014-01-16 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  268 
 include/linux/thermal.h|   23 
 2 files changed, 291 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index ba38438..4f84cb5 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -40,13 +40,16 @@ MODULE_LICENSE("GPL v2");
 
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_zone_idr);
 
 static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
+static LIST_HEAD(thermal_zone_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(cdev_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
@@ -54,6 +57,35 @@ static DEFINE_MUTEX(cdev_list_lock);
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
 
+#define to_thermal_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, _sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, _zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(>lock);  \
+   mutex_lock(##_list_lock);  \
+   for (i = 0; i < tz->type##_indx; i++) { \
+   if (tz->type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(##_list_lock);\
+   mutex_unlock(>lock);\
+   } while (0);\
+   ret;\
+})
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -228,6 +260,14 @@ cur_state_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   return sprintf(buf, "%s\n", tz->name);
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -237,6 +277,30 @@ static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(max_state);
 static DEVICE_ATTR_RW(cur_state);
 
+/* Thermal zone attributes */
+static DEVICE_ATTR_RO(zone_name);
+
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   mutex_lock(>lock);
+
+   /* Shift the entries in the tz->sensors array */
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   tz->sensors[j] = tz->sensors[j + 1];
+
+   tz->sensor_indx--;
+   mutex_unlock(>lock);
+}
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -391,6 +455,7 @@ EXPORT_SYMBOL_GPL(thermal_sensor_register);
 void thermal_sensor_unregister(struct thermal_sensor *ts)
 {
int i;
+   struct thermal_zone *tz;
struct thermal_sensor *pos, *next;
bool found = false;
 
@@ -410,6 +475,13 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
if (!found)
return;
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tz)
+   remove_sensor_from_zone(tz, ts);
+
+   mutex_unlock(_list_lock);
+
for (i = 0; i < ts->thresholds; i++) {
device_remove_file(>device, >thresh_attrs[i].attr);
if (ts->ops->get_hyst) {
@@ -549,3 +621,199 @@ void thermal_cdev_unregister(struct 
therm

[PATCHv5 06/10] Thermal: Add trip point sysfs nodes for sensor

2014-01-16 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_activeY,
sensorX_trip_passiveY, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  358 +++-
 include/linux/thermal.h|   39 +++-
 2 files changed, 395 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index 3134b1a..e6a35f0 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -111,6 +111,25 @@ static void release_idr(struct idr *idr, int id)
mutex_unlock(_idr_lock);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   /* Protect against tz->sensors[i] being unregistered */
+   mutex_lock(_list_lock);
+
+   for (i = 0; i < tz->sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(>sensors[i]->device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+
+   mutex_unlock(_list_lock);
+   return indx;
+}
+
 static ssize_t
 name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -271,6 +290,115 @@ zone_name_show(struct device *dev, struct 
device_attribute *attr, char *buf)
return sprintf(buf, "%s\n", tz->name);
 }
 
+static ssize_t
+active_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr->attr.name, "sensor%d_trip_active%d", , );
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+
+   mutex_lock(>lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i < 0) {
+   mutex_unlock(>lock);
+   return i;
+   }
+
+   val = tz->sensor_trip[i]->active_trips[j];
+   mutex_unlock(>lock);
+
+   return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+passive_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr->attr.name, "sensor%d_trip_passive%d", , );
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+
+   mutex_lock(>lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i < 0) {
+   mutex_unlock(>lock);
+   return i;
+   }
+
+   val = tz->sensor_trip[i]->passive_trips[j];
+   mutex_unlock(>lock);
+
+   return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+hot_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr->attr.name, "sensor%d_trip_hot", );
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", indx);
+
+   mutex_lock(>lock);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0) {
+   mutex_unlock(>lock);
+   return indx;
+   }
+
+   val = tz->sensor_trip[indx]->hot;
+   mutex_unlock(>lock);
+
+   return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+critical_trip_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr->attr.name, "sensor%d_trip_critical", );
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", indx);
+
+   mutex_lock(>lock);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0) {
+   mutex_unlock(>lock);
+   return indx;
+   }
+
+   val = tz->sensor_trip[indx]->crit;
+   mutex_unlock(>lock);
+
+   return sprintf(buf, "%d\n", val);
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -283,6 +411,41 @@ static DEVICE_ATTR_RW(cur_state);
 /* Thermal zone attributes */
 static DEVICE_ATTR_RO(zone_name);
 
+static void __remove_trip_attr(

[PATCHv5 10/10] Thermal: Dummy driver used for testing

2014-01-16 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|6 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  322 
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index f6a8057..7bfa23e 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -225,4 +225,10 @@ depends on PLAT_SAMSUNG
 source "drivers/thermal/samsung/Kconfig"
 endmenu
 
+config THERMAL_TEST
+   tristate "test driver"
+   select THERMAL_V2
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d9ae9ac..9a7ed0e 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -32,3 +32,6 @@ obj-$(CONFIG_INTEL_POWERCLAMP)+= intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
 obj-$(CONFIG_ACPI_INT3403_THERMAL) += int3403_thermal.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..6bdb22b
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,322 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~~~~~
+ * Author: Durgadoss R 
+ */
+
+#define pr_fmt(fmt)  "thermal_test: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = "ts",
+   .cdev_name = "cdev",
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, "%d\n", ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ts_data.flag = flag;
+
+   if (flag == 0) {
+   thermal_sensor_unreg

[PATCHv5 07/10] Thermal: Create Thermal map sysfs attributes for a zone

2014-01-16 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. The thermal map
shows the binding relationship between a sensor
and a cooling device within a particular zone.
This contains entries named mapY_trip_type,
mapY_sensor_name, mapY_cdev_name, mapY_trip_mask,
mapY_weightX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  275 
 include/linux/thermal.h|   25 
 2 files changed, 300 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index e6a35f0..62f95c2 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -399,6 +399,131 @@ critical_trip_show(struct device *dev,
return sprintf(buf, "%d\n", val);
 }
 
+static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr->attr.name, "map%d_trip_type", );
+   if (!ret)
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n",
+   tz->map[indx]->trip_type == THERMAL_TRIP_ACTIVE ?
+   "active" : "passive");
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr->attr.name, "map%d_sensor_name", );
+   if (!ret)
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n", tz->map[indx]->sensor_name);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr->attr.name, "map%d_cdev_name", );
+   if (!ret)
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n", tz->map[indx]->cdev_name);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr->attr.name, "map%d_trip_mask", );
+   if (!ret)
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "0x%x\n", tz->map[indx]->trip_mask);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_weights_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int i, j, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr->attr.name, "map%d_weight%d", , );
+   if (!ret)
+   return -EINVAL;
+
+   if (i < 0 || i >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[i])
+   goto exit;
+
+   if (j < 0 || j >= tz->map[i]->num_weights)
+   goto exit;
+
+   ret = sprintf(buf, "%d\n", tz->map[i]->weights[j]);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -446,6 +571,24 @@ static void __remove_trip_attr(struct thermal_zone *tz, 
int indx)
tz->trip_attr[indx] = NULL;
 }
 
+static void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr;
+
+   attr = tz->map_attr[indx];
+
+   for (i = 0; i < NUM_MAP_ATTRS; i++)
+   device_remove_file(>device, >attrs[i].attr);
+
+   for (i = 0; i < tz->map[indx]->num_weights; i++)
+   device_remove_file(>device, >weights_attr[i].attr);
+
+   kfree(tz->map_attr[indx]);
+   tz->ma

[PATCHv5 09/10] Thermal: Add ABI Documentation for sysfs interfaces

2014-01-16 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R 
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..c646585
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/zone_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_mask
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip point mask

[PATCHv5 03/10] Thermal: Add cooling device APIs

2014-01-16 Thread Durgadoss R
This patch adds the cooling device APIs to the
new thermal framework. The register/unregister
APIs stay the same. Below are some minimal
changes:
 * Use DEVICE_ATTR_RO/RW macros
 * Add 'struct idr idr' to struct thermal_cooling_device
 * Tidy up the error handling paths in register API
 * Use thermal_cdev_register as API name, to keep
   THERMAL_V2 APIs along with the existing ones.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core_new.c |  184 
 include/linux/thermal.h|   12 +++
 2 files changed, 196 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index b369a6f..ba38438 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -39,15 +39,21 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support v2");
 MODULE_LICENSE("GPL v2");
 
 static DEFINE_IDR(thermal_sensor_idr);
+static DEFINE_IDR(thermal_cdev_idr);
 
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_cdev_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
+#define to_cooling_device(_dev)\
+   container_of(_dev, struct thermal_cooling_device, device)
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -168,10 +174,69 @@ threshold_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+   return sprintf(buf, "%s\n", cdev->type);
+}
+
+static ssize_t
+max_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev->ops->get_max_state(cdev, );
+   if (ret)
+   return ret;
+   return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+cur_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev->ops->get_cur_state(cdev, );
+   if (ret)
+   return ret;
+   return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+cur_state_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = sscanf(buf, "%ld\n", );
+   if (!ret)
+   return -EINVAL;
+
+   if ((long)state < 0)
+   return -EINVAL;
+
+   ret = cdev->ops->set_cur_state(cdev, state);
+
+   return ret ? ret : count;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
 
+/* Thermal cooling device attributes */
+static DEVICE_ATTR_RO(type);
+static DEVICE_ATTR_RO(max_state);
+static DEVICE_ATTR_RW(cur_state);
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -365,3 +430,122 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
return;
 }
 EXPORT_SYMBOL_GPL(thermal_sensor_unregister);
+
+/**
+ * thermal_cdev_register() - register a new thermal cooling device
+ * @type:  the thermal cooling device type.
+ * @devdata:   device private data.
+ * @ops:   standard thermal cooling devices callbacks.
+ *
+ * This interface function adds a new thermal cooling device to
+ * /sys/class/thermal/ folder as cooling_device[0-*].
+ *
+ * Return: a pointer to the created struct thermal_cooling_device or an
+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
+ */
+struct thermal_cooling_device *thermal_cdev_register(char *type, void *devdata,
+   const struct thermal_cooling_device_ops *ops)
+{
+   struct thermal_cooling_device *cdev;
+   int result;
+
+   if (!type || (type && strlen(type) >= THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   if (!ops || !ops->get_max_state || !ops->get_cur_state ||
+   !ops->set_cur_state)
+   return ERR_PTR(-EINVAL);
+
+   cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+   if (!cdev)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(>idr);
+   result = get_idr(_cdev_idr, >id);
+   if (result)
+   goto exit_free;
+
+   strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
+   mutex_init(>lock);
+   cdev->ops = ops;
+   cdev->updated = t

[PATCHv5 00/10] Thermal Framework Enhancements

2014-01-16 Thread Durgadoss R
This patch set is a v5 of the previous versions submitted here:
[v4]: http://lwn.net/Articles/568988/
[v3]: https://lkml.org/lkml/2013/2/5/228 
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, on top
of commit 'c698a4492f01127ca90fc28cd5157f3d616fe4ff'
This is tested on a Core-i5 running ubuntu 12.04.

Changes since v4:
 * Cleaned up the thermal_release function; Now all
   kfree's are done in _unregister functions.
 * Kconfig option to selectively enable and use this
   new version of thermal_core.c
 * According to a previous comment from Rui, moved all
   new API's into a file named thermal_core_new.c
Changes since v3:
 * Added a patch to conditionally do kfree(cdev) in
   thermal_release function.
 * Reworked all sysfs attributes to have one value per file
   This includes sensor_trip_* and map_weight* attributes.
 * Added 'lock' variable in thermal_zone structure to
   protect its members.
 * Added Documentation to all functions in thermal_core.c
 * Changes all strcpy() to strlcpy()
 * Used devm_kzalloc() in places where applicable
 * Address some buffer overflow conditions and contentions
   in tz->sensors[] and tz->cdevs[].
Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 10 patches:
Patch 1/10: Remove code from thermal_release function. 
Do kfree in _unregister functions.
Patch 2/10: Creates new sensor level APIs
Patch 3/10: Adds new cooling device APIs
Patch 4/10: Creates new zone level APIs. The existing tzd structure is
kept as such for clarity and compatibility purposes.
Patch 5/10: Creates functions to add/remove a cdev to/from a zone. The
existing tcd structure need not be modified.
Patch 6/10: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
under /sys/class/thermal/zoneY/. This exposes various trip
points for sensorX present in zoneY.
Patch 7/10: Adds mapY_* sysfs node. These attributes represent the
relationship between various sensors and cooling
devices in a thermal zone.
Patch 8/10: Creates Documentation for the new APIs. A new file is
created for clarity. Final goal is to merge with the existing
file or refactor the files, as whatever seems appropriate.
Patch 9/10: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 10/10: A dummy driver that can be used for testing. This is not for merge.

Thanks to Rui for helping me in resolving some
Kconfig issues, related to this series.

Durgadoss R (10):
  Thermal: Do kfree in _unregister functions
  Thermal: Create sensor level APIs
  Thermal: Add cooling device APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 +++
 Documentation/thermal/sysfs-api2.txt  |  240 
 drivers/thermal/Kconfig   |9 +
 drivers/thermal/Makefile  |4 +
 drivers/thermal/thermal_core.c|   19 +-
 drivers/thermal/thermal_core.h|1 +
 drivers/thermal/thermal_core_new.c| 1585 +
 drivers/thermal/thermal_test.c|  322 +
 include/linux/thermal.h   |  144 ++-
 9 files changed, 2447 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_core_new.c
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv5 00/10] Thermal Framework Enhancements

2014-01-16 Thread Durgadoss R
This patch set is a v5 of the previous versions submitted here:
[v4]: http://lwn.net/Articles/568988/
[v3]: https://lkml.org/lkml/2013/2/5/228 
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, on top
of commit 'c698a4492f01127ca90fc28cd5157f3d616fe4ff'
This is tested on a Core-i5 running ubuntu 12.04.

Changes since v4:
 * Cleaned up the thermal_release function; Now all
   kfree's are done in _unregister functions.
 * Kconfig option to selectively enable and use this
   new version of thermal_core.c
 * According to a previous comment from Rui, moved all
   new API's into a file named thermal_core_new.c
Changes since v3:
 * Added a patch to conditionally do kfree(cdev) in
   thermal_release function.
 * Reworked all sysfs attributes to have one value per file
   This includes sensor_trip_* and map_weight* attributes.
 * Added 'lock' variable in thermal_zone structure to
   protect its members.
 * Added Documentation to all functions in thermal_core.c
 * Changes all strcpy() to strlcpy()
 * Used devm_kzalloc() in places where applicable
 * Address some buffer overflow conditions and contentions
   in tz-sensors[] and tz-cdevs[].
Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 10 patches:
Patch 1/10: Remove code from thermal_release function. 
Do kfree in _unregister functions.
Patch 2/10: Creates new sensor level APIs
Patch 3/10: Adds new cooling device APIs
Patch 4/10: Creates new zone level APIs. The existing tzd structure is
kept as such for clarity and compatibility purposes.
Patch 5/10: Creates functions to add/remove a cdev to/from a zone. The
existing tcd structure need not be modified.
Patch 6/10: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
under /sys/class/thermal/zoneY/. This exposes various trip
points for sensorX present in zoneY.
Patch 7/10: Adds mapY_* sysfs node. These attributes represent the
relationship between various sensors and cooling
devices in a thermal zone.
Patch 8/10: Creates Documentation for the new APIs. A new file is
created for clarity. Final goal is to merge with the existing
file or refactor the files, as whatever seems appropriate.
Patch 9/10: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 10/10: A dummy driver that can be used for testing. This is not for merge.

Thanks to Rui for helping me in resolving some
Kconfig issues, related to this series.

Durgadoss R (10):
  Thermal: Do kfree in _unregister functions
  Thermal: Create sensor level APIs
  Thermal: Add cooling device APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 +++
 Documentation/thermal/sysfs-api2.txt  |  240 
 drivers/thermal/Kconfig   |9 +
 drivers/thermal/Makefile  |4 +
 drivers/thermal/thermal_core.c|   19 +-
 drivers/thermal/thermal_core.h|1 +
 drivers/thermal/thermal_core_new.c| 1585 +
 drivers/thermal/thermal_test.c|  322 +
 include/linux/thermal.h   |  144 ++-
 9 files changed, 2447 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_core_new.c
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv5 03/10] Thermal: Add cooling device APIs

2014-01-16 Thread Durgadoss R
This patch adds the cooling device APIs to the
new thermal framework. The register/unregister
APIs stay the same. Below are some minimal
changes:
 * Use DEVICE_ATTR_RO/RW macros
 * Add 'struct idr idr' to struct thermal_cooling_device
 * Tidy up the error handling paths in register API
 * Use thermal_cdev_register as API name, to keep
   THERMAL_V2 APIs along with the existing ones.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  184 
 include/linux/thermal.h|   12 +++
 2 files changed, 196 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index b369a6f..ba38438 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -39,15 +39,21 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support v2);
 MODULE_LICENSE(GPL v2);
 
 static DEFINE_IDR(thermal_sensor_idr);
+static DEFINE_IDR(thermal_cdev_idr);
 
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_cdev_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
+#define to_cooling_device(_dev)\
+   container_of(_dev, struct thermal_cooling_device, device)
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -168,10 +174,69 @@ threshold_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+   return sprintf(buf, %s\n, cdev-type);
+}
+
+static ssize_t
+max_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev-ops-get_max_state(cdev, state);
+   if (ret)
+   return ret;
+   return sprintf(buf, %ld\n, state);
+}
+
+static ssize_t
+cur_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = cdev-ops-get_cur_state(cdev, state);
+   if (ret)
+   return ret;
+   return sprintf(buf, %ld\n, state);
+}
+
+static ssize_t
+cur_state_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct thermal_cooling_device *cdev = to_cooling_device(dev);
+   unsigned long state;
+   int ret;
+
+   ret = sscanf(buf, %ld\n, state);
+   if (!ret)
+   return -EINVAL;
+
+   if ((long)state  0)
+   return -EINVAL;
+
+   ret = cdev-ops-set_cur_state(cdev, state);
+
+   return ret ? ret : count;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
 
+/* Thermal cooling device attributes */
+static DEVICE_ATTR_RO(type);
+static DEVICE_ATTR_RO(max_state);
+static DEVICE_ATTR_RW(cur_state);
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -365,3 +430,122 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
return;
 }
 EXPORT_SYMBOL_GPL(thermal_sensor_unregister);
+
+/**
+ * thermal_cdev_register() - register a new thermal cooling device
+ * @type:  the thermal cooling device type.
+ * @devdata:   device private data.
+ * @ops:   standard thermal cooling devices callbacks.
+ *
+ * This interface function adds a new thermal cooling device to
+ * /sys/class/thermal/ folder as cooling_device[0-*].
+ *
+ * Return: a pointer to the created struct thermal_cooling_device or an
+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
+ */
+struct thermal_cooling_device *thermal_cdev_register(char *type, void *devdata,
+   const struct thermal_cooling_device_ops *ops)
+{
+   struct thermal_cooling_device *cdev;
+   int result;
+
+   if (!type || (type  strlen(type) = THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   if (!ops || !ops-get_max_state || !ops-get_cur_state ||
+   !ops-set_cur_state)
+   return ERR_PTR(-EINVAL);
+
+   cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+   if (!cdev)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(cdev-idr);
+   result = get_idr(thermal_cdev_idr, cdev-id);
+   if (result)
+   goto exit_free;
+
+   strlcpy(cdev-type, type ? : , sizeof(cdev-type));
+   mutex_init(cdev-lock);
+   cdev-ops = ops;
+   cdev-updated = true;
+   cdev-device.class = thermal_class;
+   cdev-devdata = devdata;
+
+   dev_set_name(cdev-device

[PATCHv5 09/10] Thermal: Add ABI Documentation for sysfs interfaces

2014-01-16 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..c646585
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/zone_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  January 2014
+KernelVersion: 3.13
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel/User space

[PATCHv5 07/10] Thermal: Create Thermal map sysfs attributes for a zone

2014-01-16 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. The thermal map
shows the binding relationship between a sensor
and a cooling device within a particular zone.
This contains entries named mapY_trip_type,
mapY_sensor_name, mapY_cdev_name, mapY_trip_mask,
mapY_weightX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  275 
 include/linux/thermal.h|   25 
 2 files changed, 300 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index e6a35f0..62f95c2 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -399,6 +399,131 @@ critical_trip_show(struct device *dev,
return sprintf(buf, %d\n, val);
 }
 
+static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr-attr.name, map%d_trip_type, indx);
+   if (!ret)
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n,
+   tz-map[indx]-trip_type == THERMAL_TRIP_ACTIVE ?
+   active : passive);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr-attr.name, map%d_sensor_name, indx);
+   if (!ret)
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n, tz-map[indx]-sensor_name);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr-attr.name, map%d_cdev_name, indx);
+   if (!ret)
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n, tz-map[indx]-cdev_name);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr-attr.name, map%d_trip_mask, indx);
+   if (!ret)
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, 0x%x\n, tz-map[indx]-trip_mask);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_weights_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int i, j, ret;
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   ret = sscanf(attr-attr.name, map%d_weight%d, i, j);
+   if (!ret)
+   return -EINVAL;
+
+   if (i  0 || i = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[i])
+   goto exit;
+
+   if (j  0 || j = tz-map[i]-num_weights)
+   goto exit;
+
+   ret = sprintf(buf, %d\n, tz-map[i]-weights[j]);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -446,6 +571,24 @@ static void __remove_trip_attr(struct thermal_zone *tz, 
int indx)
tz-trip_attr[indx] = NULL;
 }
 
+static void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr;
+
+   attr = tz-map_attr[indx];
+
+   for (i = 0; i  NUM_MAP_ATTRS; i++)
+   device_remove_file(tz-device, attr-attrs[i].attr);
+
+   for (i = 0; i  tz-map[indx]-num_weights; i++)
+   device_remove_file(tz-device, attr-weights_attr[i].attr);
+
+   kfree(tz-map_attr[indx]);
+   tz-map_attr[indx] = NULL;
+   tz-map[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -470,6 +613,14 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
}
 
tz-sensor_indx

[PATCHv5 10/10] Thermal: Dummy driver used for testing

2014-01-16 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|6 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  322 
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index f6a8057..7bfa23e 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -225,4 +225,10 @@ depends on PLAT_SAMSUNG
 source drivers/thermal/samsung/Kconfig
 endmenu
 
+config THERMAL_TEST
+   tristate test driver
+   select THERMAL_V2
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d9ae9ac..9a7ed0e 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -32,3 +32,6 @@ obj-$(CONFIG_INTEL_POWERCLAMP)+= intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
 obj-$(CONFIG_ACPI_INT3403_THERMAL) += int3403_thermal.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..6bdb22b
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,322 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~
+ * Author: Durgadoss R durgados...@intel.com
+ */
+
+#define pr_fmt(fmt)  thermal_test:  fmt
+
+#include linux/module.h
+#include linux/init.h
+#include linux/err.h
+#include linux/param.h
+#include linux/device.h
+#include linux/slab.h
+#include linux/pm.h
+#include linux/platform_device.h
+#include linux/thermal.h
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = ts,
+   .cdev_name = cdev,
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, %d\n, ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, flag))
+   return -EINVAL

[PATCHv5 06/10] Thermal: Add trip point sysfs nodes for sensor

2014-01-16 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_activeY,
sensorX_trip_passiveY, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  358 +++-
 include/linux/thermal.h|   39 +++-
 2 files changed, 395 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index 3134b1a..e6a35f0 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -111,6 +111,25 @@ static void release_idr(struct idr *idr, int id)
mutex_unlock(thermal_idr_lock);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   /* Protect against tz-sensors[i] being unregistered */
+   mutex_lock(sensor_list_lock);
+
+   for (i = 0; i  tz-sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(tz-sensors[i]-device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+
+   mutex_unlock(sensor_list_lock);
+   return indx;
+}
+
 static ssize_t
 name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -271,6 +290,115 @@ zone_name_show(struct device *dev, struct 
device_attribute *attr, char *buf)
return sprintf(buf, %s\n, tz-name);
 }
 
+static ssize_t
+active_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr-attr.name, sensor%d_trip_active%d, i, j);
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+
+   mutex_lock(tz-lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i  0) {
+   mutex_unlock(tz-lock);
+   return i;
+   }
+
+   val = tz-sensor_trip[i]-active_trips[j];
+   mutex_unlock(tz-lock);
+
+   return sprintf(buf, %d\n, val);
+}
+
+static ssize_t
+passive_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr-attr.name, sensor%d_trip_passive%d, i, j);
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+
+   mutex_lock(tz-lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i  0) {
+   mutex_unlock(tz-lock);
+   return i;
+   }
+
+   val = tz-sensor_trip[i]-passive_trips[j];
+   mutex_unlock(tz-lock);
+
+   return sprintf(buf, %d\n, val);
+}
+
+static ssize_t
+hot_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr-attr.name, sensor%d_trip_hot, indx);
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, indx);
+
+   mutex_lock(tz-lock);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0) {
+   mutex_unlock(tz-lock);
+   return indx;
+   }
+
+   val = tz-sensor_trip[indx]-hot;
+   mutex_unlock(tz-lock);
+
+   return sprintf(buf, %d\n, val);
+}
+
+static ssize_t
+critical_trip_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   val = sscanf(attr-attr.name, sensor%d_trip_critical, indx);
+   if (!val)
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, indx);
+
+   mutex_lock(tz-lock);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0) {
+   mutex_unlock(tz-lock);
+   return indx;
+   }
+
+   val = tz-sensor_trip[indx]-crit;
+   mutex_unlock(tz-lock);
+
+   return sprintf(buf, %d\n, val);
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -283,6 +411,41 @@ static DEVICE_ATTR_RW(cur_state);
 /* Thermal zone attributes */
 static DEVICE_ATTR_RO(zone_name);
 
+static void __remove_trip_attr(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_trip_attr *attr = tz-trip_attr[indx];
+   struct thermal_trip_point *trip = tz-sensor_trip[indx];
+
+   if (!attr

[PATCHv5 08/10] Thermal: Add Documentation to new APIs

2014-01-16 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/thermal/sysfs-api2.txt |  240 ++
 1 file changed, 240 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..dd03297
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,240 @@
+Thermal Framework
+-
+
+Written by Durgadoss R durgados...@intel.com
+Copyright (c) 2014 Intel Corporation
+
+Created on: 15 January 2014
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides

[PATCHv5 04/10] Thermal: Create zone level APIs

2014-01-16 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  268 
 include/linux/thermal.h|   23 
 2 files changed, 291 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index ba38438..4f84cb5 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -40,13 +40,16 @@ MODULE_LICENSE(GPL v2);
 
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_zone_idr);
 
 static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
+static LIST_HEAD(thermal_zone_list);
 
 static DEFINE_MUTEX(thermal_idr_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(cdev_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
@@ -54,6 +57,35 @@ static DEFINE_MUTEX(cdev_list_lock);
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
 
+#define to_thermal_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, thermal_sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, thermal_zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(tz-lock);  \
+   mutex_lock(type##_list_lock);  \
+   for (i = 0; i  tz-type##_indx; i++) { \
+   if (tz-type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(type##_list_lock);\
+   mutex_unlock(tz-lock);\
+   } while (0);\
+   ret;\
+})
+
 static int get_idr(struct idr *idr, int *id)
 {
int ret;
@@ -228,6 +260,14 @@ cur_state_store(struct device *dev, struct 
device_attribute *attr,
return ret ? ret : count;
 }
 
+static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_thermal_zone(dev);
+
+   return sprintf(buf, %s\n, tz-name);
+}
+
 /* Thermal sensor attributes */
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(temp);
@@ -237,6 +277,30 @@ static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(max_state);
 static DEVICE_ATTR_RW(cur_state);
 
+/* Thermal zone attributes */
+static DEVICE_ATTR_RO(zone_name);
+
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
+   mutex_lock(tz-lock);
+
+   /* Shift the entries in the tz-sensors array */
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   tz-sensors[j] = tz-sensors[j + 1];
+
+   tz-sensor_indx--;
+   mutex_unlock(tz-lock);
+}
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -391,6 +455,7 @@ EXPORT_SYMBOL_GPL(thermal_sensor_register);
 void thermal_sensor_unregister(struct thermal_sensor *ts)
 {
int i;
+   struct thermal_zone *tz;
struct thermal_sensor *pos, *next;
bool found = false;
 
@@ -410,6 +475,13 @@ void thermal_sensor_unregister(struct thermal_sensor *ts)
if (!found)
return;
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tz)
+   remove_sensor_from_zone(tz, ts);
+
+   mutex_unlock(zone_list_lock);
+
for (i = 0; i  ts-thresholds; i++) {
device_remove_file(ts-device, ts-thresh_attrs[i].attr);
if (ts-ops-get_hyst) {
@@ -549,3 +621,199 @@ void thermal_cdev_unregister(struct 
thermal_cooling_device *cdev)
return;
 }
 EXPORT_SYMBOL_GPL

[PATCHv5 05/10] Thermal: Add APIs to bind cdev to new zone structure

2014-01-16 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the existing cooling device implementation.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core_new.c |  135 
 include/linux/thermal.h|8 +++
 2 files changed, 143 insertions(+)

diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
index 4f84cb5..3134b1a 100644
--- a/drivers/thermal/thermal_core_new.c
+++ b/drivers/thermal/thermal_core_new.c
@@ -66,6 +66,9 @@ static DEFINE_MUTEX(zone_list_lock);
 #define for_each_thermal_zone(pos) \
list_for_each_entry(pos, thermal_zone_list, node)
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, thermal_cdev_list, node)
+
 #define GET_INDEX(tz, ptr, type)   \
 ({ \
int i, ret = -EINVAL;   \
@@ -301,6 +304,27 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
mutex_unlock(tz-lock);
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(cdev-device.kobj));
+
+   mutex_lock(tz-lock);
+
+   /* Shift the entries in the tz-cdevs array */
+   for (j = indx; j  MAX_CDEVS_PER_ZONE - 1; j++)
+   tz-cdevs[j] = tz-cdevs[j + 1];
+
+   tz-cdev_indx--;
+   mutex_unlock(tz-lock);
+}
+
 /**
  * thermal_create_sensor_sysfs - create sysfs nodes for sensorX
  * @ts:the thermal sensor
@@ -593,6 +617,7 @@ EXPORT_SYMBOL_GPL(thermal_cdev_register);
 void thermal_cdev_unregister(struct thermal_cooling_device *cdev)
 {
struct thermal_cooling_device *pos, *next;
+   struct thermal_zone *tz;
bool found = false;
 
if (!cdev)
@@ -610,6 +635,13 @@ void thermal_cdev_unregister(struct thermal_cooling_device 
*cdev)
if (!found)
return;
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tz)
+   remove_cdev_from_zone(tz, cdev);
+
+   mutex_unlock(zone_list_lock);
+
device_remove_file(cdev-device, dev_attr_type);
device_remove_file(cdev-device, dev_attr_max_state);
device_remove_file(cdev-device, dev_attr_cur_state);
@@ -688,6 +720,7 @@ void thermal_remove_thermal_zone(struct thermal_zone *tz)
 {
struct thermal_zone *pos, *next;
struct thermal_sensor *ts;
+   struct thermal_cooling_device *cdev;
bool found = false;
 
if (!tz)
@@ -709,6 +742,9 @@ void thermal_remove_thermal_zone(struct thermal_zone *tz)
for_each_thermal_sensor(ts)
remove_sensor_from_zone(tz, ts);
 
+   for_each_cdev(cdev)
+   remove_cdev_from_zone(tz, cdev);
+
device_remove_file(tz-device, dev_attr_zone_name);
 
mutex_destroy(tz-lock);
@@ -817,3 +853,102 @@ exit_zone:
return ret;
 }
 EXPORT_SYMBOL_GPL(thermal_add_sensor_to_zone);
+
+/**
+ * thermal_get_cdev_by_name() - search for a cdev and returns its reference
+ * @name: cooling device name to fetch the reference
+ *
+ * On success returns a reference to an unique cdev with
+ * the name matching that of @name, an ERR_PTR otherwise:
+ * -EINVAL for invalid paramenters
+ * -ENODEV for cdev not found
+ * -EEXIST for multiple matches
+ */
+struct thermal_cooling_device *thermal_get_cdev_by_name(const char *name)
+{
+   int found = 0;
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = ERR_PTR(-EINVAL);
+
+   if (!name)
+   return cdev;
+
+   mutex_lock(cdev_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos-type, name, THERMAL_NAME_LENGTH)) {
+   found++;
+   cdev = pos;
+   }
+   }
+   mutex_unlock(cdev_list_lock);
+
+   /*
+* Nothing has been found; return an error code for it.
+* Return success only when an unique cdev is found.
+*/
+   if (found == 0)
+   cdev = ERR_PTR(-ENODEV);
+   else if (found  1)
+   cdev = ERR_PTR(-EEXIST);
+
+   return cdev;
+}
+EXPORT_SYMBOL_GPL(thermal_get_cdev_by_name);
+
+/**
+ * thermal_add_cdev_to_zone - Add @cdev to thermal zone @tz
+ * @tz:Thermal zone reference
+ * @cdev:  Cooling device reference
+ *
+ * Returns 0 on success, otherwise
+ * -EINVAL for invalid paramenters
+ * -EINVAL when trying to add more cdevs than MAX_CDEVS_PER_ZONE
+ * -EEXIST when trying add existing cdev again
+ */
+int thermal_add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL

[PATCHv5 02/10] Thermal: Create sensor level APIs

2014-01-16 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework, in a new file named
thermal_core_new.c. The thermal_class variable
is moved as extern to thermal_core.h to
facilitate co-existence of both the APIs.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|3 +
 drivers/thermal/Makefile   |1 +
 drivers/thermal/thermal_core.c |2 +-
 drivers/thermal/thermal_core.h |1 +
 drivers/thermal/thermal_core_new.c |  367 
 include/linux/thermal.h|   37 
 6 files changed, 410 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/thermal_core_new.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 35c0664..f6a8057 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,9 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_V2
+   bool
+
 config THERMAL_HWMON
bool
prompt Expose thermal sensors as hwmon device
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 54e4ec9..d9ae9ac 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_THERMAL)  += thermal_sys.o
 thermal_sys-y  += thermal_core.o
+thermal_sys-$(CONFIG_THERMAL_V2) += thermal_core_new.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 165afc6..a17702f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1045,7 +1045,7 @@ static void thermal_release(struct device *dev)
/* No-op since kfree(dev) is done in _unregister functions */
 }
 
-static struct class thermal_class = {
+struct class thermal_class = {
.name = thermal,
.dev_release = thermal_release,
 };
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 3db339f..adf817c 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -27,6 +27,7 @@
 #include linux/device.h
 #include linux/thermal.h
 
+extern struct class thermal_class;
 /* Initial state of a cooling device during binding */
 #define THERMAL_NO_TARGET -1UL
 
diff --git a/drivers/thermal/thermal_core_new.c 
b/drivers/thermal/thermal_core_new.c
new file mode 100644
index 000..b369a6f
--- /dev/null
+++ b/drivers/thermal/thermal_core_new.c
@@ -0,0 +1,367 @@
+/*
+ *  thermal_core_new.c - Generic Thermal Management Sysfs support.
+ *  Derived from the previous thermal_core.c
+ *  This adds multiple sensor per zone support along with various
+ *  options to provide platform data for Thermal management.
+ *
+ *  Copyright (C) 2014 Intel Corporation
+ *
+ *  ~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME :  fmt
+
+#include linux/module.h
+#include linux/device.h
+#include linux/err.h
+#include linux/slab.h
+#include linux/kdev_t.h
+#include linux/idr.h
+#include linux/thermal.h
+#include linux/reboot.h
+#include linux/string.h
+
+#include thermal_core.h
+
+MODULE_AUTHOR(Durgadoss R);
+MODULE_DESCRIPTION(Generic thermal management sysfs support v2);
+MODULE_LICENSE(GPL v2);
+
+static DEFINE_IDR(thermal_sensor_idr);
+
+static LIST_HEAD(thermal_sensor_list);
+
+static DEFINE_MUTEX(thermal_idr_lock);
+static DEFINE_MUTEX(sensor_list_lock);
+
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static int get_idr(struct idr *idr, int *id)
+{
+   int ret;
+
+   mutex_lock(thermal_idr_lock);
+   ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+   mutex_unlock(thermal_idr_lock);
+
+   if (unlikely(ret  0))
+   return ret;
+
+   *id = ret;
+   return 0;
+}
+
+static void release_idr(struct idr *idr, int id)
+{
+   mutex_lock(thermal_idr_lock);
+   idr_remove(idr, id);
+   mutex_unlock

[PATCHv5 01/10] Thermal: Do kfree in _unregister functions

2014-01-16 Thread Durgadoss R
Currently the thermal_release function does
kfree for all devices when they call device_unregister.
This makes code scattering i.e whenever we add new
devices (to thermal class) we need to add its
corresponding kfree in thermal_release function.
And the if-else is also growing lengthy.

Instead, do all kfree() of devices in their own
_unregister functions. This makes the code look
clean and easy to maintain.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |   17 +
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 338a88b..165afc6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1042,18 +1042,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device);
 
 static void thermal_release(struct device *dev)
 {
-   struct thermal_zone_device *tz;
-   struct thermal_cooling_device *cdev;
-
-   if (!strncmp(dev_name(dev), thermal_zone,
-sizeof(thermal_zone) - 1)) {
-   tz = to_thermal_zone(dev);
-   kfree(tz);
-   } else if(!strncmp(dev_name(dev), cooling_device,
-   sizeof(cooling_device) - 1)){
-   cdev = to_cooling_device(dev);
-   kfree(cdev);
-   }
+   /* No-op since kfree(dev) is done in _unregister functions */
 }
 
 static struct class thermal_class = {
@@ -1146,6 +1135,7 @@ __thermal_cooling_device_register(struct device_node *np,
 unregister:
release_idr(thermal_cdev_idr, thermal_idr_lock, cdev-id);
device_unregister(cdev-device);
+   kfree(cdev);
return ERR_PTR(result);
 }
 
@@ -1250,6 +1240,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
release_idr(thermal_cdev_idr, thermal_idr_lock, cdev-id);
device_unregister(cdev-device);
+   kfree(cdev);
return;
 }
 EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
@@ -1563,6 +1554,7 @@ struct thermal_zone_device 
*thermal_zone_device_register(const char *type,
 unregister:
release_idr(thermal_tz_idr, thermal_idr_lock, tz-id);
device_unregister(tz-device);
+   kfree(tz);
return ERR_PTR(result);
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_register);
@@ -1630,6 +1622,7 @@ void thermal_zone_device_unregister(struct 
thermal_zone_device *tz)
idr_destroy(tz-idr);
mutex_destroy(tz-lock);
device_unregister(tz-device);
+   kfree(tz);
return;
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv4 6/9] Thermal: Create Thermal map sysfs attributes for a zone

2013-10-01 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. The thermal map
shows the binding relationship between a sensor
and a cooling device within a particular zone.
This contains entries named mapY_trip_type,
mapY_sensor_name, mapY_cdev_name, mapY_trip_mask,
mapY_weightX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |  252 +++-
 include/linux/thermal.h|   26 +
 2 files changed, 277 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d6e29f6..e1289a4 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -548,6 +548,24 @@ static void __remove_trip_attr(struct thermal_zone *tz, 
int indx)
tz->trip_attr[indx] = NULL;
 }
 
+static void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr;
+
+   attr = tz->map_attr[indx];
+
+   for (i = 0; i < NUM_MAP_ATTRS; i++)
+   device_remove_file(>device, >attrs[i].attr);
+
+   for (i = 0; i < tz->map[indx]->num_weights; i++)
+   device_remove_file(>device, >weights_attr[i].attr);
+
+   kfree(tz->map_attr[indx]);
+   tz->map_attr[indx] = NULL;
+   tz->map[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -572,6 +590,14 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
}
 
tz->sensor_indx--;
+
+   /* Remove all mappings associated with this sensor */
+   for (j = 0; j < MAX_MAPS_PER_ZONE; j++) {
+   if (tz->map[j] && !strnicmp(ts->name, tz->map[j]->sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, j);
+   }
+   }
mutex_unlock(>lock);
 }
 
@@ -593,6 +619,14 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz->cdevs[j] = tz->cdevs[j + 1];
 
tz->cdev_indx--;
+
+   /* Remove all mappings associated with this sensor */
+   for (j = 0; j < MAX_MAPS_PER_ZONE; j++) {
+   if (tz->map[j] && !strnicmp(cdev->type, tz->map[j]->cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, j);
+   }
+   }
mutex_unlock(>lock);
 }
 
@@ -1117,6 +1151,126 @@ critical_trip_show(struct device *dev,
return sprintf(buf, "%d\n", val);
 }
 
+static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_trip_type", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n",
+   tz->map[indx]->trip_type == THERMAL_TRIP_ACTIVE ?
+   "active" : "passive");
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_sensor_name", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n", tz->map[indx]->sensor_name);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_cdev_name", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (!tz->map[indx])
+   goto exit;
+
+   ret = sprintf(buf, "%s\n", tz->map[indx]->cdev_name);
+exit:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_trip_mas

[PATCHv4 5/9] Thermal: Add trip point sysfs nodes for sensor

2013-10-01 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_activeY,
sensorX_trip_passiveY, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |  344 +++-
 include/linux/thermal.h|   40 -
 2 files changed, 379 insertions(+), 5 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3c4ef62..d6e29f6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -494,6 +494,60 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   /* Protect against tz->sensors[i] being unregistered */
+   mutex_lock(_list_lock);
+
+   for (i = 0; i < tz->sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(>sensors[i]->device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+
+   mutex_unlock(_list_lock);
+   return indx;
+}
+
+static void __remove_trip_attr(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_trip_attr *attr = tz->trip_attr[indx];
+   struct thermal_trip_point *trip = tz->sensor_trip[indx];
+
+   if (!attr || !trip)
+   return;
+
+   if (trip->crit != THERMAL_TRIPS_NONE)
+   device_remove_file(>device, >crit_attr.attr);
+
+   if (trip->hot != THERMAL_TRIPS_NONE)
+   device_remove_file(>device, >hot_attr.attr);
+
+   if (trip->num_passive_trips > 0) {
+   for (i = 0; i < trip->num_passive_trips; i++) {
+   device_remove_file(>device,
+   >passive_attrs[i].attr);
+   }
+   kfree(attr->passive_attrs);
+   }
+
+   if (trip->num_active_trips > 0) {
+   for (i = 0; i < trip->num_active_trips; i++) {
+   device_remove_file(>device,
+   >active_attrs[i].attr);
+   }
+   kfree(attr->active_attrs);
+   }
+
+   kfree(tz->trip_attr[indx]);
+   tz->trip_attr[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -503,13 +557,19 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
if (indx < 0)
return;
 
-   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
-
mutex_lock(>lock);
 
+   /* Remove trip point attributes associated with this sensor */
+   __remove_trip_attr(tz, indx);
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
/* Shift the entries in the tz->sensors array */
-   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++) {
tz->sensors[j] = tz->sensors[j + 1];
+   tz->sensor_trip[j] = tz->sensor_trip[j + 1];
+   tz->trip_attr[j] = tz->trip_attr[j + 1];
+   }
 
tz->sensor_indx--;
mutex_unlock(>lock);
@@ -952,6 +1012,111 @@ emul_temp_store(struct device *dev, struct 
device_attribute *attr,
 static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
 #endif/*CONFIG_THERMAL_EMULATION*/
 
+static ssize_t
+active_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_active%d", , ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+
+   mutex_lock(>lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i < 0) {
+   mutex_unlock(>lock);
+   return i;
+   }
+
+   val = tz->sensor_trip[i]->active_trips[j];
+   mutex_unlock(>lock);
+
+   return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+passive_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_passive%d", , ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+
+   mutex_

[PATCHv4 7/9] Thermal: Add Documentation to new APIs

2013-10-01 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  248 ++
 1 file changed, 248 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..c456dad
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,248 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2013 Intel Corporation
+
+Created on: 25 September 2013
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information

[PATCHv4 2/9] Thermal: Create sensor level APIs

2013-10-01 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |  284 
 include/linux/thermal.h|   29 
 2 files changed, 313 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 8c5131d..8c46567 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -45,13 +45,16 @@ MODULE_LICENSE("GPL v2");
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -463,6 +466,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, "%s\n", ts->name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts->ops->get_temp(ts, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_hyst(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_threshold(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -772,6 +872,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1585,6 +1689,186 @@ static void remove_trip_attrs(struc

[PATCHv4 8/9] Thermal: Add ABI Documentation for sysfs interfaces

2013-10-01 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R 
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..36e23da
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_mask
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip point mask

[PATCHv4 4/9] Thermal: Add APIs to bind cdev to new zone structure

2013-10-01 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |  136 
 include/linux/thermal.h|9 +++
 2 files changed, 145 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index a053b60..3c4ef62 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -86,6 +87,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, _cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -511,6 +515,27 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
mutex_unlock(>lock);
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   mutex_lock(>lock);
+
+   /* Shift the entries in the tz->cdevs array */
+   for (j = indx; j < MAX_CDEVS_PER_ZONE - 1; j++)
+   tz->cdevs[j] = tz->cdevs[j + 1];
+
+   tz->cdev_indx--;
+   mutex_unlock(>lock);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1555,6 +1580,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1592,6 +1618,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(_list_lock);
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(_list_lock);
+
if (cdev->type[0])
device_remove_file(>device, _attr_cdev_type);
device_remove_file(>device, _attr_max_state);
@@ -1873,6 +1906,7 @@ void remove_thermal_zone(struct thermal_zone *tz)
 {
struct thermal_zone *pos, *next;
struct thermal_sensor *ts;
+   struct thermal_cooling_device *cdev;
bool found = false;
 
if (!tz)
@@ -1894,6 +1928,9 @@ void remove_thermal_zone(struct thermal_zone *tz)
for_each_thermal_sensor(ts)
remove_sensor_from_zone(tz, ts);
 
+   for_each_cdev(cdev)
+   remove_cdev_from_zone(tz, cdev);
+
device_remove_file(>device, _attr_zone_name);
 
mutex_destroy(>lock);
@@ -1909,6 +1946,47 @@ exit:
 EXPORT_SYMBOL(remove_thermal_zone);
 
 /**
+ * get_cdev_by_name() - search for a cdev and returns its reference
+ * @name: cooling device name to fetch the reference
+ *
+ * On success returns a reference to an unique cdev with
+ * the name matching that of @name, an ERR_PTR otherwise:
+ * -EINVAL for invalid paramenters
+ * -ENODEV for cdev not found
+ * -EEXIST for multiple matches
+ */
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   int found = 0;
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = ERR_PTR(-EINVAL);
+
+   if (!name)
+   return cdev;
+
+   mutex_lock(_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos->type, name, THERMAL_NAME_LENGTH)) {
+   found++;
+   cdev = pos;
+   }
+   }
+   mutex_unlock(_list_lock);
+
+   /*
+* Nothing has been found; return an error code for it.
+* Return success only when an unique cdev is found.
+*/
+   if (found == 0)
+   cdev = ERR_PTR(-ENODEV);
+   else if (found > 1)
+   cdev = ERR_PTR(-EEXIST);
+
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
+/**
  * get_sensor_by_name() - search for a sensor and returns its reference
  * @name: thermal sensor name to fetch the reference
  *
@@ -2003,6 +2081,64 @@ exit_zone:
 EXPORT_SYMBOL(add_sensor_to_zone);
 
 /**
+ * add_cdev_to_zone - Add @cdev to thermal zone @tz
+ * @tz:Thermal zone reference
+ * @cdev:  Cooling device reference
+ *
+ * Returns 0 on success, otherwise
+ * -EINVAL for invalid paramenters
+ * -EINVAL when trying to a

[PATCHv4 0/9] Thermal Framework Enhancements

2013-10-01 Thread Durgadoss R
This patch set is a v4 of the previous versions submitted here:
[v3]: https://lkml.org/lkml/2013/2/5/228 
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, on top
of commit 'f61d5b4d52e077756ce9dbc47ce737da898ad01d'
This is tested on a Core-i5 and an Atom netbook,
running ubuntu 12.04.

Changes since v3:
 * Added a patch to conditionally do kfree(cdev) in
   thermal_release function.
 * Reworked all sysfs attributes to have one value per file
   This includes sensor_trip_* and map_weight* attributes.
 * Added 'lock' variable in thermal_zone structure to
   protect its members.
 * Added Documentation to all functions in thermal_core.c
 * Changes all strcpy() to strlcpy()
 * Used devm_kzalloc() in places where applicable
 * Address some buffer overflow conditions and contentions
   in tz->sensors[] and tz->cdevs[].
Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 9 patches:
Patch 1/9: Fixes a kfree issue. This is required so that the new sensor
   and zone devices are not freed accidently.
   We can do two things here:
   1) Conditionally free every device
   2) Remove this _release function, and free the memory
  in corresponding _unregister functions.
   I prefer 2) and we can have this as a separate patch
   outside this series; but would like to see the opinion
   of maintainers'.
Patch 2/9: Creates new sensor level APIs
Patch 3/9: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 4/9: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 5/9: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 6/9: Adds mapY_* sysfs node. These attributes represent
Patch 7/9: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 8/9: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 9/9: A dummy driver that can be used for testing. This is not for merge.

Sorry for the long delay in resubmitting this patch set.
Thanks to Eduardo, Wei Ni, for their comments on v3.

Durgadoss R (9):
  Thermal: Check for validity before doing kfree
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 +++
 Documentation/thermal/sysfs-api2.txt  |  248 +
 drivers/thermal/Kconfig   |5 +
 drivers/thermal/Makefile  |3 +
 drivers/thermal/thermal_core.c| 1406 +++--
 drivers/thermal/thermal_test.c|  322 ++
 include/linux/thermal.h   |  127 ++-
 7 files changed, 2180 insertions(+), 68 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv4 3/9] Thermal: Create zone level APIs

2013-10-01 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |  267 +++-
 include/linux/thermal.h|   23 
 2 files changed, 289 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 8c46567..a053b60 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -44,19 +44,48 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support");
 MODULE_LICENSE("GPL v2");
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, _sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, _zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(>lock);  \
+   mutex_lock(##_list_lock);  \
+   for (i = 0; i < tz->type##_indx; i++) { \
+   if (tz->type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(##_list_lock);\
+   mutex_unlock(>lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -461,15 +490,47 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   mutex_lock(>lock);
+
+   /* Shift the entries in the tz->sensors array */
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   tz->sensors[j] = tz->sensors[j + 1];
+
+   tz->sensor_indx--;
+   mutex_unlock(>lock);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, "%s\n", tz->name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -876,6 +937,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1689,7 +1752,7 @@ static void remove_trip_attrs(struct thermal_zone_device 
*tz)
kfree(tz->trip_hyst_attrs);
 }
 
- /**
+/**
  * enable_sensor_thresholds - create sysfs nodes for thresholdX
  * @ts:the thermal sensor
  * @count: Number of thresholds supported by sensor hardware
@@ -1746,6 +1809,200 @@ static int enable_sensor_th

[PATCHv4 1/9] Thermal: Check for validity before doing kfree

2013-10-01 Thread Durgadoss R
The thermal_release function is called whenever
any device belonging to 'thermal' class unregisters.
This function performs kfree(cdev) without any check.
In cases where there are more device registrations
other than just 'thermal_zone' and 'cooling_device'
this might accidently free memory allocated them
silently; and cause memory errors.

This patch changes this behavior by doing
kfree(cdev) only when the device pointer belongs
to a real cdev i.e. cooling_device.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_core.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 1f02e8e..8c5131d 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1280,7 +1280,8 @@ static void thermal_release(struct device *dev)
 sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev);
kfree(tz);
-   } else {
+   } else if(!strncmp(dev_name(dev), "cooling_device",
+   sizeof("cooling_device") - 1)){
cdev = to_cooling_device(dev);
kfree(cdev);
}
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv4 9/9] Thermal: Dummy driver used for testing

2013-10-01 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  322 
 3 files changed, 330 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index ae18f02..d4b8458 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -192,4 +192,9 @@ depends on PLAT_SAMSUNG
 source "drivers/thermal/samsung/Kconfig"
 endmenu
 
+config THERMAL_TEST
+   tristate "test driver"
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c19df7a..ccff09e 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -26,3 +26,6 @@ obj-$(CONFIG_DB8500_CPUFREQ_COOLING)  += 
db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..6d34bca
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,322 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~~~~~
+ * Author: Durgadoss R 
+ */
+
+#define pr_fmt(fmt)  "thermal_test: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = "ts",
+   .cdev_name = "cdev",
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, "%d\n", ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ts_data.flag = flag;
+
+   if (flag == 0) {
+   thermal_sensor_unregister(ts);
+   

[PATCHv4 1/9] Thermal: Check for validity before doing kfree

2013-10-01 Thread Durgadoss R
The thermal_release function is called whenever
any device belonging to 'thermal' class unregisters.
This function performs kfree(cdev) without any check.
In cases where there are more device registrations
other than just 'thermal_zone' and 'cooling_device'
this might accidently free memory allocated them
silently; and cause memory errors.

This patch changes this behavior by doing
kfree(cdev) only when the device pointer belongs
to a real cdev i.e. cooling_device.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 1f02e8e..8c5131d 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1280,7 +1280,8 @@ static void thermal_release(struct device *dev)
 sizeof(thermal_zone) - 1)) {
tz = to_thermal_zone(dev);
kfree(tz);
-   } else {
+   } else if(!strncmp(dev_name(dev), cooling_device,
+   sizeof(cooling_device) - 1)){
cdev = to_cooling_device(dev);
kfree(cdev);
}
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv4 3/9] Thermal: Create zone level APIs

2013-10-01 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |  267 +++-
 include/linux/thermal.h|   23 
 2 files changed, 289 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 8c46567..a053b60 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -44,19 +44,48 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support);
 MODULE_LICENSE(GPL v2);
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, thermal_sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, thermal_zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(tz-lock);  \
+   mutex_lock(type##_list_lock);  \
+   for (i = 0; i  tz-type##_indx; i++) { \
+   if (tz-type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(type##_list_lock);\
+   mutex_unlock(tz-lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -461,15 +490,47 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
+   mutex_lock(tz-lock);
+
+   /* Shift the entries in the tz-sensors array */
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   tz-sensors[j] = tz-sensors[j + 1];
+
+   tz-sensor_indx--;
+   mutex_unlock(tz-lock);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, %s\n, tz-name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -876,6 +937,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1689,7 +1752,7 @@ static void remove_trip_attrs(struct thermal_zone_device 
*tz)
kfree(tz-trip_hyst_attrs);
 }
 
- /**
+/**
  * enable_sensor_thresholds - create sysfs nodes for thresholdX
  * @ts:the thermal sensor
  * @count: Number of thresholds supported by sensor hardware
@@ -1746,6 +1809,200 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count

[PATCHv4 9/9] Thermal: Dummy driver used for testing

2013-10-01 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  322 
 3 files changed, 330 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index ae18f02..d4b8458 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -192,4 +192,9 @@ depends on PLAT_SAMSUNG
 source drivers/thermal/samsung/Kconfig
 endmenu
 
+config THERMAL_TEST
+   tristate test driver
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c19df7a..ccff09e 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -26,3 +26,6 @@ obj-$(CONFIG_DB8500_CPUFREQ_COOLING)  += 
db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..6d34bca
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,322 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~
+ * Author: Durgadoss R durgados...@intel.com
+ */
+
+#define pr_fmt(fmt)  thermal_test:  fmt
+
+#include linux/module.h
+#include linux/init.h
+#include linux/err.h
+#include linux/param.h
+#include linux/device.h
+#include linux/slab.h
+#include linux/pm.h
+#include linux/platform_device.h
+#include linux/thermal.h
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = ts,
+   .cdev_name = cdev,
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, %d\n, ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, flag))
+   return -EINVAL;
+
+   ts_data.flag

[PATCHv4 4/9] Thermal: Add APIs to bind cdev to new zone structure

2013-10-01 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |  136 
 include/linux/thermal.h|9 +++
 2 files changed, 145 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index a053b60..3c4ef62 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -86,6 +87,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, thermal_cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -511,6 +515,27 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
mutex_unlock(tz-lock);
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(cdev-device.kobj));
+
+   mutex_lock(tz-lock);
+
+   /* Shift the entries in the tz-cdevs array */
+   for (j = indx; j  MAX_CDEVS_PER_ZONE - 1; j++)
+   tz-cdevs[j] = tz-cdevs[j + 1];
+
+   tz-cdev_indx--;
+   mutex_unlock(tz-lock);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1555,6 +1580,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1592,6 +1618,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(thermal_list_lock);
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(zone_list_lock);
+
if (cdev-type[0])
device_remove_file(cdev-device, dev_attr_cdev_type);
device_remove_file(cdev-device, dev_attr_max_state);
@@ -1873,6 +1906,7 @@ void remove_thermal_zone(struct thermal_zone *tz)
 {
struct thermal_zone *pos, *next;
struct thermal_sensor *ts;
+   struct thermal_cooling_device *cdev;
bool found = false;
 
if (!tz)
@@ -1894,6 +1928,9 @@ void remove_thermal_zone(struct thermal_zone *tz)
for_each_thermal_sensor(ts)
remove_sensor_from_zone(tz, ts);
 
+   for_each_cdev(cdev)
+   remove_cdev_from_zone(tz, cdev);
+
device_remove_file(tz-device, dev_attr_zone_name);
 
mutex_destroy(tz-lock);
@@ -1909,6 +1946,47 @@ exit:
 EXPORT_SYMBOL(remove_thermal_zone);
 
 /**
+ * get_cdev_by_name() - search for a cdev and returns its reference
+ * @name: cooling device name to fetch the reference
+ *
+ * On success returns a reference to an unique cdev with
+ * the name matching that of @name, an ERR_PTR otherwise:
+ * -EINVAL for invalid paramenters
+ * -ENODEV for cdev not found
+ * -EEXIST for multiple matches
+ */
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   int found = 0;
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = ERR_PTR(-EINVAL);
+
+   if (!name)
+   return cdev;
+
+   mutex_lock(cdev_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos-type, name, THERMAL_NAME_LENGTH)) {
+   found++;
+   cdev = pos;
+   }
+   }
+   mutex_unlock(cdev_list_lock);
+
+   /*
+* Nothing has been found; return an error code for it.
+* Return success only when an unique cdev is found.
+*/
+   if (found == 0)
+   cdev = ERR_PTR(-ENODEV);
+   else if (found  1)
+   cdev = ERR_PTR(-EEXIST);
+
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
+/**
  * get_sensor_by_name() - search for a sensor and returns its reference
  * @name: thermal sensor name to fetch the reference
  *
@@ -2003,6 +2081,64 @@ exit_zone:
 EXPORT_SYMBOL(add_sensor_to_zone);
 
 /**
+ * add_cdev_to_zone - Add @cdev to thermal zone @tz
+ * @tz:Thermal zone reference
+ * @cdev:  Cooling device reference
+ *
+ * Returns 0 on success, otherwise
+ * -EINVAL for invalid paramenters
+ * -EINVAL

[PATCHv4 0/9] Thermal Framework Enhancements

2013-10-01 Thread Durgadoss R
This patch set is a v4 of the previous versions submitted here:
[v3]: https://lkml.org/lkml/2013/2/5/228 
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, on top
of commit 'f61d5b4d52e077756ce9dbc47ce737da898ad01d'
This is tested on a Core-i5 and an Atom netbook,
running ubuntu 12.04.

Changes since v3:
 * Added a patch to conditionally do kfree(cdev) in
   thermal_release function.
 * Reworked all sysfs attributes to have one value per file
   This includes sensor_trip_* and map_weight* attributes.
 * Added 'lock' variable in thermal_zone structure to
   protect its members.
 * Added Documentation to all functions in thermal_core.c
 * Changes all strcpy() to strlcpy()
 * Used devm_kzalloc() in places where applicable
 * Address some buffer overflow conditions and contentions
   in tz-sensors[] and tz-cdevs[].
Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 9 patches:
Patch 1/9: Fixes a kfree issue. This is required so that the new sensor
   and zone devices are not freed accidently.
   We can do two things here:
   1) Conditionally free every device
   2) Remove this _release function, and free the memory
  in corresponding _unregister functions.
   I prefer 2) and we can have this as a separate patch
   outside this series; but would like to see the opinion
   of maintainers'.
Patch 2/9: Creates new sensor level APIs
Patch 3/9: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 4/9: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 5/9: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 6/9: Adds mapY_* sysfs node. These attributes represent
Patch 7/9: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 8/9: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 9/9: A dummy driver that can be used for testing. This is not for merge.

Sorry for the long delay in resubmitting this patch set.
Thanks to Eduardo, Wei Ni, for their comments on v3.

Durgadoss R (9):
  Thermal: Check for validity before doing kfree
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 +++
 Documentation/thermal/sysfs-api2.txt  |  248 +
 drivers/thermal/Kconfig   |5 +
 drivers/thermal/Makefile  |3 +
 drivers/thermal/thermal_core.c| 1406 +++--
 drivers/thermal/thermal_test.c|  322 ++
 include/linux/thermal.h   |  127 ++-
 7 files changed, 2180 insertions(+), 68 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv4 8/9] Thermal: Add ABI Documentation for sysfs interfaces

2013-10-01 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..36e23da
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_activeM
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Active Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passiveN
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Passive Trip point temperature in mC for sensorY in
+   thermal zoneX.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  October 2013
+KernelVersion: 3.12
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel/User space thermal

[PATCHv4 7/9] Thermal: Add Documentation to new APIs

2013-10-01 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/thermal/sysfs-api2.txt |  248 ++
 1 file changed, 248 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..c456dad
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,248 @@
+Thermal Framework
+-
+
+Written by Durgadoss R durgados...@intel.com
+Copyright (c) 2013 Intel Corporation
+
+Created on: 25 September 2013
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (e.g how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. We see a lot of chip drivers,
+starting to use thermal framework; we should keep it really
+light-weight for them to do so but at the same time provide all
+the necessary features to participate in platform thermal management.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides

[PATCHv4 2/9] Thermal: Create sensor level APIs

2013-10-01 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |  284 
 include/linux/thermal.h|   29 
 2 files changed, 313 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 8c5131d..8c46567 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -45,13 +45,16 @@ MODULE_LICENSE(GPL v2);
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -463,6 +466,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, %s\n, ts-name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts-ops-get_temp(ts, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_hyst(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_threshold(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -772,6 +872,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1585,6 +1689,186 @@ static void remove_trip_attrs(struct 
thermal_zone_device *tz)
kfree(tz-trip_hyst_attrs);
 }
 
+ /**
+ * enable_sensor_thresholds - create sysfs nodes for thresholdX

[PATCHv4 5/9] Thermal: Add trip point sysfs nodes for sensor

2013-10-01 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_activeY,
sensorX_trip_passiveY, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |  344 +++-
 include/linux/thermal.h|   40 -
 2 files changed, 379 insertions(+), 5 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3c4ef62..d6e29f6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -494,6 +494,60 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   /* Protect against tz-sensors[i] being unregistered */
+   mutex_lock(sensor_list_lock);
+
+   for (i = 0; i  tz-sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(tz-sensors[i]-device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+
+   mutex_unlock(sensor_list_lock);
+   return indx;
+}
+
+static void __remove_trip_attr(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_trip_attr *attr = tz-trip_attr[indx];
+   struct thermal_trip_point *trip = tz-sensor_trip[indx];
+
+   if (!attr || !trip)
+   return;
+
+   if (trip-crit != THERMAL_TRIPS_NONE)
+   device_remove_file(tz-device, attr-crit_attr.attr);
+
+   if (trip-hot != THERMAL_TRIPS_NONE)
+   device_remove_file(tz-device, attr-hot_attr.attr);
+
+   if (trip-num_passive_trips  0) {
+   for (i = 0; i  trip-num_passive_trips; i++) {
+   device_remove_file(tz-device,
+   attr-passive_attrs[i].attr);
+   }
+   kfree(attr-passive_attrs);
+   }
+
+   if (trip-num_active_trips  0) {
+   for (i = 0; i  trip-num_active_trips; i++) {
+   device_remove_file(tz-device,
+   attr-active_attrs[i].attr);
+   }
+   kfree(attr-active_attrs);
+   }
+
+   kfree(tz-trip_attr[indx]);
+   tz-trip_attr[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -503,13 +557,19 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
if (indx  0)
return;
 
-   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
-
mutex_lock(tz-lock);
 
+   /* Remove trip point attributes associated with this sensor */
+   __remove_trip_attr(tz, indx);
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
/* Shift the entries in the tz-sensors array */
-   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++) {
tz-sensors[j] = tz-sensors[j + 1];
+   tz-sensor_trip[j] = tz-sensor_trip[j + 1];
+   tz-trip_attr[j] = tz-trip_attr[j + 1];
+   }
 
tz-sensor_indx--;
mutex_unlock(tz-lock);
@@ -952,6 +1012,111 @@ emul_temp_store(struct device *dev, struct 
device_attribute *attr,
 static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
 #endif/*CONFIG_THERMAL_EMULATION*/
 
+static ssize_t
+active_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_active%d, i, j))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+
+   mutex_lock(tz-lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i  0) {
+   mutex_unlock(tz-lock);
+   return i;
+   }
+
+   val = tz-sensor_trip[i]-active_trips[j];
+   mutex_unlock(tz-lock);
+
+   return sprintf(buf, %d\n, val);
+}
+
+static ssize_t
+passive_trip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, j, val;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_passive%d, i, j))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+
+   mutex_lock(tz-lock);
+
+   i = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (i  0) {
+   mutex_unlock(tz-lock);
+   return i;
+   }
+
+   val

[PATCHv4 6/9] Thermal: Create Thermal map sysfs attributes for a zone

2013-10-01 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. The thermal map
shows the binding relationship between a sensor
and a cooling device within a particular zone.
This contains entries named mapY_trip_type,
mapY_sensor_name, mapY_cdev_name, mapY_trip_mask,
mapY_weightX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_core.c |  252 +++-
 include/linux/thermal.h|   26 +
 2 files changed, 277 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d6e29f6..e1289a4 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -548,6 +548,24 @@ static void __remove_trip_attr(struct thermal_zone *tz, 
int indx)
tz-trip_attr[indx] = NULL;
 }
 
+static void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr;
+
+   attr = tz-map_attr[indx];
+
+   for (i = 0; i  NUM_MAP_ATTRS; i++)
+   device_remove_file(tz-device, attr-attrs[i].attr);
+
+   for (i = 0; i  tz-map[indx]-num_weights; i++)
+   device_remove_file(tz-device, attr-weights_attr[i].attr);
+
+   kfree(tz-map_attr[indx]);
+   tz-map_attr[indx] = NULL;
+   tz-map[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -572,6 +590,14 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
}
 
tz-sensor_indx--;
+
+   /* Remove all mappings associated with this sensor */
+   for (j = 0; j  MAX_MAPS_PER_ZONE; j++) {
+   if (tz-map[j]  !strnicmp(ts-name, tz-map[j]-sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, j);
+   }
+   }
mutex_unlock(tz-lock);
 }
 
@@ -593,6 +619,14 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz-cdevs[j] = tz-cdevs[j + 1];
 
tz-cdev_indx--;
+
+   /* Remove all mappings associated with this sensor */
+   for (j = 0; j  MAX_MAPS_PER_ZONE; j++) {
+   if (tz-map[j]  !strnicmp(cdev-type, tz-map[j]-cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, j);
+   }
+   }
mutex_unlock(tz-lock);
 }
 
@@ -1117,6 +1151,126 @@ critical_trip_show(struct device *dev,
return sprintf(buf, %d\n, val);
 }
 
+static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_trip_type, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n,
+   tz-map[indx]-trip_type == THERMAL_TRIP_ACTIVE ?
+   active : passive);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_sensor_name, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n, tz-map[indx]-sensor_name);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_cdev_name, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, %s\n, tz-map[indx]-cdev_name);
+exit:
+   mutex_unlock(tz-lock);
+   return ret;
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx, ret = -EINVAL;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_trip_mask, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   mutex_lock(tz-lock);
+
+   if (!tz-map[indx])
+   goto exit;
+
+   ret = sprintf(buf, 0x%x\n, tz-map[indx]-trip_mask);
+exit

[PATCH 2/8] Thermal: Create zone level APIs

2013-02-05 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  196 +
 include/linux/thermal.h   |   22 +
 2 files changed, 218 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index cb94497..838d4fb 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -43,19 +43,46 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support");
 MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, _sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, _zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(##_list_lock);  \
+   for (i = 0; i < tz->type##_indx; i++) { \
+   if (tz->type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(##_list_lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -421,15 +448,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->sensors array */
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   tz->sensors[j] = tz->sensors[j + 1];
+
+   tz->sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, "%s\n", tz->name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -811,6 +867,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1656,6 +1714,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name && strlen(name) >= THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(>idr);
+   ret = get_idr(_zone_idr, _idr_lock, >id);
+   if

[PATCH 4/8] Thermal: Add trip point sysfs nodes for sensor

2013-02-05 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_active,
sensorX_trip_passive, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  225 -
 include/linux/thermal.h   |   38 ++-
 2 files changed, 260 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index bf703b1..69a60a4 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -452,6 +452,37 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   mutex_lock(_list_lock);
+   for (i = 0; i < tz->sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(>sensors[i]->device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return indx;
+}
+
+static void inline __remove_trip_attr(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_trip_attr *attr = tz->trip_attr[indx];
+
+   if (!attr)
+   return;
+
+   for (i = 0; i < NUM_TRIP_TYPES; i++)
+   device_remove_file(>device, >attrs[i].attr);
+
+   kfree(tz->trip_attr[indx]);
+   tz->trip_attr[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -463,9 +494,15 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
 
sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
 
+   /* Remove trip point attributes associated with this sensor */
+   __remove_trip_attr(tz, indx);
+
/* Shift the entries in the tz->sensors array */
-   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++) {
tz->sensors[j] = tz->sensors[j + 1];
+   tz->sensor_trip[j] = tz->sensor_trip[j + 1];
+   tz->trip_attr[j] = tz->trip_attr[j + 1];
+   }
 
tz->sensor_indx--;
 }
@@ -879,6 +916,99 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
return sprintf(buf, "%s\n", tz->governor->name);
 }
 
+static ssize_t
+active_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_active", ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_active_trips <= 0)
+   return sprintf(buf, "\n");
+
+   ret += sprintf(buf, "0x%x", tz->sensor_trip[indx]->active_trip_mask);
+   for (i = 0; i < tz->sensor_trip[indx]->num_active_trips; i++) {
+   ret += sprintf(buf + ret, " %d",
+   tz->sensor_trip[indx]->active_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+ptrip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_passive", ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_passive_trips <= 0)
+   return sprintf(buf, "\n");
+
+   for (i = 0; i < tz->sensor_trip[indx]->num_passive_trips; i++) {
+   ret += sprintf(buf + ret, "%d ",
+   tz->sensor_trip[indx]->passive_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+hot_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_hot", ))
+   return -EINVAL;
+
+  

[PATCH 5/8] Thermal: Create Thermal map sysfs attributes for a zone

2013-02-05 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. This contains
entries named mapY_trip_type, mapY_sensor_name,
mapY_cdev_name, mapY_trip_mask, mapY_weights.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  221 -
 include/linux/thermal.h   |   25 +
 2 files changed, 244 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 69a60a4..e284b67 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -525,6 +525,44 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz->cdev_indx--;
 }
 
+static inline void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr = tz->map_attr[indx];
+
+   for (i = 0; i < NUM_MAP_ATTRS; i++)
+   device_remove_file(>device, >attrs[i].attr);
+
+   kfree(tz->map_attr[indx]);
+   tz->map[indx] = NULL;
+}
+
+static void remove_sensor_map_entry(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(ts->name, tz->map[i]->sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, i);
+   }
+   }
+}
+
+static void remove_cdev_map_entry(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(cdev->type, tz->map[i]->cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, i);
+   }
+   }
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -917,6 +955,107 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
 }
 
 static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   char *trip;
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_trip_type", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   trip = (tz->map[indx]->trip_type == THERMAL_TRIP_ACTIVE) ?
+   "active" : "passive";
+   return sprintf(buf, "%s\n", trip);
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_sensor_name", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   return sprintf(buf, "%s\n", tz->map[indx]->sensor_name);
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_cdev_name", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   return sprintf(buf, "%s\n", tz->map[indx]->cdev_name);
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_trip_mask", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   return sprintf(buf, "0x%x\n", tz->map[indx]->trip_mask);
+}
+
+static ssize_t map_weights_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   struct thermal_map *map;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d_weights", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   

[PATCH 8/8] Thermal: Dummy driver used for testing

2013-02-05 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |2 +
 drivers/thermal/thermal_test.c |  324 
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index faf38c5..eadef5b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -141,4 +141,9 @@ config INTEL_POWERCLAMP
  enforce idle time which results in more package C-state residency. The
  user interface is exposed via generic thermal framework.
 
+config THERMAL_TEST
+   tristate "test driver"
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 574f5f5..ee0f687 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_DB8500_THERMAL)  += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
 
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..d92b68b
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,324 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~
+ * Author: Durgadoss R 
+ */
+
+#define pr_fmt(fmt)  "thermal_test: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = "ts",
+   .cdev_name = "cdev",
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, "%d\n", ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+ 

[PATCH 6/8] Thermal: Add Documentation to new APIs

2013-02-05 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  247 ++
 1 file changed, 247 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..24e23f4
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,247 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2012 Intel Corporation
+
+Created on: 4 November 2012
+Updated on: 5 February 2013
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (like how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. The reason I am saying this is because
+we are seeing a lot of chip drivers, starting to use thermal framework,
+and we should keep it really light-weight for them to do so.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information between

[PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure

2013-02-05 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |9 +
 2 files changed, 89 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 838d4fb..bf703b1 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -57,6 +57,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -83,6 +84,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, _cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -466,6 +470,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz->sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->cdevs array */
+   for (j = indx; j < MAX_CDEVS_PER_ZONE - 1; j++)
+   tz->cdevs[j] = tz->cdevs[j + 1];
+
+   tz->cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1462,6 +1484,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1499,6 +1522,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(_list_lock);
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(_list_lock);
+
if (cdev->type[0])
device_remove_file(>device, _attr_cdev_type);
device_remove_file(>device, _attr_max_state);
@@ -1794,6 +1824,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos->type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1844,6 +1891,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   ret = GET_INDEX(tz, cdev, cdev);
+   if (ret >= 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(_list_lock);
+   ret = sysfs_create_link(>device.kobj, >device.kobj,
+   kobject_name(>device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz->cdevs[tz->cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(_list_lock);
+exit_zone:
+   mutex_unlock(_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 2194519..c841414 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -57,6 +57,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -217,6 +219,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct thermal_cooling_device *cdevs[MAX_CDEVS_P

[PATCH 7/8] Thermal: Add ABI Documentation for sysfs interfaces

2013-02-05 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R 
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..00f033a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_active
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Space separated list of active trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passive
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Space separated list of passive trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_mask
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip point

[PATCHv3 0/8] Thermal Framework Enhancements

2013-02-05 Thread Durgadoss R
This patch set is a v3 of the previous versions submitted here:
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, and is
tested on a Core-i5 and an Atom netbook.

Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 8 patches:
Patch 1/8: Creates new sensor level APIs
Patch 2/8: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/8: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/8: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 5/8: Adds mapY_* sysfs node. These attributes represent
   the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/8: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/8: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 8/8: A dummy driver that can be used for testing. This is not for merge.

Durgadoss R (8):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 
 Documentation/thermal/sysfs-api2.txt  |  247 ++
 drivers/thermal/Kconfig   |5 +
 drivers/thermal/Makefile  |2 +
 drivers/thermal/thermal_sys.c |  994 +
 drivers/thermal/thermal_test.c|  324 
 include/linux/thermal.h   |  123 ++-
 7 files changed, 1831 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/8] Thermal: Create sensor level APIs

2013-02-05 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  280 +
 include/linux/thermal.h   |   29 +
 2 files changed, 309 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 0a1bf6b..cb94497 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,13 +44,16 @@ MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -423,6 +426,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, "%s\n", ts->name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts->ops->get_temp(ts, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_hyst(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_threshold(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -707,6 +807,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1493,6 +1597,182 @@ static void remove_trip_attrs(struct 
therma

[PATCHv3 0/8] Thermal Framework Enhancements

2013-02-05 Thread Durgadoss R
This patch set is a v3 of the previous versions submitted here:
[v2]: http://lwn.net/Articles/531720/
[v1]: https://lkml.org/lkml/2012/12/18/108 
[RFC]:https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -next tree, and is
tested on a Core-i5 and an Atom netbook.

Changes since v2:
 * Reworked the map sysfs attributes in patch [5/8]
 * Dropped configuration for maximum sensors and
   cooling devices, through Kconfig.
 * Added __remove_trip_attr method
 * Renamed __clean_map_entry to __remove_map_entry
   for consistency in naming.
Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 8 patches:
Patch 1/8: Creates new sensor level APIs
Patch 2/8: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/8: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/8: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 5/8: Adds mapY_* sysfs node. These attributes represent
   the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/8: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/8: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 8/8: A dummy driver that can be used for testing. This is not for merge.

Durgadoss R (8):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create Thermal map sysfs attributes for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |  137 
 Documentation/thermal/sysfs-api2.txt  |  247 ++
 drivers/thermal/Kconfig   |5 +
 drivers/thermal/Makefile  |2 +
 drivers/thermal/thermal_sys.c |  994 +
 drivers/thermal/thermal_test.c|  324 
 include/linux/thermal.h   |  123 ++-
 7 files changed, 1831 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/8] Thermal: Create sensor level APIs

2013-02-05 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  280 +
 include/linux/thermal.h   |   29 +
 2 files changed, 309 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 0a1bf6b..cb94497 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,13 +44,16 @@ MODULE_LICENSE(GPL);
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -423,6 +426,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, %s\n, ts-name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts-ops-get_temp(ts, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_hyst(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_threshold(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -707,6 +807,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1493,6 +1597,182 @@ static void remove_trip_attrs(struct 
thermal_zone_device *tz)
 }
 
 /**
+ * enable_sensor_thresholds - create sysfs nodes for thresholdX
+ * @ts:the thermal sensor

[PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure

2013-02-05 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |9 +
 2 files changed, 89 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 838d4fb..bf703b1 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -57,6 +57,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -83,6 +84,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, thermal_cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -466,6 +470,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz-sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(cdev-device.kobj));
+
+   /* Shift the entries in the tz-cdevs array */
+   for (j = indx; j  MAX_CDEVS_PER_ZONE - 1; j++)
+   tz-cdevs[j] = tz-cdevs[j + 1];
+
+   tz-cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1462,6 +1484,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1499,6 +1522,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(thermal_list_lock);
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(zone_list_lock);
+
if (cdev-type[0])
device_remove_file(cdev-device, dev_attr_cdev_type);
device_remove_file(cdev-device, dev_attr_max_state);
@@ -1794,6 +1824,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(cdev_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos-type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(cdev_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1844,6 +1891,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(zone_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   ret = GET_INDEX(tz, cdev, cdev);
+   if (ret = 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(cdev_list_lock);
+   ret = sysfs_create_link(tz-device.kobj, cdev-device.kobj,
+   kobject_name(cdev-device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz-cdevs[tz-cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(cdev_list_lock);
+exit_zone:
+   mutex_unlock(zone_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 2194519..c841414 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -57,6 +57,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -217,6 +219,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct thermal_cooling_device

[PATCH 7/8] Thermal: Add ABI Documentation for sysfs interfaces

2013-02-05 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/ABI/testing/sysfs-class-thermal |  137 +
 1 file changed, 137 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..00f033a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,137 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_active
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Space separated list of active trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passive
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Space separated list of passive trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_trip_type
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the trip_type for a
+   particular map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_sensor_name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the sensor
+   used in this map(Y).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY_cdev_name
+Date:  February 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. This interface provides the name of the cooling
+   device used in this map(Y).
+Users: Kernel

[PATCH 6/8] Thermal: Add Documentation to new APIs

2013-02-05 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/thermal/sysfs-api2.txt |  247 ++
 1 file changed, 247 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..24e23f4
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,247 @@
+Thermal Framework
+-
+
+Written by Durgadoss R durgados...@intel.com
+Copyright (c) 2012 Intel Corporation
+
+Created on: 4 November 2012
+Updated on: 5 February 2013
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (like how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. The reason I am saying this is because
+we are seeing a lot of chip drivers, starting to use thermal framework,
+and we should keep it really light-weight for them to do so.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding

[PATCH 8/8] Thermal: Dummy driver used for testing

2013-02-05 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |2 +
 drivers/thermal/thermal_test.c |  324 
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index faf38c5..eadef5b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -141,4 +141,9 @@ config INTEL_POWERCLAMP
  enforce idle time which results in more package C-state residency. The
  user interface is exposed via generic thermal framework.
 
+config THERMAL_TEST
+   tristate test driver
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 574f5f5..ee0f687 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_DB8500_THERMAL)  += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
 
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..d92b68b
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,324 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ * ~~
+ * Author: Durgadoss R durgados...@intel.com
+ */
+
+#define pr_fmt(fmt)  thermal_test:  fmt
+
+#include linux/module.h
+#include linux/init.h
+#include linux/err.h
+#include linux/param.h
+#include linux/device.h
+#include linux/slab.h
+#include linux/pm.h
+#include linux/platform_device.h
+#include linux/thermal.h
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = ts,
+   .cdev_name = cdev,
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, %d\n, ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long

[PATCH 5/8] Thermal: Create Thermal map sysfs attributes for a zone

2013-02-05 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. This contains
entries named mapY_trip_type, mapY_sensor_name,
mapY_cdev_name, mapY_trip_mask, mapY_weights.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  221 -
 include/linux/thermal.h   |   25 +
 2 files changed, 244 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 69a60a4..e284b67 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -525,6 +525,44 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz-cdev_indx--;
 }
 
+static inline void __remove_map_entry(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_map_attr *attr = tz-map_attr[indx];
+
+   for (i = 0; i  NUM_MAP_ATTRS; i++)
+   device_remove_file(tz-device, attr-attrs[i].attr);
+
+   kfree(tz-map_attr[indx]);
+   tz-map[indx] = NULL;
+}
+
+static void remove_sensor_map_entry(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int i;
+
+   for (i = 0; i  MAX_MAPS_PER_ZONE; i++) {
+   if (tz-map[i]  !strnicmp(ts-name, tz-map[i]-sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, i);
+   }
+   }
+}
+
+static void remove_cdev_map_entry(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int i;
+
+   for (i = 0; i  MAX_MAPS_PER_ZONE; i++) {
+   if (tz-map[i]  !strnicmp(cdev-type, tz-map[i]-cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __remove_map_entry(tz, i);
+   }
+   }
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -917,6 +955,107 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
 }
 
 static ssize_t
+map_ttype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   char *trip;
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_trip_type, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   trip = (tz-map[indx]-trip_type == THERMAL_TRIP_ACTIVE) ?
+   active : passive;
+   return sprintf(buf, %s\n, trip);
+}
+
+static ssize_t map_ts_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_sensor_name, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   return sprintf(buf, %s\n, tz-map[indx]-sensor_name);
+}
+
+static ssize_t map_cdev_name_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_cdev_name, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   return sprintf(buf, %s\n, tz-map[indx]-cdev_name);
+}
+
+static ssize_t map_trip_mask_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_trip_mask, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   return sprintf(buf, 0x%x\n, tz-map[indx]-trip_mask);
+}
+
+static ssize_t map_weights_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   struct thermal_map *map;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d_weights, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   map = tz-map[indx];
+
+   ret += sprintf(buf, %d, map-weights[0]);
+   for (i = 1; i  map-num_weights; i++)
+   ret += sprintf(buf + ret,  %d, map-weights[i]);
+
+   ret += sprintf(buf + ret, \n);
+   return ret

[PATCH 4/8] Thermal: Add trip point sysfs nodes for sensor

2013-02-05 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_active,
sensorX_trip_passive, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  225 -
 include/linux/thermal.h   |   38 ++-
 2 files changed, 260 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index bf703b1..69a60a4 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -452,6 +452,37 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   mutex_lock(sensor_list_lock);
+   for (i = 0; i  tz-sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(tz-sensors[i]-device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+   mutex_unlock(sensor_list_lock);
+   return indx;
+}
+
+static void inline __remove_trip_attr(struct thermal_zone *tz, int indx)
+{
+   int i;
+   struct thermal_trip_attr *attr = tz-trip_attr[indx];
+
+   if (!attr)
+   return;
+
+   for (i = 0; i  NUM_TRIP_TYPES; i++)
+   device_remove_file(tz-device, attr-attrs[i].attr);
+
+   kfree(tz-trip_attr[indx]);
+   tz-trip_attr[indx] = NULL;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -463,9 +494,15 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
 
sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
 
+   /* Remove trip point attributes associated with this sensor */
+   __remove_trip_attr(tz, indx);
+
/* Shift the entries in the tz-sensors array */
-   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++) {
tz-sensors[j] = tz-sensors[j + 1];
+   tz-sensor_trip[j] = tz-sensor_trip[j + 1];
+   tz-trip_attr[j] = tz-trip_attr[j + 1];
+   }
 
tz-sensor_indx--;
 }
@@ -879,6 +916,99 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
return sprintf(buf, %s\n, tz-governor-name);
 }
 
+static ssize_t
+active_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_active, i))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   if (tz-sensor_trip[indx]-num_active_trips = 0)
+   return sprintf(buf, Not available\n);
+
+   ret += sprintf(buf, 0x%x, tz-sensor_trip[indx]-active_trip_mask);
+   for (i = 0; i  tz-sensor_trip[indx]-num_active_trips; i++) {
+   ret += sprintf(buf + ret,  %d,
+   tz-sensor_trip[indx]-active_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, \n);
+   return ret;
+}
+
+static ssize_t
+ptrip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_passive, i))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   if (tz-sensor_trip[indx]-num_passive_trips = 0)
+   return sprintf(buf, Not available\n);
+
+   for (i = 0; i  tz-sensor_trip[indx]-num_passive_trips; i++) {
+   ret += sprintf(buf + ret, %d ,
+   tz-sensor_trip[indx]-passive_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, \n);
+   return ret;
+}
+
+static ssize_t
+hot_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_hot, indx))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, indx);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   return sprintf(buf, %d\n, tz-sensor_trip[indx]-hot);
+}
+
+static ssize_t

[PATCH 2/8] Thermal: Create zone level APIs

2013-02-05 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  196 +
 include/linux/thermal.h   |   22 +
 2 files changed, 218 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index cb94497..838d4fb 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -43,19 +43,46 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support);
 MODULE_LICENSE(GPL);
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, thermal_sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, thermal_zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(type##_list_lock);  \
+   for (i = 0; i  tz-type##_indx; i++) { \
+   if (tz-type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(type##_list_lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -421,15 +448,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
+   /* Shift the entries in the tz-sensors array */
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   tz-sensors[j] = tz-sensors[j + 1];
+
+   tz-sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, %s\n, tz-name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -811,6 +867,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1656,6 +1714,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name  strlen(name) = THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(tz-idr);
+   ret = get_idr(thermal_zone_idr, thermal_idr_lock, tz-id);
+   if (ret)
+   goto exit_free

[PATCH 2/9] Thermal: Create zone level APIs

2013-01-06 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  196 +
 include/linux/thermal.h   |   22 +
 2 files changed, 218 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b2becb9..513b0fc 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,19 +44,46 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support");
 MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, _sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, _zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(##_list_lock);  \
+   for (i = 0; i < tz->type##_indx; i++) { \
+   if (tz->type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(##_list_lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -419,15 +446,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->sensors array */
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   tz->sensors[j] = tz->sensors[j + 1];
+
+   tz->sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, "%s\n", tz->name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -809,6 +865,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1654,6 +1712,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name && strlen(name) >= THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(>idr);
+   ret = get_idr(_zone_idr, _idr_lock, >id);
+   if

[PATCH 4/9] Thermal: Add trip point sysfs nodes for sensor

2013-01-06 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_active,
sensorX_trip_passive, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  211 -
 include/linux/thermal.h   |   38 +++-
 2 files changed, 246 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 332bd61..1958bb8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -450,6 +450,22 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   mutex_lock(_list_lock);
+   for (i = 0; i < tz->sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(>sensors[i]->device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return indx;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -461,9 +477,16 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
 
sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
 
+   /* Remove trip point attributes associated with this sensor */
+   kfree(tz->trip_attr[indx]);
+   tz->trip_attr[indx] = NULL;
+
/* Shift the entries in the tz->sensors array */
-   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++) {
tz->sensors[j] = tz->sensors[j + 1];
+   tz->sensor_trip[j] = tz->sensor_trip[j + 1];
+   tz->trip_attr[j] = tz->trip_attr[j + 1];
+   }
 
tz->sensor_indx--;
 }
@@ -877,6 +900,99 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
return sprintf(buf, "%s\n", tz->governor->name);
 }
 
+static ssize_t
+active_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_active", ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_active_trips <= 0)
+   return sprintf(buf, "\n");
+
+   ret += sprintf(buf, "0x%x", tz->sensor_trip[indx]->active_trip_mask);
+   for (i = 0; i < tz->sensor_trip[indx]->num_active_trips; i++) {
+   ret += sprintf(buf + ret, " %d",
+   tz->sensor_trip[indx]->active_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+ptrip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_passive", ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_passive_trips <= 0)
+   return sprintf(buf, "\n");
+
+   for (i = 0; i < tz->sensor_trip[indx]->num_passive_trips; i++) {
+   ret += sprintf(buf + ret, "%d ",
+   tz->sensor_trip[indx]->passive_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+hot_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "sensor%d_trip_hot", ))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, "sensor%d", indx);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx < 0)
+   return indx;
+
+   return sprintf(buf, "%d\n", tz->sensor_trip[indx]->hot);
+}
+
+static ssize_t
+critical_show(struct device *dev, struct device_attribute *attr,

[PATCHv2 0/9] Thermal Framework Enhancements

2013-01-06 Thread Durgadoss R
This patch set is a v2 of the previous versions submitted here:
[v1]:  https://lkml.org/lkml/2012/12/18/108 
[RFC]: https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -thermal tree, and is
tested on a Core-i5 and an Atom netbook.

Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 9 patches:
Patch 1/9: Creates new sensor level APIs
Patch 2/9: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/9: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/9: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 5/9: Adds mapX sysfs node. It is a compact representation
   of the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/9: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/9: Make PER ZONE values configurable through Kconfig
Patch 8/9: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 9/9: A dummy driver that can be used for testing. This is not for merge.

Thanks to Greg-KH, Hongbo Zhang and Joe Perches for their comments on v1.

Durgadoss R (9):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create 'mapX' sysfs node for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Make PER_ZONE values configurable
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |   93 +++
 Documentation/thermal/sysfs-api2.txt  |  248 +++
 drivers/thermal/Kconfig   |   19 +
 drivers/thermal/Makefile  |3 +
 drivers/thermal/thermal_sys.c |  881 +
 drivers/thermal/thermal_test.c|  315 +
 include/linux/thermal.h   |  117 +++-
 7 files changed, 1675 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 7/9] Thermal: Make PER_ZONE values configurable

2013-01-06 Thread Durgadoss R
This patch makes MAX_SENSORS_PER_ZONE and
MAX_CDEVS_PER_ZONE values configurable. The
default value is 1, and range is 1-12.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig |   14 ++
 include/linux/thermal.h |6 +++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d96da07..c5ba3340 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,20 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_MAX_SENSORS_PER_ZONE
+   int "Maximum number of sensors allowed per thermal zone"
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of sensors allowed per zone
+
+config THERMAL_MAX_CDEVS_PER_ZONE
+   int "Maximum number of cooling devices allowed per thermal zone"
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of cooling devices allowed per zone
+
 config THERMAL_HWMON
bool
depends on HWMON=y || HWMON=THERMAL
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 187fadb..cf19fba 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -50,9 +50,9 @@
 /* Default Thermal Governor: Does Linear Throttling */
 #define DEFAULT_THERMAL_GOVERNOR   "step_wise"
 
-#define MAX_SENSORS_PER_ZONE   5
-
-#define MAX_CDEVS_PER_ZONE 5
+/* Maximum number of sensors/cdevs per zone, defined through Kconfig */
+#define MAX_SENSORS_PER_ZONE   CONFIG_THERMAL_MAX_SENSORS_PER_ZONE
+#define MAX_CDEVS_PER_ZONE CONFIG_THERMAL_MAX_CDEVS_PER_ZONE
 
 /* If we map each sensor with every possible cdev for a zone */
 #define MAX_MAPS_PER_ZONE  (MAX_SENSORS_PER_ZONE * MAX_CDEVS_PER_ZONE)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 9/9] Thermal: Dummy driver used for testing

2013-01-06 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  329 
 3 files changed, 337 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c5ba3340..3b92a76 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -136,4 +136,9 @@ config DB8500_CPUFREQ_COOLING
  bound cpufreq cooling device turns active to set CPU frequency low to
  cool down the CPU.
 
+config THERMAL_TEST
+   tristate "test driver"
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d8da683..02c3edb 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_RCAR_THERMAL)+= rcar_thermal.o
 obj-$(CONFIG_EXYNOS_THERMAL)   += exynos_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)   += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..137b562
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,329 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~
+ * Author: Durgadoss R 
+ */
+
+#define pr_fmt(fmt)  "thermal_test: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = "ts",
+   .cdev_name = "cdev",
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, "%d\n", ts_data.flag);
+}
+
+sta

[PATCH 8/9] Thermal: Add ABI Documentation for sysfs interfaces

2013-01-06 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R 
---
 Documentation/ABI/testing/sysfs-class-thermal |   93 +
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..d1a450e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,93 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_active
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Space separated list of active trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passive
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Space separated list of passive trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list 
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. See Documentation/thermal/sysfs-api2.txt for more
+   information on this interface.
+Users: Kernel/User space thermal governors
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 6/9] Thermal: Add Documentation to new APIs

2013-01-06 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  248 ++
 1 file changed, 248 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..ffd0402
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,248 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2012 Intel Corporation
+
+Created on: 4 November 2012
+Updated on: 18 December 2012
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (like how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. The reason I am saying this is because
+we are seeing a lot of chip drivers, starting to use thermal framework,
+and we should keep it really light-weight for them to do so.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information between

[PATCH 5/9] Thermal: Create 'mapX' sysfs node for a zone

2013-01-06 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. This contains
entries named map0, map1 .. mapN. Each map has the
following space separated values:
trip_type sensor_name cdev_name trip_mask weights

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  122 -
 include/linux/thermal.h   |   19 +++
 2 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 1958bb8..5f806d1 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -509,6 +509,39 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz->cdev_indx--;
 }
 
+static inline void __clean_map_entry(struct thermal_zone *tz, int i)
+{
+   device_remove_file(>device, >map_attr[i]->attr);
+   kfree(tz->map_attr[i]);
+   tz->map[i] = NULL;
+}
+
+static void remove_sensor_map_entry(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(ts->name, tz->map[i]->sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
+static void remove_cdev_map_entry(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(cdev->type, tz->map[i]->cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -901,6 +934,39 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
 }
 
 static ssize_t
+map_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   char *trip;
+   int i, indx, ret = 0;
+   struct thermal_map *map;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr->attr.name, "map%d", ))
+   return -EINVAL;
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   map = tz->map[indx];
+
+   trip = (map->trip_type == THERMAL_TRIP_ACTIVE) ?
+   "active" : "passive";
+   ret += sprintf(buf, "%s", trip);
+   ret += sprintf(buf + ret, " %s", map->sensor_name);
+   ret += sprintf(buf + ret, " %s", map->cdev_name);
+   ret += sprintf(buf + ret, " 0x%x", map->trip_mask);
+
+   for (i = 0; i < map->num_weights; i++)
+   ret += sprintf(buf + ret, " %d", map->weights[i]);
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
 active_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
int i, indx, ret = 0;
@@ -1639,8 +1705,10 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_lock(_list_lock);
 
-   for_each_thermal_zone(tmp_tz)
+   for_each_thermal_zone(tmp_tz) {
remove_cdev_from_zone(tmp_tz, cdev);
+   remove_cdev_map_entry(tmp_tz, cdev);
+   }
 
mutex_unlock(_list_lock);
 
@@ -1978,6 +2046,9 @@ void remove_thermal_zone(struct thermal_zone *tz)
kobject_name(>cdevs[i]->device.kobj));
}
 
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++)
+   __clean_map_entry(tz, i);
+
release_idr(_zone_idr, _idr_lock, tz->id);
idr_destroy(>idr);
 
@@ -2023,6 +2094,51 @@ struct thermal_sensor *get_sensor_by_name(const char 
*name)
 }
 EXPORT_SYMBOL(get_sensor_by_name);
 
+int add_map_entry(struct thermal_zone *tz, struct thermal_map *map)
+{
+   int ret, indx;
+
+   if (!tz || !map)
+   return -EINVAL;
+
+   mutex_lock(_list_lock);
+
+   for (indx = 0; indx < MAX_MAPS_PER_ZONE; indx++) {
+   if (tz->map[indx] == NULL)
+   break;
+   }
+
+   if (indx >= MAX_MAPS_PER_ZONE) {
+   ret = -EINVAL;
+   goto exit;
+   }
+
+   tz->map_attr[indx] = kzalloc(sizeof(struct thermal_attr), GFP_KERNEL);
+   if (!tz->map_attr[indx]) {
+   ret = -ENOMEM;
+   goto exit;
+   }
+
+   sprintf(tz->map_attr[indx]->name, "map%d", indx);
+
+   tz->map_attr[indx]->attr.attr.name = tz->map_attr[indx]->name;
+   tz->map_attr[indx]->attr.attr.mode = S_I

[PATCH 3/9] Thermal: Add APIs to bind cdev to new zone structure

2013-01-06 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |9 +
 2 files changed, 89 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 513b0fc..332bd61 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -84,6 +85,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, _cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -464,6 +468,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz->sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->cdevs array */
+   for (j = indx; j < MAX_CDEVS_PER_ZONE - 1; j++)
+   tz->cdevs[j] = tz->cdevs[j + 1];
+
+   tz->cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1460,6 +1482,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1497,6 +1520,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(_list_lock);
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(_list_lock);
+
if (cdev->type[0])
device_remove_file(>device, _attr_cdev_type);
device_remove_file(>device, _attr_max_state);
@@ -1792,6 +1822,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos->type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1842,6 +1889,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   ret = GET_INDEX(tz, cdev, cdev);
+   if (ret >= 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(_list_lock);
+   ret = sysfs_create_link(>device.kobj, >device.kobj,
+   kobject_name(>device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz->cdevs[tz->cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(_list_lock);
+exit_zone:
+   mutex_unlock(_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f5b9540..12cc953 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -51,6 +51,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -209,6 +211,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct thermal_cooling_device *cdevs[MAX_CDEVS_P

[PATCH 1/9] Thermal: Create sensor level APIs

2013-01-06 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  280 +
 include/linux/thermal.h   |   29 +
 2 files changed, 309 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8f0f37b..b2becb9 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -45,13 +45,16 @@ MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -421,6 +424,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, "%s\n", ts->name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts->ops->get_temp(ts, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_hyst(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_threshold(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -705,6 +805,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1491,6 +1595,182 @@ static void remove_trip_attrs(struct 
therma

[PATCH 1/9] Thermal: Create sensor level APIs

2013-01-06 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  280 +
 include/linux/thermal.h   |   29 +
 2 files changed, 309 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8f0f37b..b2becb9 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -45,13 +45,16 @@ MODULE_LICENSE(GPL);
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -421,6 +424,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, %s\n, ts-name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts-ops-get_temp(ts, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_hyst(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d_hyst, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   ret = ts-ops-get_threshold(ts, indx, val);
+
+   return ret ? ret : sprintf(buf, %ld\n, val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts-ops-set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr-attr.name, threshold%d, indx))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, val))
+   return -EINVAL;
+
+   ret = ts-ops-set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -705,6 +805,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1491,6 +1595,182 @@ static void remove_trip_attrs(struct 
thermal_zone_device *tz)
 }
 
 /**
+ * enable_sensor_thresholds - create sysfs nodes for thresholdX
+ * @ts:the thermal sensor

[PATCH 3/9] Thermal: Add APIs to bind cdev to new zone structure

2013-01-06 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |9 +
 2 files changed, 89 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 513b0fc..332bd61 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -84,6 +85,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
ret;\
 })
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, thermal_cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -464,6 +468,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz-sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, cdev, cdev);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(cdev-device.kobj));
+
+   /* Shift the entries in the tz-cdevs array */
+   for (j = indx; j  MAX_CDEVS_PER_ZONE - 1; j++)
+   tz-cdevs[j] = tz-cdevs[j + 1];
+
+   tz-cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1460,6 +1482,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1497,6 +1520,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(thermal_list_lock);
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(zone_list_lock);
+
if (cdev-type[0])
device_remove_file(cdev-device, dev_attr_cdev_type);
device_remove_file(cdev-device, dev_attr_max_state);
@@ -1792,6 +1822,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(cdev_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos-type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(cdev_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1842,6 +1889,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(zone_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   ret = GET_INDEX(tz, cdev, cdev);
+   if (ret = 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(cdev_list_lock);
+   ret = sysfs_create_link(tz-device.kobj, cdev-device.kobj,
+   kobject_name(cdev-device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz-cdevs[tz-cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(cdev_list_lock);
+exit_zone:
+   mutex_unlock(zone_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f5b9540..12cc953 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -51,6 +51,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -209,6 +211,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct thermal_cooling_device

[PATCH 5/9] Thermal: Create 'mapX' sysfs node for a zone

2013-01-06 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/zoneX/. This contains
entries named map0, map1 .. mapN. Each map has the
following space separated values:
trip_type sensor_name cdev_name trip_mask weights

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  122 -
 include/linux/thermal.h   |   19 +++
 2 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 1958bb8..5f806d1 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -509,6 +509,39 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz-cdev_indx--;
 }
 
+static inline void __clean_map_entry(struct thermal_zone *tz, int i)
+{
+   device_remove_file(tz-device, tz-map_attr[i]-attr);
+   kfree(tz-map_attr[i]);
+   tz-map[i] = NULL;
+}
+
+static void remove_sensor_map_entry(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int i;
+
+   for (i = 0; i  MAX_MAPS_PER_ZONE; i++) {
+   if (tz-map[i]  !strnicmp(ts-name, tz-map[i]-sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
+static void remove_cdev_map_entry(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int i;
+
+   for (i = 0; i  MAX_MAPS_PER_ZONE; i++) {
+   if (tz-map[i]  !strnicmp(cdev-type, tz-map[i]-cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -901,6 +934,39 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
 }
 
 static ssize_t
+map_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   char *trip;
+   int i, indx, ret = 0;
+   struct thermal_map *map;
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, map%d, indx))
+   return -EINVAL;
+
+   if (indx  0 || indx = MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz-map[indx])
+   return sprintf(buf, Unavailable\n);
+
+   map = tz-map[indx];
+
+   trip = (map-trip_type == THERMAL_TRIP_ACTIVE) ?
+   active : passive;
+   ret += sprintf(buf, %s, trip);
+   ret += sprintf(buf + ret,  %s, map-sensor_name);
+   ret += sprintf(buf + ret,  %s, map-cdev_name);
+   ret += sprintf(buf + ret,  0x%x, map-trip_mask);
+
+   for (i = 0; i  map-num_weights; i++)
+   ret += sprintf(buf + ret,  %d, map-weights[i]);
+
+   ret += sprintf(buf + ret, \n);
+   return ret;
+}
+
+static ssize_t
 active_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
int i, indx, ret = 0;
@@ -1639,8 +1705,10 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_lock(zone_list_lock);
 
-   for_each_thermal_zone(tmp_tz)
+   for_each_thermal_zone(tmp_tz) {
remove_cdev_from_zone(tmp_tz, cdev);
+   remove_cdev_map_entry(tmp_tz, cdev);
+   }
 
mutex_unlock(zone_list_lock);
 
@@ -1978,6 +2046,9 @@ void remove_thermal_zone(struct thermal_zone *tz)
kobject_name(tz-cdevs[i]-device.kobj));
}
 
+   for (i = 0; i  MAX_MAPS_PER_ZONE; i++)
+   __clean_map_entry(tz, i);
+
release_idr(thermal_zone_idr, thermal_idr_lock, tz-id);
idr_destroy(tz-idr);
 
@@ -2023,6 +2094,51 @@ struct thermal_sensor *get_sensor_by_name(const char 
*name)
 }
 EXPORT_SYMBOL(get_sensor_by_name);
 
+int add_map_entry(struct thermal_zone *tz, struct thermal_map *map)
+{
+   int ret, indx;
+
+   if (!tz || !map)
+   return -EINVAL;
+
+   mutex_lock(zone_list_lock);
+
+   for (indx = 0; indx  MAX_MAPS_PER_ZONE; indx++) {
+   if (tz-map[indx] == NULL)
+   break;
+   }
+
+   if (indx = MAX_MAPS_PER_ZONE) {
+   ret = -EINVAL;
+   goto exit;
+   }
+
+   tz-map_attr[indx] = kzalloc(sizeof(struct thermal_attr), GFP_KERNEL);
+   if (!tz-map_attr[indx]) {
+   ret = -ENOMEM;
+   goto exit;
+   }
+
+   sprintf(tz-map_attr[indx]-name, map%d, indx);
+
+   tz-map_attr[indx]-attr.attr.name = tz-map_attr[indx]-name;
+   tz-map_attr[indx]-attr.attr.mode = S_IRUGO;
+   tz-map_attr[indx]-attr.show = map_show;
+
+   sysfs_attr_init(tz-map_attr[indx]-attr.attr);
+   ret = device_create_file(tz-device, tz-map_attr[indx]-attr);
+   if (ret) {
+   kfree(tz-map_attr[indx]);
+   goto exit

[PATCH 6/9] Thermal: Add Documentation to new APIs

2013-01-06 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/thermal/sysfs-api2.txt |  248 ++
 1 file changed, 248 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..ffd0402
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,248 @@
+Thermal Framework
+-
+
+Written by Durgadoss R durgados...@intel.com
+Copyright (c) 2012 Intel Corporation
+
+Created on: 4 November 2012
+Updated on: 18 December 2012
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (like how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. The reason I am saying this is because
+we are seeing a lot of chip drivers, starting to use thermal framework,
+and we should keep it really light-weight for them to do so.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka

[PATCH 8/9] Thermal: Add ABI Documentation for sysfs interfaces

2013-01-06 Thread Durgadoss R
This patch adds Documentation for ABI's introduced
for thermal subsystem (under /sys/class/thermal/).

Signed-off-by: Durgadoss R durgados...@intel.com
---
 Documentation/ABI/testing/sysfs-class-thermal |   93 +
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal

diff --git a/Documentation/ABI/testing/sysfs-class-thermal 
b/Documentation/ABI/testing/sysfs-class-thermal
new file mode 100644
index 000..d1a450e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-thermal
@@ -0,0 +1,93 @@
+What:  /sys/class/thermal/sensorX/temp
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Exposes 'temperature' of a thermal sensor in mC
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/name
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal sensor
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/sensorX/thresholdY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Programmable threshold (in terms of mC). On reaching
+   this, the thermal governors may take action to control
+   temperature.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/name
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Name of the thermal zone.
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a sensor associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/cooling_deviceY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Symlink to a cooling device associated with this zone.
+Users: User space thermal governors or applications
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_active
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Space separated list of active trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_passive
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Space separated list of passive trip points for 'sensorY'
+   in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_hot
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Hot trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/sensorY_trip_critical
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Critical trip point for 'sensorY' in 'zoneX' (in mC).
+Users: Kernel/User space thermal governors
+
+What:  /sys/class/thermal/zoneX/mapY
+Date:  January 2013
+KernelVersion: 3.8
+Contact:   Linux PM Mailing list linux...@vger.kernel.org
+Description:
+   Mapping information between a sensor and a cooling device
+   in 'zoneX'. See Documentation/thermal/sysfs-api2.txt for more
+   information on this interface.
+Users: Kernel/User space thermal governors
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 9/9] Thermal: Dummy driver used for testing

2013-01-06 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  329 
 3 files changed, 337 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c5ba3340..3b92a76 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -136,4 +136,9 @@ config DB8500_CPUFREQ_COOLING
  bound cpufreq cooling device turns active to set CPU frequency low to
  cool down the CPU.
 
+config THERMAL_TEST
+   tristate test driver
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d8da683..02c3edb 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_RCAR_THERMAL)+= rcar_thermal.o
 obj-$(CONFIG_EXYNOS_THERMAL)   += exynos_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)   += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..137b562
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,329 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~
+ * Author: Durgadoss R durgados...@intel.com
+ */
+
+#define pr_fmt(fmt)  thermal_test:  fmt
+
+#include linux/module.h
+#include linux/init.h
+#include linux/err.h
+#include linux/param.h
+#include linux/device.h
+#include linux/slab.h
+#include linux/pm.h
+#include linux/platform_device.h
+#include linux/thermal.h
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+int wts[5] = {50, 50, 50, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static struct thermal_map map = {
+   .trip_type = THERMAL_TRIP_PASSIVE,
+   .sensor_name = ts,
+   .cdev_name = cdev,
+   .num_weights = 5,
+   .trip_mask = 0x0F,
+   .weights = wts,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct

[PATCH 7/9] Thermal: Make PER_ZONE values configurable

2013-01-06 Thread Durgadoss R
This patch makes MAX_SENSORS_PER_ZONE and
MAX_CDEVS_PER_ZONE values configurable. The
default value is 1, and range is 1-12.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig |   14 ++
 include/linux/thermal.h |6 +++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d96da07..c5ba3340 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,20 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_MAX_SENSORS_PER_ZONE
+   int Maximum number of sensors allowed per thermal zone
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of sensors allowed per zone
+
+config THERMAL_MAX_CDEVS_PER_ZONE
+   int Maximum number of cooling devices allowed per thermal zone
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of cooling devices allowed per zone
+
 config THERMAL_HWMON
bool
depends on HWMON=y || HWMON=THERMAL
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 187fadb..cf19fba 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -50,9 +50,9 @@
 /* Default Thermal Governor: Does Linear Throttling */
 #define DEFAULT_THERMAL_GOVERNOR   step_wise
 
-#define MAX_SENSORS_PER_ZONE   5
-
-#define MAX_CDEVS_PER_ZONE 5
+/* Maximum number of sensors/cdevs per zone, defined through Kconfig */
+#define MAX_SENSORS_PER_ZONE   CONFIG_THERMAL_MAX_SENSORS_PER_ZONE
+#define MAX_CDEVS_PER_ZONE CONFIG_THERMAL_MAX_CDEVS_PER_ZONE
 
 /* If we map each sensor with every possible cdev for a zone */
 #define MAX_MAPS_PER_ZONE  (MAX_SENSORS_PER_ZONE * MAX_CDEVS_PER_ZONE)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCHv2 0/9] Thermal Framework Enhancements

2013-01-06 Thread Durgadoss R
This patch set is a v2 of the previous versions submitted here:
[v1]:  https://lkml.org/lkml/2012/12/18/108 
[RFC]: https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -thermal tree, and is
tested on a Core-i5 and an Atom netbook.

Changes Since v1:
 * Removed kobject creation for thermal_trip and thermal_map
   nodes as per Greg-KH's comments.
 * Added ABI Documentation under 'testing'.
 * Modified the GET_INDEX macro to be more linux-like, thanks
   to Joe Perches.
 * Added get_[sensor/cdev]_by_name APIs to thermal.h

This series contains 9 patches:
Patch 1/9: Creates new sensor level APIs
Patch 2/9: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/9: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/9: Adds sensorX_trip_[active/passive/hot/critical] sysfs nodes,
   under /sys/class/thermal/zoneY/. This exposes various trip
   points for sensorX present in zoneY.
Patch 5/9: Adds mapX sysfs node. It is a compact representation
   of the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/9: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/9: Make PER ZONE values configurable through Kconfig
Patch 8/9: Add ABI documentation for sysfs interfaces introduced in this patch.
Patch 9/9: A dummy driver that can be used for testing. This is not for merge.

Thanks to Greg-KH, Hongbo Zhang and Joe Perches for their comments on v1.

Durgadoss R (9):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add trip point sysfs nodes for sensor
  Thermal: Create 'mapX' sysfs node for a zone
  Thermal: Add Documentation to new APIs
  Thermal: Make PER_ZONE values configurable
  Thermal: Add ABI Documentation for sysfs interfaces
  Thermal: Dummy driver used for testing

 Documentation/ABI/testing/sysfs-class-thermal |   93 +++
 Documentation/thermal/sysfs-api2.txt  |  248 +++
 drivers/thermal/Kconfig   |   19 +
 drivers/thermal/Makefile  |3 +
 drivers/thermal/thermal_sys.c |  881 +
 drivers/thermal/thermal_test.c|  315 +
 include/linux/thermal.h   |  117 +++-
 7 files changed, 1675 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-thermal
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/9] Thermal: Add trip point sysfs nodes for sensor

2013-01-06 Thread Durgadoss R
This patch adds a trip point related sysfs nodes
for each sensor under a zone in /sys/class/thermal/zoneX/.
The nodes will be named, sensorX_trip_active,
sensorX_trip_passive, sensorX_trip_hot, sensorX_trip_critical
for active, passive, hot and critical trip points
respectively for sensorX.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  211 -
 include/linux/thermal.h   |   38 +++-
 2 files changed, 246 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 332bd61..1958bb8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -450,6 +450,22 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   mutex_lock(sensor_list_lock);
+   for (i = 0; i  tz-sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(tz-sensors[i]-device.kobj),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+   mutex_unlock(sensor_list_lock);
+   return indx;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -461,9 +477,16 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
 
sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
 
+   /* Remove trip point attributes associated with this sensor */
+   kfree(tz-trip_attr[indx]);
+   tz-trip_attr[indx] = NULL;
+
/* Shift the entries in the tz-sensors array */
-   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++) {
tz-sensors[j] = tz-sensors[j + 1];
+   tz-sensor_trip[j] = tz-sensor_trip[j + 1];
+   tz-trip_attr[j] = tz-trip_attr[j + 1];
+   }
 
tz-sensor_indx--;
 }
@@ -877,6 +900,99 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
return sprintf(buf, %s\n, tz-governor-name);
 }
 
+static ssize_t
+active_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_active, i))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   if (tz-sensor_trip[indx]-num_active_trips = 0)
+   return sprintf(buf, Not available\n);
+
+   ret += sprintf(buf, 0x%x, tz-sensor_trip[indx]-active_trip_mask);
+   for (i = 0; i  tz-sensor_trip[indx]-num_active_trips; i++) {
+   ret += sprintf(buf + ret,  %d,
+   tz-sensor_trip[indx]-active_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, \n);
+   return ret;
+}
+
+static ssize_t
+ptrip_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_passive, i))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, i);
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   if (tz-sensor_trip[indx]-num_passive_trips = 0)
+   return sprintf(buf, Not available\n);
+
+   for (i = 0; i  tz-sensor_trip[indx]-num_passive_trips; i++) {
+   ret += sprintf(buf + ret, %d ,
+   tz-sensor_trip[indx]-passive_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, \n);
+   return ret;
+}
+
+static ssize_t
+hot_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_hot, indx))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, indx);
+
+   indx = get_sensor_indx_by_kobj(tz, kobj_name);
+   if (indx  0)
+   return indx;
+
+   return sprintf(buf, %d\n, tz-sensor_trip[indx]-hot);
+}
+
+static ssize_t
+critical_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx;
+   char kobj_name[THERMAL_NAME_LENGTH];
+   struct thermal_zone *tz = to_zone(dev);
+
+   if (!sscanf(attr-attr.name, sensor%d_trip_hot, indx))
+   return -EINVAL;
+
+   snprintf(kobj_name, THERMAL_NAME_LENGTH, sensor%d, indx

[PATCH 2/9] Thermal: Create zone level APIs

2013-01-06 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  196 +
 include/linux/thermal.h   |   22 +
 2 files changed, 218 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b2becb9..513b0fc 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,19 +44,46 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support);
 MODULE_LICENSE(GPL);
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, thermal_sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, thermal_zone_list, node)
+
+#define GET_INDEX(tz, ptr, type)   \
+({ \
+   int i, ret = -EINVAL;   \
+   do {\
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(type##_list_lock);  \
+   for (i = 0; i  tz-type##_indx; i++) { \
+   if (tz-type##s[i] == ptr) {\
+   ret = i;\
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(type##_list_lock);\
+   } while (0);\
+   ret;\
+})
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -419,15 +446,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   indx = GET_INDEX(tz, ts, sensor);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
+   /* Shift the entries in the tz-sensors array */
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   tz-sensors[j] = tz-sensors[j + 1];
+
+   tz-sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, %s\n, tz-name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -809,6 +865,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1654,6 +1712,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name  strlen(name) = THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(tz-idr);
+   ret = get_idr(thermal_zone_idr, thermal_idr_lock, tz-id);
+   if (ret)
+   goto exit_free

[PATCH 1/8] Thermal: Create sensor level APIs

2012-12-18 Thread Durgadoss R
This patch creates sensor level APIs, in the
generic thermal framework.

A Thermal sensor is a piece of hardware that can report
temperature of the spot in which it is placed. A thermal
sensor driver reads the temperature from this sensor
and reports it out. This kind of driver can be in
any subsystem. If the sensor needs to participate
in platform thermal management, the corresponding
driver can use the APIs introduced in this patch, to
register(or unregister) with the thermal framework.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  280 +
 include/linux/thermal.h   |   29 +
 2 files changed, 309 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 8f0f37b..b2becb9 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -45,13 +45,16 @@ MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
+static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
+static LIST_HEAD(thermal_sensor_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 static struct thermal_governor *__find_governor(const char *name)
@@ -421,6 +424,103 @@ static void thermal_zone_device_check(struct work_struct 
*work)
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_thermal_sensor(_dev) \
+   container_of(_dev, struct thermal_sensor, device)
+
+static ssize_t
+sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   return sprintf(buf, "%s\n", ts->name);
+}
+
+static ssize_t
+sensor_temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   ret = ts->ops->get_temp(ts, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_hyst(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+hyst_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_hyst)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d_hyst", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_hyst(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
+static ssize_t
+threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   ret = ts->ops->get_threshold(ts, indx, );
+
+   return ret ? ret : sprintf(buf, "%ld\n", val);
+}
+
+static ssize_t
+threshold_store(struct device *dev, struct device_attribute *attr,
+  const char *buf, size_t count)
+{
+   int indx, ret;
+   long val;
+   struct thermal_sensor *ts = to_thermal_sensor(dev);
+
+   if (!ts->ops->set_threshold)
+   return -EPERM;
+
+   if (!sscanf(attr->attr.name, "threshold%d", ))
+   return -EINVAL;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ret = ts->ops->set_threshold(ts, indx, val);
+
+   return ret ? ret : count;
+}
+
 static ssize_t
 type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -705,6 +805,10 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
+/* Thermal sensor attributes */
+static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
+static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1491,6 +1595,182 @@ static void remove_trip_attrs(struct 
therma

[PATCH 5/8] Thermal: Add 'thermal_map' sysfs node

2012-12-18 Thread Durgadoss R
This patch creates a thermal map sysfs node under
/sys/class/thermal/thermal_zoneX/. This contains
entries named map0, map1 .. mapN. Each map has the
following space separated values:
trip_type sensor_name cdev_name trip_mask weights

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  149 -
 include/linux/thermal.h   |   29 
 2 files changed, 176 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 29ec073..a3adc00 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -506,6 +506,41 @@ static void remove_cdev_from_zone(struct thermal_zone *tz,
tz->cdev_indx--;
 }
 
+static void __clean_map_entry(struct thermal_zone *tz, int i)
+{
+   tz->map[i] = NULL;
+   sysfs_remove_file(tz->kobj_thermal_map, >map_attr[i]->attr.attr);
+   /* Free map attributes */
+   kfree(tz->map_attr[i]);
+   tz->map_attr[i] = NULL;
+}
+
+static void remove_sensor_map_entry(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(ts->name, tz->map[i]->sensor_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
+static void remove_cdev_map_entry(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int i;
+
+   for (i = 0; i < MAX_MAPS_PER_ZONE; i++) {
+   if (tz->map[i] && !strnicmp(cdev->type, tz->map[i]->cdev_name,
+   THERMAL_NAME_LENGTH)) {
+   __clean_map_entry(tz, i);
+   }
+   }
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -898,6 +933,52 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
 }
 
 static ssize_t
+map_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   struct thermal_zone *tz;
+   struct thermal_map *map;
+   struct device *dev;
+   char *trip;
+
+   /*
+* For maps under /sys/class/thermal/zoneX/thermal_map/mapY:
+* attr points to mapY
+* kobj points to thermal_map
+* kobj->parent points to zoneX
+*/
+
+   /* Get zone pointer */
+   dev = container_of(kobj->parent, struct device, kobj);
+   tz = to_zone(dev);
+   if (!tz)
+   return -EINVAL;
+
+   sscanf(attr->attr.name, "map%d", );
+
+   if (indx < 0 || indx >= MAX_MAPS_PER_ZONE)
+   return -EINVAL;
+
+   if (!tz->map[indx])
+   return sprintf(buf, "\n");
+
+   map = tz->map[indx];
+
+   trip = (map->trip_type == THERMAL_TRIP_ACTIVE) ?
+   "active" : "passive";
+   ret += sprintf(buf, "%s", trip);
+   ret += sprintf(buf + ret, " %s", map->sensor_name);
+   ret += sprintf(buf + ret, " %s", map->cdev_name);
+   ret += sprintf(buf + ret, " 0x%x", map->trip_mask);
+
+   for (i = 0; i < map->num_weights; i++)
+   ret += sprintf(buf + ret, " %d", map->weights[i]);
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
 active_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
int i, indx, ret = 0;
@@ -1676,8 +1757,10 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_lock(_list_lock);
 
-   for_each_thermal_zone(tmp_tz)
+   for_each_thermal_zone(tmp_tz) {
remove_cdev_from_zone(tmp_tz, cdev);
+   remove_cdev_map_entry(tmp_tz, cdev);
+   }
 
mutex_unlock(_list_lock);
 
@@ -1931,12 +2014,19 @@ struct thermal_zone *create_thermal_zone(const char 
*name, void *devdata)
if (!tz->kobj_thermal_trip)
goto exit_name;
 
+   tz->kobj_thermal_map = kobject_create_and_add("thermal_map",
+   >device.kobj);
+   if (!tz->kobj_thermal_map)
+   goto exit_trip;
+
/* Add this zone to the global list of thermal zones */
mutex_lock(_list_lock);
list_add_tail(>node, _zone_list);
mutex_unlock(_list_lock);
return tz;
 
+exit_trip:
+   kobject_del(tz->kobj_thermal_trip);
 exit_name:
device_remove_file(>device, _attr_zone_name);
 exit_unregister:
@@ -2000,6 +2090,12 @@ void remove_thermal_zone(struct thermal_zone *tz)
kobject_name(>cdevs[i]->device.kobj));
 

[PATCH 4/8] Thermal: Add Thermal_trip sysfs node

2012-12-18 Thread Durgadoss R
This patch adds a thermal_trip directory under
/sys/class/thermal/zoneX. This directory contains
the trip point values for sensors bound to this
zone.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  237 -
 include/linux/thermal.h   |   37 +++
 2 files changed, 272 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b39bf97..29ec073 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -448,6 +448,22 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static int get_sensor_indx_by_kobj(struct thermal_zone *tz, const char *name)
+{
+   int i, indx = -EINVAL;
+
+   mutex_lock(_list_lock);
+   for (i = 0; i < tz->sensor_indx; i++) {
+   if (!strnicmp(name, kobject_name(tz->kobj_trip[i]),
+   THERMAL_NAME_LENGTH)) {
+   indx = i;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return indx;
+}
+
 static void remove_sensor_from_zone(struct thermal_zone *tz,
struct thermal_sensor *ts)
 {
@@ -459,9 +475,15 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
 
sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
 
+   /* Delete this sensor's trip Kobject */
+   kobject_del(tz->kobj_trip[indx]);
+
/* Shift the entries in the tz->sensors array */
-   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++) {
tz->sensors[j] = tz->sensors[j + 1];
+   tz->sensor_trip[j] = tz->sensor_trip[j + 1];
+   tz->kobj_trip[j] = tz->kobj_trip[j + 1];
+   }
 
tz->sensor_indx--;
 }
@@ -875,6 +897,120 @@ policy_show(struct device *dev, struct device_attribute 
*devattr, char *buf)
return sprintf(buf, "%s\n", tz->governor->name);
 }
 
+static ssize_t
+active_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   struct thermal_zone *tz;
+   struct device *dev;
+
+   /* In this function, for
+* /sys/class/thermal/zoneX/thermal_trip/sensorY:
+* attr points to sysfs node 'active'
+* kobj points to sensorY
+* kobj->parent points to thermal_trip
+* kobj->parent->parent points to zoneX
+*/
+
+   /* Get the zone pointer */
+   dev = container_of(kobj->parent->parent, struct device, kobj);
+   tz = to_zone(dev);
+   if (!tz)
+   return -EINVAL;
+
+   /*
+* We need this because in the sysfs tree, 'sensorY' is
+* not really the sensor pointer. It just has the name
+* 'sensorY'; whereas 'zoneX' is actually the zone pointer.
+* This means container_of(kobj, struct device, kobj) will not
+* provide the actual sensor pointer.
+*/
+   indx = get_sensor_indx_by_kobj(tz, kobject_name(kobj));
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_active_trips <= 0)
+   return sprintf(buf, "\n");
+
+   ret += sprintf(buf, "0x%x", tz->sensor_trip[indx]->active_trip_mask);
+   for (i = 0; i < tz->sensor_trip[indx]->num_active_trips; i++) {
+   ret += sprintf(buf + ret, " %d",
+   tz->sensor_trip[indx]->active_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+ptrip_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+   int i, indx, ret = 0;
+   struct thermal_zone *tz;
+   struct device *dev;
+
+   /* Get the zone pointer */
+   dev = container_of(kobj->parent->parent, struct device, kobj);
+   tz = to_zone(dev);
+   if (!tz)
+   return -EINVAL;
+
+   indx = get_sensor_indx_by_kobj(tz, kobject_name(kobj));
+   if (indx < 0)
+   return indx;
+
+   if (tz->sensor_trip[indx]->num_passive_trips <= 0)
+   return sprintf(buf, "\n");
+
+   for (i = 0; i < tz->sensor_trip[indx]->num_passive_trips; i++) {
+   ret += sprintf(buf + ret, "%d ",
+   tz->sensor_trip[indx]->passive_trips[i]);
+   }
+
+   ret += sprintf(buf + ret, "\n");
+   return ret;
+}
+
+static ssize_t
+hot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+   int indx;
+   struct thermal_zone *tz;
+   struct device *dev;
+
+   /* Get the zone pointer */
+   dev = container_of(kobj->parent->parent, struct device, kob

[PATCH 6/8] Thermal: Add Documentation to new APIs

2012-12-18 Thread Durgadoss R
This patch adds Documentation for the new APIs
introduced in this patch set. The documentation
also has a model sysfs structure for reference.

Signed-off-by: Durgadoss R 
---
 Documentation/thermal/sysfs-api2.txt |  248 ++
 1 file changed, 248 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt

diff --git a/Documentation/thermal/sysfs-api2.txt 
b/Documentation/thermal/sysfs-api2.txt
new file mode 100644
index 000..ffd0402
--- /dev/null
+++ b/Documentation/thermal/sysfs-api2.txt
@@ -0,0 +1,248 @@
+Thermal Framework
+-
+
+Written by Durgadoss R 
+Copyright (c) 2012 Intel Corporation
+
+Created on: 4 November 2012
+Updated on: 18 December 2012
+
+0. Introduction
+---
+The Linux thermal framework provides a set of interfaces for thermal
+sensors and thermal cooling devices (fan, processor...) to register
+with the thermal management solution and to be a part of it.
+
+This document focuses on how to enable new thermal sensors and cooling
+devices to participate in thermal management. This solution is intended
+to be 'light-weight' and platform/architecture independent. Any thermal
+sensor/cooling device should be able to use the infrastructure easily.
+
+The goal of thermal framework is to expose the thermal sensor/zone and
+cooling device attributes in a consistent way. This will help the
+thermal governors to make use of the information to manage platform
+thermals efficiently.
+
+The thermal sensor source file can be generic (can be any sensor driver,
+in any subsystem). This driver will use the sensor APIs and register with
+thermal framework to participate in platform Thermal management. This
+does not (and should not) know about which zone it belongs to, or any
+other information about platform thermals. A sensor driver is a standalone
+piece of code, which can optionally register with thermal framework.
+
+However, for any platform, there should be a platformX_thermal.c file,
+which will know about the platform thermal characteristics (like how many
+sensors, zones, cooling devices, etc.. And how they are related to each other
+i.e the mapping information). Only in this file, the zone level APIs should
+be used, in which case the file will have all information required to attach
+various sensors to a particular zone.
+
+This way, we can have one platform level thermal file, which can support
+multiple platforms (may be)using the same set of sensors (but)binded in
+a different way. This file can get the platform thermal information
+through Firmware, ACPI tables, device tree etc.
+
+Unfortunately, today we don't have many drivers that can be clearly
+differentiated as 'sensor_file.c' and 'platform_thermal_file.c'.
+But very soon we will need/have. The reason I am saying this is because
+we are seeing a lot of chip drivers, starting to use thermal framework,
+and we should keep it really light-weight for them to do so.
+
+An Example: drivers/hwmon/emc1403.c - a generic thermal chip driver
+In one platform this sensor can belong to 'ZoneA' and in another the
+same can belong to 'ZoneB'. But, emc1403.c does not really care about
+where does it belong. It just reports temperature.
+
+1. Terminology
+--
+This section describes the terminology used in the rest of this
+document as well as the thermal framework code.
+
+thermal_sensor: Hardware that can report temperature of a particular
+   spot in the platform, where it is placed. The temperature
+   reported by the sensor is the 'real' temperature reported
+   by the hardware.
+thermal_zone:  A virtual area on the device, that gets heated up. It may
+   have one or more thermal sensors attached to it.
+cooling_device:Any component that can help in reducing the temperature 
of
+   a 'hot spot' either by reducing its performance (passive
+   cooling) or by other means(Active cooling E.g. Fan)
+
+trip_points:   Various temperature levels for each sensor. As of now, we
+   have four levels namely active, passive, hot and critical.
+   Hot and critical trip point support only one value whereas
+   active and passive can have any number of values. These
+   temperature values can come from platform data, and are
+   exposed through sysfs in a consistent manner. Stand-alone
+   thermal sensor drivers are not expected to know these values.
+   These values are RO.
+thresholds:These are programmable temperature limits, on reaching which
+   the thermal sensor generates an interrupt. The framework is
+   notified about this interrupt to take appropriate action.
+   There can be as many number of thresholds as that of the
+   hardware supports. These values are RW.
+
+thermal_map:   This provides the mapping (aka binding) information between

[PATCH 7/8] Thermal: Make PER_ZONE values configurable

2012-12-18 Thread Durgadoss R
This patch makes MAX_SENSORS_PER_ZONE and
MAX_CDEVS_PER_ZONE values configurable. The
default value is 1, and range is 1-12.

Signed-off-by: Durgadoss R 
---
No great reason for using 12.
---
 drivers/thermal/Kconfig |   14 ++
 include/linux/thermal.h |6 +++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d96da07..c5ba3340 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,20 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_MAX_SENSORS_PER_ZONE
+   int "Maximum number of sensors allowed per thermal zone"
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of sensors allowed per zone
+
+config THERMAL_MAX_CDEVS_PER_ZONE
+   int "Maximum number of cooling devices allowed per thermal zone"
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of cooling devices allowed per zone
+
 config THERMAL_HWMON
bool
depends on HWMON=y || HWMON=THERMAL
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 581dc87..7b0359b 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -49,9 +49,9 @@
 /* Default Thermal Governor: Does Linear Throttling */
 #define DEFAULT_THERMAL_GOVERNOR   "step_wise"
 
-#define MAX_SENSORS_PER_ZONE   5
-
-#define MAX_CDEVS_PER_ZONE 5
+/* Maximum number of sensors/cdevs per zone, defined through Kconfig */
+#define MAX_SENSORS_PER_ZONE   CONFIG_THERMAL_MAX_SENSORS_PER_ZONE
+#define MAX_CDEVS_PER_ZONE CONFIG_THERMAL_MAX_CDEVS_PER_ZONE
 
 /* If we map each sensor with every possible cdev for a zone */
 #define MAX_MAPS_PER_ZONE  (MAX_SENSORS_PER_ZONE * MAX_CDEVS_PER_ZONE)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 8/8] Thermal: Dummy driver used for testing

2012-12-18 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  315 
 3 files changed, 323 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c5ba3340..3b92a76 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -136,4 +136,9 @@ config DB8500_CPUFREQ_COOLING
  bound cpufreq cooling device turns active to set CPU frequency low to
  cool down the CPU.
 
+config THERMAL_TEST
+   tristate "test driver"
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d8da683..02c3edb 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_RCAR_THERMAL)+= rcar_thermal.o
 obj-$(CONFIG_EXYNOS_THERMAL)   += exynos_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)   += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..5a11e34
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,315 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~
+ * Author: Durgadoss R 
+ */
+
+#define pr_fmt(fmt)  "thermal_test: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, "%d\n", ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag;
+
+   if (kstrtol(buf, 10, ))
+   return -EINVAL;
+
+   ts_data.flag = flag;
+
+   if (flag == 0) {
+ 

[PATCH 2/8] Thermal: Create zone level APIs

2012-12-18 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |  194 +
 include/linux/thermal.h   |   21 +
 2 files changed, 215 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b2becb9..06d5a12 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,19 +44,44 @@ MODULE_DESCRIPTION("Generic thermal management sysfs 
support");
 MODULE_LICENSE("GPL");
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, _sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, _zone_list, node)
+
+#define GET_INDEX(tz, ptr, indx, type) \
+   do {\
+   int i;  \
+   indx = -EINVAL; \
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(##_list_lock);  \
+   for (i = 0; i < tz->type##_indx; i++) { \
+   if (tz->type##s[i] == ptr) {\
+   indx = i;   \
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(##_list_lock);\
+   } while (0)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -419,15 +444,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   GET_INDEX(tz, ts, indx, sensor);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->sensors array */
+   for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
+   tz->sensors[j] = tz->sensors[j + 1];
+
+   tz->sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, "%s\n", tz->name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -809,6 +863,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1654,6 +1710,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name && strlen(name) >= THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(>idr);
+   ret = get_idr(_zone_idr, _idr_lock, >id);
+   if (ret)
+   goto exit_free;
+
+   strcpy(tz->name, name);
+   tz->devdata =

[PATCH 0/8] Thermal Framework Enhancements

2012-12-18 Thread Durgadoss R
This patch is a v1 based on the RFC submitted here:
https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -thermal tree, and is
tested on a Core-i5 and an Atom netbook.

This series contains 8 patches:
Patch 1/8: Creates new sensor level APIs
Patch 2/8: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/8: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/8: Adds a thermal_trip sysfs node, which exposes various trip
   points for all sensors present in a zone.
Patch 5/8: Adds a thermal_map sysfs node. It is a compact representation
   of the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/8: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/8: Make PER ZONE values configurable through Kconfig
Patch 8/8: A dummy driver that can be used for testing. This is not for merge.

Thanks to Rui Zhang, Honghbo Zhang, Wei Ni for their feedback on the
RFC version.

Durgadoss R (8):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add Thermal_trip sysfs node
  Thermal: Add 'thermal_map' sysfs node
  Thermal: Add Documentation to new APIs
  Thermal: Make PER_ZONE values configurable
  Thermal: Dummy driver used for testing

 Documentation/thermal/sysfs-api2.txt |  248 +
 drivers/thermal/Kconfig  |   19 +
 drivers/thermal/Makefile |3 +
 drivers/thermal/thermal_sys.c|  932 ++
 drivers/thermal/thermal_test.c   |  315 
 include/linux/thermal.h  |  124 +
 6 files changed, 1641 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure

2012-12-18 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R 
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |8 +
 2 files changed, 88 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 06d5a12..b39bf97 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -82,6 +83,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
mutex_unlock(##_list_lock);\
} while (0)
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, _cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -462,6 +466,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz->sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   GET_INDEX(tz, cdev, indx, cdev);
+   if (indx < 0)
+   return;
+
+   sysfs_remove_link(>device.kobj, kobject_name(>device.kobj));
+
+   /* Shift the entries in the tz->cdevs array */
+   for (j = indx; j < MAX_CDEVS_PER_ZONE - 1; j++)
+   tz->cdevs[j] = tz->cdevs[j + 1];
+
+   tz->cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1458,6 +1480,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1495,6 +1518,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(_list_lock);
 
+   mutex_lock(_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(_list_lock);
+
if (cdev->type[0])
device_remove_file(>device, _attr_cdev_type);
device_remove_file(>device, _attr_max_state);
@@ -1790,6 +1820,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos->type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1840,6 +1887,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   GET_INDEX(tz, cdev, ret, cdev);
+   if (ret >= 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(_list_lock);
+   ret = sysfs_create_link(>device.kobj, >device.kobj,
+   kobject_name(>device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz->cdevs[tz->cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(_list_lock);
+exit_zone:
+   mutex_unlock(_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f08f774..c4e45c7 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -51,6 +51,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -209,6 +211,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct thermal_cooling_device *cdevs[MAX_CDEVS_P

[PATCH 0/8] Thermal Framework Enhancements

2012-12-18 Thread Durgadoss R
This patch is a v1 based on the RFC submitted here:
https://patchwork.kernel.org/patch/1758921/

This patch set is based on Rui's -thermal tree, and is
tested on a Core-i5 and an Atom netbook.

This series contains 8 patches:
Patch 1/8: Creates new sensor level APIs
Patch 2/8: Creates new zone level APIs. The existing tzd structure is
   kept as such for clarity and compatibility purposes.
Patch 3/8: Creates functions to add/remove a cdev to/from a zone. The
   existing tcd structure need not be modified.
Patch 4/8: Adds a thermal_trip sysfs node, which exposes various trip
   points for all sensors present in a zone.
Patch 5/8: Adds a thermal_map sysfs node. It is a compact representation
   of the binding relationship between a sensor and a cdev,
   within a zone.
Patch 6/8: Creates Documentation for the new APIs. A new file is
   created for clarity. Final goal is to merge with the existing
   file or refactor the files, as whatever seems appropriate.
Patch 7/8: Make PER ZONE values configurable through Kconfig
Patch 8/8: A dummy driver that can be used for testing. This is not for merge.

Thanks to Rui Zhang, Honghbo Zhang, Wei Ni for their feedback on the
RFC version.

Durgadoss R (8):
  Thermal: Create sensor level APIs
  Thermal: Create zone level APIs
  Thermal: Add APIs to bind cdev to new zone structure
  Thermal: Add Thermal_trip sysfs node
  Thermal: Add 'thermal_map' sysfs node
  Thermal: Add Documentation to new APIs
  Thermal: Make PER_ZONE values configurable
  Thermal: Dummy driver used for testing

 Documentation/thermal/sysfs-api2.txt |  248 +
 drivers/thermal/Kconfig  |   19 +
 drivers/thermal/Makefile |3 +
 drivers/thermal/thermal_sys.c|  932 ++
 drivers/thermal/thermal_test.c   |  315 
 include/linux/thermal.h  |  124 +
 6 files changed, 1641 insertions(+)
 create mode 100644 Documentation/thermal/sysfs-api2.txt
 create mode 100644 drivers/thermal/thermal_test.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure

2012-12-18 Thread Durgadoss R
This patch creates new APIs to add/remove a
cdev to/from a zone. This patch does not change
the old cooling device implementation.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |   80 +
 include/linux/thermal.h   |8 +
 2 files changed, 88 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 06d5a12..b39bf97 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -58,6 +58,7 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
 static DEFINE_MUTEX(zone_list_lock);
+static DEFINE_MUTEX(cdev_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
 #define for_each_thermal_sensor(pos) \
@@ -82,6 +83,9 @@ static DEFINE_MUTEX(thermal_governor_lock);
mutex_unlock(type##_list_lock);\
} while (0)
 
+#define for_each_cdev(pos) \
+   list_for_each_entry(pos, thermal_cdev_list, node)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -462,6 +466,24 @@ static void remove_sensor_from_zone(struct thermal_zone 
*tz,
tz-sensor_indx--;
 }
 
+static void remove_cdev_from_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int j, indx;
+
+   GET_INDEX(tz, cdev, indx, cdev);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(cdev-device.kobj));
+
+   /* Shift the entries in the tz-cdevs array */
+   for (j = indx; j  MAX_CDEVS_PER_ZONE - 1; j++)
+   tz-cdevs[j] = tz-cdevs[j + 1];
+
+   tz-cdev_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -1458,6 +1480,7 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
int i;
const struct thermal_zone_params *tzp;
struct thermal_zone_device *tz;
+   struct thermal_zone *tmp_tz;
struct thermal_cooling_device *pos = NULL;
 
if (!cdev)
@@ -1495,6 +1518,13 @@ void thermal_cooling_device_unregister(struct 
thermal_cooling_device *cdev)
 
mutex_unlock(thermal_list_lock);
 
+   mutex_lock(zone_list_lock);
+
+   for_each_thermal_zone(tmp_tz)
+   remove_cdev_from_zone(tmp_tz, cdev);
+
+   mutex_unlock(zone_list_lock);
+
if (cdev-type[0])
device_remove_file(cdev-device, dev_attr_cdev_type);
device_remove_file(cdev-device, dev_attr_max_state);
@@ -1790,6 +1820,23 @@ exit:
 }
 EXPORT_SYMBOL(remove_thermal_zone);
 
+struct thermal_cooling_device *get_cdev_by_name(const char *name)
+{
+   struct thermal_cooling_device *pos;
+   struct thermal_cooling_device *cdev = NULL;
+
+   mutex_lock(cdev_list_lock);
+   for_each_cdev(pos) {
+   if (!strnicmp(pos-type, name, THERMAL_NAME_LENGTH)) {
+   cdev = pos;
+   break;
+   }
+   }
+   mutex_unlock(cdev_list_lock);
+   return cdev;
+}
+EXPORT_SYMBOL(get_cdev_by_name);
+
 struct thermal_sensor *get_sensor_by_name(const char *name)
 {
struct thermal_sensor *pos;
@@ -1840,6 +1887,39 @@ exit_zone:
 }
 EXPORT_SYMBOL(add_sensor_to_zone);
 
+int add_cdev_to_zone(struct thermal_zone *tz,
+   struct thermal_cooling_device *cdev)
+{
+   int ret;
+
+   if (!tz || !cdev)
+   return -EINVAL;
+
+   mutex_lock(zone_list_lock);
+
+   /* Ensure we are not adding the same cdev again!! */
+   GET_INDEX(tz, cdev, ret, cdev);
+   if (ret = 0) {
+   ret = -EEXIST;
+   goto exit_zone;
+   }
+
+   mutex_lock(cdev_list_lock);
+   ret = sysfs_create_link(tz-device.kobj, cdev-device.kobj,
+   kobject_name(cdev-device.kobj));
+   if (ret)
+   goto exit_cdev;
+
+   tz-cdevs[tz-cdev_indx++] = cdev;
+
+exit_cdev:
+   mutex_unlock(cdev_list_lock);
+exit_zone:
+   mutex_unlock(zone_list_lock);
+   return ret;
+}
+EXPORT_SYMBOL(add_cdev_to_zone);
+
 /**
  * thermal_sensor_register - register a new thermal sensor
  * @name:  name of the thermal sensor
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index f08f774..c4e45c7 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -51,6 +51,8 @@
 
 #define MAX_SENSORS_PER_ZONE   5
 
+#define MAX_CDEVS_PER_ZONE 5
+
 struct thermal_sensor;
 struct thermal_zone_device;
 struct thermal_cooling_device;
@@ -209,6 +211,10 @@ struct thermal_zone {
/* Sensor level information */
int sensor_indx; /* index into 'sensors' array */
struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
+
+   /* cdev level information */
+   int cdev_indx; /* index into 'cdevs' array */
+   struct

[PATCH 2/8] Thermal: Create zone level APIs

2012-12-18 Thread Durgadoss R
This patch adds a new thermal_zone structure to
thermal.h. Also, adds zone level APIs to the thermal
framework.

A thermal zone is a hot spot on the platform, which
can have one or more sensors and cooling devices attached
to it. These sensors can be mapped to a set of cooling
devices, which when throttled, can help to bring down
the temperature of the hot spot.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/thermal_sys.c |  194 +
 include/linux/thermal.h   |   21 +
 2 files changed, 215 insertions(+)

diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b2becb9..06d5a12 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -44,19 +44,44 @@ MODULE_DESCRIPTION(Generic thermal management sysfs 
support);
 MODULE_LICENSE(GPL);
 
 static DEFINE_IDR(thermal_tz_idr);
+static DEFINE_IDR(thermal_zone_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_IDR(thermal_sensor_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_sensor_list);
+static LIST_HEAD(thermal_zone_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(sensor_list_lock);
+static DEFINE_MUTEX(zone_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+#define for_each_thermal_sensor(pos) \
+   list_for_each_entry(pos, thermal_sensor_list, node)
+
+#define for_each_thermal_zone(pos) \
+   list_for_each_entry(pos, thermal_zone_list, node)
+
+#define GET_INDEX(tz, ptr, indx, type) \
+   do {\
+   int i;  \
+   indx = -EINVAL; \
+   if (!tz || !ptr)\
+   break;  \
+   mutex_lock(type##_list_lock);  \
+   for (i = 0; i  tz-type##_indx; i++) { \
+   if (tz-type##s[i] == ptr) {\
+   indx = i;   \
+   break;  \
+   }   \
+   }   \
+   mutex_unlock(type##_list_lock);\
+   } while (0)
+
 static struct thermal_governor *__find_governor(const char *name)
 {
struct thermal_governor *pos;
@@ -419,15 +444,44 @@ static void thermal_zone_device_check(struct work_struct 
*work)
thermal_zone_device_update(tz);
 }
 
+static void remove_sensor_from_zone(struct thermal_zone *tz,
+   struct thermal_sensor *ts)
+{
+   int j, indx;
+
+   GET_INDEX(tz, ts, indx, sensor);
+   if (indx  0)
+   return;
+
+   sysfs_remove_link(tz-device.kobj, kobject_name(ts-device.kobj));
+
+   /* Shift the entries in the tz-sensors array */
+   for (j = indx; j  MAX_SENSORS_PER_ZONE - 1; j++)
+   tz-sensors[j] = tz-sensors[j + 1];
+
+   tz-sensor_indx--;
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)
 
+#define to_zone(_dev) \
+   container_of(_dev, struct thermal_zone, device)
+
 #define to_thermal_sensor(_dev) \
container_of(_dev, struct thermal_sensor, device)
 
 static ssize_t
+zone_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct thermal_zone *tz = to_zone(dev);
+
+   return sprintf(buf, %s\n, tz-name);
+}
+
+static ssize_t
 sensor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
struct thermal_sensor *ts = to_thermal_sensor(dev);
@@ -809,6 +863,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, 
policy_store);
 static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
 static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
 
+static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
+
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)\
container_of(_dev, struct thermal_cooling_device, device)
@@ -1654,6 +1710,136 @@ static int enable_sensor_thresholds(struct 
thermal_sensor *ts, int count)
return 0;
 }
 
+struct thermal_zone *create_thermal_zone(const char *name, void *devdata)
+{
+   struct thermal_zone *tz;
+   int ret;
+
+   if (!name || (name  strlen(name) = THERMAL_NAME_LENGTH))
+   return ERR_PTR(-EINVAL);
+
+   tz = kzalloc(sizeof(*tz), GFP_KERNEL);
+   if (!tz)
+   return ERR_PTR(-ENOMEM);
+
+   idr_init(tz-idr);
+   ret = get_idr(thermal_zone_idr, thermal_idr_lock, tz-id);
+   if (ret)
+   goto exit_free;
+
+   strcpy(tz-name, name);
+   tz-devdata = devdata;
+   tz-device.class

[PATCH 8/8] Thermal: Dummy driver used for testing

2012-12-18 Thread Durgadoss R
This patch has a dummy driver that can be used for
testing purposes. This patch is not for merge.

Signed-off-by: Durgadoss R durgados...@intel.com
---
 drivers/thermal/Kconfig|5 +
 drivers/thermal/Makefile   |3 +
 drivers/thermal/thermal_test.c |  315 
 3 files changed, 323 insertions(+)
 create mode 100644 drivers/thermal/thermal_test.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c5ba3340..3b92a76 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -136,4 +136,9 @@ config DB8500_CPUFREQ_COOLING
  bound cpufreq cooling device turns active to set CPU frequency low to
  cool down the CPU.
 
+config THERMAL_TEST
+   tristate test driver
+   help
+ Enable this to test the thermal framework.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d8da683..02c3edb 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_RCAR_THERMAL)+= rcar_thermal.o
 obj-$(CONFIG_EXYNOS_THERMAL)   += exynos_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)   += db8500_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)   += db8500_cpufreq_cooling.o
+
+# dummy driver for testing
+obj-$(CONFIG_THERMAL_TEST) += thermal_test.o
diff --git a/drivers/thermal/thermal_test.c b/drivers/thermal/thermal_test.c
new file mode 100644
index 000..5a11e34
--- /dev/null
+++ b/drivers/thermal/thermal_test.c
@@ -0,0 +1,315 @@
+/*
+ * thermal_test.c - This driver can be used to test Thermal
+ *Framework changes. Not specific to any
+ *platform. Fills the log buffer generously ;)
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * ~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~
+ * Author: Durgadoss R durgados...@intel.com
+ */
+
+#define pr_fmt(fmt)  thermal_test:  fmt
+
+#include linux/module.h
+#include linux/init.h
+#include linux/err.h
+#include linux/param.h
+#include linux/device.h
+#include linux/slab.h
+#include linux/pm.h
+#include linux/platform_device.h
+#include linux/thermal.h
+
+#define MAX_THERMAL_ZONES  2
+#define MAX_THERMAL_SENSORS2
+#define MAX_COOLING_DEVS   4
+#define NUM_THRESHOLDS 3
+
+static struct ts_data {
+   int curr_temp;
+   int flag;
+} ts_data;
+
+int active_trips[10] = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10};
+int passive_trips[5] = {100, 90, 60, 50, 40};
+
+static struct platform_device *pdev;
+static unsigned long cur_cdev_state = 2;
+static struct thermal_sensor *ts, *ts1;
+static struct thermal_zone *tz;
+static struct thermal_cooling_device *cdev;
+
+static long thermal_thresholds[NUM_THRESHOLDS] = {3, 4, 5};
+
+static struct thermal_trip_point trip = {
+   .hot = 90,
+   .crit = 100,
+   .num_passive_trips = 5,
+   .passive_trips = passive_trips,
+   .num_active_trips = 10,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xCFF,
+};
+
+static struct thermal_trip_point trip1 = {
+   .hot = 95,
+   .crit = 125,
+   .num_passive_trips = 0,
+   .passive_trips = passive_trips,
+   .num_active_trips = 6,
+   .active_trips = active_trips,
+   .active_trip_mask = 0xFF,
+};
+
+static int read_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = cur_cdev_state;
+   return 0;
+}
+
+static int write_cur_state(struct thermal_cooling_device *cdev,
+   unsigned long state)
+{
+   cur_cdev_state = state;
+   return 0;
+}
+
+static int read_max_state(struct thermal_cooling_device *cdev,
+   unsigned long *state)
+{
+   *state = 5;
+   return 0;
+}
+
+static int read_curr_temp(struct thermal_sensor *ts, long *temp)
+{
+   *temp = ts_data.curr_temp;
+   return 0;
+}
+
+static ssize_t
+flag_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+   return sprintf(buf, %d\n, ts_data.flag);
+}
+
+static ssize_t
+flag_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   long flag

[PATCH 7/8] Thermal: Make PER_ZONE values configurable

2012-12-18 Thread Durgadoss R
This patch makes MAX_SENSORS_PER_ZONE and
MAX_CDEVS_PER_ZONE values configurable. The
default value is 1, and range is 1-12.

Signed-off-by: Durgadoss R durgados...@intel.com
---
No great reason for using 12.
---
 drivers/thermal/Kconfig |   14 ++
 include/linux/thermal.h |6 +++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d96da07..c5ba3340 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -15,6 +15,20 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_MAX_SENSORS_PER_ZONE
+   int Maximum number of sensors allowed per thermal zone
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of sensors allowed per zone
+
+config THERMAL_MAX_CDEVS_PER_ZONE
+   int Maximum number of cooling devices allowed per thermal zone
+   default 1
+   range 1 12
+   ---help---
+ Specify the number of cooling devices allowed per zone
+
 config THERMAL_HWMON
bool
depends on HWMON=y || HWMON=THERMAL
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 581dc87..7b0359b 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -49,9 +49,9 @@
 /* Default Thermal Governor: Does Linear Throttling */
 #define DEFAULT_THERMAL_GOVERNOR   step_wise
 
-#define MAX_SENSORS_PER_ZONE   5
-
-#define MAX_CDEVS_PER_ZONE 5
+/* Maximum number of sensors/cdevs per zone, defined through Kconfig */
+#define MAX_SENSORS_PER_ZONE   CONFIG_THERMAL_MAX_SENSORS_PER_ZONE
+#define MAX_CDEVS_PER_ZONE CONFIG_THERMAL_MAX_CDEVS_PER_ZONE
 
 /* If we map each sensor with every possible cdev for a zone */
 #define MAX_MAPS_PER_ZONE  (MAX_SENSORS_PER_ZONE * MAX_CDEVS_PER_ZONE)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   >