| .. | .. |
|---|
| 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; |
|---|