Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Peter Feuerer and committed by
Zhang Rui
e4dbf98f 52addcf9

+155
+10
drivers/thermal/Kconfig
··· 84 84 Enable this to manage platform thermals using a simple linear 85 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 97 config THERMAL_GOV_USER_SPACE 88 98 bool "User_space thermal governor" 89 99 help
+1
drivers/thermal/Makefile
··· 11 11 12 12 # governors 13 13 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o 14 + thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o 14 15 thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o 15 16 thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o 16 17
+131
drivers/thermal/gov_bang_bang.c
··· 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 + }
+5
drivers/thermal/thermal_core.c
··· 1790 1790 if (result) 1791 1791 return result; 1792 1792 1793 + result = thermal_gov_bang_bang_register(); 1794 + if (result) 1795 + return result; 1796 + 1793 1797 return thermal_gov_user_space_register(); 1794 1798 } 1795 1799 ··· 1801 1797 { 1802 1798 thermal_gov_step_wise_unregister(); 1803 1799 thermal_gov_fair_share_unregister(); 1800 + thermal_gov_bang_bang_unregister(); 1804 1801 thermal_gov_user_space_unregister(); 1805 1802 } 1806 1803
+8
drivers/thermal/thermal_core.h
··· 69 69 static inline void thermal_gov_fair_share_unregister(void) {} 70 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 80 #ifdef CONFIG_THERMAL_GOV_USER_SPACE 73 81 int thermal_gov_user_space_register(void); 74 82 void thermal_gov_user_space_unregister(void);