.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $) |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
---|
5 | 6 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@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; either version 2 of the License, or (at |
---|
12 | | - * your option) any later version. |
---|
13 | | - * |
---|
14 | | - * This program is distributed in the hope that it will be useful, but |
---|
15 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
17 | | - * General Public License for more details. |
---|
18 | | - * |
---|
19 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
20 | 7 | * |
---|
21 | 8 | * This driver fully implements the ACPI thermal policy as described in the |
---|
22 | 9 | * ACPI 2.0 Specification. |
---|
.. | .. |
---|
24 | 11 | * TBD: 1. Implement passive cooling hysteresis. |
---|
25 | 12 | * 2. Enhance passive cooling (CPU) states/limit interface to support |
---|
26 | 13 | * concepts of 'multiple limiters', upper/lower limits, etc. |
---|
27 | | - * |
---|
28 | 14 | */ |
---|
29 | 15 | |
---|
30 | 16 | #include <linux/kernel.h> |
---|
.. | .. |
---|
41 | 27 | #include <linux/acpi.h> |
---|
42 | 28 | #include <linux/workqueue.h> |
---|
43 | 29 | #include <linux/uaccess.h> |
---|
| 30 | +#include <linux/units.h> |
---|
44 | 31 | |
---|
45 | 32 | #define PREFIX "ACPI: " |
---|
46 | 33 | |
---|
.. | .. |
---|
185 | 172 | struct acpi_thermal_trips trips; |
---|
186 | 173 | struct acpi_handle_list devices; |
---|
187 | 174 | struct thermal_zone_device *thermal_zone; |
---|
188 | | - int tz_enabled; |
---|
189 | | - int kelvin_offset; |
---|
| 175 | + int kelvin_offset; /* in millidegrees */ |
---|
190 | 176 | struct work_struct thermal_check_work; |
---|
191 | 177 | struct mutex thermal_check_lock; |
---|
192 | 178 | refcount_t thermal_check_count; |
---|
.. | .. |
---|
241 | 227 | if (!tz) |
---|
242 | 228 | return -EINVAL; |
---|
243 | 229 | |
---|
244 | | - if (!acpi_has_method(tz->device->handle, "_SCP")) { |
---|
245 | | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); |
---|
| 230 | + if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle, |
---|
| 231 | + "_SCP", mode))) |
---|
246 | 232 | return -ENODEV; |
---|
247 | | - } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle, |
---|
248 | | - "_SCP", mode))) { |
---|
249 | | - return -ENODEV; |
---|
250 | | - } |
---|
251 | 233 | |
---|
252 | 234 | return 0; |
---|
253 | 235 | } |
---|
.. | .. |
---|
317 | 299 | if (crt == -1) { |
---|
318 | 300 | tz->trips.critical.flags.valid = 0; |
---|
319 | 301 | } else if (crt > 0) { |
---|
320 | | - unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt); |
---|
| 302 | + unsigned long crt_k = celsius_to_deci_kelvin(crt); |
---|
| 303 | + |
---|
321 | 304 | /* |
---|
322 | 305 | * Allow override critical threshold |
---|
323 | 306 | */ |
---|
.. | .. |
---|
353 | 336 | if (psv == -1) { |
---|
354 | 337 | status = AE_SUPPORT; |
---|
355 | 338 | } else if (psv > 0) { |
---|
356 | | - tmp = CELSIUS_TO_DECI_KELVIN(psv); |
---|
| 339 | + tmp = celsius_to_deci_kelvin(psv); |
---|
357 | 340 | status = AE_OK; |
---|
358 | 341 | } else { |
---|
359 | 342 | status = acpi_evaluate_integer(tz->device->handle, |
---|
.. | .. |
---|
433 | 416 | break; |
---|
434 | 417 | if (i == 1) |
---|
435 | 418 | tz->trips.active[0].temperature = |
---|
436 | | - CELSIUS_TO_DECI_KELVIN(act); |
---|
| 419 | + celsius_to_deci_kelvin(act); |
---|
437 | 420 | else |
---|
438 | 421 | /* |
---|
439 | 422 | * Don't allow override higher than |
---|
.. | .. |
---|
441 | 424 | */ |
---|
442 | 425 | tz->trips.active[i - 1].temperature = |
---|
443 | 426 | (tz->trips.active[i - 2].temperature < |
---|
444 | | - CELSIUS_TO_DECI_KELVIN(act) ? |
---|
| 427 | + celsius_to_deci_kelvin(act) ? |
---|
445 | 428 | tz->trips.active[i - 2].temperature : |
---|
446 | | - CELSIUS_TO_DECI_KELVIN(act)); |
---|
| 429 | + celsius_to_deci_kelvin(act)); |
---|
447 | 430 | break; |
---|
448 | 431 | } else { |
---|
449 | 432 | tz->trips.active[i].temperature = tmp; |
---|
.. | .. |
---|
479 | 462 | break; |
---|
480 | 463 | } |
---|
481 | 464 | |
---|
482 | | - if ((flag & ACPI_TRIPS_DEVICES) |
---|
483 | | - && acpi_has_method(tz->device->handle, "_TZD")) { |
---|
| 465 | + if (flag & ACPI_TRIPS_DEVICES) { |
---|
484 | 466 | memset(&devices, 0, sizeof(devices)); |
---|
485 | 467 | status = acpi_evaluate_reference(tz->device->handle, "_TZD", |
---|
486 | 468 | NULL, &devices); |
---|
.. | .. |
---|
529 | 511 | if (result) |
---|
530 | 512 | return result; |
---|
531 | 513 | |
---|
532 | | - *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature, |
---|
| 514 | + *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature, |
---|
533 | 515 | tz->kelvin_offset); |
---|
534 | | - return 0; |
---|
535 | | -} |
---|
536 | | - |
---|
537 | | -static int thermal_get_mode(struct thermal_zone_device *thermal, |
---|
538 | | - enum thermal_device_mode *mode) |
---|
539 | | -{ |
---|
540 | | - struct acpi_thermal *tz = thermal->devdata; |
---|
541 | | - |
---|
542 | | - if (!tz) |
---|
543 | | - return -EINVAL; |
---|
544 | | - |
---|
545 | | - *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED : |
---|
546 | | - THERMAL_DEVICE_DISABLED; |
---|
547 | | - |
---|
548 | | - return 0; |
---|
549 | | -} |
---|
550 | | - |
---|
551 | | -static void acpi_thermal_check_fn(struct work_struct *work); |
---|
552 | | - |
---|
553 | | -static int thermal_set_mode(struct thermal_zone_device *thermal, |
---|
554 | | - enum thermal_device_mode mode) |
---|
555 | | -{ |
---|
556 | | - struct acpi_thermal *tz = thermal->devdata; |
---|
557 | | - int enable; |
---|
558 | | - |
---|
559 | | - if (!tz) |
---|
560 | | - return -EINVAL; |
---|
561 | | - |
---|
562 | | - /* |
---|
563 | | - * enable/disable thermal management from ACPI thermal driver |
---|
564 | | - */ |
---|
565 | | - if (mode == THERMAL_DEVICE_ENABLED) |
---|
566 | | - enable = 1; |
---|
567 | | - else if (mode == THERMAL_DEVICE_DISABLED) { |
---|
568 | | - enable = 0; |
---|
569 | | - pr_warn("thermal zone will be disabled\n"); |
---|
570 | | - } else |
---|
571 | | - return -EINVAL; |
---|
572 | | - |
---|
573 | | - if (enable != tz->tz_enabled) { |
---|
574 | | - tz->tz_enabled = enable; |
---|
575 | | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
---|
576 | | - "%s kernel ACPI thermal control\n", |
---|
577 | | - tz->tz_enabled ? "Enable" : "Disable")); |
---|
578 | | - acpi_thermal_check_fn(&tz->thermal_check_work); |
---|
579 | | - } |
---|
580 | 516 | return 0; |
---|
581 | 517 | } |
---|
582 | 518 | |
---|
.. | .. |
---|
636 | 572 | |
---|
637 | 573 | if (tz->trips.critical.flags.valid) { |
---|
638 | 574 | if (!trip) { |
---|
639 | | - *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 575 | + *temp = deci_kelvin_to_millicelsius_with_offset( |
---|
640 | 576 | tz->trips.critical.temperature, |
---|
641 | 577 | tz->kelvin_offset); |
---|
642 | 578 | return 0; |
---|
.. | .. |
---|
646 | 582 | |
---|
647 | 583 | if (tz->trips.hot.flags.valid) { |
---|
648 | 584 | if (!trip) { |
---|
649 | | - *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 585 | + *temp = deci_kelvin_to_millicelsius_with_offset( |
---|
650 | 586 | tz->trips.hot.temperature, |
---|
651 | 587 | tz->kelvin_offset); |
---|
652 | 588 | return 0; |
---|
.. | .. |
---|
656 | 592 | |
---|
657 | 593 | if (tz->trips.passive.flags.valid) { |
---|
658 | 594 | if (!trip) { |
---|
659 | | - *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 595 | + *temp = deci_kelvin_to_millicelsius_with_offset( |
---|
660 | 596 | tz->trips.passive.temperature, |
---|
661 | 597 | tz->kelvin_offset); |
---|
662 | 598 | return 0; |
---|
.. | .. |
---|
667 | 603 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && |
---|
668 | 604 | tz->trips.active[i].flags.valid; i++) { |
---|
669 | 605 | if (!trip) { |
---|
670 | | - *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 606 | + *temp = deci_kelvin_to_millicelsius_with_offset( |
---|
671 | 607 | tz->trips.active[i].temperature, |
---|
672 | 608 | tz->kelvin_offset); |
---|
673 | 609 | return 0; |
---|
.. | .. |
---|
684 | 620 | struct acpi_thermal *tz = thermal->devdata; |
---|
685 | 621 | |
---|
686 | 622 | if (tz->trips.critical.flags.valid) { |
---|
687 | | - *temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 623 | + *temperature = deci_kelvin_to_millicelsius_with_offset( |
---|
688 | 624 | tz->trips.critical.temperature, |
---|
689 | 625 | tz->kelvin_offset); |
---|
690 | 626 | return 0; |
---|
.. | .. |
---|
704 | 640 | |
---|
705 | 641 | if (type == THERMAL_TRIP_ACTIVE) { |
---|
706 | 642 | int trip_temp; |
---|
707 | | - int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( |
---|
| 643 | + int temp = deci_kelvin_to_millicelsius_with_offset( |
---|
708 | 644 | tz->temperature, tz->kelvin_offset); |
---|
709 | 645 | if (thermal_get_trip_temp(thermal, trip, &trip_temp)) |
---|
710 | 646 | return -EINVAL; |
---|
.. | .. |
---|
866 | 802 | .bind = acpi_thermal_bind_cooling_device, |
---|
867 | 803 | .unbind = acpi_thermal_unbind_cooling_device, |
---|
868 | 804 | .get_temp = thermal_get_temp, |
---|
869 | | - .get_mode = thermal_get_mode, |
---|
870 | | - .set_mode = thermal_set_mode, |
---|
871 | 805 | .get_trip_type = thermal_get_trip_type, |
---|
872 | 806 | .get_trip_temp = thermal_get_trip_temp, |
---|
873 | 807 | .get_crit_temp = thermal_get_crit_temp, |
---|
.. | .. |
---|
911 | 845 | result = sysfs_create_link(&tz->device->dev.kobj, |
---|
912 | 846 | &tz->thermal_zone->device.kobj, "thermal_zone"); |
---|
913 | 847 | if (result) |
---|
914 | | - return result; |
---|
| 848 | + goto unregister_tzd; |
---|
915 | 849 | |
---|
916 | 850 | result = sysfs_create_link(&tz->thermal_zone->device.kobj, |
---|
917 | 851 | &tz->device->dev.kobj, "device"); |
---|
918 | 852 | if (result) |
---|
919 | | - return result; |
---|
| 853 | + goto remove_tz_link; |
---|
920 | 854 | |
---|
921 | 855 | status = acpi_bus_attach_private_data(tz->device->handle, |
---|
922 | 856 | tz->thermal_zone); |
---|
923 | | - if (ACPI_FAILURE(status)) |
---|
924 | | - return -ENODEV; |
---|
| 857 | + if (ACPI_FAILURE(status)) { |
---|
| 858 | + result = -ENODEV; |
---|
| 859 | + goto remove_dev_link; |
---|
| 860 | + } |
---|
925 | 861 | |
---|
926 | | - tz->tz_enabled = 1; |
---|
| 862 | + result = thermal_zone_device_enable(tz->thermal_zone); |
---|
| 863 | + if (result) |
---|
| 864 | + goto acpi_bus_detach; |
---|
927 | 865 | |
---|
928 | 866 | dev_info(&tz->device->dev, "registered as thermal_zone%d\n", |
---|
929 | 867 | tz->thermal_zone->id); |
---|
| 868 | + |
---|
930 | 869 | return 0; |
---|
| 870 | + |
---|
| 871 | +acpi_bus_detach: |
---|
| 872 | + acpi_bus_detach_private_data(tz->device->handle); |
---|
| 873 | +remove_dev_link: |
---|
| 874 | + sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); |
---|
| 875 | +remove_tz_link: |
---|
| 876 | + sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone"); |
---|
| 877 | +unregister_tzd: |
---|
| 878 | + thermal_zone_device_unregister(tz->thermal_zone); |
---|
| 879 | + |
---|
| 880 | + return result; |
---|
931 | 881 | } |
---|
932 | 882 | |
---|
933 | 883 | static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) |
---|
.. | .. |
---|
1061 | 1011 | { |
---|
1062 | 1012 | if (tz->trips.critical.flags.valid && |
---|
1063 | 1013 | (tz->trips.critical.temperature % 5) == 1) |
---|
1064 | | - tz->kelvin_offset = 2731; |
---|
| 1014 | + tz->kelvin_offset = 273100; |
---|
1065 | 1015 | else |
---|
1066 | | - tz->kelvin_offset = 2732; |
---|
| 1016 | + tz->kelvin_offset = 273200; |
---|
1067 | 1017 | } |
---|
1068 | 1018 | |
---|
1069 | 1019 | static void acpi_thermal_check_fn(struct work_struct *work) |
---|
.. | .. |
---|
1071 | 1021 | struct acpi_thermal *tz = container_of(work, struct acpi_thermal, |
---|
1072 | 1022 | thermal_check_work); |
---|
1073 | 1023 | |
---|
1074 | | - if (!tz->tz_enabled) |
---|
1075 | | - return; |
---|
1076 | 1024 | /* |
---|
1077 | 1025 | * In general, it is not sufficient to check the pending bit, because |
---|
1078 | 1026 | * subsequent instances of this function may be queued after one of them |
---|
.. | .. |
---|
1127 | 1075 | INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); |
---|
1128 | 1076 | |
---|
1129 | 1077 | pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), |
---|
1130 | | - acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature)); |
---|
| 1078 | + acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature)); |
---|
1131 | 1079 | goto end; |
---|
1132 | 1080 | |
---|
1133 | 1081 | free_memory: |
---|
.. | .. |
---|
1172 | 1120 | return -EINVAL; |
---|
1173 | 1121 | |
---|
1174 | 1122 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { |
---|
1175 | | - if (!(&tz->trips.active[i])) |
---|
1176 | | - break; |
---|
1177 | 1123 | if (!tz->trips.active[i].flags.valid) |
---|
1178 | 1124 | break; |
---|
1179 | 1125 | tz->trips.active[i].flags.enabled = 1; |
---|