1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * thermal.c - Generic Thermal Management Sysfs support. |
4 | * |
5 | * Copyright (C) 2008 Intel Corp |
6 | * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> |
7 | * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | #include <linux/device.h> |
13 | #include <linux/err.h> |
14 | #include <linux/export.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/kdev_t.h> |
17 | #include <linux/idr.h> |
18 | #include <linux/thermal.h> |
19 | #include <linux/reboot.h> |
20 | #include <linux/string.h> |
21 | #include <linux/of.h> |
22 | #include <linux/suspend.h> |
23 | |
24 | #define CREATE_TRACE_POINTS |
25 | #include "thermal_trace.h" |
26 | |
27 | #include "thermal_core.h" |
28 | #include "thermal_hwmon.h" |
29 | |
30 | static DEFINE_IDA(thermal_tz_ida); |
31 | static DEFINE_IDA(thermal_cdev_ida); |
32 | |
33 | static LIST_HEAD(thermal_tz_list); |
34 | static LIST_HEAD(thermal_cdev_list); |
35 | static LIST_HEAD(thermal_governor_list); |
36 | |
37 | static DEFINE_MUTEX(thermal_list_lock); |
38 | static DEFINE_MUTEX(thermal_governor_lock); |
39 | |
40 | static atomic_t in_suspend; |
41 | |
42 | static struct thermal_governor *def_governor; |
43 | |
44 | /* |
45 | * Governor section: set of functions to handle thermal governors |
46 | * |
47 | * Functions to help in the life cycle of thermal governors within |
48 | * the thermal core and by the thermal governor code. |
49 | */ |
50 | |
51 | static struct thermal_governor *__find_governor(const char *name) |
52 | { |
53 | struct thermal_governor *pos; |
54 | |
55 | if (!name || !name[0]) |
56 | return def_governor; |
57 | |
58 | list_for_each_entry(pos, &thermal_governor_list, governor_list) |
59 | if (!strncasecmp(s1: name, s2: pos->name, THERMAL_NAME_LENGTH)) |
60 | return pos; |
61 | |
62 | return NULL; |
63 | } |
64 | |
65 | /** |
66 | * bind_previous_governor() - bind the previous governor of the thermal zone |
67 | * @tz: a valid pointer to a struct thermal_zone_device |
68 | * @failed_gov_name: the name of the governor that failed to register |
69 | * |
70 | * Register the previous governor of the thermal zone after a new |
71 | * governor has failed to be bound. |
72 | */ |
73 | static void bind_previous_governor(struct thermal_zone_device *tz, |
74 | const char *failed_gov_name) |
75 | { |
76 | if (tz->governor && tz->governor->bind_to_tz) { |
77 | if (tz->governor->bind_to_tz(tz)) { |
78 | dev_err(&tz->device, |
79 | "governor %s failed to bind and the previous one (%s) failed to bind again, thermal zone %s has no governor\n" , |
80 | failed_gov_name, tz->governor->name, tz->type); |
81 | tz->governor = NULL; |
82 | } |
83 | } |
84 | } |
85 | |
86 | /** |
87 | * thermal_set_governor() - Switch to another governor |
88 | * @tz: a valid pointer to a struct thermal_zone_device |
89 | * @new_gov: pointer to the new governor |
90 | * |
91 | * Change the governor of thermal zone @tz. |
92 | * |
93 | * Return: 0 on success, an error if the new governor's bind_to_tz() failed. |
94 | */ |
95 | static int thermal_set_governor(struct thermal_zone_device *tz, |
96 | struct thermal_governor *new_gov) |
97 | { |
98 | int ret = 0; |
99 | |
100 | if (tz->governor && tz->governor->unbind_from_tz) |
101 | tz->governor->unbind_from_tz(tz); |
102 | |
103 | if (new_gov && new_gov->bind_to_tz) { |
104 | ret = new_gov->bind_to_tz(tz); |
105 | if (ret) { |
106 | bind_previous_governor(tz, failed_gov_name: new_gov->name); |
107 | |
108 | return ret; |
109 | } |
110 | } |
111 | |
112 | tz->governor = new_gov; |
113 | |
114 | return ret; |
115 | } |
116 | |
117 | int thermal_register_governor(struct thermal_governor *governor) |
118 | { |
119 | int err; |
120 | const char *name; |
121 | struct thermal_zone_device *pos; |
122 | |
123 | if (!governor) |
124 | return -EINVAL; |
125 | |
126 | mutex_lock(&thermal_governor_lock); |
127 | |
128 | err = -EBUSY; |
129 | if (!__find_governor(name: governor->name)) { |
130 | bool match_default; |
131 | |
132 | err = 0; |
133 | list_add(new: &governor->governor_list, head: &thermal_governor_list); |
134 | match_default = !strncmp(governor->name, |
135 | DEFAULT_THERMAL_GOVERNOR, |
136 | THERMAL_NAME_LENGTH); |
137 | |
138 | if (!def_governor && match_default) |
139 | def_governor = governor; |
140 | } |
141 | |
142 | mutex_lock(&thermal_list_lock); |
143 | |
144 | list_for_each_entry(pos, &thermal_tz_list, node) { |
145 | /* |
146 | * only thermal zones with specified tz->tzp->governor_name |
147 | * may run with tz->govenor unset |
148 | */ |
149 | if (pos->governor) |
150 | continue; |
151 | |
152 | name = pos->tzp->governor_name; |
153 | |
154 | if (!strncasecmp(s1: name, s2: governor->name, THERMAL_NAME_LENGTH)) { |
155 | int ret; |
156 | |
157 | ret = thermal_set_governor(tz: pos, new_gov: governor); |
158 | if (ret) |
159 | dev_err(&pos->device, |
160 | "Failed to set governor %s for thermal zone %s: %d\n" , |
161 | governor->name, pos->type, ret); |
162 | } |
163 | } |
164 | |
165 | mutex_unlock(lock: &thermal_list_lock); |
166 | mutex_unlock(lock: &thermal_governor_lock); |
167 | |
168 | return err; |
169 | } |
170 | |
171 | void thermal_unregister_governor(struct thermal_governor *governor) |
172 | { |
173 | struct thermal_zone_device *pos; |
174 | |
175 | if (!governor) |
176 | return; |
177 | |
178 | mutex_lock(&thermal_governor_lock); |
179 | |
180 | if (!__find_governor(name: governor->name)) |
181 | goto exit; |
182 | |
183 | mutex_lock(&thermal_list_lock); |
184 | |
185 | list_for_each_entry(pos, &thermal_tz_list, node) { |
186 | if (!strncasecmp(s1: pos->governor->name, s2: governor->name, |
187 | THERMAL_NAME_LENGTH)) |
188 | thermal_set_governor(tz: pos, NULL); |
189 | } |
190 | |
191 | mutex_unlock(lock: &thermal_list_lock); |
192 | list_del(entry: &governor->governor_list); |
193 | exit: |
194 | mutex_unlock(lock: &thermal_governor_lock); |
195 | } |
196 | |
197 | int thermal_zone_device_set_policy(struct thermal_zone_device *tz, |
198 | char *policy) |
199 | { |
200 | struct thermal_governor *gov; |
201 | int ret = -EINVAL; |
202 | |
203 | mutex_lock(&thermal_governor_lock); |
204 | mutex_lock(&tz->lock); |
205 | |
206 | if (!device_is_registered(dev: &tz->device)) |
207 | goto exit; |
208 | |
209 | gov = __find_governor(name: strim(policy)); |
210 | if (!gov) |
211 | goto exit; |
212 | |
213 | ret = thermal_set_governor(tz, new_gov: gov); |
214 | |
215 | exit: |
216 | mutex_unlock(lock: &tz->lock); |
217 | mutex_unlock(lock: &thermal_governor_lock); |
218 | |
219 | thermal_notify_tz_gov_change(tz_id: tz->id, name: policy); |
220 | |
221 | return ret; |
222 | } |
223 | |
224 | int thermal_build_list_of_policies(char *buf) |
225 | { |
226 | struct thermal_governor *pos; |
227 | ssize_t count = 0; |
228 | |
229 | mutex_lock(&thermal_governor_lock); |
230 | |
231 | list_for_each_entry(pos, &thermal_governor_list, governor_list) { |
232 | count += sysfs_emit_at(buf, at: count, fmt: "%s " , pos->name); |
233 | } |
234 | count += sysfs_emit_at(buf, at: count, fmt: "\n" ); |
235 | |
236 | mutex_unlock(lock: &thermal_governor_lock); |
237 | |
238 | return count; |
239 | } |
240 | |
241 | static void __init thermal_unregister_governors(void) |
242 | { |
243 | struct thermal_governor **governor; |
244 | |
245 | for_each_governor_table(governor) |
246 | thermal_unregister_governor(governor: *governor); |
247 | } |
248 | |
249 | static int __init thermal_register_governors(void) |
250 | { |
251 | int ret = 0; |
252 | struct thermal_governor **governor; |
253 | |
254 | for_each_governor_table(governor) { |
255 | ret = thermal_register_governor(governor: *governor); |
256 | if (ret) { |
257 | pr_err("Failed to register governor: '%s'" , |
258 | (*governor)->name); |
259 | break; |
260 | } |
261 | |
262 | pr_info("Registered thermal governor '%s'" , |
263 | (*governor)->name); |
264 | } |
265 | |
266 | if (ret) { |
267 | struct thermal_governor **gov; |
268 | |
269 | for_each_governor_table(gov) { |
270 | if (gov == governor) |
271 | break; |
272 | thermal_unregister_governor(governor: *gov); |
273 | } |
274 | } |
275 | |
276 | return ret; |
277 | } |
278 | |
279 | /* |
280 | * Zone update section: main control loop applied to each zone while monitoring |
281 | * |
282 | * in polling mode. The monitoring is done using a workqueue. |
283 | * Same update may be done on a zone by calling thermal_zone_device_update(). |
284 | * |
285 | * An update means: |
286 | * - Non-critical trips will invoke the governor responsible for that zone; |
287 | * - Hot trips will produce a notification to userspace; |
288 | * - Critical trip point will cause a system shutdown. |
289 | */ |
290 | static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, |
291 | unsigned long delay) |
292 | { |
293 | if (delay) |
294 | mod_delayed_work(wq: system_freezable_power_efficient_wq, |
295 | dwork: &tz->poll_queue, delay); |
296 | else |
297 | cancel_delayed_work(dwork: &tz->poll_queue); |
298 | } |
299 | |
300 | static void monitor_thermal_zone(struct thermal_zone_device *tz) |
301 | { |
302 | if (tz->mode != THERMAL_DEVICE_ENABLED) |
303 | thermal_zone_device_set_polling(tz, delay: 0); |
304 | else if (tz->passive) |
305 | thermal_zone_device_set_polling(tz, delay: tz->passive_delay_jiffies); |
306 | else if (tz->polling_delay_jiffies) |
307 | thermal_zone_device_set_polling(tz, delay: tz->polling_delay_jiffies); |
308 | } |
309 | |
310 | static void handle_non_critical_trips(struct thermal_zone_device *tz, |
311 | const struct thermal_trip *trip) |
312 | { |
313 | tz->governor ? tz->governor->throttle(tz, trip) : |
314 | def_governor->throttle(tz, trip); |
315 | } |
316 | |
317 | void thermal_zone_device_critical(struct thermal_zone_device *tz) |
318 | { |
319 | /* |
320 | * poweroff_delay_ms must be a carefully profiled positive value. |
321 | * Its a must for forced_emergency_poweroff_work to be scheduled. |
322 | */ |
323 | int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS; |
324 | |
325 | dev_emerg(&tz->device, "%s: critical temperature reached, " |
326 | "shutting down\n" , tz->type); |
327 | |
328 | hw_protection_shutdown(reason: "Temperature too high" , ms_until_forced: poweroff_delay_ms); |
329 | } |
330 | EXPORT_SYMBOL(thermal_zone_device_critical); |
331 | |
332 | static void handle_critical_trips(struct thermal_zone_device *tz, |
333 | const struct thermal_trip *trip) |
334 | { |
335 | /* If we have not crossed the trip_temp, we do not care. */ |
336 | if (trip->temperature <= 0 || tz->temperature < trip->temperature) |
337 | return; |
338 | |
339 | trace_thermal_zone_trip(tz, trip: thermal_zone_trip_id(tz, trip), trip_type: trip->type); |
340 | |
341 | if (trip->type == THERMAL_TRIP_CRITICAL) |
342 | tz->ops->critical(tz); |
343 | else if (tz->ops->hot) |
344 | tz->ops->hot(tz); |
345 | } |
346 | |
347 | static void handle_thermal_trip(struct thermal_zone_device *tz, |
348 | const struct thermal_trip *trip) |
349 | { |
350 | if (trip->temperature == THERMAL_TEMP_INVALID) |
351 | return; |
352 | |
353 | if (tz->last_temperature != THERMAL_TEMP_INVALID) { |
354 | if (tz->last_temperature < trip->temperature && |
355 | tz->temperature >= trip->temperature) |
356 | thermal_notify_tz_trip_up(tz_id: tz->id, |
357 | id: thermal_zone_trip_id(tz, trip), |
358 | temp: tz->temperature); |
359 | if (tz->last_temperature >= trip->temperature && |
360 | tz->temperature < trip->temperature - trip->hysteresis) |
361 | thermal_notify_tz_trip_down(tz_id: tz->id, |
362 | id: thermal_zone_trip_id(tz, trip), |
363 | temp: tz->temperature); |
364 | } |
365 | |
366 | if (trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) |
367 | handle_critical_trips(tz, trip); |
368 | else |
369 | handle_non_critical_trips(tz, trip); |
370 | } |
371 | |
372 | static void update_temperature(struct thermal_zone_device *tz) |
373 | { |
374 | int temp, ret; |
375 | |
376 | ret = __thermal_zone_get_temp(tz, temp: &temp); |
377 | if (ret) { |
378 | if (ret != -EAGAIN) |
379 | dev_warn(&tz->device, |
380 | "failed to read out thermal zone (%d)\n" , |
381 | ret); |
382 | return; |
383 | } |
384 | |
385 | tz->last_temperature = tz->temperature; |
386 | tz->temperature = temp; |
387 | |
388 | trace_thermal_temperature(tz); |
389 | |
390 | thermal_genl_sampling_temp(id: tz->id, temp); |
391 | } |
392 | |
393 | static void thermal_zone_device_init(struct thermal_zone_device *tz) |
394 | { |
395 | struct thermal_instance *pos; |
396 | tz->temperature = THERMAL_TEMP_INVALID; |
397 | tz->prev_low_trip = -INT_MAX; |
398 | tz->prev_high_trip = INT_MAX; |
399 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) |
400 | pos->initialized = false; |
401 | } |
402 | |
403 | void __thermal_zone_device_update(struct thermal_zone_device *tz, |
404 | enum thermal_notify_event event) |
405 | { |
406 | const struct thermal_trip *trip; |
407 | |
408 | if (atomic_read(v: &in_suspend)) |
409 | return; |
410 | |
411 | if (WARN_ONCE(!tz->ops->get_temp, |
412 | "'%s' must not be called without 'get_temp' ops set\n" , |
413 | __func__)) |
414 | return; |
415 | |
416 | if (!thermal_zone_device_is_enabled(tz)) |
417 | return; |
418 | |
419 | update_temperature(tz); |
420 | |
421 | __thermal_zone_set_trips(tz); |
422 | |
423 | tz->notify_event = event; |
424 | |
425 | for_each_trip(tz, trip) |
426 | handle_thermal_trip(tz, trip); |
427 | |
428 | monitor_thermal_zone(tz); |
429 | } |
430 | |
431 | static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, |
432 | enum thermal_device_mode mode) |
433 | { |
434 | int ret = 0; |
435 | |
436 | mutex_lock(&tz->lock); |
437 | |
438 | /* do nothing if mode isn't changing */ |
439 | if (mode == tz->mode) { |
440 | mutex_unlock(lock: &tz->lock); |
441 | |
442 | return ret; |
443 | } |
444 | |
445 | if (!device_is_registered(dev: &tz->device)) { |
446 | mutex_unlock(lock: &tz->lock); |
447 | |
448 | return -ENODEV; |
449 | } |
450 | |
451 | if (tz->ops->change_mode) |
452 | ret = tz->ops->change_mode(tz, mode); |
453 | |
454 | if (!ret) |
455 | tz->mode = mode; |
456 | |
457 | __thermal_zone_device_update(tz, event: THERMAL_EVENT_UNSPECIFIED); |
458 | |
459 | mutex_unlock(lock: &tz->lock); |
460 | |
461 | if (mode == THERMAL_DEVICE_ENABLED) |
462 | thermal_notify_tz_enable(tz_id: tz->id); |
463 | else |
464 | thermal_notify_tz_disable(tz_id: tz->id); |
465 | |
466 | return ret; |
467 | } |
468 | |
469 | int thermal_zone_device_enable(struct thermal_zone_device *tz) |
470 | { |
471 | return thermal_zone_device_set_mode(tz, mode: THERMAL_DEVICE_ENABLED); |
472 | } |
473 | EXPORT_SYMBOL_GPL(thermal_zone_device_enable); |
474 | |
475 | int thermal_zone_device_disable(struct thermal_zone_device *tz) |
476 | { |
477 | return thermal_zone_device_set_mode(tz, mode: THERMAL_DEVICE_DISABLED); |
478 | } |
479 | EXPORT_SYMBOL_GPL(thermal_zone_device_disable); |
480 | |
481 | int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) |
482 | { |
483 | lockdep_assert_held(&tz->lock); |
484 | |
485 | return tz->mode == THERMAL_DEVICE_ENABLED; |
486 | } |
487 | |
488 | void thermal_zone_device_update(struct thermal_zone_device *tz, |
489 | enum thermal_notify_event event) |
490 | { |
491 | mutex_lock(&tz->lock); |
492 | if (device_is_registered(dev: &tz->device)) |
493 | __thermal_zone_device_update(tz, event); |
494 | mutex_unlock(lock: &tz->lock); |
495 | } |
496 | EXPORT_SYMBOL_GPL(thermal_zone_device_update); |
497 | |
498 | static void thermal_zone_device_check(struct work_struct *work) |
499 | { |
500 | struct thermal_zone_device *tz = container_of(work, struct |
501 | thermal_zone_device, |
502 | poll_queue.work); |
503 | thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); |
504 | } |
505 | |
506 | int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), |
507 | void *data) |
508 | { |
509 | struct thermal_governor *gov; |
510 | int ret = 0; |
511 | |
512 | mutex_lock(&thermal_governor_lock); |
513 | list_for_each_entry(gov, &thermal_governor_list, governor_list) { |
514 | ret = cb(gov, data); |
515 | if (ret) |
516 | break; |
517 | } |
518 | mutex_unlock(lock: &thermal_governor_lock); |
519 | |
520 | return ret; |
521 | } |
522 | |
523 | int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, |
524 | void *), void *data) |
525 | { |
526 | struct thermal_cooling_device *cdev; |
527 | int ret = 0; |
528 | |
529 | mutex_lock(&thermal_list_lock); |
530 | list_for_each_entry(cdev, &thermal_cdev_list, node) { |
531 | ret = cb(cdev, data); |
532 | if (ret) |
533 | break; |
534 | } |
535 | mutex_unlock(lock: &thermal_list_lock); |
536 | |
537 | return ret; |
538 | } |
539 | |
540 | int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), |
541 | void *data) |
542 | { |
543 | struct thermal_zone_device *tz; |
544 | int ret = 0; |
545 | |
546 | mutex_lock(&thermal_list_lock); |
547 | list_for_each_entry(tz, &thermal_tz_list, node) { |
548 | ret = cb(tz, data); |
549 | if (ret) |
550 | break; |
551 | } |
552 | mutex_unlock(lock: &thermal_list_lock); |
553 | |
554 | return ret; |
555 | } |
556 | |
557 | struct thermal_zone_device *thermal_zone_get_by_id(int id) |
558 | { |
559 | struct thermal_zone_device *tz, *match = NULL; |
560 | |
561 | mutex_lock(&thermal_list_lock); |
562 | list_for_each_entry(tz, &thermal_tz_list, node) { |
563 | if (tz->id == id) { |
564 | match = tz; |
565 | break; |
566 | } |
567 | } |
568 | mutex_unlock(lock: &thermal_list_lock); |
569 | |
570 | return match; |
571 | } |
572 | |
573 | /* |
574 | * Device management section: cooling devices, zones devices, and binding |
575 | * |
576 | * Set of functions provided by the thermal core for: |
577 | * - cooling devices lifecycle: registration, unregistration, |
578 | * binding, and unbinding. |
579 | * - thermal zone devices lifecycle: registration, unregistration, |
580 | * binding, and unbinding. |
581 | */ |
582 | |
583 | /** |
584 | * thermal_bind_cdev_to_trip - bind a cooling device to a thermal zone |
585 | * @tz: pointer to struct thermal_zone_device |
586 | * @trip: trip point the cooling devices is associated with in this zone. |
587 | * @cdev: pointer to struct thermal_cooling_device |
588 | * @upper: the Maximum cooling state for this trip point. |
589 | * THERMAL_NO_LIMIT means no upper limit, |
590 | * and the cooling device can be in max_state. |
591 | * @lower: the Minimum cooling state can be used for this trip point. |
592 | * THERMAL_NO_LIMIT means no lower limit, |
593 | * and the cooling device can be in cooling state 0. |
594 | * @weight: The weight of the cooling device to be bound to the |
595 | * thermal zone. Use THERMAL_WEIGHT_DEFAULT for the |
596 | * default value |
597 | * |
598 | * This interface function bind a thermal cooling device to the certain trip |
599 | * point of a thermal zone device. |
600 | * This function is usually called in the thermal zone device .bind callback. |
601 | * |
602 | * Return: 0 on success, the proper error value otherwise. |
603 | */ |
604 | int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, |
605 | const struct thermal_trip *trip, |
606 | struct thermal_cooling_device *cdev, |
607 | unsigned long upper, unsigned long lower, |
608 | unsigned int weight) |
609 | { |
610 | struct thermal_instance *dev; |
611 | struct thermal_instance *pos; |
612 | struct thermal_zone_device *pos1; |
613 | struct thermal_cooling_device *pos2; |
614 | bool upper_no_limit; |
615 | int result; |
616 | |
617 | list_for_each_entry(pos1, &thermal_tz_list, node) { |
618 | if (pos1 == tz) |
619 | break; |
620 | } |
621 | list_for_each_entry(pos2, &thermal_cdev_list, node) { |
622 | if (pos2 == cdev) |
623 | break; |
624 | } |
625 | |
626 | if (tz != pos1 || cdev != pos2) |
627 | return -EINVAL; |
628 | |
629 | /* lower default 0, upper default max_state */ |
630 | lower = lower == THERMAL_NO_LIMIT ? 0 : lower; |
631 | |
632 | if (upper == THERMAL_NO_LIMIT) { |
633 | upper = cdev->max_state; |
634 | upper_no_limit = true; |
635 | } else { |
636 | upper_no_limit = false; |
637 | } |
638 | |
639 | if (lower > upper || upper > cdev->max_state) |
640 | return -EINVAL; |
641 | |
642 | dev = kzalloc(size: sizeof(*dev), GFP_KERNEL); |
643 | if (!dev) |
644 | return -ENOMEM; |
645 | dev->tz = tz; |
646 | dev->cdev = cdev; |
647 | dev->trip = trip; |
648 | dev->upper = upper; |
649 | dev->upper_no_limit = upper_no_limit; |
650 | dev->lower = lower; |
651 | dev->target = THERMAL_NO_TARGET; |
652 | dev->weight = weight; |
653 | |
654 | result = ida_alloc(ida: &tz->ida, GFP_KERNEL); |
655 | if (result < 0) |
656 | goto free_mem; |
657 | |
658 | dev->id = result; |
659 | sprintf(buf: dev->name, fmt: "cdev%d" , dev->id); |
660 | result = |
661 | sysfs_create_link(kobj: &tz->device.kobj, target: &cdev->device.kobj, name: dev->name); |
662 | if (result) |
663 | goto release_ida; |
664 | |
665 | snprintf(buf: dev->attr_name, size: sizeof(dev->attr_name), fmt: "cdev%d_trip_point" , |
666 | dev->id); |
667 | sysfs_attr_init(&dev->attr.attr); |
668 | dev->attr.attr.name = dev->attr_name; |
669 | dev->attr.attr.mode = 0444; |
670 | dev->attr.show = trip_point_show; |
671 | result = device_create_file(device: &tz->device, entry: &dev->attr); |
672 | if (result) |
673 | goto remove_symbol_link; |
674 | |
675 | snprintf(buf: dev->weight_attr_name, size: sizeof(dev->weight_attr_name), |
676 | fmt: "cdev%d_weight" , dev->id); |
677 | sysfs_attr_init(&dev->weight_attr.attr); |
678 | dev->weight_attr.attr.name = dev->weight_attr_name; |
679 | dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO; |
680 | dev->weight_attr.show = weight_show; |
681 | dev->weight_attr.store = weight_store; |
682 | result = device_create_file(device: &tz->device, entry: &dev->weight_attr); |
683 | if (result) |
684 | goto remove_trip_file; |
685 | |
686 | mutex_lock(&tz->lock); |
687 | mutex_lock(&cdev->lock); |
688 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) |
689 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
690 | result = -EEXIST; |
691 | break; |
692 | } |
693 | if (!result) { |
694 | list_add_tail(new: &dev->tz_node, head: &tz->thermal_instances); |
695 | list_add_tail(new: &dev->cdev_node, head: &cdev->thermal_instances); |
696 | atomic_set(v: &tz->need_update, i: 1); |
697 | } |
698 | mutex_unlock(lock: &cdev->lock); |
699 | mutex_unlock(lock: &tz->lock); |
700 | |
701 | if (!result) |
702 | return 0; |
703 | |
704 | device_remove_file(dev: &tz->device, attr: &dev->weight_attr); |
705 | remove_trip_file: |
706 | device_remove_file(dev: &tz->device, attr: &dev->attr); |
707 | remove_symbol_link: |
708 | sysfs_remove_link(kobj: &tz->device.kobj, name: dev->name); |
709 | release_ida: |
710 | ida_free(&tz->ida, id: dev->id); |
711 | free_mem: |
712 | kfree(objp: dev); |
713 | return result; |
714 | } |
715 | EXPORT_SYMBOL_GPL(thermal_bind_cdev_to_trip); |
716 | |
717 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, |
718 | int trip_index, |
719 | struct thermal_cooling_device *cdev, |
720 | unsigned long upper, unsigned long lower, |
721 | unsigned int weight) |
722 | { |
723 | if (trip_index < 0 || trip_index >= tz->num_trips) |
724 | return -EINVAL; |
725 | |
726 | return thermal_bind_cdev_to_trip(tz, &tz->trips[trip_index], cdev, |
727 | upper, lower, weight); |
728 | } |
729 | EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); |
730 | |
731 | /** |
732 | * thermal_unbind_cdev_from_trip - unbind a cooling device from a thermal zone. |
733 | * @tz: pointer to a struct thermal_zone_device. |
734 | * @trip: trip point the cooling devices is associated with in this zone. |
735 | * @cdev: pointer to a struct thermal_cooling_device. |
736 | * |
737 | * This interface function unbind a thermal cooling device from the certain |
738 | * trip point of a thermal zone device. |
739 | * This function is usually called in the thermal zone device .unbind callback. |
740 | * |
741 | * Return: 0 on success, the proper error value otherwise. |
742 | */ |
743 | int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, |
744 | const struct thermal_trip *trip, |
745 | struct thermal_cooling_device *cdev) |
746 | { |
747 | struct thermal_instance *pos, *next; |
748 | |
749 | mutex_lock(&tz->lock); |
750 | mutex_lock(&cdev->lock); |
751 | list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { |
752 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
753 | list_del(entry: &pos->tz_node); |
754 | list_del(entry: &pos->cdev_node); |
755 | mutex_unlock(lock: &cdev->lock); |
756 | mutex_unlock(lock: &tz->lock); |
757 | goto unbind; |
758 | } |
759 | } |
760 | mutex_unlock(lock: &cdev->lock); |
761 | mutex_unlock(lock: &tz->lock); |
762 | |
763 | return -ENODEV; |
764 | |
765 | unbind: |
766 | device_remove_file(dev: &tz->device, attr: &pos->weight_attr); |
767 | device_remove_file(dev: &tz->device, attr: &pos->attr); |
768 | sysfs_remove_link(kobj: &tz->device.kobj, name: pos->name); |
769 | ida_free(&tz->ida, id: pos->id); |
770 | kfree(objp: pos); |
771 | return 0; |
772 | } |
773 | EXPORT_SYMBOL_GPL(thermal_unbind_cdev_from_trip); |
774 | |
775 | int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, |
776 | int trip_index, |
777 | struct thermal_cooling_device *cdev) |
778 | { |
779 | if (trip_index < 0 || trip_index >= tz->num_trips) |
780 | return -EINVAL; |
781 | |
782 | return thermal_unbind_cdev_from_trip(tz, &tz->trips[trip_index], cdev); |
783 | } |
784 | EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); |
785 | |
786 | static void thermal_release(struct device *dev) |
787 | { |
788 | struct thermal_zone_device *tz; |
789 | struct thermal_cooling_device *cdev; |
790 | |
791 | if (!strncmp(dev_name(dev), "thermal_zone" , |
792 | sizeof("thermal_zone" ) - 1)) { |
793 | tz = to_thermal_zone(dev); |
794 | thermal_zone_destroy_device_groups(tz); |
795 | mutex_destroy(lock: &tz->lock); |
796 | kfree(objp: tz); |
797 | } else if (!strncmp(dev_name(dev), "cooling_device" , |
798 | sizeof("cooling_device" ) - 1)) { |
799 | cdev = to_cooling_device(dev); |
800 | thermal_cooling_device_destroy_sysfs(cdev); |
801 | kfree(objp: cdev->type); |
802 | ida_free(&thermal_cdev_ida, id: cdev->id); |
803 | kfree(objp: cdev); |
804 | } |
805 | } |
806 | |
807 | static struct class *thermal_class; |
808 | |
809 | static inline |
810 | void print_bind_err_msg(struct thermal_zone_device *tz, |
811 | struct thermal_cooling_device *cdev, int ret) |
812 | { |
813 | dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n" , |
814 | tz->type, cdev->type, ret); |
815 | } |
816 | |
817 | static void bind_cdev(struct thermal_cooling_device *cdev) |
818 | { |
819 | int ret; |
820 | struct thermal_zone_device *pos = NULL; |
821 | |
822 | list_for_each_entry(pos, &thermal_tz_list, node) { |
823 | if (pos->ops->bind) { |
824 | ret = pos->ops->bind(pos, cdev); |
825 | if (ret) |
826 | print_bind_err_msg(tz: pos, cdev, ret); |
827 | } |
828 | } |
829 | } |
830 | |
831 | /** |
832 | * __thermal_cooling_device_register() - register a new thermal cooling device |
833 | * @np: a pointer to a device tree node. |
834 | * @type: the thermal cooling device type. |
835 | * @devdata: device private data. |
836 | * @ops: standard thermal cooling devices callbacks. |
837 | * |
838 | * This interface function adds a new thermal cooling device (fan/processor/...) |
839 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself |
840 | * to all the thermal zone devices registered at the same time. |
841 | * It also gives the opportunity to link the cooling device to a device tree |
842 | * node, so that it can be bound to a thermal zone created out of device tree. |
843 | * |
844 | * Return: a pointer to the created struct thermal_cooling_device or an |
845 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. |
846 | */ |
847 | static struct thermal_cooling_device * |
848 | __thermal_cooling_device_register(struct device_node *np, |
849 | const char *type, void *devdata, |
850 | const struct thermal_cooling_device_ops *ops) |
851 | { |
852 | struct thermal_cooling_device *cdev; |
853 | struct thermal_zone_device *pos = NULL; |
854 | int id, ret; |
855 | |
856 | if (!ops || !ops->get_max_state || !ops->get_cur_state || |
857 | !ops->set_cur_state) |
858 | return ERR_PTR(error: -EINVAL); |
859 | |
860 | if (!thermal_class) |
861 | return ERR_PTR(error: -ENODEV); |
862 | |
863 | cdev = kzalloc(size: sizeof(*cdev), GFP_KERNEL); |
864 | if (!cdev) |
865 | return ERR_PTR(error: -ENOMEM); |
866 | |
867 | ret = ida_alloc(ida: &thermal_cdev_ida, GFP_KERNEL); |
868 | if (ret < 0) |
869 | goto out_kfree_cdev; |
870 | cdev->id = ret; |
871 | id = ret; |
872 | |
873 | cdev->type = kstrdup(s: type ? type : "" , GFP_KERNEL); |
874 | if (!cdev->type) { |
875 | ret = -ENOMEM; |
876 | goto out_ida_remove; |
877 | } |
878 | |
879 | mutex_init(&cdev->lock); |
880 | INIT_LIST_HEAD(list: &cdev->thermal_instances); |
881 | cdev->np = np; |
882 | cdev->ops = ops; |
883 | cdev->updated = false; |
884 | cdev->device.class = thermal_class; |
885 | cdev->devdata = devdata; |
886 | |
887 | ret = cdev->ops->get_max_state(cdev, &cdev->max_state); |
888 | if (ret) |
889 | goto out_cdev_type; |
890 | |
891 | thermal_cooling_device_setup_sysfs(cdev); |
892 | |
893 | ret = dev_set_name(dev: &cdev->device, name: "cooling_device%d" , cdev->id); |
894 | if (ret) |
895 | goto out_cooling_dev; |
896 | |
897 | ret = device_register(dev: &cdev->device); |
898 | if (ret) { |
899 | /* thermal_release() handles rest of the cleanup */ |
900 | put_device(dev: &cdev->device); |
901 | return ERR_PTR(error: ret); |
902 | } |
903 | |
904 | /* Add 'this' new cdev to the global cdev list */ |
905 | mutex_lock(&thermal_list_lock); |
906 | |
907 | list_add(new: &cdev->node, head: &thermal_cdev_list); |
908 | |
909 | /* Update binding information for 'this' new cdev */ |
910 | bind_cdev(cdev); |
911 | |
912 | list_for_each_entry(pos, &thermal_tz_list, node) |
913 | if (atomic_cmpxchg(v: &pos->need_update, old: 1, new: 0)) |
914 | thermal_zone_device_update(pos, |
915 | THERMAL_EVENT_UNSPECIFIED); |
916 | |
917 | mutex_unlock(lock: &thermal_list_lock); |
918 | |
919 | return cdev; |
920 | |
921 | out_cooling_dev: |
922 | thermal_cooling_device_destroy_sysfs(cdev); |
923 | out_cdev_type: |
924 | kfree(objp: cdev->type); |
925 | out_ida_remove: |
926 | ida_free(&thermal_cdev_ida, id); |
927 | out_kfree_cdev: |
928 | kfree(objp: cdev); |
929 | return ERR_PTR(error: ret); |
930 | } |
931 | |
932 | /** |
933 | * thermal_cooling_device_register() - register a new thermal cooling device |
934 | * @type: the thermal cooling device type. |
935 | * @devdata: device private data. |
936 | * @ops: standard thermal cooling devices callbacks. |
937 | * |
938 | * This interface function adds a new thermal cooling device (fan/processor/...) |
939 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself |
940 | * to all the thermal zone devices registered at the same time. |
941 | * |
942 | * Return: a pointer to the created struct thermal_cooling_device or an |
943 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. |
944 | */ |
945 | struct thermal_cooling_device * |
946 | thermal_cooling_device_register(const char *type, void *devdata, |
947 | const struct thermal_cooling_device_ops *ops) |
948 | { |
949 | return __thermal_cooling_device_register(NULL, type, devdata, ops); |
950 | } |
951 | EXPORT_SYMBOL_GPL(thermal_cooling_device_register); |
952 | |
953 | /** |
954 | * thermal_of_cooling_device_register() - register an OF thermal cooling device |
955 | * @np: a pointer to a device tree node. |
956 | * @type: the thermal cooling device type. |
957 | * @devdata: device private data. |
958 | * @ops: standard thermal cooling devices callbacks. |
959 | * |
960 | * This function will register a cooling device with device tree node reference. |
961 | * This interface function adds a new thermal cooling device (fan/processor/...) |
962 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself |
963 | * to all the thermal zone devices registered at the same time. |
964 | * |
965 | * Return: a pointer to the created struct thermal_cooling_device or an |
966 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. |
967 | */ |
968 | struct thermal_cooling_device * |
969 | thermal_of_cooling_device_register(struct device_node *np, |
970 | const char *type, void *devdata, |
971 | const struct thermal_cooling_device_ops *ops) |
972 | { |
973 | return __thermal_cooling_device_register(np, type, devdata, ops); |
974 | } |
975 | EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register); |
976 | |
977 | static void thermal_cooling_device_release(struct device *dev, void *res) |
978 | { |
979 | thermal_cooling_device_unregister( |
980 | *(struct thermal_cooling_device **)res); |
981 | } |
982 | |
983 | /** |
984 | * devm_thermal_of_cooling_device_register() - register an OF thermal cooling |
985 | * device |
986 | * @dev: a valid struct device pointer of a sensor device. |
987 | * @np: a pointer to a device tree node. |
988 | * @type: the thermal cooling device type. |
989 | * @devdata: device private data. |
990 | * @ops: standard thermal cooling devices callbacks. |
991 | * |
992 | * This function will register a cooling device with device tree node reference. |
993 | * This interface function adds a new thermal cooling device (fan/processor/...) |
994 | * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself |
995 | * to all the thermal zone devices registered at the same time. |
996 | * |
997 | * Return: a pointer to the created struct thermal_cooling_device or an |
998 | * ERR_PTR. Caller must check return value with IS_ERR*() helpers. |
999 | */ |
1000 | struct thermal_cooling_device * |
1001 | devm_thermal_of_cooling_device_register(struct device *dev, |
1002 | struct device_node *np, |
1003 | char *type, void *devdata, |
1004 | const struct thermal_cooling_device_ops *ops) |
1005 | { |
1006 | struct thermal_cooling_device **ptr, *tcd; |
1007 | |
1008 | ptr = devres_alloc(thermal_cooling_device_release, sizeof(*ptr), |
1009 | GFP_KERNEL); |
1010 | if (!ptr) |
1011 | return ERR_PTR(error: -ENOMEM); |
1012 | |
1013 | tcd = __thermal_cooling_device_register(np, type, devdata, ops); |
1014 | if (IS_ERR(ptr: tcd)) { |
1015 | devres_free(res: ptr); |
1016 | return tcd; |
1017 | } |
1018 | |
1019 | *ptr = tcd; |
1020 | devres_add(dev, res: ptr); |
1021 | |
1022 | return tcd; |
1023 | } |
1024 | EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register); |
1025 | |
1026 | static bool thermal_cooling_device_present(struct thermal_cooling_device *cdev) |
1027 | { |
1028 | struct thermal_cooling_device *pos = NULL; |
1029 | |
1030 | list_for_each_entry(pos, &thermal_cdev_list, node) { |
1031 | if (pos == cdev) |
1032 | return true; |
1033 | } |
1034 | |
1035 | return false; |
1036 | } |
1037 | |
1038 | /** |
1039 | * thermal_cooling_device_update - Update a cooling device object |
1040 | * @cdev: Target cooling device. |
1041 | * |
1042 | * Update @cdev to reflect a change of the underlying hardware or platform. |
1043 | * |
1044 | * Must be called when the maximum cooling state of @cdev becomes invalid and so |
1045 | * its .get_max_state() callback needs to be run to produce the new maximum |
1046 | * cooling state value. |
1047 | */ |
1048 | void thermal_cooling_device_update(struct thermal_cooling_device *cdev) |
1049 | { |
1050 | struct thermal_instance *ti; |
1051 | unsigned long state; |
1052 | |
1053 | if (IS_ERR_OR_NULL(ptr: cdev)) |
1054 | return; |
1055 | |
1056 | /* |
1057 | * Hold thermal_list_lock throughout the update to prevent the device |
1058 | * from going away while being updated. |
1059 | */ |
1060 | mutex_lock(&thermal_list_lock); |
1061 | |
1062 | if (!thermal_cooling_device_present(cdev)) |
1063 | goto unlock_list; |
1064 | |
1065 | /* |
1066 | * Update under the cdev lock to prevent the state from being set beyond |
1067 | * the new limit concurrently. |
1068 | */ |
1069 | mutex_lock(&cdev->lock); |
1070 | |
1071 | if (cdev->ops->get_max_state(cdev, &cdev->max_state)) |
1072 | goto unlock; |
1073 | |
1074 | thermal_cooling_device_stats_reinit(cdev); |
1075 | |
1076 | list_for_each_entry(ti, &cdev->thermal_instances, cdev_node) { |
1077 | if (ti->upper == cdev->max_state) |
1078 | continue; |
1079 | |
1080 | if (ti->upper < cdev->max_state) { |
1081 | if (ti->upper_no_limit) |
1082 | ti->upper = cdev->max_state; |
1083 | |
1084 | continue; |
1085 | } |
1086 | |
1087 | ti->upper = cdev->max_state; |
1088 | if (ti->lower > ti->upper) |
1089 | ti->lower = ti->upper; |
1090 | |
1091 | if (ti->target == THERMAL_NO_TARGET) |
1092 | continue; |
1093 | |
1094 | if (ti->target > ti->upper) |
1095 | ti->target = ti->upper; |
1096 | } |
1097 | |
1098 | if (cdev->ops->get_cur_state(cdev, &state) || state > cdev->max_state) |
1099 | goto unlock; |
1100 | |
1101 | thermal_cooling_device_stats_update(cdev, new_state: state); |
1102 | |
1103 | unlock: |
1104 | mutex_unlock(lock: &cdev->lock); |
1105 | |
1106 | unlock_list: |
1107 | mutex_unlock(lock: &thermal_list_lock); |
1108 | } |
1109 | EXPORT_SYMBOL_GPL(thermal_cooling_device_update); |
1110 | |
1111 | /** |
1112 | * thermal_cooling_device_unregister - removes a thermal cooling device |
1113 | * @cdev: the thermal cooling device to remove. |
1114 | * |
1115 | * thermal_cooling_device_unregister() must be called when a registered |
1116 | * thermal cooling device is no longer needed. |
1117 | */ |
1118 | void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) |
1119 | { |
1120 | struct thermal_zone_device *tz; |
1121 | |
1122 | if (!cdev) |
1123 | return; |
1124 | |
1125 | mutex_lock(&thermal_list_lock); |
1126 | |
1127 | if (!thermal_cooling_device_present(cdev)) { |
1128 | mutex_unlock(lock: &thermal_list_lock); |
1129 | return; |
1130 | } |
1131 | |
1132 | list_del(entry: &cdev->node); |
1133 | |
1134 | /* Unbind all thermal zones associated with 'this' cdev */ |
1135 | list_for_each_entry(tz, &thermal_tz_list, node) { |
1136 | if (tz->ops->unbind) |
1137 | tz->ops->unbind(tz, cdev); |
1138 | } |
1139 | |
1140 | mutex_unlock(lock: &thermal_list_lock); |
1141 | |
1142 | device_unregister(dev: &cdev->device); |
1143 | } |
1144 | EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); |
1145 | |
1146 | static void bind_tz(struct thermal_zone_device *tz) |
1147 | { |
1148 | int ret; |
1149 | struct thermal_cooling_device *pos = NULL; |
1150 | |
1151 | if (!tz->ops->bind) |
1152 | return; |
1153 | |
1154 | mutex_lock(&thermal_list_lock); |
1155 | |
1156 | list_for_each_entry(pos, &thermal_cdev_list, node) { |
1157 | ret = tz->ops->bind(tz, pos); |
1158 | if (ret) |
1159 | print_bind_err_msg(tz, cdev: pos, ret); |
1160 | } |
1161 | |
1162 | mutex_unlock(lock: &thermal_list_lock); |
1163 | } |
1164 | |
1165 | static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms) |
1166 | { |
1167 | *delay_jiffies = msecs_to_jiffies(m: delay_ms); |
1168 | if (delay_ms > 1000) |
1169 | *delay_jiffies = round_jiffies(j: *delay_jiffies); |
1170 | } |
1171 | |
1172 | int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp) |
1173 | { |
1174 | int i, ret = -EINVAL; |
1175 | |
1176 | if (tz->ops->get_crit_temp) |
1177 | return tz->ops->get_crit_temp(tz, temp); |
1178 | |
1179 | if (!tz->trips) |
1180 | return -EINVAL; |
1181 | |
1182 | mutex_lock(&tz->lock); |
1183 | |
1184 | for (i = 0; i < tz->num_trips; i++) { |
1185 | if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) { |
1186 | *temp = tz->trips[i].temperature; |
1187 | ret = 0; |
1188 | break; |
1189 | } |
1190 | } |
1191 | |
1192 | mutex_unlock(lock: &tz->lock); |
1193 | |
1194 | return ret; |
1195 | } |
1196 | EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp); |
1197 | |
1198 | /** |
1199 | * thermal_zone_device_register_with_trips() - register a new thermal zone device |
1200 | * @type: the thermal zone device type |
1201 | * @trips: a pointer to an array of thermal trips |
1202 | * @num_trips: the number of trip points the thermal zone support |
1203 | * @mask: a bit string indicating the writeablility of trip points |
1204 | * @devdata: private device data |
1205 | * @ops: standard thermal zone device callbacks |
1206 | * @tzp: thermal zone platform parameters |
1207 | * @passive_delay: number of milliseconds to wait between polls when |
1208 | * performing passive cooling |
1209 | * @polling_delay: number of milliseconds to wait between polls when checking |
1210 | * whether trip points have been crossed (0 for interrupt |
1211 | * driven systems) |
1212 | * |
1213 | * This interface function adds a new thermal zone device (sensor) to |
1214 | * /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the |
1215 | * thermal cooling devices registered at the same time. |
1216 | * thermal_zone_device_unregister() must be called when the device is no |
1217 | * longer needed. The passive cooling depends on the .get_trend() return value. |
1218 | * |
1219 | * Return: a pointer to the created struct thermal_zone_device or an |
1220 | * in case of error, an ERR_PTR. Caller must check return value with |
1221 | * IS_ERR*() helpers. |
1222 | */ |
1223 | struct thermal_zone_device * |
1224 | thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask, |
1225 | void *devdata, struct thermal_zone_device_ops *ops, |
1226 | const struct thermal_zone_params *tzp, int passive_delay, |
1227 | int polling_delay) |
1228 | { |
1229 | struct thermal_zone_device *tz; |
1230 | int id; |
1231 | int result; |
1232 | struct thermal_governor *governor; |
1233 | |
1234 | if (!type || strlen(type) == 0) { |
1235 | pr_err("No thermal zone type defined\n" ); |
1236 | return ERR_PTR(error: -EINVAL); |
1237 | } |
1238 | |
1239 | if (strlen(type) >= THERMAL_NAME_LENGTH) { |
1240 | pr_err("Thermal zone name (%s) too long, should be under %d chars\n" , |
1241 | type, THERMAL_NAME_LENGTH); |
1242 | return ERR_PTR(error: -EINVAL); |
1243 | } |
1244 | |
1245 | /* |
1246 | * Max trip count can't exceed 31 as the "mask >> num_trips" condition. |
1247 | * For example, shifting by 32 will result in compiler warning: |
1248 | * warning: right shift count >= width of type [-Wshift-count- overflow] |
1249 | * |
1250 | * Also "mask >> num_trips" will always be true with 32 bit shift. |
1251 | * E.g. mask = 0x80000000 for trip id 31 to be RW. Then |
1252 | * mask >> 32 = 0x80000000 |
1253 | * This will result in failure for the below condition. |
1254 | * |
1255 | * Check will be true when the bit 31 of the mask is set. |
1256 | * 32 bit shift will cause overflow of 4 byte integer. |
1257 | */ |
1258 | if (num_trips > (BITS_PER_TYPE(int) - 1) || num_trips < 0 || mask >> num_trips) { |
1259 | pr_err("Incorrect number of thermal trips\n" ); |
1260 | return ERR_PTR(error: -EINVAL); |
1261 | } |
1262 | |
1263 | if (!ops) { |
1264 | pr_err("Thermal zone device ops not defined\n" ); |
1265 | return ERR_PTR(error: -EINVAL); |
1266 | } |
1267 | |
1268 | if (num_trips > 0 && !trips) |
1269 | return ERR_PTR(error: -EINVAL); |
1270 | |
1271 | if (!thermal_class) |
1272 | return ERR_PTR(error: -ENODEV); |
1273 | |
1274 | tz = kzalloc(size: sizeof(*tz), GFP_KERNEL); |
1275 | if (!tz) |
1276 | return ERR_PTR(error: -ENOMEM); |
1277 | |
1278 | if (tzp) { |
1279 | tz->tzp = kmemdup(p: tzp, size: sizeof(*tzp), GFP_KERNEL); |
1280 | if (!tz->tzp) { |
1281 | result = -ENOMEM; |
1282 | goto free_tz; |
1283 | } |
1284 | } |
1285 | |
1286 | INIT_LIST_HEAD(list: &tz->thermal_instances); |
1287 | ida_init(ida: &tz->ida); |
1288 | mutex_init(&tz->lock); |
1289 | id = ida_alloc(ida: &thermal_tz_ida, GFP_KERNEL); |
1290 | if (id < 0) { |
1291 | result = id; |
1292 | goto free_tzp; |
1293 | } |
1294 | |
1295 | tz->id = id; |
1296 | strscpy(p: tz->type, q: type, size: sizeof(tz->type)); |
1297 | |
1298 | if (!ops->critical) |
1299 | ops->critical = thermal_zone_device_critical; |
1300 | |
1301 | tz->ops = ops; |
1302 | tz->device.class = thermal_class; |
1303 | tz->devdata = devdata; |
1304 | tz->trips = trips; |
1305 | tz->num_trips = num_trips; |
1306 | |
1307 | thermal_set_delay_jiffies(delay_jiffies: &tz->passive_delay_jiffies, delay_ms: passive_delay); |
1308 | thermal_set_delay_jiffies(delay_jiffies: &tz->polling_delay_jiffies, delay_ms: polling_delay); |
1309 | |
1310 | /* sys I/F */ |
1311 | /* Add nodes that are always present via .groups */ |
1312 | result = thermal_zone_create_device_groups(tz, mask); |
1313 | if (result) |
1314 | goto remove_id; |
1315 | |
1316 | /* A new thermal zone needs to be updated anyway. */ |
1317 | atomic_set(v: &tz->need_update, i: 1); |
1318 | |
1319 | result = dev_set_name(dev: &tz->device, name: "thermal_zone%d" , tz->id); |
1320 | if (result) { |
1321 | thermal_zone_destroy_device_groups(tz); |
1322 | goto remove_id; |
1323 | } |
1324 | result = device_register(dev: &tz->device); |
1325 | if (result) |
1326 | goto release_device; |
1327 | |
1328 | /* Update 'this' zone's governor information */ |
1329 | mutex_lock(&thermal_governor_lock); |
1330 | |
1331 | if (tz->tzp) |
1332 | governor = __find_governor(name: tz->tzp->governor_name); |
1333 | else |
1334 | governor = def_governor; |
1335 | |
1336 | result = thermal_set_governor(tz, new_gov: governor); |
1337 | if (result) { |
1338 | mutex_unlock(lock: &thermal_governor_lock); |
1339 | goto unregister; |
1340 | } |
1341 | |
1342 | mutex_unlock(lock: &thermal_governor_lock); |
1343 | |
1344 | if (!tz->tzp || !tz->tzp->no_hwmon) { |
1345 | result = thermal_add_hwmon_sysfs(tz); |
1346 | if (result) |
1347 | goto unregister; |
1348 | } |
1349 | |
1350 | mutex_lock(&thermal_list_lock); |
1351 | list_add_tail(new: &tz->node, head: &thermal_tz_list); |
1352 | mutex_unlock(lock: &thermal_list_lock); |
1353 | |
1354 | /* Bind cooling devices for this zone */ |
1355 | bind_tz(tz); |
1356 | |
1357 | INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); |
1358 | |
1359 | thermal_zone_device_init(tz); |
1360 | /* Update the new thermal zone and mark it as already updated. */ |
1361 | if (atomic_cmpxchg(v: &tz->need_update, old: 1, new: 0)) |
1362 | thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); |
1363 | |
1364 | thermal_notify_tz_create(tz_id: tz->id, name: tz->type); |
1365 | |
1366 | return tz; |
1367 | |
1368 | unregister: |
1369 | device_del(dev: &tz->device); |
1370 | release_device: |
1371 | put_device(dev: &tz->device); |
1372 | tz = NULL; |
1373 | remove_id: |
1374 | ida_free(&thermal_tz_ida, id); |
1375 | free_tzp: |
1376 | kfree(objp: tz->tzp); |
1377 | free_tz: |
1378 | kfree(objp: tz); |
1379 | return ERR_PTR(error: result); |
1380 | } |
1381 | EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips); |
1382 | |
1383 | struct thermal_zone_device *thermal_tripless_zone_device_register( |
1384 | const char *type, |
1385 | void *devdata, |
1386 | struct thermal_zone_device_ops *ops, |
1387 | const struct thermal_zone_params *tzp) |
1388 | { |
1389 | return thermal_zone_device_register_with_trips(type, NULL, 0, 0, devdata, |
1390 | ops, tzp, 0, 0); |
1391 | } |
1392 | EXPORT_SYMBOL_GPL(thermal_tripless_zone_device_register); |
1393 | |
1394 | void *thermal_zone_device_priv(struct thermal_zone_device *tzd) |
1395 | { |
1396 | return tzd->devdata; |
1397 | } |
1398 | EXPORT_SYMBOL_GPL(thermal_zone_device_priv); |
1399 | |
1400 | const char *thermal_zone_device_type(struct thermal_zone_device *tzd) |
1401 | { |
1402 | return tzd->type; |
1403 | } |
1404 | EXPORT_SYMBOL_GPL(thermal_zone_device_type); |
1405 | |
1406 | int thermal_zone_device_id(struct thermal_zone_device *tzd) |
1407 | { |
1408 | return tzd->id; |
1409 | } |
1410 | EXPORT_SYMBOL_GPL(thermal_zone_device_id); |
1411 | |
1412 | struct device *thermal_zone_device(struct thermal_zone_device *tzd) |
1413 | { |
1414 | return &tzd->device; |
1415 | } |
1416 | EXPORT_SYMBOL_GPL(thermal_zone_device); |
1417 | |
1418 | /** |
1419 | * thermal_zone_device_unregister - removes the registered thermal zone device |
1420 | * @tz: the thermal zone device to remove |
1421 | */ |
1422 | void thermal_zone_device_unregister(struct thermal_zone_device *tz) |
1423 | { |
1424 | int tz_id; |
1425 | struct thermal_cooling_device *cdev; |
1426 | struct thermal_zone_device *pos = NULL; |
1427 | |
1428 | if (!tz) |
1429 | return; |
1430 | |
1431 | tz_id = tz->id; |
1432 | |
1433 | mutex_lock(&thermal_list_lock); |
1434 | list_for_each_entry(pos, &thermal_tz_list, node) |
1435 | if (pos == tz) |
1436 | break; |
1437 | if (pos != tz) { |
1438 | /* thermal zone device not found */ |
1439 | mutex_unlock(lock: &thermal_list_lock); |
1440 | return; |
1441 | } |
1442 | list_del(entry: &tz->node); |
1443 | |
1444 | /* Unbind all cdevs associated with 'this' thermal zone */ |
1445 | list_for_each_entry(cdev, &thermal_cdev_list, node) |
1446 | if (tz->ops->unbind) |
1447 | tz->ops->unbind(tz, cdev); |
1448 | |
1449 | mutex_unlock(lock: &thermal_list_lock); |
1450 | |
1451 | cancel_delayed_work_sync(dwork: &tz->poll_queue); |
1452 | |
1453 | thermal_set_governor(tz, NULL); |
1454 | |
1455 | thermal_remove_hwmon_sysfs(tz); |
1456 | ida_free(&thermal_tz_ida, id: tz->id); |
1457 | ida_destroy(ida: &tz->ida); |
1458 | |
1459 | mutex_lock(&tz->lock); |
1460 | device_del(dev: &tz->device); |
1461 | mutex_unlock(lock: &tz->lock); |
1462 | |
1463 | kfree(objp: tz->tzp); |
1464 | |
1465 | put_device(dev: &tz->device); |
1466 | |
1467 | thermal_notify_tz_delete(tz_id); |
1468 | } |
1469 | EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); |
1470 | |
1471 | /** |
1472 | * thermal_zone_get_zone_by_name() - search for a zone and returns its ref |
1473 | * @name: thermal zone name to fetch the temperature |
1474 | * |
1475 | * When only one zone is found with the passed name, returns a reference to it. |
1476 | * |
1477 | * Return: On success returns a reference to an unique thermal zone with |
1478 | * matching name equals to @name, an ERR_PTR otherwise (-EINVAL for invalid |
1479 | * paramenters, -ENODEV for not found and -EEXIST for multiple matches). |
1480 | */ |
1481 | struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name) |
1482 | { |
1483 | struct thermal_zone_device *pos = NULL, *ref = ERR_PTR(error: -EINVAL); |
1484 | unsigned int found = 0; |
1485 | |
1486 | if (!name) |
1487 | goto exit; |
1488 | |
1489 | mutex_lock(&thermal_list_lock); |
1490 | list_for_each_entry(pos, &thermal_tz_list, node) |
1491 | if (!strncasecmp(s1: name, s2: pos->type, THERMAL_NAME_LENGTH)) { |
1492 | found++; |
1493 | ref = pos; |
1494 | } |
1495 | mutex_unlock(lock: &thermal_list_lock); |
1496 | |
1497 | /* nothing has been found, thus an error code for it */ |
1498 | if (found == 0) |
1499 | ref = ERR_PTR(error: -ENODEV); |
1500 | else if (found > 1) |
1501 | /* Success only when an unique zone is found */ |
1502 | ref = ERR_PTR(error: -EEXIST); |
1503 | |
1504 | exit: |
1505 | return ref; |
1506 | } |
1507 | EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name); |
1508 | |
1509 | static int thermal_pm_notify(struct notifier_block *nb, |
1510 | unsigned long mode, void *_unused) |
1511 | { |
1512 | struct thermal_zone_device *tz; |
1513 | |
1514 | switch (mode) { |
1515 | case PM_HIBERNATION_PREPARE: |
1516 | case PM_RESTORE_PREPARE: |
1517 | case PM_SUSPEND_PREPARE: |
1518 | atomic_set(v: &in_suspend, i: 1); |
1519 | break; |
1520 | case PM_POST_HIBERNATION: |
1521 | case PM_POST_RESTORE: |
1522 | case PM_POST_SUSPEND: |
1523 | atomic_set(v: &in_suspend, i: 0); |
1524 | list_for_each_entry(tz, &thermal_tz_list, node) { |
1525 | thermal_zone_device_init(tz); |
1526 | thermal_zone_device_update(tz, |
1527 | THERMAL_EVENT_UNSPECIFIED); |
1528 | } |
1529 | break; |
1530 | default: |
1531 | break; |
1532 | } |
1533 | return 0; |
1534 | } |
1535 | |
1536 | static struct notifier_block thermal_pm_nb = { |
1537 | .notifier_call = thermal_pm_notify, |
1538 | }; |
1539 | |
1540 | static int __init thermal_init(void) |
1541 | { |
1542 | int result; |
1543 | |
1544 | result = thermal_netlink_init(); |
1545 | if (result) |
1546 | goto error; |
1547 | |
1548 | result = thermal_register_governors(); |
1549 | if (result) |
1550 | goto unregister_netlink; |
1551 | |
1552 | thermal_class = kzalloc(size: sizeof(*thermal_class), GFP_KERNEL); |
1553 | if (!thermal_class) { |
1554 | result = -ENOMEM; |
1555 | goto unregister_governors; |
1556 | } |
1557 | |
1558 | thermal_class->name = "thermal" ; |
1559 | thermal_class->dev_release = thermal_release; |
1560 | |
1561 | result = class_register(class: thermal_class); |
1562 | if (result) { |
1563 | kfree(objp: thermal_class); |
1564 | thermal_class = NULL; |
1565 | goto unregister_governors; |
1566 | } |
1567 | |
1568 | result = register_pm_notifier(nb: &thermal_pm_nb); |
1569 | if (result) |
1570 | pr_warn("Thermal: Can not register suspend notifier, return %d\n" , |
1571 | result); |
1572 | |
1573 | return 0; |
1574 | |
1575 | unregister_governors: |
1576 | thermal_unregister_governors(); |
1577 | unregister_netlink: |
1578 | thermal_netlink_exit(); |
1579 | error: |
1580 | mutex_destroy(lock: &thermal_list_lock); |
1581 | mutex_destroy(lock: &thermal_governor_lock); |
1582 | return result; |
1583 | } |
1584 | postcore_initcall(thermal_init); |
1585 | |