diff options
| author | Durgadoss R <durgadoss.r@intel.com> | 2012-09-21 02:36:04 -0400 |
|---|---|---|
| committer | Zhang Rui <rui.zhang@intel.com> | 2012-11-05 01:00:07 -0500 |
| commit | e151a202a084f9f4310d1aa4398325c56ca95fda (patch) | |
| tree | 200f8dcd62f7702e5bda755253d99ec98f5d0fa4 /drivers/thermal | |
| parent | 4ccc5743ae70530f758c7d7ec9a0ca58878e584b (diff) | |
Thermal: Introduce a step_wise thermal governor
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>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
| -rw-r--r-- | drivers/thermal/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/thermal/Makefile | 1 | ||||
| -rw-r--r-- | drivers/thermal/step_wise.c | 194 |
3 files changed, 201 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 84b0f0382e5..7e1b6de6856 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
| @@ -61,3 +61,9 @@ config FAIR_SHARE | |||
| 61 | depends on THERMAL | 61 | depends on THERMAL |
| 62 | help | 62 | help |
| 63 | Enable this to manage platform thermals using fair-share governor. | 63 | Enable this to manage platform thermals using fair-share governor. |
| 64 | |||
| 65 | config STEP_WISE | ||
| 66 | bool "Step_wise thermal governor" | ||
| 67 | depends on THERMAL | ||
| 68 | help | ||
| 69 | Enable this to manage platform thermals using a simple linear | ||
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 30540dde408..4e53c00fe89 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
| @@ -8,3 +8,4 @@ obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o | |||
| 8 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o | 8 | obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o |
| 9 | obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o | 9 | obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o |
| 10 | obj-$(CONFIG_FAIR_SHARE) += fair_share.o | 10 | obj-$(CONFIG_FAIR_SHARE) += fair_share.o |
| 11 | 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 00000000000..3f9cfcf66cc --- /dev/null +++ b/drivers/thermal/step_wise.c | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | /* | ||
| 2 | * step_wise.c - A step-by-step Thermal throttling governor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Intel Corp | ||
| 5 | * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com> | ||
| 6 | * | ||
| 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; version 2 of the License. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
| 21 | * | ||
| 22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 23 | */ | ||
| 24 | |||
| 25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 26 | |||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/thermal.h> | ||
| 29 | |||
| 30 | #include "thermal_core.h" | ||
| 31 | |||
| 32 | /* | ||
| 33 | * If the temperature is higher than a trip point, | ||
| 34 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling | ||
| 35 | * state for this trip point | ||
| 36 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling | ||
| 37 | * state for this trip point | ||
| 38 | */ | ||
| 39 | static unsigned long get_target_state(struct thermal_instance *instance, | ||
| 40 | enum thermal_trend trend) | ||
| 41 | { | ||
| 42 | struct thermal_cooling_device *cdev = instance->cdev; | ||
| 43 | unsigned long cur_state; | ||
| 44 | |||
| 45 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
| 46 | |||
| 47 | if (trend == THERMAL_TREND_RAISING) { | ||
| 48 | cur_state = cur_state < instance->upper ? | ||
| 49 | (cur_state + 1) : instance->upper; | ||
| 50 | } else if (trend == THERMAL_TREND_DROPPING) { | ||
| 51 | cur_state = cur_state > instance->lower ? | ||
| 52 | (cur_state - 1) : instance->lower; | ||
| 53 | } | ||
| 54 | |||
| 55 | return cur_state; | ||
| 56 | } | ||
| 57 | |||
| 58 | static void update_passive_instance(struct thermal_zone_device *tz, | ||
| 59 | enum thermal_trip_type type, int value) | ||
| 60 | { | ||
| 61 | /* | ||
| 62 | * If value is +1, activate a passive instance. | ||
| 63 | * If value is -1, deactivate a passive instance. | ||
| 64 | */ | ||
| 65 | if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE) | ||
| 66 | tz->passive += value; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void update_instance_for_throttle(struct thermal_zone_device *tz, | ||
| 70 | int trip, enum thermal_trip_type trip_type, | ||
| 71 | enum thermal_trend trend) | ||
| 72 | { | ||
| 73 | struct thermal_instance *instance; | ||
| 74 | |||
| 75 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
| 76 | if (instance->trip != trip) | ||
| 77 | continue; | ||
| 78 | |||
| 79 | instance->target = get_target_state(instance, trend); | ||
| 80 | |||
| 81 | /* Activate a passive thermal instance */ | ||
| 82 | if (instance->target == THERMAL_NO_TARGET) | ||
| 83 | update_passive_instance(tz, trip_type, 1); | ||
| 84 | |||
| 85 | instance->cdev->updated = false; /* cdev needs update */ | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | static void update_instance_for_dethrottle(struct thermal_zone_device *tz, | ||
| 90 | int trip, enum thermal_trip_type trip_type) | ||
| 91 | { | ||
| 92 | struct thermal_instance *instance; | ||
| 93 | struct thermal_cooling_device *cdev; | ||
| 94 | unsigned long cur_state; | ||
| 95 | |||
| 96 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
| 97 | if (instance->trip != trip || | ||
| 98 | instance->target == THERMAL_NO_TARGET) | ||
| 99 | continue; | ||
| 100 | |||
| 101 | cdev = instance->cdev; | ||
| 102 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
| 103 | |||
| 104 | instance->target = cur_state > instance->lower ? | ||
| 105 | (cur_state - 1) : THERMAL_NO_TARGET; | ||
| 106 | |||
| 107 | /* Deactivate a passive thermal instance */ | ||
| 108 | if (instance->target == THERMAL_NO_TARGET) | ||
| 109 | update_passive_instance(tz, trip_type, -1); | ||
| 110 | |||
| 111 | cdev->updated = false; /* cdev needs update */ | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | ||
| 116 | { | ||
| 117 | long trip_temp; | ||
| 118 | enum thermal_trip_type trip_type; | ||
| 119 | enum thermal_trend trend; | ||
| 120 | |||
| 121 | if (trip == THERMAL_TRIPS_NONE) { | ||
| 122 | trip_temp = tz->forced_passive; | ||
| 123 | trip_type = THERMAL_TRIPS_NONE; | ||
| 124 | } else { | ||
| 125 | tz->ops->get_trip_temp(tz, trip, &trip_temp); | ||
| 126 | tz->ops->get_trip_type(tz, trip, &trip_type); | ||
| 127 | } | ||
| 128 | |||
| 129 | trend = get_tz_trend(tz, trip); | ||
| 130 | |||
| 131 | mutex_lock(&tz->lock); | ||
| 132 | |||
| 133 | if (tz->temperature >= trip_temp) | ||
| 134 | update_instance_for_throttle(tz, trip, trip_type, trend); | ||
| 135 | else | ||
| 136 | update_instance_for_dethrottle(tz, trip, trip_type); | ||
| 137 | |||
| 138 | mutex_unlock(&tz->lock); | ||
| 139 | } | ||
| 140 | |||
| 141 | /** | ||
| 142 | * step_wise_throttle - throttles devices asscciated with the given zone | ||
| 143 | * @tz - thermal_zone_device | ||
| 144 | * @trip - the trip point | ||
| 145 | * @trip_type - type of the trip point | ||
| 146 | * | ||
| 147 | * Throttling Logic: This uses the trend of the thermal zone to throttle. | ||
| 148 | * If the thermal zone is 'heating up' this throttles all the cooling | ||
| 149 | * devices associated with the zone and its particular trip point, by one | ||
| 150 | * step. If the zone is 'cooling down' it brings back the performance of | ||
| 151 | * the devices by one step. | ||
| 152 | */ | ||
| 153 | int step_wise_throttle(struct thermal_zone_device *tz, int trip) | ||
| 154 | { | ||
| 155 | struct thermal_instance *instance; | ||
| 156 | |||
| 157 | thermal_zone_trip_update(tz, trip); | ||
| 158 | |||
| 159 | if (tz->forced_passive) | ||
| 160 | thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE); | ||
| 161 | |||
| 162 | mutex_lock(&tz->lock); | ||
| 163 | |||
| 164 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) | ||
| 165 | thermal_cdev_update(instance->cdev); | ||
| 166 | |||
| 167 | mutex_unlock(&tz->lock); | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | struct thermal_governor thermal_gov_step_wise = { | ||
| 173 | .name = DEFAULT_THERMAL_GOVERNOR, | ||
| 174 | .throttle = step_wise_throttle, | ||
| 175 | .owner = THIS_MODULE, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static int __init thermal_gov_step_wise_init(void) | ||
| 179 | { | ||
| 180 | return thermal_register_governor(&thermal_gov_step_wise); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void __exit thermal_gov_step_wise_exit(void) | ||
| 184 | { | ||
| 185 | thermal_unregister_governor(&thermal_gov_step_wise); | ||
| 186 | } | ||
| 187 | |||
| 188 | /* This should load after thermal framework */ | ||
| 189 | fs_initcall(thermal_gov_step_wise_init); | ||
| 190 | module_exit(thermal_gov_step_wise_exit); | ||
| 191 | |||
| 192 | MODULE_AUTHOR("Durgadoss R"); | ||
| 193 | MODULE_DESCRIPTION("A step-by-step thermal throttling governor"); | ||
| 194 | MODULE_LICENSE("GPL"); | ||
