* [PATCHv3 00/15] Thermal_Framework_Enhancements
@ 2012-09-01 11:51 Durgadoss R
2012-09-01 11:51 ` [PATCHv3 01/15] Thermal: Refactor thermal.h file Durgadoss R
` (14 more replies)
0 siblings, 15 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch series is a v3 of the series submitted here:
http://www.spinics.net/lists/linux-acpi/msg37375.html
These patches are based on Rui's tree here: (branch - thermal)
git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
Changes since v2:
* Made thermal_zone_params as argument to tzd_register()
* Introduced Thermal governor register/unregister APIs
* Added 'write' permission for policy sysfs attribute
* Added function pointer based implemention for thermal
governors.
* Added a 'dummy' user space governor in thermal_sys.c
* Renamed 'do_binding' and 'update_bind_info' functions as
'bind_tz' and 'bind_cdev' respectively
* Updated Documentation for all the changes
Changes since v1:
* Created thermal_core.h
* Removed get_cdev_by_name API, as it is no longer needed
* Introduced thermal_bind_params inside thermal_zone_params
* Use a single arbitrator by making thermal_cdev_update global
* Added more documentation on EXPORT_SYMBOL APIs in thermal_sys.c
* Various minor fixes based on comments from Rui and Eduardo.
Durgadoss R (15):
Thermal: Refactor thermal.h file
Thermal: Move thermal_instance to thermal_core.h
Thermal: Add get trend, get instance API's to thermal_sys
Thermal: Add platform level information to thermal.h
Thermal: Pass zone parameters as argument to tzd_register
Thermal: Add thermal governor registration APIs
Thermal: Add a policy sysfs attribute
Thermal: Update binding logic based on platform data
Thermal: Make thermal_cdev_update as a global function
Thermal: Introduce fair_share thermal governor
Thermal: Introduce a step_wise thermal governor
Thermal: Register a governor for user space
Thermal: Remove throttling logic out of thermal_sys.c
Thermal: Add a notification API
Thermal: Add documentation for platform layer data
Documentation/thermal/sysfs-api.txt | 64 ++
drivers/acpi/thermal.c | 6 +-
drivers/platform/x86/acerhdf.c | 2 +-
drivers/platform/x86/intel_mid_thermal.c | 2 +-
drivers/power/power_supply_core.c | 2 +-
drivers/staging/omap-thermal/omap-thermal-common.c | 2 +-
drivers/thermal/Kconfig | 12 +
drivers/thermal/Makefile | 4 +-
drivers/thermal/fair_share.c | 133 ++++
drivers/thermal/spear_thermal.c | 2 +-
drivers/thermal/step_wise.c | 194 ++++++
drivers/thermal/thermal_core.h | 53 ++
drivers/thermal/thermal_sys.c | 715 +++++++++++++-------
include/linux/thermal.h | 130 +++-
14 files changed, 1031 insertions(+), 290 deletions(-)
create mode 100644 drivers/thermal/fair_share.c
create mode 100644 drivers/thermal/step_wise.c
create mode 100644 drivers/thermal/thermal_core.h
--
1.7.9.5
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCHv3 01/15] Thermal: Refactor thermal.h file
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 02/15] Thermal: Move thermal_instance to thermal_core.h Durgadoss R
` (13 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch rearranges the code in thermal.h file,
in the following order, so that it is easy to
read/maintain.
1. All #defines
2. All enums
3. All fops structures
4. All device structures
5. All function declarations
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
include/linux/thermal.h | 78 ++++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 35 deletions(-)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 91b3481..8611e3e 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -29,6 +29,23 @@
#include <linux/device.h>
#include <linux/workqueue.h>
+#define THERMAL_TRIPS_NONE -1
+#define THERMAL_MAX_TRIPS 12
+#define THERMAL_NAME_LENGTH 20
+
+/* No upper/lower limit requirement */
+#define THERMAL_NO_LIMIT -1UL
+
+/* Unit conversion macros */
+#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \
+ ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
+#define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
+
+/* Adding event notification support elements */
+#define THERMAL_GENL_FAMILY_NAME "thermal_event"
+#define THERMAL_GENL_VERSION 0x01
+#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group"
+
struct thermal_zone_device;
struct thermal_cooling_device;
@@ -50,6 +67,30 @@ enum thermal_trend {
THERMAL_TREND_DROPPING, /* temperature is dropping */
};
+/* Events supported by Thermal Netlink */
+enum events {
+ THERMAL_AUX0,
+ THERMAL_AUX1,
+ THERMAL_CRITICAL,
+ THERMAL_DEV_FAULT,
+};
+
+/* attributes of thermal_genl_family */
+enum {
+ THERMAL_GENL_ATTR_UNSPEC,
+ THERMAL_GENL_ATTR_EVENT,
+ __THERMAL_GENL_ATTR_MAX,
+};
+#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
+
+/* commands supported by the thermal_genl_family */
+enum {
+ THERMAL_GENL_CMD_UNSPEC,
+ THERMAL_GENL_CMD_EVENT,
+ __THERMAL_GENL_CMD_MAX,
+};
+#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
+
struct thermal_zone_device_ops {
int (*bind) (struct thermal_zone_device *,
struct thermal_cooling_device *);
@@ -83,11 +124,6 @@ struct thermal_cooling_device_ops {
int (*set_cur_state) (struct thermal_cooling_device *, unsigned long);
};
-#define THERMAL_NO_LIMIT -1UL /* no upper/lower limit requirement */
-
-#define THERMAL_TRIPS_NONE -1
-#define THERMAL_MAX_TRIPS 12
-#define THERMAL_NAME_LENGTH 20
struct thermal_cooling_device {
int id;
char type[THERMAL_NAME_LENGTH];
@@ -100,10 +136,6 @@ struct thermal_cooling_device {
struct list_head node;
};
-#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \
- ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-#define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
-
struct thermal_attr {
struct device_attribute attr;
char name[THERMAL_NAME_LENGTH];
@@ -131,38 +163,13 @@ struct thermal_zone_device {
struct list_head node;
struct delayed_work poll_queue;
};
-/* Adding event notification support elements */
-#define THERMAL_GENL_FAMILY_NAME "thermal_event"
-#define THERMAL_GENL_VERSION 0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group"
-
-enum events {
- THERMAL_AUX0,
- THERMAL_AUX1,
- THERMAL_CRITICAL,
- THERMAL_DEV_FAULT,
-};
struct thermal_genl_event {
u32 orig;
enum events event;
};
-/* attributes of thermal_genl_family */
-enum {
- THERMAL_GENL_ATTR_UNSPEC,
- THERMAL_GENL_ATTR_EVENT,
- __THERMAL_GENL_ATTR_MAX,
-};
-#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
-
-/* commands supported by the thermal_genl_family */
-enum {
- THERMAL_GENL_CMD_UNSPEC,
- THERMAL_GENL_CMD_EVENT,
- __THERMAL_GENL_CMD_MAX,
-};
-#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
+/* Function declarations */
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, const struct thermal_zone_device_ops *, int, int);
void thermal_zone_device_unregister(struct thermal_zone_device *);
@@ -173,6 +180,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
struct thermal_cooling_device *);
void thermal_zone_device_update(struct thermal_zone_device *);
+
struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
const struct thermal_cooling_device_ops *);
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 02/15] Thermal: Move thermal_instance to thermal_core.h
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
2012-09-01 11:51 ` [PATCHv3 01/15] Thermal: Refactor thermal.h file Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 03/15] Thermal: Add get trend, get instance API's to thermal_sys Durgadoss R
` (12 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch creates a thermal_core.h file which can contain
all defines used by the core thermal framework files. For
now, move the thermal_instance structure to thermal_core.h
This structure is used by files under drivers/thermal/.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_core.h | 53 ++++++++++++++++++++++++++++++++++++++++
drivers/thermal/thermal_sys.c | 23 ++---------------
2 files changed, 55 insertions(+), 21 deletions(-)
create mode 100644 drivers/thermal/thermal_core.h
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
new file mode 100644
index 0000000..0d3205a
--- /dev/null
+++ b/drivers/thermal/thermal_core.h
@@ -0,0 +1,53 @@
+/*
+ * thermal_core.h
+ *
+ * Copyright (C) 2012 Intel Corp
+ * Author: Durgadoss R <durgadoss.r@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#ifndef __THERMAL_CORE_H__
+#define __THERMAL_CORE_H__
+
+#include <linux/device.h>
+#include <linux/thermal.h>
+
+/* Initial state of a cooling device during binding */
+#define THERMAL_NO_TARGET -1UL
+
+/*
+ * This structure is used to describe the behavior of
+ * a certain cooling device on a certain trip point
+ * in a certain thermal zone
+ */
+struct thermal_instance {
+ int id;
+ char name[THERMAL_NAME_LENGTH];
+ struct thermal_zone_device *tz;
+ struct thermal_cooling_device *cdev;
+ int trip;
+ unsigned long upper; /* Highest cooling state for this trip point */
+ unsigned long lower; /* Lowest cooling state for this trip point */
+ unsigned long target; /* expected cooling state */
+ char attr_name[THERMAL_NAME_LENGTH];
+ struct device_attribute attr;
+ struct list_head tz_node; /* node in tz->thermal_instances */
+ struct list_head cdev_node; /* node in cdev->thermal_instances */
+};
+
+#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 5be8728..0e71b00 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -37,31 +37,12 @@
#include <net/netlink.h>
#include <net/genetlink.h>
+#include "thermal_core.h"
+
MODULE_AUTHOR("Zhang Rui");
MODULE_DESCRIPTION("Generic thermal management sysfs support");
MODULE_LICENSE("GPL");
-#define THERMAL_NO_TARGET -1UL
-/*
- * This structure is used to describe the behavior of
- * a certain cooling device on a certain trip point
- * in a certain thermal zone
- */
-struct thermal_instance {
- int id;
- char name[THERMAL_NAME_LENGTH];
- struct thermal_zone_device *tz;
- struct thermal_cooling_device *cdev;
- int trip;
- unsigned long upper; /* Highest cooling state for this trip point */
- unsigned long lower; /* Lowest cooling state for this trip point */
- unsigned long target; /* expected cooling state */
- char attr_name[THERMAL_NAME_LENGTH];
- struct device_attribute attr;
- struct list_head tz_node; /* node in tz->thermal_instances */
- struct list_head cdev_node; /* node in cdev->thermal_instances */
-};
-
static DEFINE_IDR(thermal_tz_idr);
static DEFINE_IDR(thermal_cdev_idr);
static DEFINE_MUTEX(thermal_idr_lock);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 03/15] Thermal: Add get trend, get instance API's to thermal_sys
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
2012-09-01 11:51 ` [PATCHv3 01/15] Thermal: Refactor thermal.h file Durgadoss R
2012-09-01 11:51 ` [PATCHv3 02/15] Thermal: Move thermal_instance to thermal_core.h Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 04/15] Thermal: Add platform level information to thermal.h Durgadoss R
` (11 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds the following API's to thermal_sys.c, that
can be used by other Thermal drivers.
* get_tz_trend: obtain the trend of the given thermal zone
* get_thermal_instance: obtain the instance corresponding
to the given tz, cdev and the trip point.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 4 ++++
2 files changed, 44 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 0e71b00..5e141b5 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -82,6 +82,46 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
mutex_unlock(lock);
}
+int get_tz_trend(struct thermal_zone_device *tz, int trip)
+{
+ enum thermal_trend trend;
+
+ if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
+ if (tz->temperature > tz->last_temperature)
+ trend = THERMAL_TREND_RAISING;
+ else if (tz->temperature < tz->last_temperature)
+ trend = THERMAL_TREND_DROPPING;
+ else
+ trend = THERMAL_TREND_STABLE;
+ }
+
+ return trend;
+}
+EXPORT_SYMBOL(get_tz_trend);
+
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int trip)
+{
+ struct thermal_instance *pos = NULL;
+ struct thermal_instance *target_instance = NULL;
+
+ mutex_lock(&tz->lock);
+ mutex_lock(&cdev->lock);
+
+ list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+ target_instance = pos;
+ break;
+ }
+ }
+
+ mutex_unlock(&cdev->lock);
+ mutex_unlock(&tz->lock);
+
+ return target_instance;
+}
+EXPORT_SYMBOL(get_thermal_instance);
+
/* sys I/F for thermal zone */
#define to_thermal_zone(_dev) \
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 8611e3e..32af124 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -185,6 +185,10 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
const struct thermal_cooling_device_ops *);
void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+int get_tz_trend(struct thermal_zone_device *, int);
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
+ struct thermal_cooling_device *, int);
+
#ifdef CONFIG_NET
extern int thermal_generate_netlink_event(u32 orig, enum events event);
#else
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 04/15] Thermal: Add platform level information to thermal.h
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (2 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 03/15] Thermal: Add get trend, get instance API's to thermal_sys Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 05/15] Thermal: Pass zone parameters as argument to tzd_register Durgadoss R
` (10 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds platform level information to thermal.h
by introducing two structures to hold:
* bind parameters for a thermal zone,
* zone level platform parameters
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
include/linux/thermal.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 32af124..4caa32e 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -157,6 +157,7 @@ struct thermal_zone_device {
int passive;
unsigned int forced_passive;
const struct thermal_zone_device_ops *ops;
+ const struct thermal_zone_params *tzp;
struct list_head thermal_instances;
struct idr idr;
struct mutex lock; /* protect thermal_instances list */
@@ -164,6 +165,34 @@ struct thermal_zone_device {
struct delayed_work poll_queue;
};
+/* Structure that holds binding parameters for a zone */
+struct thermal_bind_params {
+ struct thermal_cooling_device *cdev;
+
+ /*
+ * This is a measure of 'how effectively these devices can
+ * cool 'this' thermal zone. The shall be determined by platform
+ * characterization. This is on a 'percentage' scale.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int weight;
+
+ /*
+ * This is a bit mask that gives the binding relation between this
+ * thermal zone and cdev, for a particular trip point.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int trip_mask;
+ int (*match) (struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev);
+};
+
+/* Structure to define Thermal Zone parameters */
+struct thermal_zone_params {
+ int num_tbps; /* Number of tbp entries */
+ struct thermal_bind_params *tbp;
+};
+
struct thermal_genl_event {
u32 orig;
enum events event;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 05/15] Thermal: Pass zone parameters as argument to tzd_register
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (3 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 04/15] Thermal: Add platform level information to thermal.h Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 06/15] Thermal: Add thermal governor registration APIs Durgadoss R
` (9 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds the thermal zone parameter as an argument to
the tzd_register() function call; and updates other drivers
using this function.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/acpi/thermal.c | 6 +++---
drivers/platform/x86/acerhdf.c | 2 +-
drivers/platform/x86/intel_mid_thermal.c | 2 +-
drivers/power/power_supply_core.c | 2 +-
drivers/staging/omap-thermal/omap-thermal-common.c | 2 +-
drivers/thermal/spear_thermal.c | 2 +-
drivers/thermal/thermal_sys.c | 3 +++
include/linux/thermal.h | 3 ++-
8 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index bd66bd2..d999eda 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -898,14 +898,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
if (tz->trips.passive.flags.valid)
tz->thermal_zone =
thermal_zone_device_register("acpitz", trips, 0, tz,
- &acpi_thermal_zone_ops,
+ &acpi_thermal_zone_ops, NULL,
tz->trips.passive.tsp*100,
tz->polling_frequency*100);
else
tz->thermal_zone =
thermal_zone_device_register("acpitz", trips, 0, tz,
- &acpi_thermal_zone_ops, 0,
- tz->polling_frequency*100);
+ &acpi_thermal_zone_ops, NULL,
+ 0, tz->polling_frequency*100);
if (IS_ERR(tz->thermal_zone))
return -ENODEV;
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 84c5688..c2e3e63 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -662,7 +662,7 @@ static int acerhdf_register_thermal(void)
return -EINVAL;
thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
- &acerhdf_dev_ops, 0,
+ &acerhdf_dev_ops, NULL, 0,
(kernelmode) ? interval*1000 : 0);
if (IS_ERR(thz_dev))
return -EINVAL;
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index c809761..93de090 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -502,7 +502,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
goto err;
}
pinfo->tzd[i] = thermal_zone_device_register(name[i],
- 0, 0, td_info, &tzd_ops, 0, 0);
+ 0, 0, td_info, &tzd_ops, NULL, 0, 0);
if (IS_ERR(pinfo->tzd[i])) {
kfree(td_info);
ret = PTR_ERR(pinfo->tzd[i]);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 2436f13..f77a412 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -201,7 +201,7 @@ static int psy_register_thermal(struct power_supply *psy)
for (i = 0; i < psy->num_properties; i++) {
if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
- psy, &psy_tzd_ops, 0, 0);
+ psy, &psy_tzd_ops, NULL, 0, 0);
if (IS_ERR(psy->tzd))
return PTR_ERR(psy->tzd);
break;
diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
index 0675a5e..2f115bf 100644
--- a/drivers/staging/omap-thermal/omap-thermal-common.c
+++ b/drivers/staging/omap-thermal/omap-thermal-common.c
@@ -246,7 +246,7 @@ int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
/* Create thermal zone */
data->omap_thermal = thermal_zone_device_register(domain,
OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops,
- 0, FAST_TEMP_MONITORING_RATE, 0, 0);
+ NULL, FAST_TEMP_MONITORING_RATE, 0);
if (IS_ERR_OR_NULL(data->omap_thermal)) {
dev_err(bg_ptr->dev, "thermal zone device is NULL\n");
return PTR_ERR(data->omap_thermal);
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 9bc9692..6b2d8b2 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
writel_relaxed(stdev->flags, stdev->thermal_base);
spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
- stdev, &ops, 0, 0);
+ stdev, &ops, NULL, 0, 0);
if (IS_ERR(spear_thermal)) {
dev_err(&pdev->dev, "thermal zone device is NULL\n");
ret = PTR_ERR(spear_thermal);
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 5e141b5..a642d1c 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1343,6 +1343,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
* @mask: a bit string indicating the writeablility of trip points
* @devdata: private device data
* @ops: standard thermal zone device callbacks
+ * @tzp: thermal zone platform parameters
* @passive_delay: number of milliseconds to wait between polls when
* performing passive cooling
* @polling_delay: number of milliseconds to wait between polls when checking
@@ -1355,6 +1356,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
struct thermal_zone_device *thermal_zone_device_register(const char *type,
int trips, int mask, void *devdata,
const struct thermal_zone_device_ops *ops,
+ const struct thermal_zone_params *tzp,
int passive_delay, int polling_delay)
{
struct thermal_zone_device *tz;
@@ -1388,6 +1390,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
strcpy(tz->type, type);
tz->ops = ops;
+ tz->tzp = tzp;
tz->device.class = &thermal_class;
tz->devdata = devdata;
tz->trips = trips;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 4caa32e..58cb1c0 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -200,7 +200,8 @@ struct thermal_genl_event {
/* Function declarations */
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
- void *, const struct thermal_zone_device_ops *, int, int);
+ void *, const struct thermal_zone_device_ops *,
+ const struct thermal_zone_params *, int, int);
void thermal_zone_device_unregister(struct thermal_zone_device *);
int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 06/15] Thermal: Add thermal governor registration APIs
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (4 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 05/15] Thermal: Pass zone parameters as argument to tzd_register Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-10 8:28 ` Zhang Rui
2012-09-01 11:51 ` [PATCHv3 07/15] Thermal: Add a policy sysfs attribute Durgadoss R
` (8 subsequent siblings)
14 siblings, 1 reply; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch creates a structure to hold platform
thermal governor information, and provides APIs
for individual thermal governors to register/unregister
with the Thermal framework.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 90 +++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 16 ++++++++
2 files changed, 106 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index a642d1c..541da47 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -49,7 +49,86 @@ static DEFINE_MUTEX(thermal_idr_lock);
static LIST_HEAD(thermal_tz_list);
static LIST_HEAD(thermal_cdev_list);
+static LIST_HEAD(thermal_governor_list);
+
static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(thermal_governor_lock);
+
+static struct thermal_governor *__find_governor(const char *name)
+{
+ struct thermal_governor *pos;
+
+ list_for_each_entry(pos, &thermal_governor_list, governor_list)
+ if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
+ return pos;
+
+ return NULL;
+}
+
+int thermal_register_governor(struct thermal_governor *governor)
+{
+ int err;
+ const char *name;
+ struct thermal_zone_device *pos;
+
+ if (!governor)
+ return -EINVAL;
+
+ mutex_lock(&thermal_governor_lock);
+
+ err = -EBUSY;
+ if (__find_governor(governor->name) == NULL) {
+ err = 0;
+ list_add(&governor->governor_list, &thermal_governor_list);
+ }
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (pos->governor)
+ continue;
+ if (pos->tzp)
+ name = pos->tzp->governor_name;
+ else
+ name = DEFAULT_THERMAL_GOVERNOR;
+ if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+ pos->governor = governor;
+ }
+
+ mutex_unlock(&thermal_list_lock);
+ mutex_unlock(&thermal_governor_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(thermal_register_governor);
+
+void thermal_unregister_governor(struct thermal_governor *governor)
+{
+ struct thermal_zone_device *pos;
+
+ if (!governor)
+ return;
+
+ mutex_lock(&thermal_governor_lock);
+
+ if (__find_governor(governor->name) == NULL)
+ goto exit;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!strnicmp(pos->governor->name, governor->name,
+ THERMAL_NAME_LENGTH))
+ pos->governor = NULL;
+ }
+
+ mutex_unlock(&thermal_list_lock);
+ list_del(&governor->governor_list);
+exit:
+ mutex_unlock(&thermal_governor_lock);
+ return;
+}
+EXPORT_SYMBOL_GPL(thermal_unregister_governor);
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
@@ -1439,6 +1518,16 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
if (result)
goto unregister;
+ /* Update 'this' zone's governor information */
+ mutex_lock(&thermal_governor_lock);
+
+ if (tz->tzp)
+ tz->governor = __find_governor(tz->tzp->governor_name);
+ else
+ tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
+
+ mutex_unlock(&thermal_governor_lock);
+
result = thermal_add_hwmon_sysfs(tz);
if (result)
goto unregister;
@@ -1502,6 +1591,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
if (tz->ops->get_mode)
device_remove_file(&tz->device, &dev_attr_mode);
remove_trip_attrs(tz);
+ tz->governor = NULL;
thermal_remove_hwmon_sysfs(tz);
release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 58cb1c0..6182bd5 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -46,6 +46,9 @@
#define THERMAL_GENL_VERSION 0x01
#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group"
+/* Default Thermal Governor: Does Linear Throttling */
+#define DEFAULT_THERMAL_GOVERNOR "step_wise"
+
struct thermal_zone_device;
struct thermal_cooling_device;
@@ -158,6 +161,7 @@ struct thermal_zone_device {
unsigned int forced_passive;
const struct thermal_zone_device_ops *ops;
const struct thermal_zone_params *tzp;
+ struct thermal_governor *governor;
struct list_head thermal_instances;
struct idr idr;
struct mutex lock; /* protect thermal_instances list */
@@ -165,6 +169,14 @@ struct thermal_zone_device {
struct delayed_work poll_queue;
};
+/* Structure that holds thermal governor information */
+struct thermal_governor {
+ char name[THERMAL_NAME_LENGTH];
+ int (*throttle)(struct thermal_zone_device *tz, int trip);
+ struct list_head governor_list;
+ struct module *owner;
+};
+
/* Structure that holds binding parameters for a zone */
struct thermal_bind_params {
struct thermal_cooling_device *cdev;
@@ -189,6 +201,7 @@ struct thermal_bind_params {
/* Structure to define Thermal Zone parameters */
struct thermal_zone_params {
+ char governor_name[THERMAL_NAME_LENGTH];
int num_tbps; /* Number of tbp entries */
struct thermal_bind_params *tbp;
};
@@ -219,6 +232,9 @@ int get_tz_trend(struct thermal_zone_device *, int);
struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
struct thermal_cooling_device *, int);
+int thermal_register_governor(struct thermal_governor *);
+void thermal_unregister_governor(struct thermal_governor *);
+
#ifdef CONFIG_NET
extern int thermal_generate_netlink_event(u32 orig, enum events event);
#else
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 07/15] Thermal: Add a policy sysfs attribute
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (5 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 06/15] Thermal: Add thermal governor registration APIs Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 08/15] Thermal: Update binding logic based on platform data Durgadoss R
` (7 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds a policy sysfs attribute to a thermal zone.
This attribute denotes the throttling governor used for the
zone. This is a RW attribute.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 34 +++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 541da47..72851e6 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -454,10 +454,33 @@ passive_show(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", tz->forced_passive);
}
+static ssize_t
+policy_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ struct thermal_governor *gov = __find_governor(buf);
+
+ if (!gov)
+ return -EINVAL;
+
+ tz->governor = gov;
+ return count;
+}
+
+static ssize_t
+policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%s\n", tz->governor->name);
+}
+
static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(temp, 0444, temp_show, NULL);
static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
@@ -1511,10 +1534,14 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
passive = 1;
}
- if (!passive)
- result = device_create_file(&tz->device,
- &dev_attr_passive);
+ if (!passive) {
+ result = device_create_file(&tz->device, &dev_attr_passive);
+ if (result)
+ goto unregister;
+ }
+ /* Create policy attribute */
+ result = device_create_file(&tz->device, &dev_attr_policy);
if (result)
goto unregister;
@@ -1590,6 +1617,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
device_remove_file(&tz->device, &dev_attr_temp);
if (tz->ops->get_mode)
device_remove_file(&tz->device, &dev_attr_mode);
+ device_remove_file(&tz->device, &dev_attr_policy);
remove_trip_attrs(tz);
tz->governor = NULL;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 08/15] Thermal: Update binding logic based on platform data
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (6 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 07/15] Thermal: Add a policy sysfs attribute Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 09/15] Thermal: Make thermal_cdev_update as a global function Durgadoss R
` (6 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch updates the binding logic in thermal_sys.c
It uses the platform layer data to bind a thermal zone
to a cdev for a particular trip point.
* If we do not have platform data and do not have
.bind defined, do not bind.
* If we do not have platform data but .bind is
defined, then use tz->ops->bind.
* If we have platform data, use it to create binding.
The same logic sequence is followed for unbind also.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 183 +++++++++++++++++++++++++++++++++++------
1 file changed, 157 insertions(+), 26 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 72851e6..b7bf14b 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -201,6 +201,111 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
}
EXPORT_SYMBOL(get_thermal_instance);
+static void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret)
+{
+ dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+ tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev)
+{
+ int i, ret;
+
+ for (i = 0; i < tz->trips; i++) {
+ if (mask & (1 << i)) {
+ ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+ THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+ if (ret)
+ print_bind_err_msg(tz, cdev, ret);
+ }
+ }
+}
+
+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+ int i, ret;
+ const struct thermal_zone_params *tzp;
+ struct thermal_zone_device *pos = NULL;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!pos->tzp && !pos->ops->bind)
+ continue;
+
+ if (!pos->tzp && pos->ops->bind) {
+ ret = pos->ops->bind(pos, cdev);
+ if (ret)
+ print_bind_err_msg(pos, cdev, ret);
+ }
+
+ tzp = pos->tzp;
+ if (!tzp->tbp)
+ return;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(pos, cdev))
+ continue;
+ tzp->tbp[i].cdev = cdev;
+ __bind(pos, tzp->tbp[i].trip_mask, cdev);
+ }
+ }
+
+ mutex_unlock(&thermal_list_lock);
+}
+
+static void bind_tz(struct thermal_zone_device *tz)
+{
+ int i, ret;
+ struct thermal_cooling_device *pos = NULL;
+ const struct thermal_zone_params *tzp = tz->tzp;
+
+ if (!tzp && !tz->ops->bind)
+ return;
+
+ mutex_lock(&thermal_list_lock);
+
+ /* If there is no platform data, try to use ops->bind */
+ if (!tzp && tz->ops->bind) {
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ ret = tz->ops->bind(tz, pos);
+ if (ret)
+ print_bind_err_msg(tz, pos, ret);
+ }
+ goto exit;
+ }
+
+ if (!tzp->tbp)
+ goto exit;
+
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(tz, pos))
+ continue;
+ tzp->tbp[i].cdev = pos;
+ __bind(tz, tzp->tbp[i].trip_mask, pos);
+ }
+ }
+exit:
+ mutex_unlock(&thermal_list_lock);
+}
+
/* sys I/F for thermal zone */
#define to_thermal_zone(_dev) \
@@ -1020,7 +1125,6 @@ thermal_cooling_device_register(char *type, void *devdata,
const struct thermal_cooling_device_ops *ops)
{
struct thermal_cooling_device *cdev;
- struct thermal_zone_device *pos;
int result;
if (strlen(type) >= THERMAL_NAME_LENGTH)
@@ -1070,20 +1174,15 @@ thermal_cooling_device_register(char *type, void *devdata,
if (result)
goto unregister;
+ /* Add 'this' new cdev to the global cdev list */
mutex_lock(&thermal_list_lock);
list_add(&cdev->node, &thermal_cdev_list);
- list_for_each_entry(pos, &thermal_tz_list, node) {
- if (!pos->ops->bind)
- continue;
- result = pos->ops->bind(pos, cdev);
- if (result)
- break;
-
- }
mutex_unlock(&thermal_list_lock);
- if (!result)
- return cdev;
+ /* Update binding information for 'this' new cdev */
+ bind_cdev(cdev);
+
+ return cdev;
unregister:
release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
@@ -1099,10 +1198,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register);
* thermal_cooling_device_unregister() must be called when the device is no
* longer needed.
*/
-void thermal_cooling_device_unregister(struct
- thermal_cooling_device
- *cdev)
+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_cooling_device *pos = NULL;
@@ -1119,12 +1218,28 @@ void thermal_cooling_device_unregister(struct
return;
}
list_del(&cdev->node);
+
+ /* Unbind all thermal zones associated with 'this' cdev */
list_for_each_entry(tz, &thermal_tz_list, node) {
- if (!tz->ops->unbind)
+ if (tz->ops->unbind) {
+ tz->ops->unbind(tz, cdev);
+ continue;
+ }
+
+ if (!tz->tzp || !tz->tzp->tbp)
continue;
- tz->ops->unbind(tz, cdev);
+
+ tzp = tz->tzp;
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev == cdev) {
+ __unbind(tz, tzp->tbp[i].trip_mask, cdev);
+ tzp->tbp[i].cdev = NULL;
+ }
+ }
}
+
mutex_unlock(&thermal_list_lock);
+
if (cdev->type[0])
device_remove_file(&cdev->device, &dev_attr_cdev_type);
device_remove_file(&cdev->device, &dev_attr_max_state);
@@ -1462,7 +1577,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
int passive_delay, int polling_delay)
{
struct thermal_zone_device *tz;
- struct thermal_cooling_device *pos;
enum thermal_trip_type trip_type;
int result;
int count;
@@ -1561,14 +1675,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
mutex_lock(&thermal_list_lock);
list_add_tail(&tz->node, &thermal_tz_list);
- if (ops->bind)
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- result = ops->bind(tz, pos);
- if (result)
- break;
- }
mutex_unlock(&thermal_list_lock);
+ /* Bind cooling devices for this zone */
+ bind_tz(tz);
+
INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
thermal_zone_device_update(tz);
@@ -1589,12 +1700,16 @@ EXPORT_SYMBOL(thermal_zone_device_register);
*/
void thermal_zone_device_unregister(struct thermal_zone_device *tz)
{
+ int i;
+ const struct thermal_zone_params *tzp;
struct thermal_cooling_device *cdev;
struct thermal_zone_device *pos = NULL;
if (!tz)
return;
+ tzp = tz->tzp;
+
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
if (pos == tz)
@@ -1605,9 +1720,25 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
return;
}
list_del(&tz->node);
- if (tz->ops->unbind)
- list_for_each_entry(cdev, &thermal_cdev_list, node)
- tz->ops->unbind(tz, cdev);
+
+ /* Unbind all cdevs associated with 'this' thermal zone */
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ if (tz->ops->unbind) {
+ tz->ops->unbind(tz, cdev);
+ continue;
+ }
+
+ if (!tzp || !tzp->tbp)
+ break;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev == cdev) {
+ __unbind(tz, tzp->tbp[i].trip_mask, cdev);
+ tzp->tbp[i].cdev = NULL;
+ }
+ }
+ }
+
mutex_unlock(&thermal_list_lock);
thermal_zone_device_set_polling(tz, 0);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 09/15] Thermal: Make thermal_cdev_update as a global function
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (7 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 08/15] Thermal: Update binding logic based on platform data Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 10/15] Thermal: Introduce fair_share thermal governor Durgadoss R
` (5 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch makes the thermal_cdev_update function as a
global one, so that other files can use it. This function
serves as a single arbitrator to set the state of a cooling
device.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 5 +++--
include/linux/thermal.h | 1 +
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index b7bf14b..936b025 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1251,7 +1251,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL(thermal_cooling_device_unregister);
-static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
+void thermal_cdev_update(struct thermal_cooling_device *cdev)
{
struct thermal_instance *instance;
unsigned long target = 0;
@@ -1272,13 +1272,14 @@ static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
cdev->ops->set_cur_state(cdev, target);
cdev->updated = true;
}
+EXPORT_SYMBOL(thermal_cdev_update);
static void thermal_zone_do_update(struct thermal_zone_device *tz)
{
struct thermal_instance *instance;
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
- thermal_cdev_do_update(instance->cdev);
+ thermal_cdev_update(instance->cdev);
}
/*
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 6182bd5..2bd9158 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -231,6 +231,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *);
int get_tz_trend(struct thermal_zone_device *, int);
struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
struct thermal_cooling_device *, int);
+void thermal_cdev_update(struct thermal_cooling_device *);
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 10/15] Thermal: Introduce fair_share thermal governor
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (8 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 09/15] Thermal: Make thermal_cdev_update as a global function Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 11/15] Thermal: Introduce a step_wise " Durgadoss R
` (4 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch introduces a simple 'weight' based
governor named fair_share governor. Whenever the
thermal framework gets notified of the trip point
violation, this governor (if configured), throttles
the cooling devices associated with a thermal zone.
This mapping between a thermal zone and a cooling device
and the effectiveness of cooling are provided in the
platform layer.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/Kconfig | 6 ++
drivers/thermal/Makefile | 3 +-
drivers/thermal/fair_share.c | 133 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 drivers/thermal/fair_share.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3ab2bd5..f5110c0 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -27,3 +27,9 @@ config SPEAR_THERMAL
help
Enable this to plug the SPEAr thermal sensor driver into the Linux
thermal framework
+
+config FAIR_SHARE
+ bool "Fair-share thermal governor"
+ depends on THERMAL
+ help
+ Enable this to manage platform thermals using fair-share governor.
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index a9fff0b..4ffe1a8 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,4 +3,5 @@
#
obj-$(CONFIG_THERMAL) += thermal_sys.o
-obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
+obj-$(CONFIG_FAIR_SHARE) += fair_share.o
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
new file mode 100644
index 0000000..5d3a7a3
--- /dev/null
+++ b/drivers/thermal/fair_share.c
@@ -0,0 +1,133 @@
+/*
+ * fair_share.c - A simple weight based Thermal governor
+ *
+ * Copyright (C) 2012 Intel Corp
+ * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * get_trip_level: - obtains the current trip level for a zone
+ * @tz: thermal zone device
+ */
+static int get_trip_level(struct thermal_zone_device *tz)
+{
+ int count = 0;
+ unsigned long trip_temp;
+
+ if (tz->trips == 0 || !tz->ops->get_trip_temp)
+ return 0;
+
+ for (count = 0; count < tz->trips; count++) {
+ tz->ops->get_trip_temp(tz, count, &trip_temp);
+ if (tz->temperature < trip_temp)
+ break;
+ }
+ return count;
+}
+
+static long get_target_state(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int weight, int level)
+{
+ unsigned long max_state;
+
+ cdev->ops->get_max_state(cdev, &max_state);
+
+ return (long)(weight * level * max_state) / (100 * tz->trips);
+}
+
+/**
+ * fair_share_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ *
+ * Throttling Logic: This uses three parameters to calculate the new
+ * throttle state of the cooling devices associated with the given zone.
+ *
+ * Parameters used for Throttling:
+ * P1. max_state: Maximum throttle state exposed by the cooling device.
+ * P2. weight[i]/100:
+ * How 'effective' the 'i'th device is, in cooling the given zone.
+ * P3. cur_trip_level/max_no_of_trips:
+ * This describes the extent to which the devices should be throttled.
+ * We do not want to throttle too much when we trip a lower temperature,
+ * whereas the throttling is at full swing if we trip critical levels.
+ * (Heavily assumes the trip points are in ascending order)
+ * new_state of cooling device = P3 * P2 * P1
+ */
+int fair_share_throttle(struct thermal_zone_device *tz, int trip)
+{
+ const struct thermal_zone_params *tzp;
+ struct thermal_cooling_device *cdev;
+ struct thermal_instance *instance;
+ int i;
+ int cur_trip_level = get_trip_level(tz);
+
+ if (!tz->tzp || !tz->tzp->tbp)
+ return -EINVAL;
+
+ tzp = tz->tzp;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (!tzp->tbp[i].cdev)
+ continue;
+
+ cdev = tzp->tbp[i].cdev;
+ instance = get_thermal_instance(tz, cdev, trip);
+ if (!instance)
+ continue;
+
+ instance->target = get_target_state(tz, cdev,
+ tzp->tbp[i].weight, cur_trip_level);
+
+ instance->cdev->updated = false;
+ thermal_cdev_update(cdev);
+ }
+ return 0;
+}
+
+struct thermal_governor thermal_gov_fair_share = {
+ .name = "fair_share",
+ .throttle = fair_share_throttle,
+ .owner = THIS_MODULE,
+};
+
+static int __init thermal_gov_fair_share_init(void)
+{
+ return thermal_register_governor(&thermal_gov_fair_share);
+}
+
+static void __exit thermal_gov_fair_share_exit(void)
+{
+ thermal_unregister_governor(&thermal_gov_fair_share);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_fair_share_init);
+module_exit(thermal_gov_fair_share_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
+MODULE_LICENSE("GPL");
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 11/15] Thermal: Introduce a step_wise thermal governor
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (9 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 10/15] Thermal: Introduce fair_share thermal governor Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 12/15] Thermal: Register a governor for user space Durgadoss R
` (3 subsequent siblings)
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds a simple step_wise governor to the
generic thermal layer. This algorithm throttles the
cooling devices in a linear fashion. If the 'trend'
is heating, it throttles by one step. And if the
thermal trend is cooling it de-throttles by one step.
This actually moves the throttling logic from thermal_sys.c
and puts inside step_wise.c, without any change.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/Kconfig | 6 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/step_wise.c | 194 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 201 insertions(+)
create mode 100644 drivers/thermal/step_wise.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index f5110c0..0401cdf 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -33,3 +33,9 @@ config FAIR_SHARE
depends on THERMAL
help
Enable this to manage platform thermals using fair-share governor.
+
+config STEP_WISE
+ bool "Step_wise thermal governor"
+ depends on THERMAL
+ help
+ Enable this to manage platform thermals using a simple linear
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 4ffe1a8..c2c0ce0 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_THERMAL) += thermal_sys.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_FAIR_SHARE) += fair_share.o
+obj-$(CONFIG_STEP_WISE) += step_wise.o
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
new file mode 100644
index 0000000..3f9cfcf
--- /dev/null
+++ b/drivers/thermal/step_wise.c
@@ -0,0 +1,194 @@
+/*
+ * step_wise.c - A step-by-step Thermal throttling governor
+ *
+ * Copyright (C) 2012 Intel Corp
+ * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/*
+ * If the temperature is higher than a trip point,
+ * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
+ * state for this trip point
+ * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
+ * state for this trip point
+ */
+static unsigned long get_target_state(struct thermal_instance *instance,
+ enum thermal_trend trend)
+{
+ struct thermal_cooling_device *cdev = instance->cdev;
+ unsigned long cur_state;
+
+ cdev->ops->get_cur_state(cdev, &cur_state);
+
+ if (trend == THERMAL_TREND_RAISING) {
+ cur_state = cur_state < instance->upper ?
+ (cur_state + 1) : instance->upper;
+ } else if (trend == THERMAL_TREND_DROPPING) {
+ cur_state = cur_state > instance->lower ?
+ (cur_state - 1) : instance->lower;
+ }
+
+ return cur_state;
+}
+
+static void update_passive_instance(struct thermal_zone_device *tz,
+ enum thermal_trip_type type, int value)
+{
+ /*
+ * If value is +1, activate a passive instance.
+ * If value is -1, deactivate a passive instance.
+ */
+ if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
+ tz->passive += value;
+}
+
+static void update_instance_for_throttle(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type,
+ enum thermal_trend trend)
+{
+ struct thermal_instance *instance;
+
+ list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+ if (instance->trip != trip)
+ continue;
+
+ instance->target = get_target_state(instance, trend);
+
+ /* Activate a passive thermal instance */
+ if (instance->target == THERMAL_NO_TARGET)
+ update_passive_instance(tz, trip_type, 1);
+
+ instance->cdev->updated = false; /* cdev needs update */
+ }
+}
+
+static void update_instance_for_dethrottle(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+{
+ struct thermal_instance *instance;
+ struct thermal_cooling_device *cdev;
+ unsigned long cur_state;
+
+ list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+ if (instance->trip != trip ||
+ instance->target == THERMAL_NO_TARGET)
+ continue;
+
+ cdev = instance->cdev;
+ cdev->ops->get_cur_state(cdev, &cur_state);
+
+ instance->target = cur_state > instance->lower ?
+ (cur_state - 1) : THERMAL_NO_TARGET;
+
+ /* Deactivate a passive thermal instance */
+ if (instance->target == THERMAL_NO_TARGET)
+ update_passive_instance(tz, trip_type, -1);
+
+ cdev->updated = false; /* cdev needs update */
+ }
+}
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+{
+ long trip_temp;
+ enum thermal_trip_type trip_type;
+ enum thermal_trend trend;
+
+ if (trip == THERMAL_TRIPS_NONE) {
+ trip_temp = tz->forced_passive;
+ trip_type = THERMAL_TRIPS_NONE;
+ } else {
+ tz->ops->get_trip_temp(tz, trip, &trip_temp);
+ tz->ops->get_trip_type(tz, trip, &trip_type);
+ }
+
+ trend = get_tz_trend(tz, trip);
+
+ mutex_lock(&tz->lock);
+
+ if (tz->temperature >= trip_temp)
+ update_instance_for_throttle(tz, trip, trip_type, trend);
+ else
+ update_instance_for_dethrottle(tz, trip, trip_type);
+
+ mutex_unlock(&tz->lock);
+}
+
+/**
+ * step_wise_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ * @trip - the trip point
+ * @trip_type - type of the trip point
+ *
+ * Throttling Logic: This uses the trend of the thermal zone to throttle.
+ * If the thermal zone is 'heating up' this throttles all the cooling
+ * devices associated with the zone and its particular trip point, by one
+ * step. If the zone is 'cooling down' it brings back the performance of
+ * the devices by one step.
+ */
+int step_wise_throttle(struct thermal_zone_device *tz, int trip)
+{
+ struct thermal_instance *instance;
+
+ thermal_zone_trip_update(tz, trip);
+
+ if (tz->forced_passive)
+ thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
+
+ mutex_lock(&tz->lock);
+
+ list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+ thermal_cdev_update(instance->cdev);
+
+ mutex_unlock(&tz->lock);
+
+ return 0;
+}
+
+struct thermal_governor thermal_gov_step_wise = {
+ .name = DEFAULT_THERMAL_GOVERNOR,
+ .throttle = step_wise_throttle,
+ .owner = THIS_MODULE,
+};
+
+static int __init thermal_gov_step_wise_init(void)
+{
+ return thermal_register_governor(&thermal_gov_step_wise);
+}
+
+static void __exit thermal_gov_step_wise_exit(void)
+{
+ thermal_unregister_governor(&thermal_gov_step_wise);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_step_wise_init);
+module_exit(thermal_gov_step_wise_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A step-by-step thermal throttling governor");
+MODULE_LICENSE("GPL");
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 12/15] Thermal: Register a governor for user space
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (10 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 11/15] Thermal: Introduce a step_wise " Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-10 8:37 ` Zhang Rui
2012-09-01 11:51 ` [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c Durgadoss R
` (2 subsequent siblings)
14 siblings, 1 reply; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch registers a governor which will let the
user land manage the platform thermals. Whenever a
trip happens, this governor just notifies the user
space using kobj_uevent().
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 18 ++++++++++++++++++
include/linux/thermal.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 936b025..93672aa 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -130,6 +130,15 @@ exit:
}
EXPORT_SYMBOL_GPL(thermal_unregister_governor);
+static int notify_user_space(struct thermal_zone_device *tz, int trip)
+{
+ mutex_lock(&tz->lock);
+ kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
+ mutex_unlock(&tz->lock);
+
+ return 0;
+}
+
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
int err;
@@ -1860,6 +1869,12 @@ static inline int genetlink_init(void) { return 0; }
static inline void genetlink_exit(void) {}
#endif /* !CONFIG_NET */
+struct thermal_governor thermal_gov_user_space = {
+ .name = USER_SPACE_THERMAL_GOVERNOR,
+ .throttle = notify_user_space,
+ .owner = THIS_MODULE,
+};
+
static int __init thermal_init(void)
{
int result = 0;
@@ -1871,6 +1886,8 @@ static int __init thermal_init(void)
mutex_destroy(&thermal_idr_lock);
mutex_destroy(&thermal_list_lock);
}
+ /* Register a governor to notify user space */
+ thermal_register_governor(&thermal_gov_user_space);
result = genetlink_init();
return result;
}
@@ -1882,6 +1899,7 @@ static void __exit thermal_exit(void)
idr_destroy(&thermal_cdev_idr);
mutex_destroy(&thermal_idr_lock);
mutex_destroy(&thermal_list_lock);
+ thermal_unregister_governor(&thermal_gov_user_space);
genetlink_exit();
}
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 2bd9158..aa903dd 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -48,6 +48,8 @@
/* Default Thermal Governor: Does Linear Throttling */
#define DEFAULT_THERMAL_GOVERNOR "step_wise"
+/* User space Thermal governor */
+#define USER_SPACE_THERMAL_GOVERNOR "user_space"
struct thermal_zone_device;
struct thermal_cooling_device;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (11 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 12/15] Thermal: Register a governor for user space Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-10 8:44 ` Zhang Rui
2012-09-01 11:51 ` [PATCHv3 14/15] Thermal: Add a notification API Durgadoss R
2012-09-01 11:51 ` [PATCHv3 15/15] Thermal: Add documentation for platform layer data Durgadoss R
14 siblings, 1 reply; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch removes the throttling logic out of
thermal_sys.c; also refactors the code into smaller
functions so that are easy to read/maintain.
* Seperates the handling of critical and non-critical trips
* Re-arranges the set_polling and device_check methods, so
that all related functions are arranged in one place.
* Removes the 'do_update' and 'trip_update' method, as part
of moving the throttling logic out of thermal_sys.c
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 313 +++++++++++++++--------------------------
1 file changed, 112 insertions(+), 201 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 93672aa..086c1c9 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -315,6 +315,118 @@ exit:
mutex_unlock(&thermal_list_lock);
}
+static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
+ int delay)
+{
+ cancel_delayed_work(&(tz->poll_queue));
+
+ if (!delay)
+ return;
+
+ if (delay > 1000)
+ queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
+ round_jiffies(msecs_to_jiffies(delay)));
+ else
+ queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
+ msecs_to_jiffies(delay));
+}
+
+static void monitor_thermal_zone(struct thermal_zone_device *tz)
+{
+ mutex_lock(&tz->lock);
+
+ if (tz->passive)
+ thermal_zone_device_set_polling(tz, tz->passive_delay);
+ else if (tz->polling_delay)
+ thermal_zone_device_set_polling(tz, tz->polling_delay);
+ else
+ thermal_zone_device_set_polling(tz, 0);
+
+ mutex_unlock(&tz->lock);
+}
+
+static void handle_non_critical_trips(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+{
+ tz->governor->throttle(tz, trip);
+}
+
+static void handle_critical_trips(struct thermal_zone_device *tz,
+ int trip, enum thermal_trip_type trip_type)
+{
+ long trip_temp;
+
+ tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+ /* If we have not crossed the trip_temp, we do not care. */
+ if (tz->temperature < trip_temp)
+ return;
+
+ if (tz->ops->notify)
+ tz->ops->notify(tz, trip, trip_type);
+
+ if (trip_type == THERMAL_TRIP_CRITICAL) {
+ pr_emerg("Critical temperature reached(%d C),shutting down\n",
+ tz->temperature / 1000);
+ orderly_poweroff(true);
+ }
+}
+
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+{
+ enum thermal_trip_type type;
+
+ tz->ops->get_trip_type(tz, trip, &type);
+
+ if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
+ handle_critical_trips(tz, trip, type);
+ else
+ handle_non_critical_trips(tz, trip, type);
+ /*
+ * Alright, we handled this trip successfully.
+ * So, start monitoring again.
+ */
+ monitor_thermal_zone(tz);
+}
+
+static void update_temperature(struct thermal_zone_device *tz)
+{
+ long temp;
+ int ret;
+
+ mutex_lock(&tz->lock);
+
+ ret = tz->ops->get_temp(tz, &temp);
+ if (ret) {
+ pr_warn("failed to read out thermal zone %d\n", tz->id);
+ return;
+ }
+
+ tz->last_temperature = tz->temperature;
+ tz->temperature = temp;
+
+ mutex_unlock(&tz->lock);
+}
+
+void thermal_zone_device_update(struct thermal_zone_device *tz)
+{
+ int count;
+
+ update_temperature(tz);
+
+ for (count = 0; count < tz->trips; count++)
+ handle_thermal_trip(tz, count);
+}
+EXPORT_SYMBOL(thermal_zone_device_update);
+
+static void thermal_zone_device_check(struct work_struct *work)
+{
+ struct thermal_zone_device *tz = container_of(work, struct
+ thermal_zone_device,
+ poll_queue.work);
+ thermal_zone_device_update(tz);
+}
+
/* sys I/F for thermal zone */
#define to_thermal_zone(_dev) \
@@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
}
#endif
-static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
- int delay)
-{
- cancel_delayed_work(&(tz->poll_queue));
-
- if (!delay)
- return;
-
- if (delay > 1000)
- queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
- round_jiffies(msecs_to_jiffies(delay)));
- else
- queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
- msecs_to_jiffies(delay));
-}
-
-static void thermal_zone_device_check(struct work_struct *work)
-{
- struct thermal_zone_device *tz = container_of(work, struct
- thermal_zone_device,
- poll_queue.work);
- thermal_zone_device_update(tz);
-}
-
/**
* thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
* @tz: thermal zone device
@@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL(thermal_cdev_update);
-static void thermal_zone_do_update(struct thermal_zone_device *tz)
-{
- struct thermal_instance *instance;
-
- list_for_each_entry(instance, &tz->thermal_instances, tz_node)
- thermal_cdev_update(instance->cdev);
-}
-
-/*
- * Cooling algorithm for both active and passive cooling
- *
- * 1. if the temperature is higher than a trip point,
- * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
- * state for this trip point
- * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
- * state for this trip point
- *
- * 2. if the temperature is lower than a trip point, use lower
- * cooling state for this trip point
- *
- * Note that this behaves the same as the previous passive cooling
- * algorithm.
- */
-
-static void thermal_zone_trip_update(struct thermal_zone_device *tz,
- int trip, long temp)
-{
- struct thermal_instance *instance;
- struct thermal_cooling_device *cdev = NULL;
- unsigned long cur_state, max_state;
- long trip_temp;
- enum thermal_trip_type trip_type;
- enum thermal_trend trend;
-
- if (trip == THERMAL_TRIPS_NONE) {
- trip_temp = tz->forced_passive;
- trip_type = THERMAL_TRIPS_NONE;
- } else {
- tz->ops->get_trip_temp(tz, trip, &trip_temp);
- tz->ops->get_trip_type(tz, trip, &trip_type);
- }
-
- if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
- /*
- * compare the current temperature and previous temperature
- * to get the thermal trend, if no special requirement
- */
- if (tz->temperature > tz->last_temperature)
- trend = THERMAL_TREND_RAISING;
- else if (tz->temperature < tz->last_temperature)
- trend = THERMAL_TREND_DROPPING;
- else
- trend = THERMAL_TREND_STABLE;
- }
-
- if (temp >= trip_temp) {
- list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
- if (instance->trip != trip)
- continue;
-
- cdev = instance->cdev;
-
- cdev->ops->get_cur_state(cdev, &cur_state);
- cdev->ops->get_max_state(cdev, &max_state);
-
- if (trend == THERMAL_TREND_RAISING) {
- cur_state = cur_state < instance->upper ?
- (cur_state + 1) : instance->upper;
- } else if (trend == THERMAL_TREND_DROPPING) {
- cur_state = cur_state > instance->lower ?
- (cur_state - 1) : instance->lower;
- }
-
- /* activate a passive thermal instance */
- if ((trip_type == THERMAL_TRIP_PASSIVE ||
- trip_type == THERMAL_TRIPS_NONE) &&
- instance->target == THERMAL_NO_TARGET)
- tz->passive++;
-
- instance->target = cur_state;
- cdev->updated = false; /* cooling device needs update */
- }
- } else { /* below trip */
- list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
- if (instance->trip != trip)
- continue;
-
- /* Do not use the inactive thermal instance */
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- cdev = instance->cdev;
- cdev->ops->get_cur_state(cdev, &cur_state);
-
- cur_state = cur_state > instance->lower ?
- (cur_state - 1) : THERMAL_NO_TARGET;
-
- /* deactivate a passive thermal instance */
- if ((trip_type == THERMAL_TRIP_PASSIVE ||
- trip_type == THERMAL_TRIPS_NONE) &&
- cur_state == THERMAL_NO_TARGET)
- tz->passive--;
- instance->target = cur_state;
- cdev->updated = false; /* cooling device needs update */
- }
- }
-
- return;
-}
-/**
- * thermal_zone_device_update - force an update of a thermal zone's state
- * @ttz: the thermal zone to update
- */
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
-{
- int count, ret = 0;
- long temp, trip_temp;
- enum thermal_trip_type trip_type;
-
- mutex_lock(&tz->lock);
-
- if (tz->ops->get_temp(tz, &temp)) {
- /* get_temp failed - retry it later */
- pr_warn("failed to read out thermal zone %d\n", tz->id);
- goto leave;
- }
-
- tz->last_temperature = tz->temperature;
- tz->temperature = temp;
-
- for (count = 0; count < tz->trips; count++) {
- tz->ops->get_trip_type(tz, count, &trip_type);
- tz->ops->get_trip_temp(tz, count, &trip_temp);
-
- switch (trip_type) {
- case THERMAL_TRIP_CRITICAL:
- if (temp >= trip_temp) {
- if (tz->ops->notify)
- ret = tz->ops->notify(tz, count,
- trip_type);
- if (!ret) {
- pr_emerg("Critical temperature reached (%ld C), shutting down\n",
- temp/1000);
- orderly_poweroff(true);
- }
- }
- break;
- case THERMAL_TRIP_HOT:
- if (temp >= trip_temp)
- if (tz->ops->notify)
- tz->ops->notify(tz, count, trip_type);
- break;
- case THERMAL_TRIP_ACTIVE:
- thermal_zone_trip_update(tz, count, temp);
- break;
- case THERMAL_TRIP_PASSIVE:
- if (temp >= trip_temp || tz->passive)
- thermal_zone_trip_update(tz, count, temp);
- break;
- }
- }
-
- if (tz->forced_passive)
- thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
- thermal_zone_do_update(tz);
-
-leave:
- if (tz->passive)
- thermal_zone_device_set_polling(tz, tz->passive_delay);
- else if (tz->polling_delay)
- thermal_zone_device_set_polling(tz, tz->polling_delay);
- else
- thermal_zone_device_set_polling(tz, 0);
- mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL(thermal_zone_device_update);
-
/**
* create_trip_attrs - create attributes for trip points
* @tz: the thermal zone device
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 14/15] Thermal: Add a notification API
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (12 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
2012-09-01 11:51 ` [PATCHv3 15/15] Thermal: Add documentation for platform layer data Durgadoss R
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds a notification API which the sensor drivers'
can use to notify the framework. The framework then takes
care of the throttling according to the configured policy.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
drivers/thermal/thermal_sys.c | 18 ++++++++++++++++++
include/linux/thermal.h | 1 +
2 files changed, 19 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 086c1c9..e006d03 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1372,6 +1372,24 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
EXPORT_SYMBOL(thermal_cdev_update);
/**
+ * notify_thermal_framework - Sensor drivers use this API to notify framework
+ * @tz: thermal zone device
+ * @trip: indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
+ */
+void notify_thermal_framework(struct thermal_zone_device *tz, int trip)
+{
+ handle_thermal_trip(tz, trip);
+}
+EXPORT_SYMBOL(notify_thermal_framework);
+
+/**
* create_trip_attrs - create attributes for trip points
* @tz: the thermal zone device
* @mask: Writeable trip point bitmap.
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index aa903dd..c5deba0 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -234,6 +234,7 @@ int get_tz_trend(struct thermal_zone_device *, int);
struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
struct thermal_cooling_device *, int);
void thermal_cdev_update(struct thermal_cooling_device *);
+void notify_thermal_framework(struct thermal_zone_device *, int);
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCHv3 15/15] Thermal: Add documentation for platform layer data
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
` (13 preceding siblings ...)
2012-09-01 11:51 ` [PATCHv3 14/15] Thermal: Add a notification API Durgadoss R
@ 2012-09-01 11:51 ` Durgadoss R
14 siblings, 0 replies; 24+ messages in thread
From: Durgadoss R @ 2012-09-01 11:51 UTC (permalink / raw)
To: lenb, rui.zhang; +Cc: linux-acpi, eduardo.valentin, Durgadoss R
This patch adds documentation for thermal_bind_params
and thermal_zone_params structures. Also, adds details
on EXPORT_SYMBOL APIs.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
Documentation/thermal/sysfs-api.txt | 64 +++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index ca1a1a3..88c0233 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -112,6 +112,29 @@ temperature) and throttle appropriate devices.
trip: indicates which trip point the cooling devices is associated with
in this thermal zone.
+1.4 Thermal Zone Parameters
+1.4.1 struct thermal_bind_params
+ This structure defines the following parameters that are used to bind
+ a zone with a cooling device for a particular trip point.
+ .cdev: The cooling device pointer
+ .weight: The 'influence' of a particular cooling device on this zone.
+ This is on a percentage scale. The sum of all these weights
+ (for a particular zone) cannot exceed 100.
+ .trip_mask:This is a bit mask that gives the binding relation between
+ this thermal zone and cdev, for a particular trip point.
+ If nth bit is set, then the cdev and thermal zone are bound
+ for trip point n.
+ .match: This call back returns success(0) if the 'tz and cdev' need to
+ be bound, as per platform data.
+1.4.2 struct thermal_zone_params
+ This structure defines the platform level parameters for a thermal zone.
+ This data, for each thermal zone should come from the platform layer.
+ This is an optional feature where some platforms can choose not to
+ provide this data.
+ .governor_name: Name of the thermal governor used for this zone
+ .num_tbps: Number of thermal_bind_params entries for this zone
+ .tbp: thermal_bind_params entries
+
2. sysfs attributes structure
RO read only value
@@ -126,6 +149,7 @@ Thermal zone device sys I/F, created once it's registered:
|---type: Type of the thermal zone
|---temp: Current temperature
|---mode: Working mode of the thermal zone
+ |---policy: Thermal governor used for this zone
|---trip_point_[0-*]_temp: Trip point temperature
|---trip_point_[0-*]_type: Trip point type
|---trip_point_[0-*]_hyst: Hysteresis value for this trip point
@@ -187,6 +211,10 @@ mode
charge of the thermal management.
RW, Optional
+policy
+ One of the various thermal governors used for a particular zone.
+ RW, Required
+
trip_point_[0-*]_temp
The temperature above which trip point will be fired.
Unit: millidegree Celsius
@@ -264,6 +292,7 @@ method, the sys I/F structure will be built like this:
|---type: acpitz
|---temp: 37000
|---mode: enabled
+ |---policy: step_wise
|---trip_point_0_temp: 100000
|---trip_point_0_type: critical
|---trip_point_1_temp: 80000
@@ -305,3 +334,38 @@ to a thermal_zone_device when it registers itself with the framework. The
event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
THERMAL_DEV_FAULT}. Notification can be sent when the current temperature
crosses any of the configured thresholds.
+
+5. Export Symbol APIs:
+
+5.1: get_tz_trend:
+This function returns the trend of a thermal zone, i.e the rate of change
+of temperature of the thermal zone. Ideally, the thermal sensor drivers
+are supposed to implement the callback. If they don't, the thermal
+framework calculated the trend by comparing the previous and the current
+temperature values.
+
+5.2:get_thermal_instance:
+This function returns the thermal_instance corresponding to a given
+{thermal_zone, cooling_device, trip_point} combination. Returns NULL
+if such an instance does not exist.
+
+5.3:notify_thermal_framework:
+This function handles the trip events from sensor drivers. It starts
+throttling the cooling devices according to the policy configured.
+For CRITICAL and HOT trip points, this notifies the respective drivers,
+and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+The throttling policy is based on the configured platform data; if no
+platform data is provided, this uses the step_wise throttling policy.
+
+5.4:thermal_cdev_update:
+This function serves as an arbitrator to set the state of a cooling
+device. It sets the cooling device to the deepest cooling state if
+possible.
+
+5.5:thermal_register_governor:
+This function lets the various thermal governors to register themselves
+with the Thermal framework. At run time, depending on a zone's platform
+data, a particular governor is used for throttling.
+
+5.6:thermal_unregister_governor:
+This function unregisters a governor from the thermal framework.
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCHv3 06/15] Thermal: Add thermal governor registration APIs
2012-09-01 11:51 ` [PATCHv3 06/15] Thermal: Add thermal governor registration APIs Durgadoss R
@ 2012-09-10 8:28 ` Zhang Rui
0 siblings, 0 replies; 24+ messages in thread
From: Zhang Rui @ 2012-09-10 8:28 UTC (permalink / raw)
To: Durgadoss R; +Cc: lenb, linux-acpi, eduardo.valentin
On 六, 2012-09-01 at 17:21 +0530, Durgadoss R wrote:
> This patch creates a structure to hold platform
> thermal governor information, and provides APIs
> for individual thermal governors to register/unregister
> with the Thermal framework.
>
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> ---
> drivers/thermal/thermal_sys.c | 90 +++++++++++++++++++++++++++++++++++++++++
> include/linux/thermal.h | 16 ++++++++
> 2 files changed, 106 insertions(+)
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index a642d1c..541da47 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -49,7 +49,86 @@ static DEFINE_MUTEX(thermal_idr_lock);
>
> static LIST_HEAD(thermal_tz_list);
> static LIST_HEAD(thermal_cdev_list);
> +static LIST_HEAD(thermal_governor_list);
> +
> static DEFINE_MUTEX(thermal_list_lock);
> +static DEFINE_MUTEX(thermal_governor_lock);
> +
> +static struct thermal_governor *__find_governor(const char *name)
> +{
> + struct thermal_governor *pos;
> +
> + list_for_each_entry(pos, &thermal_governor_list, governor_list)
> + if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
> + return pos;
> +
I'm wondering if we should return NULL here or not.
because you are invoking tz->governor->throttle() without any checking.
if there is no matched governor, fall back to the default one instead.
> + return NULL;
> +}
> +
> +int thermal_register_governor(struct thermal_governor *governor)
> +{
> + int err;
> + const char *name;
> + struct thermal_zone_device *pos;
> +
> + if (!governor)
> + return -EINVAL;
> +
> + mutex_lock(&thermal_governor_lock);
> +
> + err = -EBUSY;
> + if (__find_governor(governor->name) == NULL) {
> + err = 0;
> + list_add(&governor->governor_list, &thermal_governor_list);
> + }
> +
> + mutex_lock(&thermal_list_lock);
> +
> + list_for_each_entry(pos, &thermal_tz_list, node) {
> + if (pos->governor)
> + continue;
> + if (pos->tzp)
> + name = pos->tzp->governor_name;
> + else
> + name = DEFAULT_THERMAL_GOVERNOR;
> + if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
> + pos->governor = governor;
> + }
> +
> + mutex_unlock(&thermal_list_lock);
> + mutex_unlock(&thermal_governor_lock);
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(thermal_register_governor);
> +
> +void thermal_unregister_governor(struct thermal_governor *governor)
> +{
> + struct thermal_zone_device *pos;
> +
> + if (!governor)
> + return;
> +
> + mutex_lock(&thermal_governor_lock);
> +
> + if (__find_governor(governor->name) == NULL)
> + goto exit;
> +
> + mutex_lock(&thermal_list_lock);
> +
> + list_for_each_entry(pos, &thermal_tz_list, node) {
> + if (!strnicmp(pos->governor->name, governor->name,
> + THERMAL_NAME_LENGTH))
> + pos->governor = NULL;
> + }
> +
> + mutex_unlock(&thermal_list_lock);
> + list_del(&governor->governor_list);
> +exit:
> + mutex_unlock(&thermal_governor_lock);
> + return;
> +}
> +EXPORT_SYMBOL_GPL(thermal_unregister_governor);
>
> static int get_idr(struct idr *idr, struct mutex *lock, int *id)
> {
> @@ -1439,6 +1518,16 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
> if (result)
> goto unregister;
>
> + /* Update 'this' zone's governor information */
> + mutex_lock(&thermal_governor_lock);
> +
> + if (tz->tzp)
what if tzp->governor_name is not set, usually this mean the platform
driver wants to use the default governor.
so the code should be
if (tz->tzp && tz->tzp->governor_name[0])
thanks,
rui
> + tz->governor = __find_governor(tz->tzp->governor_name);
> + else
> + tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
> +
> + mutex_unlock(&thermal_governor_lock);
> +
> result = thermal_add_hwmon_sysfs(tz);
> if (result)
> goto unregister;
> @@ -1502,6 +1591,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
> if (tz->ops->get_mode)
> device_remove_file(&tz->device, &dev_attr_mode);
> remove_trip_attrs(tz);
> + tz->governor = NULL;
>
> thermal_remove_hwmon_sysfs(tz);
> release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 58cb1c0..6182bd5 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -46,6 +46,9 @@
> #define THERMAL_GENL_VERSION 0x01
> #define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group"
>
> +/* Default Thermal Governor: Does Linear Throttling */
> +#define DEFAULT_THERMAL_GOVERNOR "step_wise"
> +
> struct thermal_zone_device;
> struct thermal_cooling_device;
>
> @@ -158,6 +161,7 @@ struct thermal_zone_device {
> unsigned int forced_passive;
> const struct thermal_zone_device_ops *ops;
> const struct thermal_zone_params *tzp;
> + struct thermal_governor *governor;
> struct list_head thermal_instances;
> struct idr idr;
> struct mutex lock; /* protect thermal_instances list */
> @@ -165,6 +169,14 @@ struct thermal_zone_device {
> struct delayed_work poll_queue;
> };
>
> +/* Structure that holds thermal governor information */
> +struct thermal_governor {
> + char name[THERMAL_NAME_LENGTH];
> + int (*throttle)(struct thermal_zone_device *tz, int trip);
> + struct list_head governor_list;
> + struct module *owner;
> +};
> +
> /* Structure that holds binding parameters for a zone */
> struct thermal_bind_params {
> struct thermal_cooling_device *cdev;
> @@ -189,6 +201,7 @@ struct thermal_bind_params {
>
> /* Structure to define Thermal Zone parameters */
> struct thermal_zone_params {
> + char governor_name[THERMAL_NAME_LENGTH];
> int num_tbps; /* Number of tbp entries */
> struct thermal_bind_params *tbp;
> };
> @@ -219,6 +232,9 @@ int get_tz_trend(struct thermal_zone_device *, int);
> struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
> struct thermal_cooling_device *, int);
>
> +int thermal_register_governor(struct thermal_governor *);
> +void thermal_unregister_governor(struct thermal_governor *);
> +
> #ifdef CONFIG_NET
> extern int thermal_generate_netlink_event(u32 orig, enum events event);
> #else
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCHv3 12/15] Thermal: Register a governor for user space
2012-09-01 11:51 ` [PATCHv3 12/15] Thermal: Register a governor for user space Durgadoss R
@ 2012-09-10 8:37 ` Zhang Rui
0 siblings, 0 replies; 24+ messages in thread
From: Zhang Rui @ 2012-09-10 8:37 UTC (permalink / raw)
To: Durgadoss R; +Cc: lenb, linux-acpi, eduardo.valentin
On 六, 2012-09-01 at 17:21 +0530, Durgadoss R wrote:
> This patch registers a governor which will let the
> user land manage the platform thermals. Whenever a
> trip happens, this governor just notifies the user
> space using kobj_uevent().
>
Hmm, we can make this governor configurable, not the step_wise (which is
used as the default governor), right?
thanks,
rui
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> ---
> drivers/thermal/thermal_sys.c | 18 ++++++++++++++++++
> include/linux/thermal.h | 2 ++
> 2 files changed, 20 insertions(+)
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 936b025..93672aa 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -130,6 +130,15 @@ exit:
> }
> EXPORT_SYMBOL_GPL(thermal_unregister_governor);
>
> +static int notify_user_space(struct thermal_zone_device *tz, int trip)
> +{
> + mutex_lock(&tz->lock);
> + kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
> + mutex_unlock(&tz->lock);
> +
> + return 0;
> +}
> +
> static int get_idr(struct idr *idr, struct mutex *lock, int *id)
> {
> int err;
> @@ -1860,6 +1869,12 @@ static inline int genetlink_init(void) { return 0; }
> static inline void genetlink_exit(void) {}
> #endif /* !CONFIG_NET */
>
> +struct thermal_governor thermal_gov_user_space = {
> + .name = USER_SPACE_THERMAL_GOVERNOR,
> + .throttle = notify_user_space,
> + .owner = THIS_MODULE,
> +};
> +
> static int __init thermal_init(void)
> {
> int result = 0;
> @@ -1871,6 +1886,8 @@ static int __init thermal_init(void)
> mutex_destroy(&thermal_idr_lock);
> mutex_destroy(&thermal_list_lock);
> }
> + /* Register a governor to notify user space */
> + thermal_register_governor(&thermal_gov_user_space);
> result = genetlink_init();
> return result;
> }
> @@ -1882,6 +1899,7 @@ static void __exit thermal_exit(void)
> idr_destroy(&thermal_cdev_idr);
> mutex_destroy(&thermal_idr_lock);
> mutex_destroy(&thermal_list_lock);
> + thermal_unregister_governor(&thermal_gov_user_space);
> genetlink_exit();
> }
>
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 2bd9158..aa903dd 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -48,6 +48,8 @@
>
> /* Default Thermal Governor: Does Linear Throttling */
> #define DEFAULT_THERMAL_GOVERNOR "step_wise"
> +/* User space Thermal governor */
> +#define USER_SPACE_THERMAL_GOVERNOR "user_space"
>
> struct thermal_zone_device;
> struct thermal_cooling_device;
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-01 11:51 ` [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c Durgadoss R
@ 2012-09-10 8:44 ` Zhang Rui
2012-09-10 8:56 ` R, Durgadoss
0 siblings, 1 reply; 24+ messages in thread
From: Zhang Rui @ 2012-09-10 8:44 UTC (permalink / raw)
To: Durgadoss R; +Cc: lenb, linux-acpi, eduardo.valentin
On 六, 2012-09-01 at 17:21 +0530, Durgadoss R wrote:
> This patch removes the throttling logic out of
> thermal_sys.c; also refactors the code into smaller
> functions so that are easy to read/maintain.
> * Seperates the handling of critical and non-critical trips
> * Re-arranges the set_polling and device_check methods, so
> that all related functions are arranged in one place.
> * Removes the 'do_update' and 'trip_update' method, as part
> of moving the throttling logic out of thermal_sys.c
>
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> ---
> drivers/thermal/thermal_sys.c | 313 +++++++++++++++--------------------------
> 1 file changed, 112 insertions(+), 201 deletions(-)
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 93672aa..086c1c9 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -315,6 +315,118 @@ exit:
> mutex_unlock(&thermal_list_lock);
> }
>
> +static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
> + int delay)
> +{
> + cancel_delayed_work(&(tz->poll_queue));
> +
> + if (!delay)
> + return;
> +
> + if (delay > 1000)
> + queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
> + round_jiffies(msecs_to_jiffies(delay)));
> + else
> + queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
> + msecs_to_jiffies(delay));
> +}
> +
> +static void monitor_thermal_zone(struct thermal_zone_device *tz)
> +{
> + mutex_lock(&tz->lock);
> +
> + if (tz->passive)
> + thermal_zone_device_set_polling(tz, tz->passive_delay);
> + else if (tz->polling_delay)
> + thermal_zone_device_set_polling(tz, tz->polling_delay);
> + else
> + thermal_zone_device_set_polling(tz, 0);
> +
> + mutex_unlock(&tz->lock);
> +}
> +
> +static void handle_non_critical_trips(struct thermal_zone_device *tz,
> + int trip, enum thermal_trip_type trip_type)
> +{
> + tz->governor->throttle(tz, trip);
> +}
here is the problem, we must make sure every registered thermal zone
have a governor when it is running, right?
then the default governor must always be built in.
We can have a Kconfig option for step_wise, but we should not make it
configurable by users.
or we can use prompt to get the default governor at build time. say
choice
prompt "Default thermal governor"
default THERMAL_DEFAULT_GOV_STEP_WISE
help
This option sets which thermal governor shall be loaded at
startup.
config THERMAL_DEFAULT_GOV_STEP_WISE
bool "step-wise"
select THERMAL_GOV_STEP_WISE
help
Use the thermal governor 'step-wise' as default.blabla
thanks,
rui
> +
> +static void handle_critical_trips(struct thermal_zone_device *tz,
> + int trip, enum thermal_trip_type trip_type)
> +{
> + long trip_temp;
> +
> + tz->ops->get_trip_temp(tz, trip, &trip_temp);
> +
> + /* If we have not crossed the trip_temp, we do not care. */
> + if (tz->temperature < trip_temp)
> + return;
> +
> + if (tz->ops->notify)
> + tz->ops->notify(tz, trip, trip_type);
> +
> + if (trip_type == THERMAL_TRIP_CRITICAL) {
> + pr_emerg("Critical temperature reached(%d C),shutting down\n",
> + tz->temperature / 1000);
> + orderly_poweroff(true);
> + }
> +}
> +
> +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
> +{
> + enum thermal_trip_type type;
> +
> + tz->ops->get_trip_type(tz, trip, &type);
> +
> + if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
> + handle_critical_trips(tz, trip, type);
> + else
> + handle_non_critical_trips(tz, trip, type);
> + /*
> + * Alright, we handled this trip successfully.
> + * So, start monitoring again.
> + */
> + monitor_thermal_zone(tz);
> +}
> +
> +static void update_temperature(struct thermal_zone_device *tz)
> +{
> + long temp;
> + int ret;
> +
> + mutex_lock(&tz->lock);
> +
> + ret = tz->ops->get_temp(tz, &temp);
> + if (ret) {
> + pr_warn("failed to read out thermal zone %d\n", tz->id);
> + return;
> + }
> +
> + tz->last_temperature = tz->temperature;
> + tz->temperature = temp;
> +
> + mutex_unlock(&tz->lock);
> +}
> +
> +void thermal_zone_device_update(struct thermal_zone_device *tz)
> +{
> + int count;
> +
> + update_temperature(tz);
> +
> + for (count = 0; count < tz->trips; count++)
> + handle_thermal_trip(tz, count);
> +}
> +EXPORT_SYMBOL(thermal_zone_device_update);
> +
> +static void thermal_zone_device_check(struct work_struct *work)
> +{
> + struct thermal_zone_device *tz = container_of(work, struct
> + thermal_zone_device,
> + poll_queue.work);
> + thermal_zone_device_update(tz);
> +}
> +
> /* sys I/F for thermal zone */
>
> #define to_thermal_zone(_dev) \
> @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
> }
> #endif
>
> -static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
> - int delay)
> -{
> - cancel_delayed_work(&(tz->poll_queue));
> -
> - if (!delay)
> - return;
> -
> - if (delay > 1000)
> - queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
> - round_jiffies(msecs_to_jiffies(delay)));
> - else
> - queue_delayed_work(system_freezable_wq, &(tz->poll_queue),
> - msecs_to_jiffies(delay));
> -}
> -
> -static void thermal_zone_device_check(struct work_struct *work)
> -{
> - struct thermal_zone_device *tz = container_of(work, struct
> - thermal_zone_device,
> - poll_queue.work);
> - thermal_zone_device_update(tz);
> -}
> -
> /**
> * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
> * @tz: thermal zone device
> @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
> }
> EXPORT_SYMBOL(thermal_cdev_update);
>
> -static void thermal_zone_do_update(struct thermal_zone_device *tz)
> -{
> - struct thermal_instance *instance;
> -
> - list_for_each_entry(instance, &tz->thermal_instances, tz_node)
> - thermal_cdev_update(instance->cdev);
> -}
> -
> -/*
> - * Cooling algorithm for both active and passive cooling
> - *
> - * 1. if the temperature is higher than a trip point,
> - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> - * state for this trip point
> - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> - * state for this trip point
> - *
> - * 2. if the temperature is lower than a trip point, use lower
> - * cooling state for this trip point
> - *
> - * Note that this behaves the same as the previous passive cooling
> - * algorithm.
> - */
> -
> -static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> - int trip, long temp)
> -{
> - struct thermal_instance *instance;
> - struct thermal_cooling_device *cdev = NULL;
> - unsigned long cur_state, max_state;
> - long trip_temp;
> - enum thermal_trip_type trip_type;
> - enum thermal_trend trend;
> -
> - if (trip == THERMAL_TRIPS_NONE) {
> - trip_temp = tz->forced_passive;
> - trip_type = THERMAL_TRIPS_NONE;
> - } else {
> - tz->ops->get_trip_temp(tz, trip, &trip_temp);
> - tz->ops->get_trip_type(tz, trip, &trip_type);
> - }
> -
> - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
> - /*
> - * compare the current temperature and previous temperature
> - * to get the thermal trend, if no special requirement
> - */
> - if (tz->temperature > tz->last_temperature)
> - trend = THERMAL_TREND_RAISING;
> - else if (tz->temperature < tz->last_temperature)
> - trend = THERMAL_TREND_DROPPING;
> - else
> - trend = THERMAL_TREND_STABLE;
> - }
> -
> - if (temp >= trip_temp) {
> - list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
> - if (instance->trip != trip)
> - continue;
> -
> - cdev = instance->cdev;
> -
> - cdev->ops->get_cur_state(cdev, &cur_state);
> - cdev->ops->get_max_state(cdev, &max_state);
> -
> - if (trend == THERMAL_TREND_RAISING) {
> - cur_state = cur_state < instance->upper ?
> - (cur_state + 1) : instance->upper;
> - } else if (trend == THERMAL_TREND_DROPPING) {
> - cur_state = cur_state > instance->lower ?
> - (cur_state - 1) : instance->lower;
> - }
> -
> - /* activate a passive thermal instance */
> - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> - trip_type == THERMAL_TRIPS_NONE) &&
> - instance->target == THERMAL_NO_TARGET)
> - tz->passive++;
> -
> - instance->target = cur_state;
> - cdev->updated = false; /* cooling device needs update */
> - }
> - } else { /* below trip */
> - list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
> - if (instance->trip != trip)
> - continue;
> -
> - /* Do not use the inactive thermal instance */
> - if (instance->target == THERMAL_NO_TARGET)
> - continue;
> - cdev = instance->cdev;
> - cdev->ops->get_cur_state(cdev, &cur_state);
> -
> - cur_state = cur_state > instance->lower ?
> - (cur_state - 1) : THERMAL_NO_TARGET;
> -
> - /* deactivate a passive thermal instance */
> - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> - trip_type == THERMAL_TRIPS_NONE) &&
> - cur_state == THERMAL_NO_TARGET)
> - tz->passive--;
> - instance->target = cur_state;
> - cdev->updated = false; /* cooling device needs update */
> - }
> - }
> -
> - return;
> -}
> -/**
> - * thermal_zone_device_update - force an update of a thermal zone's state
> - * @ttz: the thermal zone to update
> - */
> -
> -void thermal_zone_device_update(struct thermal_zone_device *tz)
> -{
> - int count, ret = 0;
> - long temp, trip_temp;
> - enum thermal_trip_type trip_type;
> -
> - mutex_lock(&tz->lock);
> -
> - if (tz->ops->get_temp(tz, &temp)) {
> - /* get_temp failed - retry it later */
> - pr_warn("failed to read out thermal zone %d\n", tz->id);
> - goto leave;
> - }
> -
> - tz->last_temperature = tz->temperature;
> - tz->temperature = temp;
> -
> - for (count = 0; count < tz->trips; count++) {
> - tz->ops->get_trip_type(tz, count, &trip_type);
> - tz->ops->get_trip_temp(tz, count, &trip_temp);
> -
> - switch (trip_type) {
> - case THERMAL_TRIP_CRITICAL:
> - if (temp >= trip_temp) {
> - if (tz->ops->notify)
> - ret = tz->ops->notify(tz, count,
> - trip_type);
> - if (!ret) {
> - pr_emerg("Critical temperature reached (%ld C), shutting down\n",
> - temp/1000);
> - orderly_poweroff(true);
> - }
> - }
> - break;
> - case THERMAL_TRIP_HOT:
> - if (temp >= trip_temp)
> - if (tz->ops->notify)
> - tz->ops->notify(tz, count, trip_type);
> - break;
> - case THERMAL_TRIP_ACTIVE:
> - thermal_zone_trip_update(tz, count, temp);
> - break;
> - case THERMAL_TRIP_PASSIVE:
> - if (temp >= trip_temp || tz->passive)
> - thermal_zone_trip_update(tz, count, temp);
> - break;
> - }
> - }
> -
> - if (tz->forced_passive)
> - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
> - thermal_zone_do_update(tz);
> -
> -leave:
> - if (tz->passive)
> - thermal_zone_device_set_polling(tz, tz->passive_delay);
> - else if (tz->polling_delay)
> - thermal_zone_device_set_polling(tz, tz->polling_delay);
> - else
> - thermal_zone_device_set_polling(tz, 0);
> - mutex_unlock(&tz->lock);
> -}
> -EXPORT_SYMBOL(thermal_zone_device_update);
> -
> /**
> * create_trip_attrs - create attributes for trip points
> * @tz: the thermal zone device
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-10 8:44 ` Zhang Rui
@ 2012-09-10 8:56 ` R, Durgadoss
2012-09-11 0:24 ` Zhang Rui
0 siblings, 1 reply; 24+ messages in thread
From: R, Durgadoss @ 2012-09-10 8:56 UTC (permalink / raw)
To: Zhang, Rui
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
eduardo.valentin@ti.com
Hi Rui,
> -----Original Message-----
> From: Zhang, Rui
> Sent: Monday, September 10, 2012 2:14 PM
> To: R, Durgadoss
> Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
> Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> thermal_sys.c
[cut.]
> > +
> > +static void handle_non_critical_trips(struct thermal_zone_device *tz,
> > + int trip, enum thermal_trip_type trip_type)
> > +{
> > + tz->governor->throttle(tz, trip);
> > +}
> here is the problem, we must make sure every registered thermal zone
> have a governor when it is running, right?
Yes, agree with you. Had some thoughts here, but wanted to get your opinion
before I implemented them.
1. We can make the default governor as 'user space', and make it load inside
thermal_sys.c (so that every zone will always have a default governor)
2. All other governors, that are implemented in a separate .c file can be
optional i.e. left to the user to select/deselect.
IMO, this will make our implementation easier and cleaner.
What do you think ?
Thanks,
Durga
>
> then the default governor must always be built in.
> We can have a Kconfig option for step_wise, but we should not make it
> configurable by users.
> or we can use prompt to get the default governor at build time. say
>
> choice
> prompt "Default thermal governor"
> default THERMAL_DEFAULT_GOV_STEP_WISE
> help
> This option sets which thermal governor shall be loaded at
> startup.
>
> config THERMAL_DEFAULT_GOV_STEP_WISE
> bool "step-wise"
> select THERMAL_GOV_STEP_WISE
> help
> Use the thermal governor 'step-wise' as default.blabla
>
>
> thanks,
> rui
>
> > +
> > +static void handle_critical_trips(struct thermal_zone_device *tz,
> > + int trip, enum thermal_trip_type trip_type)
> > +{
> > + long trip_temp;
> > +
> > + tz->ops->get_trip_temp(tz, trip, &trip_temp);
> > +
> > + /* If we have not crossed the trip_temp, we do not care. */
> > + if (tz->temperature < trip_temp)
> > + return;
> > +
> > + if (tz->ops->notify)
> > + tz->ops->notify(tz, trip, trip_type);
> > +
> > + if (trip_type == THERMAL_TRIP_CRITICAL) {
> > + pr_emerg("Critical temperature reached(%d C),shutting
> down\n",
> > + tz->temperature / 1000);
> > + orderly_poweroff(true);
> > + }
> > +}
> > +
> > +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
> > +{
> > + enum thermal_trip_type type;
> > +
> > + tz->ops->get_trip_type(tz, trip, &type);
> > +
> > + if (type == THERMAL_TRIP_CRITICAL || type ==
> THERMAL_TRIP_HOT)
> > + handle_critical_trips(tz, trip, type);
> > + else
> > + handle_non_critical_trips(tz, trip, type);
> > + /*
> > + * Alright, we handled this trip successfully.
> > + * So, start monitoring again.
> > + */
> > + monitor_thermal_zone(tz);
> > +}
> > +
> > +static void update_temperature(struct thermal_zone_device *tz)
> > +{
> > + long temp;
> > + int ret;
> > +
> > + mutex_lock(&tz->lock);
> > +
> > + ret = tz->ops->get_temp(tz, &temp);
> > + if (ret) {
> > + pr_warn("failed to read out thermal zone %d\n", tz->id);
> > + return;
> > + }
> > +
> > + tz->last_temperature = tz->temperature;
> > + tz->temperature = temp;
> > +
> > + mutex_unlock(&tz->lock);
> > +}
> > +
> > +void thermal_zone_device_update(struct thermal_zone_device *tz)
> > +{
> > + int count;
> > +
> > + update_temperature(tz);
> > +
> > + for (count = 0; count < tz->trips; count++)
> > + handle_thermal_trip(tz, count);
> > +}
> > +EXPORT_SYMBOL(thermal_zone_device_update);
> > +
> > +static void thermal_zone_device_check(struct work_struct *work)
> > +{
> > + struct thermal_zone_device *tz = container_of(work, struct
> > + thermal_zone_device,
> > + poll_queue.work);
> > + thermal_zone_device_update(tz);
> > +}
> > +
> > /* sys I/F for thermal zone */
> >
> > #define to_thermal_zone(_dev) \
> > @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct
> thermal_zone_device *tz)
> > }
> > #endif
> >
> > -static void thermal_zone_device_set_polling(struct thermal_zone_device
> *tz,
> > - int delay)
> > -{
> > - cancel_delayed_work(&(tz->poll_queue));
> > -
> > - if (!delay)
> > - return;
> > -
> > - if (delay > 1000)
> > - queue_delayed_work(system_freezable_wq, &(tz-
> >poll_queue),
> > - round_jiffies(msecs_to_jiffies(delay)));
> > - else
> > - queue_delayed_work(system_freezable_wq, &(tz-
> >poll_queue),
> > - msecs_to_jiffies(delay));
> > -}
> > -
> > -static void thermal_zone_device_check(struct work_struct *work)
> > -{
> > - struct thermal_zone_device *tz = container_of(work, struct
> > - thermal_zone_device,
> > - poll_queue.work);
> > - thermal_zone_device_update(tz);
> > -}
> > -
> > /**
> > * thermal_zone_bind_cooling_device - bind a cooling device to a thermal
> zone
> > * @tz: thermal zone device
> > @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct
> thermal_cooling_device *cdev)
> > }
> > EXPORT_SYMBOL(thermal_cdev_update);
> >
> > -static void thermal_zone_do_update(struct thermal_zone_device *tz)
> > -{
> > - struct thermal_instance *instance;
> > -
> > - list_for_each_entry(instance, &tz->thermal_instances, tz_node)
> > - thermal_cdev_update(instance->cdev);
> > -}
> > -
> > -/*
> > - * Cooling algorithm for both active and passive cooling
> > - *
> > - * 1. if the temperature is higher than a trip point,
> > - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > - * state for this trip point
> > - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > - * state for this trip point
> > - *
> > - * 2. if the temperature is lower than a trip point, use lower
> > - * cooling state for this trip point
> > - *
> > - * Note that this behaves the same as the previous passive cooling
> > - * algorithm.
> > - */
> > -
> > -static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> > - int trip, long temp)
> > -{
> > - struct thermal_instance *instance;
> > - struct thermal_cooling_device *cdev = NULL;
> > - unsigned long cur_state, max_state;
> > - long trip_temp;
> > - enum thermal_trip_type trip_type;
> > - enum thermal_trend trend;
> > -
> > - if (trip == THERMAL_TRIPS_NONE) {
> > - trip_temp = tz->forced_passive;
> > - trip_type = THERMAL_TRIPS_NONE;
> > - } else {
> > - tz->ops->get_trip_temp(tz, trip, &trip_temp);
> > - tz->ops->get_trip_type(tz, trip, &trip_type);
> > - }
> > -
> > - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
> > - /*
> > - * compare the current temperature and previous
> temperature
> > - * to get the thermal trend, if no special requirement
> > - */
> > - if (tz->temperature > tz->last_temperature)
> > - trend = THERMAL_TREND_RAISING;
> > - else if (tz->temperature < tz->last_temperature)
> > - trend = THERMAL_TREND_DROPPING;
> > - else
> > - trend = THERMAL_TREND_STABLE;
> > - }
> > -
> > - if (temp >= trip_temp) {
> > - list_for_each_entry(instance, &tz->thermal_instances,
> tz_node) {
> > - if (instance->trip != trip)
> > - continue;
> > -
> > - cdev = instance->cdev;
> > -
> > - cdev->ops->get_cur_state(cdev, &cur_state);
> > - cdev->ops->get_max_state(cdev, &max_state);
> > -
> > - if (trend == THERMAL_TREND_RAISING) {
> > - cur_state = cur_state < instance->upper ?
> > - (cur_state + 1) : instance->upper;
> > - } else if (trend == THERMAL_TREND_DROPPING) {
> > - cur_state = cur_state > instance->lower ?
> > - (cur_state - 1) : instance->lower;
> > - }
> > -
> > - /* activate a passive thermal instance */
> > - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> > - trip_type == THERMAL_TRIPS_NONE) &&
> > - instance->target == THERMAL_NO_TARGET)
> > - tz->passive++;
> > -
> > - instance->target = cur_state;
> > - cdev->updated = false; /* cooling device needs
> update */
> > - }
> > - } else { /* below trip */
> > - list_for_each_entry(instance, &tz->thermal_instances,
> tz_node) {
> > - if (instance->trip != trip)
> > - continue;
> > -
> > - /* Do not use the inactive thermal instance */
> > - if (instance->target == THERMAL_NO_TARGET)
> > - continue;
> > - cdev = instance->cdev;
> > - cdev->ops->get_cur_state(cdev, &cur_state);
> > -
> > - cur_state = cur_state > instance->lower ?
> > - (cur_state - 1) : THERMAL_NO_TARGET;
> > -
> > - /* deactivate a passive thermal instance */
> > - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> > - trip_type == THERMAL_TRIPS_NONE) &&
> > - cur_state == THERMAL_NO_TARGET)
> > - tz->passive--;
> > - instance->target = cur_state;
> > - cdev->updated = false; /* cooling device needs
> update */
> > - }
> > - }
> > -
> > - return;
> > -}
> > -/**
> > - * thermal_zone_device_update - force an update of a thermal zone's
> state
> > - * @ttz: the thermal zone to update
> > - */
> > -
> > -void thermal_zone_device_update(struct thermal_zone_device *tz)
> > -{
> > - int count, ret = 0;
> > - long temp, trip_temp;
> > - enum thermal_trip_type trip_type;
> > -
> > - mutex_lock(&tz->lock);
> > -
> > - if (tz->ops->get_temp(tz, &temp)) {
> > - /* get_temp failed - retry it later */
> > - pr_warn("failed to read out thermal zone %d\n", tz->id);
> > - goto leave;
> > - }
> > -
> > - tz->last_temperature = tz->temperature;
> > - tz->temperature = temp;
> > -
> > - for (count = 0; count < tz->trips; count++) {
> > - tz->ops->get_trip_type(tz, count, &trip_type);
> > - tz->ops->get_trip_temp(tz, count, &trip_temp);
> > -
> > - switch (trip_type) {
> > - case THERMAL_TRIP_CRITICAL:
> > - if (temp >= trip_temp) {
> > - if (tz->ops->notify)
> > - ret = tz->ops->notify(tz, count,
> > - trip_type);
> > - if (!ret) {
> > - pr_emerg("Critical temperature
> reached (%ld C), shutting down\n",
> > - temp/1000);
> > - orderly_poweroff(true);
> > - }
> > - }
> > - break;
> > - case THERMAL_TRIP_HOT:
> > - if (temp >= trip_temp)
> > - if (tz->ops->notify)
> > - tz->ops->notify(tz, count, trip_type);
> > - break;
> > - case THERMAL_TRIP_ACTIVE:
> > - thermal_zone_trip_update(tz, count, temp);
> > - break;
> > - case THERMAL_TRIP_PASSIVE:
> > - if (temp >= trip_temp || tz->passive)
> > - thermal_zone_trip_update(tz, count, temp);
> > - break;
> > - }
> > - }
> > -
> > - if (tz->forced_passive)
> > - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE,
> temp);
> > - thermal_zone_do_update(tz);
> > -
> > -leave:
> > - if (tz->passive)
> > - thermal_zone_device_set_polling(tz, tz->passive_delay);
> > - else if (tz->polling_delay)
> > - thermal_zone_device_set_polling(tz, tz->polling_delay);
> > - else
> > - thermal_zone_device_set_polling(tz, 0);
> > - mutex_unlock(&tz->lock);
> > -}
> > -EXPORT_SYMBOL(thermal_zone_device_update);
> > -
> > /**
> > * create_trip_attrs - create attributes for trip points
> > * @tz: the thermal zone device
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-10 8:56 ` R, Durgadoss
@ 2012-09-11 0:24 ` Zhang Rui
2012-09-11 3:05 ` R, Durgadoss
0 siblings, 1 reply; 24+ messages in thread
From: Zhang Rui @ 2012-09-11 0:24 UTC (permalink / raw)
To: R, Durgadoss
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
eduardo.valentin@ti.com
On 一, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote:
> Hi Rui,
>
> > -----Original Message-----
> > From: Zhang, Rui
> > Sent: Monday, September 10, 2012 2:14 PM
> > To: R, Durgadoss
> > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
> > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> > thermal_sys.c
> [cut.]
>
> > > +
> > > +static void handle_non_critical_trips(struct thermal_zone_device *tz,
> > > + int trip, enum thermal_trip_type trip_type)
> > > +{
> > > + tz->governor->throttle(tz, trip);
> > > +}
> > here is the problem, we must make sure every registered thermal zone
> > have a governor when it is running, right?
>
> Yes, agree with you. Had some thoughts here, but wanted to get your opinion
> before I implemented them.
>
> 1. We can make the default governor as 'user space', and make it load inside
> thermal_sys.c (so that every zone will always have a default governor)
>
No, the default governor should be step wise so that it behaves the same
as before. if we use userspace as default governor, most of the thermal
driver will stop working with this patch set.
IMO, we should make all of the governors configurable, but at least one
of them must be selected as the default governor, that's why we need
something below.
choice
prompt "Default thermal governor"
default THERMAL_DEFAULT_GOV_STEP_WISE
help
This option sets which thermal governor shall be loaded at
startup.
thanks,
rui
> 2. All other governors, that are implemented in a separate .c file can be
> optional i.e. left to the user to select/deselect.
>
> IMO, this will make our implementation easier and cleaner.
> What do you think ?
>
> Thanks,
> Durga
>
> >
> > then the default governor must always be built in.
> > We can have a Kconfig option for step_wise, but we should not make it
> > configurable by users.
> > or we can use prompt to get the default governor at build time. say
> >
> > choice
> > prompt "Default thermal governor"
> > default THERMAL_DEFAULT_GOV_STEP_WISE
> > help
> > This option sets which thermal governor shall be loaded at
> > startup.
> >
> > config THERMAL_DEFAULT_GOV_STEP_WISE
> > bool "step-wise"
> > select THERMAL_GOV_STEP_WISE
> > help
> > Use the thermal governor 'step-wise' as default.blabla
> >
> >
> > thanks,
> > rui
> >
> > > +
> > > +static void handle_critical_trips(struct thermal_zone_device *tz,
> > > + int trip, enum thermal_trip_type trip_type)
> > > +{
> > > + long trip_temp;
> > > +
> > > + tz->ops->get_trip_temp(tz, trip, &trip_temp);
> > > +
> > > + /* If we have not crossed the trip_temp, we do not care. */
> > > + if (tz->temperature < trip_temp)
> > > + return;
> > > +
> > > + if (tz->ops->notify)
> > > + tz->ops->notify(tz, trip, trip_type);
> > > +
> > > + if (trip_type == THERMAL_TRIP_CRITICAL) {
> > > + pr_emerg("Critical temperature reached(%d C),shutting
> > down\n",
> > > + tz->temperature / 1000);
> > > + orderly_poweroff(true);
> > > + }
> > > +}
> > > +
> > > +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
> > > +{
> > > + enum thermal_trip_type type;
> > > +
> > > + tz->ops->get_trip_type(tz, trip, &type);
> > > +
> > > + if (type == THERMAL_TRIP_CRITICAL || type ==
> > THERMAL_TRIP_HOT)
> > > + handle_critical_trips(tz, trip, type);
> > > + else
> > > + handle_non_critical_trips(tz, trip, type);
> > > + /*
> > > + * Alright, we handled this trip successfully.
> > > + * So, start monitoring again.
> > > + */
> > > + monitor_thermal_zone(tz);
> > > +}
> > > +
> > > +static void update_temperature(struct thermal_zone_device *tz)
> > > +{
> > > + long temp;
> > > + int ret;
> > > +
> > > + mutex_lock(&tz->lock);
> > > +
> > > + ret = tz->ops->get_temp(tz, &temp);
> > > + if (ret) {
> > > + pr_warn("failed to read out thermal zone %d\n", tz->id);
> > > + return;
> > > + }
> > > +
> > > + tz->last_temperature = tz->temperature;
> > > + tz->temperature = temp;
> > > +
> > > + mutex_unlock(&tz->lock);
> > > +}
> > > +
> > > +void thermal_zone_device_update(struct thermal_zone_device *tz)
> > > +{
> > > + int count;
> > > +
> > > + update_temperature(tz);
> > > +
> > > + for (count = 0; count < tz->trips; count++)
> > > + handle_thermal_trip(tz, count);
> > > +}
> > > +EXPORT_SYMBOL(thermal_zone_device_update);
> > > +
> > > +static void thermal_zone_device_check(struct work_struct *work)
> > > +{
> > > + struct thermal_zone_device *tz = container_of(work, struct
> > > + thermal_zone_device,
> > > + poll_queue.work);
> > > + thermal_zone_device_update(tz);
> > > +}
> > > +
> > > /* sys I/F for thermal zone */
> > >
> > > #define to_thermal_zone(_dev) \
> > > @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct
> > thermal_zone_device *tz)
> > > }
> > > #endif
> > >
> > > -static void thermal_zone_device_set_polling(struct thermal_zone_device
> > *tz,
> > > - int delay)
> > > -{
> > > - cancel_delayed_work(&(tz->poll_queue));
> > > -
> > > - if (!delay)
> > > - return;
> > > -
> > > - if (delay > 1000)
> > > - queue_delayed_work(system_freezable_wq, &(tz-
> > >poll_queue),
> > > - round_jiffies(msecs_to_jiffies(delay)));
> > > - else
> > > - queue_delayed_work(system_freezable_wq, &(tz-
> > >poll_queue),
> > > - msecs_to_jiffies(delay));
> > > -}
> > > -
> > > -static void thermal_zone_device_check(struct work_struct *work)
> > > -{
> > > - struct thermal_zone_device *tz = container_of(work, struct
> > > - thermal_zone_device,
> > > - poll_queue.work);
> > > - thermal_zone_device_update(tz);
> > > -}
> > > -
> > > /**
> > > * thermal_zone_bind_cooling_device - bind a cooling device to a thermal
> > zone
> > > * @tz: thermal zone device
> > > @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct
> > thermal_cooling_device *cdev)
> > > }
> > > EXPORT_SYMBOL(thermal_cdev_update);
> > >
> > > -static void thermal_zone_do_update(struct thermal_zone_device *tz)
> > > -{
> > > - struct thermal_instance *instance;
> > > -
> > > - list_for_each_entry(instance, &tz->thermal_instances, tz_node)
> > > - thermal_cdev_update(instance->cdev);
> > > -}
> > > -
> > > -/*
> > > - * Cooling algorithm for both active and passive cooling
> > > - *
> > > - * 1. if the temperature is higher than a trip point,
> > > - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
> > > - * state for this trip point
> > > - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
> > > - * state for this trip point
> > > - *
> > > - * 2. if the temperature is lower than a trip point, use lower
> > > - * cooling state for this trip point
> > > - *
> > > - * Note that this behaves the same as the previous passive cooling
> > > - * algorithm.
> > > - */
> > > -
> > > -static void thermal_zone_trip_update(struct thermal_zone_device *tz,
> > > - int trip, long temp)
> > > -{
> > > - struct thermal_instance *instance;
> > > - struct thermal_cooling_device *cdev = NULL;
> > > - unsigned long cur_state, max_state;
> > > - long trip_temp;
> > > - enum thermal_trip_type trip_type;
> > > - enum thermal_trend trend;
> > > -
> > > - if (trip == THERMAL_TRIPS_NONE) {
> > > - trip_temp = tz->forced_passive;
> > > - trip_type = THERMAL_TRIPS_NONE;
> > > - } else {
> > > - tz->ops->get_trip_temp(tz, trip, &trip_temp);
> > > - tz->ops->get_trip_type(tz, trip, &trip_type);
> > > - }
> > > -
> > > - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
> > > - /*
> > > - * compare the current temperature and previous
> > temperature
> > > - * to get the thermal trend, if no special requirement
> > > - */
> > > - if (tz->temperature > tz->last_temperature)
> > > - trend = THERMAL_TREND_RAISING;
> > > - else if (tz->temperature < tz->last_temperature)
> > > - trend = THERMAL_TREND_DROPPING;
> > > - else
> > > - trend = THERMAL_TREND_STABLE;
> > > - }
> > > -
> > > - if (temp >= trip_temp) {
> > > - list_for_each_entry(instance, &tz->thermal_instances,
> > tz_node) {
> > > - if (instance->trip != trip)
> > > - continue;
> > > -
> > > - cdev = instance->cdev;
> > > -
> > > - cdev->ops->get_cur_state(cdev, &cur_state);
> > > - cdev->ops->get_max_state(cdev, &max_state);
> > > -
> > > - if (trend == THERMAL_TREND_RAISING) {
> > > - cur_state = cur_state < instance->upper ?
> > > - (cur_state + 1) : instance->upper;
> > > - } else if (trend == THERMAL_TREND_DROPPING) {
> > > - cur_state = cur_state > instance->lower ?
> > > - (cur_state - 1) : instance->lower;
> > > - }
> > > -
> > > - /* activate a passive thermal instance */
> > > - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> > > - trip_type == THERMAL_TRIPS_NONE) &&
> > > - instance->target == THERMAL_NO_TARGET)
> > > - tz->passive++;
> > > -
> > > - instance->target = cur_state;
> > > - cdev->updated = false; /* cooling device needs
> > update */
> > > - }
> > > - } else { /* below trip */
> > > - list_for_each_entry(instance, &tz->thermal_instances,
> > tz_node) {
> > > - if (instance->trip != trip)
> > > - continue;
> > > -
> > > - /* Do not use the inactive thermal instance */
> > > - if (instance->target == THERMAL_NO_TARGET)
> > > - continue;
> > > - cdev = instance->cdev;
> > > - cdev->ops->get_cur_state(cdev, &cur_state);
> > > -
> > > - cur_state = cur_state > instance->lower ?
> > > - (cur_state - 1) : THERMAL_NO_TARGET;
> > > -
> > > - /* deactivate a passive thermal instance */
> > > - if ((trip_type == THERMAL_TRIP_PASSIVE ||
> > > - trip_type == THERMAL_TRIPS_NONE) &&
> > > - cur_state == THERMAL_NO_TARGET)
> > > - tz->passive--;
> > > - instance->target = cur_state;
> > > - cdev->updated = false; /* cooling device needs
> > update */
> > > - }
> > > - }
> > > -
> > > - return;
> > > -}
> > > -/**
> > > - * thermal_zone_device_update - force an update of a thermal zone's
> > state
> > > - * @ttz: the thermal zone to update
> > > - */
> > > -
> > > -void thermal_zone_device_update(struct thermal_zone_device *tz)
> > > -{
> > > - int count, ret = 0;
> > > - long temp, trip_temp;
> > > - enum thermal_trip_type trip_type;
> > > -
> > > - mutex_lock(&tz->lock);
> > > -
> > > - if (tz->ops->get_temp(tz, &temp)) {
> > > - /* get_temp failed - retry it later */
> > > - pr_warn("failed to read out thermal zone %d\n", tz->id);
> > > - goto leave;
> > > - }
> > > -
> > > - tz->last_temperature = tz->temperature;
> > > - tz->temperature = temp;
> > > -
> > > - for (count = 0; count < tz->trips; count++) {
> > > - tz->ops->get_trip_type(tz, count, &trip_type);
> > > - tz->ops->get_trip_temp(tz, count, &trip_temp);
> > > -
> > > - switch (trip_type) {
> > > - case THERMAL_TRIP_CRITICAL:
> > > - if (temp >= trip_temp) {
> > > - if (tz->ops->notify)
> > > - ret = tz->ops->notify(tz, count,
> > > - trip_type);
> > > - if (!ret) {
> > > - pr_emerg("Critical temperature
> > reached (%ld C), shutting down\n",
> > > - temp/1000);
> > > - orderly_poweroff(true);
> > > - }
> > > - }
> > > - break;
> > > - case THERMAL_TRIP_HOT:
> > > - if (temp >= trip_temp)
> > > - if (tz->ops->notify)
> > > - tz->ops->notify(tz, count, trip_type);
> > > - break;
> > > - case THERMAL_TRIP_ACTIVE:
> > > - thermal_zone_trip_update(tz, count, temp);
> > > - break;
> > > - case THERMAL_TRIP_PASSIVE:
> > > - if (temp >= trip_temp || tz->passive)
> > > - thermal_zone_trip_update(tz, count, temp);
> > > - break;
> > > - }
> > > - }
> > > -
> > > - if (tz->forced_passive)
> > > - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE,
> > temp);
> > > - thermal_zone_do_update(tz);
> > > -
> > > -leave:
> > > - if (tz->passive)
> > > - thermal_zone_device_set_polling(tz, tz->passive_delay);
> > > - else if (tz->polling_delay)
> > > - thermal_zone_device_set_polling(tz, tz->polling_delay);
> > > - else
> > > - thermal_zone_device_set_polling(tz, 0);
> > > - mutex_unlock(&tz->lock);
> > > -}
> > > -EXPORT_SYMBOL(thermal_zone_device_update);
> > > -
> > > /**
> > > * create_trip_attrs - create attributes for trip points
> > > * @tz: the thermal zone device
> >
>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-11 0:24 ` Zhang Rui
@ 2012-09-11 3:05 ` R, Durgadoss
2012-09-11 3:20 ` Zhang Rui
0 siblings, 1 reply; 24+ messages in thread
From: R, Durgadoss @ 2012-09-11 3:05 UTC (permalink / raw)
To: Zhang, Rui
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
eduardo.valentin@ti.com
Hi Rui,
> On 一, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote:
> > Hi Rui,
> >
> > > -----Original Message-----
> > > From: Zhang, Rui
> > > Sent: Monday, September 10, 2012 2:14 PM
> > > To: R, Durgadoss
> > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org;
> eduardo.valentin@ti.com
> > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> > > thermal_sys.c
> > [cut.]
> >
> > > > +
> > > > +static void handle_non_critical_trips(struct thermal_zone_device *tz,
> > > > + int trip, enum thermal_trip_type trip_type)
> > > > +{
> > > > + tz->governor->throttle(tz, trip);
> > > > +}
> > > here is the problem, we must make sure every registered thermal zone
> > > have a governor when it is running, right?
> >
> > Yes, agree with you. Had some thoughts here, but wanted to get your
> opinion
> > before I implemented them.
> >
> > 1. We can make the default governor as 'user space', and make it load
> inside
> > thermal_sys.c (so that every zone will always have a default governor)
> >
> No, the default governor should be step wise so that it behaves the same
> as before. if we use userspace as default governor, most of the thermal
> driver will stop working with this patch set.
yes, I understand. Shall make step_wise default, and always loaded.
For user space, should we move it to a new .c file, and make it like
other governors or can we keep it as it is ?
Thanks,
Durga
>
> IMO, we should make all of the governors configurable, but at least one
> of them must be selected as the default governor, that's why we need
> something below.
>
> choice
> prompt "Default thermal governor"
> default THERMAL_DEFAULT_GOV_STEP_WISE
> help
> This option sets which thermal governor shall be loaded at
> startup.
>
> thanks,
> rui
>
> > 2. All other governors, that are implemented in a separate .c file can be
> > optional i.e. left to the user to select/deselect.
> >
> > IMO, this will make our implementation easier and cleaner.
> > What do you think ?
> >
> > Thanks,
> > Durga
> >
> > >
> > > then the default governor must always be built in.
> > > We can have a Kconfig option for step_wise, but we should not make it
> > > configurable by users.
> > > or we can use prompt to get the default governor at build time. say
> > >
> > > choice
> > > prompt "Default thermal governor"
> > > default THERMAL_DEFAULT_GOV_STEP_WISE
> > > help
> > > This option sets which thermal governor shall be loaded at
> > > startup.
> > >
> > > config THERMAL_DEFAULT_GOV_STEP_WISE
> > > bool "step-wise"
> > > select THERMAL_GOV_STEP_WISE
> > > help
> > > Use the thermal governor 'step-wise' as default.blabla
> > >
> > >
> > > thanks,
> > > rui
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-11 3:05 ` R, Durgadoss
@ 2012-09-11 3:20 ` Zhang Rui
2012-09-11 3:39 ` R, Durgadoss
0 siblings, 1 reply; 24+ messages in thread
From: Zhang Rui @ 2012-09-11 3:20 UTC (permalink / raw)
To: R, Durgadoss
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
eduardo.valentin@ti.com
On 一, 2012-09-10 at 21:05 -0600, R, Durgadoss wrote:
> Hi Rui,
>
> > On 一, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote:
> > > Hi Rui,
> > >
> > > > -----Original Message-----
> > > > From: Zhang, Rui
> > > > Sent: Monday, September 10, 2012 2:14 PM
> > > > To: R, Durgadoss
> > > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org;
> > eduardo.valentin@ti.com
> > > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> > > > thermal_sys.c
> > > [cut.]
> > >
> > > > > +
> > > > > +static void handle_non_critical_trips(struct thermal_zone_device *tz,
> > > > > + int trip, enum thermal_trip_type trip_type)
> > > > > +{
> > > > > + tz->governor->throttle(tz, trip);
> > > > > +}
> > > > here is the problem, we must make sure every registered thermal zone
> > > > have a governor when it is running, right?
> > >
> > > Yes, agree with you. Had some thoughts here, but wanted to get your
> > opinion
> > > before I implemented them.
> > >
> > > 1. We can make the default governor as 'user space', and make it load
> > inside
> > > thermal_sys.c (so that every zone will always have a default governor)
> > >
> > No, the default governor should be step wise so that it behaves the same
> > as before. if we use userspace as default governor, most of the thermal
> > driver will stop working with this patch set.
>
> yes, I understand. Shall make step_wise default, and always loaded.
>
we can always make step-wise default, or we can ask users to select one
as default and load it.
> For user space, should we move it to a new .c file, and make it like
> other governors or can we keep it as it is ?
>
a new .c file for userspace governor.
> Thanks,
> Durga
>
> >
> > IMO, we should make all of the governors configurable, but at least one
> > of them must be selected as the default governor, that's why we need
> > something below.
> >
> > choice
> > prompt "Default thermal governor"
> > default THERMAL_DEFAULT_GOV_STEP_WISE
> > help
> > This option sets which thermal governor shall be loaded at
> > startup.
> >
> > thanks,
> > rui
> >
> > > 2. All other governors, that are implemented in a separate .c file can be
> > > optional i.e. left to the user to select/deselect.
> > >
> > > IMO, this will make our implementation easier and cleaner.
> > > What do you think ?
> > >
> > > Thanks,
> > > Durga
> > >
> > > >
> > > > then the default governor must always be built in.
> > > > We can have a Kconfig option for step_wise, but we should not make it
> > > > configurable by users.
> > > > or we can use prompt to get the default governor at build time. say
> > > >
> > > > choice
> > > > prompt "Default thermal governor"
> > > > default THERMAL_DEFAULT_GOV_STEP_WISE
> > > > help
> > > > This option sets which thermal governor shall be loaded at
> > > > startup.
> > > >
> > > > config THERMAL_DEFAULT_GOV_STEP_WISE
> > > > bool "step-wise"
> > > > select THERMAL_GOV_STEP_WISE
> > > > help
> > > > Use the thermal governor 'step-wise' as default.blabla
> > > >
> > > >
> > > > thanks,
> > > > rui
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c
2012-09-11 3:20 ` Zhang Rui
@ 2012-09-11 3:39 ` R, Durgadoss
0 siblings, 0 replies; 24+ messages in thread
From: R, Durgadoss @ 2012-09-11 3:39 UTC (permalink / raw)
To: Zhang, Rui
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
eduardo.valentin@ti.com
Hi Rui,
> -----Original Message-----
> From: Zhang, Rui
> Sent: Tuesday, September 11, 2012 8:51 AM
> To: R, Durgadoss
> Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
> Subject: RE: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> thermal_sys.c
>
> On 一, 2012-09-10 at 21:05 -0600, R, Durgadoss wrote:
> > Hi Rui,
> >
> > > On 一, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote:
> > > > Hi Rui,
> > > >
> > > > > -----Original Message-----
> > > > > From: Zhang, Rui
> > > > > Sent: Monday, September 10, 2012 2:14 PM
> > > > > To: R, Durgadoss
> > > > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org;
> > > eduardo.valentin@ti.com
> > > > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of
> > > > > thermal_sys.c
> > > > [cut.]
> > > >
> > > > > > +
> > > > > > +static void handle_non_critical_trips(struct thermal_zone_device
> *tz,
> > > > > > + int trip, enum thermal_trip_type trip_type)
> > > > > > +{
> > > > > > + tz->governor->throttle(tz, trip);
> > > > > > +}
> > > > > here is the problem, we must make sure every registered thermal
> zone
> > > > > have a governor when it is running, right?
> > > >
> > > > Yes, agree with you. Had some thoughts here, but wanted to get your
> > > opinion
> > > > before I implemented them.
> > > >
> > > > 1. We can make the default governor as 'user space', and make it load
> > > inside
> > > > thermal_sys.c (so that every zone will always have a default governor)
> > > >
> > > No, the default governor should be step wise so that it behaves the same
> > > as before. if we use userspace as default governor, most of the thermal
> > > driver will stop working with this patch set.
> >
> > yes, I understand. Shall make step_wise default, and always loaded.
> >
> we can always make step-wise default, or we can ask users to select one
> as default and load it.
Will always step_wise default. That will exactly mimic the old behavior.
will also create a new file for user space governor.
Thanks,
Durga
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2012-09-11 3:39 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-01 11:51 [PATCHv3 00/15] Thermal_Framework_Enhancements Durgadoss R
2012-09-01 11:51 ` [PATCHv3 01/15] Thermal: Refactor thermal.h file Durgadoss R
2012-09-01 11:51 ` [PATCHv3 02/15] Thermal: Move thermal_instance to thermal_core.h Durgadoss R
2012-09-01 11:51 ` [PATCHv3 03/15] Thermal: Add get trend, get instance API's to thermal_sys Durgadoss R
2012-09-01 11:51 ` [PATCHv3 04/15] Thermal: Add platform level information to thermal.h Durgadoss R
2012-09-01 11:51 ` [PATCHv3 05/15] Thermal: Pass zone parameters as argument to tzd_register Durgadoss R
2012-09-01 11:51 ` [PATCHv3 06/15] Thermal: Add thermal governor registration APIs Durgadoss R
2012-09-10 8:28 ` Zhang Rui
2012-09-01 11:51 ` [PATCHv3 07/15] Thermal: Add a policy sysfs attribute Durgadoss R
2012-09-01 11:51 ` [PATCHv3 08/15] Thermal: Update binding logic based on platform data Durgadoss R
2012-09-01 11:51 ` [PATCHv3 09/15] Thermal: Make thermal_cdev_update as a global function Durgadoss R
2012-09-01 11:51 ` [PATCHv3 10/15] Thermal: Introduce fair_share thermal governor Durgadoss R
2012-09-01 11:51 ` [PATCHv3 11/15] Thermal: Introduce a step_wise " Durgadoss R
2012-09-01 11:51 ` [PATCHv3 12/15] Thermal: Register a governor for user space Durgadoss R
2012-09-10 8:37 ` Zhang Rui
2012-09-01 11:51 ` [PATCHv3 13/15] Thermal: Remove throttling logic out of thermal_sys.c Durgadoss R
2012-09-10 8:44 ` Zhang Rui
2012-09-10 8:56 ` R, Durgadoss
2012-09-11 0:24 ` Zhang Rui
2012-09-11 3:05 ` R, Durgadoss
2012-09-11 3:20 ` Zhang Rui
2012-09-11 3:39 ` R, Durgadoss
2012-09-01 11:51 ` [PATCHv3 14/15] Thermal: Add a notification API Durgadoss R
2012-09-01 11:51 ` [PATCHv3 15/15] Thermal: Add documentation for platform layer data Durgadoss R
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).