diff options
author | Peter Feuerer <peter@piie.net> | 2014-07-22 11:37:13 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2014-08-27 03:45:58 -0400 |
commit | e4dbf98f7f169346f57296e173e883b7330076ab (patch) | |
tree | 9716c985db04ada091fbb35a9b93a9494e9b13e8 /drivers/thermal | |
parent | 52addcf9d6669fa439387610bc65c92fa0980cef (diff) |
thermal: Added Bang-bang thermal governor
The bang-bang thermal governor uses a hysteresis to switch abruptly on
or off a cooling device. It is intended to control fans, which can
not be throttled but just switched on or off.
Bang-bang cannot be set as default governor as it is intended for
special devices only. For those special devices the driver needs to
explicitely request it.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Andreas Mohr <andi@lisas.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Javi Merino <javi.merino@arm.com>
Cc: linux-pm@vger.kernel.org
Signed-off-by: Peter Feuerer <peter@piie.net>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/Kconfig | 10 | ||||
-rw-r--r-- | drivers/thermal/Makefile | 1 | ||||
-rw-r--r-- | drivers/thermal/gov_bang_bang.c | 131 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.c | 5 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.h | 8 |
5 files changed, 155 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 693208eb9047..2500ecc48260 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -84,6 +84,16 @@ config THERMAL_GOV_STEP_WISE | |||
84 | Enable this to manage platform thermals using a simple linear | 84 | Enable this to manage platform thermals using a simple linear |
85 | governor. | 85 | governor. |
86 | 86 | ||
87 | config THERMAL_GOV_BANG_BANG | ||
88 | bool "Bang Bang thermal governor" | ||
89 | default n | ||
90 | help | ||
91 | Enable this to manage platform thermals using bang bang governor. | ||
92 | |||
93 | Say 'Y' here if you want to use two point temperature regulation | ||
94 | used for fans without throttling. Some fan drivers depend on this | ||
95 | governor to be enabled (e.g. acerhdf). | ||
96 | |||
87 | config THERMAL_GOV_USER_SPACE | 97 | config THERMAL_GOV_USER_SPACE |
88 | bool "User_space thermal governor" | 98 | bool "User_space thermal governor" |
89 | help | 99 | help |
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 31e232f84b6b..b7e65423d7b6 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
@@ -11,6 +11,7 @@ thermal_sys-$(CONFIG_THERMAL_OF) += of-thermal.o | |||
11 | 11 | ||
12 | # governors | 12 | # governors |
13 | thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o | 13 | thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o |
14 | thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o | ||
14 | thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o | 15 | thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o |
15 | thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o | 16 | thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o |
16 | 17 | ||
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c new file mode 100644 index 000000000000..c5dd76b2ee74 --- /dev/null +++ b/drivers/thermal/gov_bang_bang.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * gov_bang_bang.c - A simple thermal throttling governor using hysteresis | ||
3 | * | ||
4 | * Copyright (C) 2014 Peter Feuerer <peter@piie.net> | ||
5 | * | ||
6 | * Based on step_wise.c with following Copyrights: | ||
7 | * Copyright (C) 2012 Intel Corp | ||
8 | * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation, version 2. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
18 | * the GNU General Public License for more details. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/thermal.h> | ||
23 | |||
24 | #include "thermal_core.h" | ||
25 | |||
26 | static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | ||
27 | { | ||
28 | long trip_temp; | ||
29 | unsigned long trip_hyst; | ||
30 | struct thermal_instance *instance; | ||
31 | |||
32 | tz->ops->get_trip_temp(tz, trip, &trip_temp); | ||
33 | tz->ops->get_trip_hyst(tz, trip, &trip_hyst); | ||
34 | |||
35 | dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n", | ||
36 | trip, trip_temp, tz->temperature, | ||
37 | trip_hyst); | ||
38 | |||
39 | mutex_lock(&tz->lock); | ||
40 | |||
41 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
42 | if (instance->trip != trip) | ||
43 | continue; | ||
44 | |||
45 | /* in case fan is in initial state, switch the fan off */ | ||
46 | if (instance->target == THERMAL_NO_TARGET) | ||
47 | instance->target = 0; | ||
48 | |||
49 | /* in case fan is neither on nor off set the fan to active */ | ||
50 | if (instance->target != 0 && instance->target != 1) { | ||
51 | pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n", | ||
52 | instance->name, instance->target); | ||
53 | instance->target = 1; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * enable fan when temperature exceeds trip_temp and disable | ||
58 | * the fan in case it falls below trip_temp minus hysteresis | ||
59 | */ | ||
60 | if (instance->target == 0 && tz->temperature >= trip_temp) | ||
61 | instance->target = 1; | ||
62 | else if (instance->target == 1 && | ||
63 | tz->temperature < trip_temp - trip_hyst) | ||
64 | instance->target = 0; | ||
65 | |||
66 | dev_dbg(&instance->cdev->device, "target=%d\n", | ||
67 | (int)instance->target); | ||
68 | |||
69 | instance->cdev->updated = false; /* cdev needs update */ | ||
70 | } | ||
71 | |||
72 | mutex_unlock(&tz->lock); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * bang_bang_control - controls devices associated with the given zone | ||
77 | * @tz - thermal_zone_device | ||
78 | * @trip - the trip point | ||
79 | * | ||
80 | * Regulation Logic: a two point regulation, deliver cooling state depending | ||
81 | * on the previous state shown in this diagram: | ||
82 | * | ||
83 | * Fan: OFF ON | ||
84 | * | ||
85 | * | | ||
86 | * | | ||
87 | * trip_temp: +---->+ | ||
88 | * | | ^ | ||
89 | * | | | | ||
90 | * | | Temperature | ||
91 | * (trip_temp - hyst): +<----+ | ||
92 | * | | ||
93 | * | | ||
94 | * | | ||
95 | * | ||
96 | * * If the fan is not running and temperature exceeds trip_temp, the fan | ||
97 | * gets turned on. | ||
98 | * * In case the fan is running, temperature must fall below | ||
99 | * (trip_temp - hyst) so that the fan gets turned off again. | ||
100 | * | ||
101 | */ | ||
102 | static int bang_bang_control(struct thermal_zone_device *tz, int trip) | ||
103 | { | ||
104 | struct thermal_instance *instance; | ||
105 | |||
106 | thermal_zone_trip_update(tz, trip); | ||
107 | |||
108 | mutex_lock(&tz->lock); | ||
109 | |||
110 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) | ||
111 | thermal_cdev_update(instance->cdev); | ||
112 | |||
113 | mutex_unlock(&tz->lock); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static struct thermal_governor thermal_gov_bang_bang = { | ||
119 | .name = "bang_bang", | ||
120 | .throttle = bang_bang_control, | ||
121 | }; | ||
122 | |||
123 | int thermal_gov_bang_bang_register(void) | ||
124 | { | ||
125 | return thermal_register_governor(&thermal_gov_bang_bang); | ||
126 | } | ||
127 | |||
128 | void thermal_gov_bang_bang_unregister(void) | ||
129 | { | ||
130 | thermal_unregister_governor(&thermal_gov_bang_bang); | ||
131 | } | ||
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 71b0ec0c370d..4c2726b55a2b 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
@@ -1790,6 +1790,10 @@ static int __init thermal_register_governors(void) | |||
1790 | if (result) | 1790 | if (result) |
1791 | return result; | 1791 | return result; |
1792 | 1792 | ||
1793 | result = thermal_gov_bang_bang_register(); | ||
1794 | if (result) | ||
1795 | return result; | ||
1796 | |||
1793 | return thermal_gov_user_space_register(); | 1797 | return thermal_gov_user_space_register(); |
1794 | } | 1798 | } |
1795 | 1799 | ||
@@ -1797,6 +1801,7 @@ static void thermal_unregister_governors(void) | |||
1797 | { | 1801 | { |
1798 | thermal_gov_step_wise_unregister(); | 1802 | thermal_gov_step_wise_unregister(); |
1799 | thermal_gov_fair_share_unregister(); | 1803 | thermal_gov_fair_share_unregister(); |
1804 | thermal_gov_bang_bang_unregister(); | ||
1800 | thermal_gov_user_space_unregister(); | 1805 | thermal_gov_user_space_unregister(); |
1801 | } | 1806 | } |
1802 | 1807 | ||
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 3db339fb636f..d15d243de27a 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h | |||
@@ -69,6 +69,14 @@ static inline int thermal_gov_fair_share_register(void) { return 0; } | |||
69 | static inline void thermal_gov_fair_share_unregister(void) {} | 69 | static inline void thermal_gov_fair_share_unregister(void) {} |
70 | #endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */ | 70 | #endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */ |
71 | 71 | ||
72 | #ifdef CONFIG_THERMAL_GOV_BANG_BANG | ||
73 | int thermal_gov_bang_bang_register(void); | ||
74 | void thermal_gov_bang_bang_unregister(void); | ||
75 | #else | ||
76 | static inline int thermal_gov_bang_bang_register(void) { return 0; } | ||
77 | static inline void thermal_gov_bang_bang_unregister(void) {} | ||
78 | #endif /* CONFIG_THERMAL_GOV_BANG_BANG */ | ||
79 | |||
72 | #ifdef CONFIG_THERMAL_GOV_USER_SPACE | 80 | #ifdef CONFIG_THERMAL_GOV_USER_SPACE |
73 | int thermal_gov_user_space_register(void); | 81 | int thermal_gov_user_space_register(void); |
74 | void thermal_gov_user_space_unregister(void); | 82 | void thermal_gov_user_space_unregister(void); |