diff options
-rw-r--r-- | drivers/thermal/thermal_sys.c | 90 | ||||
-rw-r--r-- | include/linux/thermal.h | 16 |
2 files changed, 106 insertions, 0 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index dca3bfc0e702..0afd84cb127d 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -49,7 +49,86 @@ static DEFINE_MUTEX(thermal_idr_lock); | |||
49 | 49 | ||
50 | static LIST_HEAD(thermal_tz_list); | 50 | static LIST_HEAD(thermal_tz_list); |
51 | static LIST_HEAD(thermal_cdev_list); | 51 | static LIST_HEAD(thermal_cdev_list); |
52 | static LIST_HEAD(thermal_governor_list); | ||
53 | |||
52 | static DEFINE_MUTEX(thermal_list_lock); | 54 | static DEFINE_MUTEX(thermal_list_lock); |
55 | static DEFINE_MUTEX(thermal_governor_lock); | ||
56 | |||
57 | static struct thermal_governor *__find_governor(const char *name) | ||
58 | { | ||
59 | struct thermal_governor *pos; | ||
60 | |||
61 | list_for_each_entry(pos, &thermal_governor_list, governor_list) | ||
62 | if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH)) | ||
63 | return pos; | ||
64 | |||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | int thermal_register_governor(struct thermal_governor *governor) | ||
69 | { | ||
70 | int err; | ||
71 | const char *name; | ||
72 | struct thermal_zone_device *pos; | ||
73 | |||
74 | if (!governor) | ||
75 | return -EINVAL; | ||
76 | |||
77 | mutex_lock(&thermal_governor_lock); | ||
78 | |||
79 | err = -EBUSY; | ||
80 | if (__find_governor(governor->name) == NULL) { | ||
81 | err = 0; | ||
82 | list_add(&governor->governor_list, &thermal_governor_list); | ||
83 | } | ||
84 | |||
85 | mutex_lock(&thermal_list_lock); | ||
86 | |||
87 | list_for_each_entry(pos, &thermal_tz_list, node) { | ||
88 | if (pos->governor) | ||
89 | continue; | ||
90 | if (pos->tzp) | ||
91 | name = pos->tzp->governor_name; | ||
92 | else | ||
93 | name = DEFAULT_THERMAL_GOVERNOR; | ||
94 | if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH)) | ||
95 | pos->governor = governor; | ||
96 | } | ||
97 | |||
98 | mutex_unlock(&thermal_list_lock); | ||
99 | mutex_unlock(&thermal_governor_lock); | ||
100 | |||
101 | return err; | ||
102 | } | ||
103 | EXPORT_SYMBOL_GPL(thermal_register_governor); | ||
104 | |||
105 | void thermal_unregister_governor(struct thermal_governor *governor) | ||
106 | { | ||
107 | struct thermal_zone_device *pos; | ||
108 | |||
109 | if (!governor) | ||
110 | return; | ||
111 | |||
112 | mutex_lock(&thermal_governor_lock); | ||
113 | |||
114 | if (__find_governor(governor->name) == NULL) | ||
115 | goto exit; | ||
116 | |||
117 | mutex_lock(&thermal_list_lock); | ||
118 | |||
119 | list_for_each_entry(pos, &thermal_tz_list, node) { | ||
120 | if (!strnicmp(pos->governor->name, governor->name, | ||
121 | THERMAL_NAME_LENGTH)) | ||
122 | pos->governor = NULL; | ||
123 | } | ||
124 | |||
125 | mutex_unlock(&thermal_list_lock); | ||
126 | list_del(&governor->governor_list); | ||
127 | exit: | ||
128 | mutex_unlock(&thermal_governor_lock); | ||
129 | return; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(thermal_unregister_governor); | ||
53 | 132 | ||
54 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) | 133 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) |
55 | { | 134 | { |
@@ -1437,6 +1516,16 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1437 | if (result) | 1516 | if (result) |
1438 | goto unregister; | 1517 | goto unregister; |
1439 | 1518 | ||
1519 | /* Update 'this' zone's governor information */ | ||
1520 | mutex_lock(&thermal_governor_lock); | ||
1521 | |||
1522 | if (tz->tzp) | ||
1523 | tz->governor = __find_governor(tz->tzp->governor_name); | ||
1524 | else | ||
1525 | tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR); | ||
1526 | |||
1527 | mutex_unlock(&thermal_governor_lock); | ||
1528 | |||
1440 | result = thermal_add_hwmon_sysfs(tz); | 1529 | result = thermal_add_hwmon_sysfs(tz); |
1441 | if (result) | 1530 | if (result) |
1442 | goto unregister; | 1531 | goto unregister; |
@@ -1500,6 +1589,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
1500 | if (tz->ops->get_mode) | 1589 | if (tz->ops->get_mode) |
1501 | device_remove_file(&tz->device, &dev_attr_mode); | 1590 | device_remove_file(&tz->device, &dev_attr_mode); |
1502 | remove_trip_attrs(tz); | 1591 | remove_trip_attrs(tz); |
1592 | tz->governor = NULL; | ||
1503 | 1593 | ||
1504 | thermal_remove_hwmon_sysfs(tz); | 1594 | thermal_remove_hwmon_sysfs(tz); |
1505 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1595 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 58cb1c036a0e..6182bd5f7504 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -46,6 +46,9 @@ | |||
46 | #define THERMAL_GENL_VERSION 0x01 | 46 | #define THERMAL_GENL_VERSION 0x01 |
47 | #define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group" | 47 | #define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group" |
48 | 48 | ||
49 | /* Default Thermal Governor: Does Linear Throttling */ | ||
50 | #define DEFAULT_THERMAL_GOVERNOR "step_wise" | ||
51 | |||
49 | struct thermal_zone_device; | 52 | struct thermal_zone_device; |
50 | struct thermal_cooling_device; | 53 | struct thermal_cooling_device; |
51 | 54 | ||
@@ -158,6 +161,7 @@ struct thermal_zone_device { | |||
158 | unsigned int forced_passive; | 161 | unsigned int forced_passive; |
159 | const struct thermal_zone_device_ops *ops; | 162 | const struct thermal_zone_device_ops *ops; |
160 | const struct thermal_zone_params *tzp; | 163 | const struct thermal_zone_params *tzp; |
164 | struct thermal_governor *governor; | ||
161 | struct list_head thermal_instances; | 165 | struct list_head thermal_instances; |
162 | struct idr idr; | 166 | struct idr idr; |
163 | struct mutex lock; /* protect thermal_instances list */ | 167 | struct mutex lock; /* protect thermal_instances list */ |
@@ -165,6 +169,14 @@ struct thermal_zone_device { | |||
165 | struct delayed_work poll_queue; | 169 | struct delayed_work poll_queue; |
166 | }; | 170 | }; |
167 | 171 | ||
172 | /* Structure that holds thermal governor information */ | ||
173 | struct thermal_governor { | ||
174 | char name[THERMAL_NAME_LENGTH]; | ||
175 | int (*throttle)(struct thermal_zone_device *tz, int trip); | ||
176 | struct list_head governor_list; | ||
177 | struct module *owner; | ||
178 | }; | ||
179 | |||
168 | /* Structure that holds binding parameters for a zone */ | 180 | /* Structure that holds binding parameters for a zone */ |
169 | struct thermal_bind_params { | 181 | struct thermal_bind_params { |
170 | struct thermal_cooling_device *cdev; | 182 | struct thermal_cooling_device *cdev; |
@@ -189,6 +201,7 @@ struct thermal_bind_params { | |||
189 | 201 | ||
190 | /* Structure to define Thermal Zone parameters */ | 202 | /* Structure to define Thermal Zone parameters */ |
191 | struct thermal_zone_params { | 203 | struct thermal_zone_params { |
204 | char governor_name[THERMAL_NAME_LENGTH]; | ||
192 | int num_tbps; /* Number of tbp entries */ | 205 | int num_tbps; /* Number of tbp entries */ |
193 | struct thermal_bind_params *tbp; | 206 | struct thermal_bind_params *tbp; |
194 | }; | 207 | }; |
@@ -219,6 +232,9 @@ int get_tz_trend(struct thermal_zone_device *, int); | |||
219 | struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, | 232 | struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, |
220 | struct thermal_cooling_device *, int); | 233 | struct thermal_cooling_device *, int); |
221 | 234 | ||
235 | int thermal_register_governor(struct thermal_governor *); | ||
236 | void thermal_unregister_governor(struct thermal_governor *); | ||
237 | |||
222 | #ifdef CONFIG_NET | 238 | #ifdef CONFIG_NET |
223 | extern int thermal_generate_netlink_event(u32 orig, enum events event); | 239 | extern int thermal_generate_netlink_event(u32 orig, enum events event); |
224 | #else | 240 | #else |