LCOV - code coverage report
Current view: top level - drivers/acpi - thermal.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 8 508 1.6 %
Date: 2022-03-28 15:32:58 Functions: 1 31 3.2 %
Branches: 3 334 0.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
       4                 :            :  *
       5                 :            :  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
       6                 :            :  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
       7                 :            :  *
       8                 :            :  *  This driver fully implements the ACPI thermal policy as described in the
       9                 :            :  *  ACPI 2.0 Specification.
      10                 :            :  *
      11                 :            :  *  TBD: 1. Implement passive cooling hysteresis.
      12                 :            :  *       2. Enhance passive cooling (CPU) states/limit interface to support
      13                 :            :  *          concepts of 'multiple limiters', upper/lower limits, etc.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <linux/kernel.h>
      17                 :            : #include <linux/module.h>
      18                 :            : #include <linux/dmi.h>
      19                 :            : #include <linux/init.h>
      20                 :            : #include <linux/slab.h>
      21                 :            : #include <linux/types.h>
      22                 :            : #include <linux/jiffies.h>
      23                 :            : #include <linux/kmod.h>
      24                 :            : #include <linux/reboot.h>
      25                 :            : #include <linux/device.h>
      26                 :            : #include <linux/thermal.h>
      27                 :            : #include <linux/acpi.h>
      28                 :            : #include <linux/workqueue.h>
      29                 :            : #include <linux/uaccess.h>
      30                 :            : #include <linux/units.h>
      31                 :            : 
      32                 :            : #define PREFIX "ACPI: "
      33                 :            : 
      34                 :            : #define ACPI_THERMAL_CLASS              "thermal_zone"
      35                 :            : #define ACPI_THERMAL_DEVICE_NAME        "Thermal Zone"
      36                 :            : #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
      37                 :            : #define ACPI_THERMAL_NOTIFY_THRESHOLDS  0x81
      38                 :            : #define ACPI_THERMAL_NOTIFY_DEVICES     0x82
      39                 :            : #define ACPI_THERMAL_NOTIFY_CRITICAL    0xF0
      40                 :            : #define ACPI_THERMAL_NOTIFY_HOT         0xF1
      41                 :            : #define ACPI_THERMAL_MODE_ACTIVE        0x00
      42                 :            : 
      43                 :            : #define ACPI_THERMAL_MAX_ACTIVE 10
      44                 :            : #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
      45                 :            : 
      46                 :            : #define _COMPONENT              ACPI_THERMAL_COMPONENT
      47                 :            : ACPI_MODULE_NAME("thermal");
      48                 :            : 
      49                 :            : MODULE_AUTHOR("Paul Diefenbaugh");
      50                 :            : MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
      51                 :            : MODULE_LICENSE("GPL");
      52                 :            : 
      53                 :            : static int act;
      54                 :            : module_param(act, int, 0644);
      55                 :            : MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
      56                 :            : 
      57                 :            : static int crt;
      58                 :            : module_param(crt, int, 0644);
      59                 :            : MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
      60                 :            : 
      61                 :            : static int tzp;
      62                 :            : module_param(tzp, int, 0444);
      63                 :            : MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
      64                 :            : 
      65                 :            : static int nocrt;
      66                 :            : module_param(nocrt, int, 0);
      67                 :            : MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
      68                 :            : 
      69                 :            : static int off;
      70                 :            : module_param(off, int, 0);
      71                 :            : MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
      72                 :            : 
      73                 :            : static int psv;
      74                 :            : module_param(psv, int, 0644);
      75                 :            : MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
      76                 :            : 
      77                 :            : static struct workqueue_struct *acpi_thermal_pm_queue;
      78                 :            : 
      79                 :            : static int acpi_thermal_add(struct acpi_device *device);
      80                 :            : static int acpi_thermal_remove(struct acpi_device *device);
      81                 :            : static void acpi_thermal_notify(struct acpi_device *device, u32 event);
      82                 :            : 
      83                 :            : static const struct acpi_device_id  thermal_device_ids[] = {
      84                 :            :         {ACPI_THERMAL_HID, 0},
      85                 :            :         {"", 0},
      86                 :            : };
      87                 :            : MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
      88                 :            : 
      89                 :            : #ifdef CONFIG_PM_SLEEP
      90                 :            : static int acpi_thermal_suspend(struct device *dev);
      91                 :            : static int acpi_thermal_resume(struct device *dev);
      92                 :            : #else
      93                 :            : #define acpi_thermal_suspend NULL
      94                 :            : #define acpi_thermal_resume NULL
      95                 :            : #endif
      96                 :            : static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
      97                 :            : 
      98                 :            : static struct acpi_driver acpi_thermal_driver = {
      99                 :            :         .name = "thermal",
     100                 :            :         .class = ACPI_THERMAL_CLASS,
     101                 :            :         .ids = thermal_device_ids,
     102                 :            :         .ops = {
     103                 :            :                 .add = acpi_thermal_add,
     104                 :            :                 .remove = acpi_thermal_remove,
     105                 :            :                 .notify = acpi_thermal_notify,
     106                 :            :                 },
     107                 :            :         .drv.pm = &acpi_thermal_pm,
     108                 :            : };
     109                 :            : 
     110                 :            : struct acpi_thermal_state {
     111                 :            :         u8 critical:1;
     112                 :            :         u8 hot:1;
     113                 :            :         u8 passive:1;
     114                 :            :         u8 active:1;
     115                 :            :         u8 reserved:4;
     116                 :            :         int active_index;
     117                 :            : };
     118                 :            : 
     119                 :            : struct acpi_thermal_state_flags {
     120                 :            :         u8 valid:1;
     121                 :            :         u8 enabled:1;
     122                 :            :         u8 reserved:6;
     123                 :            : };
     124                 :            : 
     125                 :            : struct acpi_thermal_critical {
     126                 :            :         struct acpi_thermal_state_flags flags;
     127                 :            :         unsigned long temperature;
     128                 :            : };
     129                 :            : 
     130                 :            : struct acpi_thermal_hot {
     131                 :            :         struct acpi_thermal_state_flags flags;
     132                 :            :         unsigned long temperature;
     133                 :            : };
     134                 :            : 
     135                 :            : struct acpi_thermal_passive {
     136                 :            :         struct acpi_thermal_state_flags flags;
     137                 :            :         unsigned long temperature;
     138                 :            :         unsigned long tc1;
     139                 :            :         unsigned long tc2;
     140                 :            :         unsigned long tsp;
     141                 :            :         struct acpi_handle_list devices;
     142                 :            : };
     143                 :            : 
     144                 :            : struct acpi_thermal_active {
     145                 :            :         struct acpi_thermal_state_flags flags;
     146                 :            :         unsigned long temperature;
     147                 :            :         struct acpi_handle_list devices;
     148                 :            : };
     149                 :            : 
     150                 :            : struct acpi_thermal_trips {
     151                 :            :         struct acpi_thermal_critical critical;
     152                 :            :         struct acpi_thermal_hot hot;
     153                 :            :         struct acpi_thermal_passive passive;
     154                 :            :         struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
     155                 :            : };
     156                 :            : 
     157                 :            : struct acpi_thermal_flags {
     158                 :            :         u8 cooling_mode:1;      /* _SCP */
     159                 :            :         u8 devices:1;           /* _TZD */
     160                 :            :         u8 reserved:6;
     161                 :            : };
     162                 :            : 
     163                 :            : struct acpi_thermal {
     164                 :            :         struct acpi_device * device;
     165                 :            :         acpi_bus_id name;
     166                 :            :         unsigned long temperature;
     167                 :            :         unsigned long last_temperature;
     168                 :            :         unsigned long polling_frequency;
     169                 :            :         volatile u8 zombie;
     170                 :            :         struct acpi_thermal_flags flags;
     171                 :            :         struct acpi_thermal_state state;
     172                 :            :         struct acpi_thermal_trips trips;
     173                 :            :         struct acpi_handle_list devices;
     174                 :            :         struct thermal_zone_device *thermal_zone;
     175                 :            :         int tz_enabled;
     176                 :            :         int kelvin_offset;      /* in millidegrees */
     177                 :            :         struct work_struct thermal_check_work;
     178                 :            : };
     179                 :            : 
     180                 :            : /* --------------------------------------------------------------------------
     181                 :            :                              Thermal Zone Management
     182                 :            :    -------------------------------------------------------------------------- */
     183                 :            : 
     184                 :          0 : static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
     185                 :            : {
     186                 :          0 :         acpi_status status = AE_OK;
     187                 :          0 :         unsigned long long tmp;
     188                 :            : 
     189         [ #  # ]:          0 :         if (!tz)
     190                 :            :                 return -EINVAL;
     191                 :            : 
     192                 :          0 :         tz->last_temperature = tz->temperature;
     193                 :            : 
     194                 :          0 :         status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
     195         [ #  # ]:          0 :         if (ACPI_FAILURE(status))
     196                 :            :                 return -ENODEV;
     197                 :            : 
     198                 :          0 :         tz->temperature = tmp;
     199                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
     200                 :          0 :                           tz->temperature));
     201                 :            : 
     202                 :          0 :         return 0;
     203                 :            : }
     204                 :            : 
     205                 :          0 : static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
     206                 :            : {
     207                 :          0 :         acpi_status status = AE_OK;
     208                 :          0 :         unsigned long long tmp;
     209                 :            : 
     210         [ #  # ]:          0 :         if (!tz)
     211                 :            :                 return -EINVAL;
     212                 :            : 
     213                 :          0 :         status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
     214         [ #  # ]:          0 :         if (ACPI_FAILURE(status))
     215                 :            :                 return -ENODEV;
     216                 :            : 
     217                 :          0 :         tz->polling_frequency = tmp;
     218                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
     219                 :          0 :                           tz->polling_frequency));
     220                 :            : 
     221                 :          0 :         return 0;
     222                 :            : }
     223                 :            : 
     224                 :          0 : static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
     225                 :            : {
     226                 :          0 :         if (!tz)
     227                 :            :                 return -EINVAL;
     228                 :            : 
     229         [ #  # ]:          0 :         if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
     230                 :            :                                                     "_SCP", mode)))
     231                 :            :                 return -ENODEV;
     232                 :            : 
     233                 :            :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :            : #define ACPI_TRIPS_CRITICAL     0x01
     237                 :            : #define ACPI_TRIPS_HOT          0x02
     238                 :            : #define ACPI_TRIPS_PASSIVE      0x04
     239                 :            : #define ACPI_TRIPS_ACTIVE       0x08
     240                 :            : #define ACPI_TRIPS_DEVICES      0x10
     241                 :            : 
     242                 :            : #define ACPI_TRIPS_REFRESH_THRESHOLDS   (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
     243                 :            : #define ACPI_TRIPS_REFRESH_DEVICES      ACPI_TRIPS_DEVICES
     244                 :            : 
     245                 :            : #define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |    \
     246                 :            :                               ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
     247                 :            :                               ACPI_TRIPS_DEVICES)
     248                 :            : 
     249                 :            : /*
     250                 :            :  * This exception is thrown out in two cases:
     251                 :            :  * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
     252                 :            :  *   when re-evaluating the AML code.
     253                 :            :  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
     254                 :            :  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
     255                 :            :  */
     256                 :            : #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)        \
     257                 :            : do {    \
     258                 :            :         if (flags != ACPI_TRIPS_INIT)   \
     259                 :            :                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,      \
     260                 :            :                 "ACPI thermal trip point %s changed\n"        \
     261                 :            :                 "Please send acpidump to linux-acpi@vger.kernel.org", str)); \
     262                 :            : } while (0)
     263                 :            : 
     264                 :          0 : static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
     265                 :            : {
     266                 :          0 :         acpi_status status = AE_OK;
     267                 :          0 :         unsigned long long tmp;
     268                 :          0 :         struct acpi_handle_list devices;
     269                 :          0 :         int valid = 0;
     270                 :          0 :         int i;
     271                 :            : 
     272                 :            :         /* Critical Shutdown */
     273         [ #  # ]:          0 :         if (flag & ACPI_TRIPS_CRITICAL) {
     274                 :          0 :                 status = acpi_evaluate_integer(tz->device->handle,
     275                 :            :                                 "_CRT", NULL, &tmp);
     276                 :          0 :                 tz->trips.critical.temperature = tmp;
     277                 :            :                 /*
     278                 :            :                  * Treat freezing temperatures as invalid as well; some
     279                 :            :                  * BIOSes return really low values and cause reboots at startup.
     280                 :            :                  * Below zero (Celsius) values clearly aren't right for sure..
     281                 :            :                  * ... so lets discard those as invalid.
     282                 :            :                  */
     283         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     284                 :          0 :                         tz->trips.critical.flags.valid = 0;
     285                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     286                 :          0 :                                           "No critical threshold\n"));
     287         [ #  # ]:          0 :                 } else if (tmp <= 2732) {
     288                 :          0 :                         pr_warn(FW_BUG "Invalid critical threshold (%llu)\n",
     289                 :            :                                 tmp);
     290                 :          0 :                         tz->trips.critical.flags.valid = 0;
     291                 :            :                 } else {
     292                 :          0 :                         tz->trips.critical.flags.valid = 1;
     293                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     294                 :            :                                           "Found critical threshold [%lu]\n",
     295                 :          0 :                                           tz->trips.critical.temperature));
     296                 :            :                 }
     297         [ #  # ]:          0 :                 if (tz->trips.critical.flags.valid == 1) {
     298         [ #  # ]:          0 :                         if (crt == -1) {
     299                 :          0 :                                 tz->trips.critical.flags.valid = 0;
     300         [ #  # ]:          0 :                         } else if (crt > 0) {
     301         [ #  # ]:          0 :                                 unsigned long crt_k = celsius_to_deci_kelvin(crt);
     302                 :            : 
     303                 :            :                                 /*
     304                 :            :                                  * Allow override critical threshold
     305                 :            :                                  */
     306         [ #  # ]:          0 :                                 if (crt_k > tz->trips.critical.temperature)
     307                 :          0 :                                         pr_warn(PREFIX "Critical threshold %d C\n",
     308                 :            :                                                 crt);
     309                 :          0 :                                 tz->trips.critical.temperature = crt_k;
     310                 :            :                         }
     311                 :            :                 }
     312                 :            :         }
     313                 :            : 
     314                 :            :         /* Critical Sleep (optional) */
     315         [ #  # ]:          0 :         if (flag & ACPI_TRIPS_HOT) {
     316                 :          0 :                 status = acpi_evaluate_integer(tz->device->handle,
     317                 :            :                                 "_HOT", NULL, &tmp);
     318         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     319                 :          0 :                         tz->trips.hot.flags.valid = 0;
     320                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     321                 :          0 :                                         "No hot threshold\n"));
     322                 :            :                 } else {
     323                 :          0 :                         tz->trips.hot.temperature = tmp;
     324                 :          0 :                         tz->trips.hot.flags.valid = 1;
     325                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     326                 :            :                                         "Found hot threshold [%lu]\n",
     327                 :          0 :                                         tz->trips.hot.temperature));
     328                 :            :                 }
     329                 :            :         }
     330                 :            : 
     331                 :            :         /* Passive (optional) */
     332   [ #  #  #  #  :          0 :         if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
                   #  # ]
     333                 :            :                 (flag == ACPI_TRIPS_INIT)) {
     334                 :          0 :                 valid = tz->trips.passive.flags.valid;
     335         [ #  # ]:          0 :                 if (psv == -1) {
     336                 :            :                         status = AE_SUPPORT;
     337         [ #  # ]:          0 :                 } else if (psv > 0) {
     338                 :          0 :                         tmp = celsius_to_deci_kelvin(psv);
     339                 :          0 :                         status = AE_OK;
     340                 :            :                 } else {
     341                 :          0 :                         status = acpi_evaluate_integer(tz->device->handle,
     342                 :            :                                 "_PSV", NULL, &tmp);
     343                 :            :                 }
     344                 :            : 
     345         [ #  # ]:          0 :                 if (ACPI_FAILURE(status))
     346                 :          0 :                         tz->trips.passive.flags.valid = 0;
     347                 :            :                 else {
     348                 :          0 :                         tz->trips.passive.temperature = tmp;
     349                 :          0 :                         tz->trips.passive.flags.valid = 1;
     350         [ #  # ]:          0 :                         if (flag == ACPI_TRIPS_INIT) {
     351                 :          0 :                                 status = acpi_evaluate_integer(
     352                 :          0 :                                                 tz->device->handle, "_TC1",
     353                 :            :                                                 NULL, &tmp);
     354         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status))
     355                 :          0 :                                         tz->trips.passive.flags.valid = 0;
     356                 :            :                                 else
     357                 :          0 :                                         tz->trips.passive.tc1 = tmp;
     358                 :          0 :                                 status = acpi_evaluate_integer(
     359                 :          0 :                                                 tz->device->handle, "_TC2",
     360                 :            :                                                 NULL, &tmp);
     361         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status))
     362                 :          0 :                                         tz->trips.passive.flags.valid = 0;
     363                 :            :                                 else
     364                 :          0 :                                         tz->trips.passive.tc2 = tmp;
     365                 :          0 :                                 status = acpi_evaluate_integer(
     366                 :          0 :                                                 tz->device->handle, "_TSP",
     367                 :            :                                                 NULL, &tmp);
     368         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status))
     369                 :          0 :                                         tz->trips.passive.flags.valid = 0;
     370                 :            :                                 else
     371                 :          0 :                                         tz->trips.passive.tsp = tmp;
     372                 :            :                         }
     373                 :            :                 }
     374                 :            :         }
     375   [ #  #  #  # ]:          0 :         if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
     376                 :          0 :                 memset(&devices, 0, sizeof(struct acpi_handle_list));
     377                 :          0 :                 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
     378                 :            :                                                         NULL, &devices);
     379         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     380                 :          0 :                         pr_warn(PREFIX "Invalid passive threshold\n");
     381                 :          0 :                         tz->trips.passive.flags.valid = 0;
     382                 :            :                 }
     383                 :            :                 else
     384                 :          0 :                         tz->trips.passive.flags.valid = 1;
     385                 :            : 
     386         [ #  # ]:          0 :                 if (memcmp(&tz->trips.passive.devices, &devices,
     387                 :            :                                 sizeof(struct acpi_handle_list))) {
     388                 :          0 :                         memcpy(&tz->trips.passive.devices, &devices,
     389                 :            :                                 sizeof(struct acpi_handle_list));
     390         [ #  # ]:          0 :                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
     391                 :            :                 }
     392                 :            :         }
     393         [ #  # ]:          0 :         if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
     394         [ #  # ]:          0 :                 if (valid != tz->trips.passive.flags.valid)
     395         [ #  # ]:          0 :                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
     396                 :            :         }
     397                 :            : 
     398                 :            :         /* Active (optional) */
     399         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
     400                 :          0 :                 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
     401                 :          0 :                 valid = tz->trips.active[i].flags.valid;
     402                 :            : 
     403         [ #  # ]:          0 :                 if (act == -1)
     404                 :            :                         break; /* disable all active trip points */
     405                 :            : 
     406   [ #  #  #  #  :          0 :                 if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
                   #  # ]
     407                 :            :                         tz->trips.active[i].flags.valid)) {
     408                 :          0 :                         status = acpi_evaluate_integer(tz->device->handle,
     409                 :            :                                                         name, NULL, &tmp);
     410         [ #  # ]:          0 :                         if (ACPI_FAILURE(status)) {
     411                 :          0 :                                 tz->trips.active[i].flags.valid = 0;
     412         [ #  # ]:          0 :                                 if (i == 0)
     413                 :            :                                         break;
     414         [ #  # ]:          0 :                                 if (act <= 0)
     415                 :            :                                         break;
     416         [ #  # ]:          0 :                                 if (i == 1)
     417                 :          0 :                                         tz->trips.active[0].temperature =
     418                 :          0 :                                                 celsius_to_deci_kelvin(act);
     419                 :            :                                 else
     420                 :            :                                         /*
     421                 :            :                                          * Don't allow override higher than
     422                 :            :                                          * the next higher trip point
     423                 :            :                                          */
     424                 :          0 :                                         tz->trips.active[i - 1].temperature =
     425                 :          0 :                                                 (tz->trips.active[i - 2].temperature <
     426                 :          0 :                                                 celsius_to_deci_kelvin(act) ?
     427                 :            :                                                 tz->trips.active[i - 2].temperature :
     428                 :            :                                                 celsius_to_deci_kelvin(act));
     429                 :            :                                 break;
     430                 :            :                         } else {
     431                 :          0 :                                 tz->trips.active[i].temperature = tmp;
     432                 :          0 :                                 tz->trips.active[i].flags.valid = 1;
     433                 :            :                         }
     434                 :            :                 }
     435                 :            : 
     436                 :          0 :                 name[2] = 'L';
     437   [ #  #  #  # ]:          0 :                 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
     438                 :          0 :                         memset(&devices, 0, sizeof(struct acpi_handle_list));
     439                 :          0 :                         status = acpi_evaluate_reference(tz->device->handle,
     440                 :            :                                                 name, NULL, &devices);
     441         [ #  # ]:          0 :                         if (ACPI_FAILURE(status)) {
     442                 :          0 :                                 pr_warn(PREFIX "Invalid active%d threshold\n",
     443                 :            :                                         i);
     444                 :          0 :                                 tz->trips.active[i].flags.valid = 0;
     445                 :            :                         }
     446                 :            :                         else
     447                 :          0 :                                 tz->trips.active[i].flags.valid = 1;
     448                 :            : 
     449         [ #  # ]:          0 :                         if (memcmp(&tz->trips.active[i].devices, &devices,
     450                 :            :                                         sizeof(struct acpi_handle_list))) {
     451                 :          0 :                                 memcpy(&tz->trips.active[i].devices, &devices,
     452                 :            :                                         sizeof(struct acpi_handle_list));
     453         [ #  # ]:          0 :                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
     454                 :            :                         }
     455                 :            :                 }
     456         [ #  # ]:          0 :                 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
     457         [ #  # ]:          0 :                         if (valid != tz->trips.active[i].flags.valid)
     458         [ #  # ]:          0 :                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
     459                 :            : 
     460         [ #  # ]:          0 :                 if (!tz->trips.active[i].flags.valid)
     461                 :            :                         break;
     462                 :            :         }
     463                 :            : 
     464         [ #  # ]:          0 :         if (flag & ACPI_TRIPS_DEVICES) {
     465                 :          0 :                 memset(&devices, 0, sizeof(devices));
     466                 :          0 :                 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
     467                 :            :                                                 NULL, &devices);
     468         [ #  # ]:          0 :                 if (ACPI_SUCCESS(status)
     469         [ #  # ]:          0 :                     && memcmp(&tz->devices, &devices, sizeof(devices))) {
     470                 :          0 :                         tz->devices = devices;
     471         [ #  # ]:          0 :                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
     472                 :            :                 }
     473                 :            :         }
     474                 :            : 
     475                 :          0 :         return 0;
     476                 :            : }
     477                 :            : 
     478                 :          0 : static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
     479                 :            : {
     480                 :          0 :         int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
     481                 :            : 
     482         [ #  # ]:          0 :         if (ret)
     483                 :            :                 return ret;
     484                 :            : 
     485                 :          0 :         valid = tz->trips.critical.flags.valid |
     486                 :          0 :                 tz->trips.hot.flags.valid |
     487                 :          0 :                 tz->trips.passive.flags.valid;
     488                 :            : 
     489         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
     490                 :          0 :                 valid |= tz->trips.active[i].flags.valid;
     491                 :            : 
     492         [ #  # ]:          0 :         if (!valid) {
     493                 :          0 :                 pr_warn(FW_BUG "No valid trip found\n");
     494                 :          0 :                 return -ENODEV;
     495                 :            :         }
     496                 :            :         return 0;
     497                 :            : }
     498                 :            : 
     499                 :          0 : static void acpi_thermal_check(void *data)
     500                 :            : {
     501                 :          0 :         struct acpi_thermal *tz = data;
     502                 :            : 
     503                 :          0 :         if (!tz->tz_enabled)
     504                 :            :                 return;
     505                 :            : 
     506                 :          0 :         thermal_zone_device_update(tz->thermal_zone,
     507                 :            :                                    THERMAL_EVENT_UNSPECIFIED);
     508                 :            : }
     509                 :            : 
     510                 :            : /* sys I/F for generic thermal sysfs support */
     511                 :            : 
     512                 :          0 : static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
     513                 :            : {
     514                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     515                 :          0 :         int result;
     516                 :            : 
     517         [ #  # ]:          0 :         if (!tz)
     518                 :            :                 return -EINVAL;
     519                 :            : 
     520                 :          0 :         result = acpi_thermal_get_temperature(tz);
     521         [ #  # ]:          0 :         if (result)
     522                 :            :                 return result;
     523                 :            : 
     524                 :          0 :         *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature,
     525                 :          0 :                                                         tz->kelvin_offset);
     526                 :          0 :         return 0;
     527                 :            : }
     528                 :            : 
     529                 :          0 : static int thermal_get_mode(struct thermal_zone_device *thermal,
     530                 :            :                                 enum thermal_device_mode *mode)
     531                 :            : {
     532                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     533                 :            : 
     534         [ #  # ]:          0 :         if (!tz)
     535                 :            :                 return -EINVAL;
     536                 :            : 
     537                 :          0 :         *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
     538                 :            :                 THERMAL_DEVICE_DISABLED;
     539                 :            : 
     540                 :          0 :         return 0;
     541                 :            : }
     542                 :            : 
     543                 :          0 : static int thermal_set_mode(struct thermal_zone_device *thermal,
     544                 :            :                                 enum thermal_device_mode mode)
     545                 :            : {
     546                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     547                 :          0 :         int enable;
     548                 :            : 
     549         [ #  # ]:          0 :         if (!tz)
     550                 :            :                 return -EINVAL;
     551                 :            : 
     552                 :            :         /*
     553                 :            :          * enable/disable thermal management from ACPI thermal driver
     554                 :            :          */
     555         [ #  # ]:          0 :         if (mode == THERMAL_DEVICE_ENABLED)
     556                 :            :                 enable = 1;
     557         [ #  # ]:          0 :         else if (mode == THERMAL_DEVICE_DISABLED) {
     558                 :          0 :                 enable = 0;
     559                 :          0 :                 pr_warn("thermal zone will be disabled\n");
     560                 :            :         } else
     561                 :            :                 return -EINVAL;
     562                 :            : 
     563         [ #  # ]:          0 :         if (enable != tz->tz_enabled) {
     564                 :          0 :                 tz->tz_enabled = enable;
     565                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     566                 :            :                         "%s kernel ACPI thermal control\n",
     567                 :          0 :                         tz->tz_enabled ? "Enable" : "Disable"));
     568         [ #  # ]:          0 :                 acpi_thermal_check(tz);
     569                 :            :         }
     570                 :            :         return 0;
     571                 :            : }
     572                 :            : 
     573                 :          0 : static int thermal_get_trip_type(struct thermal_zone_device *thermal,
     574                 :            :                                  int trip, enum thermal_trip_type *type)
     575                 :            : {
     576                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     577                 :          0 :         int i;
     578                 :            : 
     579         [ #  # ]:          0 :         if (!tz || trip < 0)
     580                 :            :                 return -EINVAL;
     581                 :            : 
     582         [ #  # ]:          0 :         if (tz->trips.critical.flags.valid) {
     583         [ #  # ]:          0 :                 if (!trip) {
     584                 :          0 :                         *type = THERMAL_TRIP_CRITICAL;
     585                 :          0 :                         return 0;
     586                 :            :                 }
     587                 :          0 :                 trip--;
     588                 :            :         }
     589                 :            : 
     590         [ #  # ]:          0 :         if (tz->trips.hot.flags.valid) {
     591         [ #  # ]:          0 :                 if (!trip) {
     592                 :          0 :                         *type = THERMAL_TRIP_HOT;
     593                 :          0 :                         return 0;
     594                 :            :                 }
     595                 :          0 :                 trip--;
     596                 :            :         }
     597                 :            : 
     598         [ #  # ]:          0 :         if (tz->trips.passive.flags.valid) {
     599         [ #  # ]:          0 :                 if (!trip) {
     600                 :          0 :                         *type = THERMAL_TRIP_PASSIVE;
     601                 :          0 :                         return 0;
     602                 :            :                 }
     603                 :          0 :                 trip--;
     604                 :            :         }
     605                 :            : 
     606         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
     607         [ #  # ]:          0 :                 tz->trips.active[i].flags.valid; i++) {
     608         [ #  # ]:          0 :                 if (!trip) {
     609                 :          0 :                         *type = THERMAL_TRIP_ACTIVE;
     610                 :          0 :                         return 0;
     611                 :            :                 }
     612                 :          0 :                 trip--;
     613                 :            :         }
     614                 :            : 
     615                 :            :         return -EINVAL;
     616                 :            : }
     617                 :            : 
     618                 :          0 : static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
     619                 :            :                                  int trip, int *temp)
     620                 :            : {
     621                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     622                 :          0 :         int i;
     623                 :            : 
     624         [ #  # ]:          0 :         if (!tz || trip < 0)
     625                 :            :                 return -EINVAL;
     626                 :            : 
     627         [ #  # ]:          0 :         if (tz->trips.critical.flags.valid) {
     628         [ #  # ]:          0 :                 if (!trip) {
     629                 :          0 :                         *temp = deci_kelvin_to_millicelsius_with_offset(
     630                 :          0 :                                 tz->trips.critical.temperature,
     631                 :          0 :                                 tz->kelvin_offset);
     632                 :          0 :                         return 0;
     633                 :            :                 }
     634                 :          0 :                 trip--;
     635                 :            :         }
     636                 :            : 
     637         [ #  # ]:          0 :         if (tz->trips.hot.flags.valid) {
     638         [ #  # ]:          0 :                 if (!trip) {
     639                 :          0 :                         *temp = deci_kelvin_to_millicelsius_with_offset(
     640                 :          0 :                                 tz->trips.hot.temperature,
     641                 :          0 :                                 tz->kelvin_offset);
     642                 :          0 :                         return 0;
     643                 :            :                 }
     644                 :          0 :                 trip--;
     645                 :            :         }
     646                 :            : 
     647         [ #  # ]:          0 :         if (tz->trips.passive.flags.valid) {
     648         [ #  # ]:          0 :                 if (!trip) {
     649                 :          0 :                         *temp = deci_kelvin_to_millicelsius_with_offset(
     650                 :          0 :                                 tz->trips.passive.temperature,
     651                 :          0 :                                 tz->kelvin_offset);
     652                 :          0 :                         return 0;
     653                 :            :                 }
     654                 :          0 :                 trip--;
     655                 :            :         }
     656                 :            : 
     657         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
     658         [ #  # ]:          0 :                 tz->trips.active[i].flags.valid; i++) {
     659         [ #  # ]:          0 :                 if (!trip) {
     660                 :          0 :                         *temp = deci_kelvin_to_millicelsius_with_offset(
     661                 :          0 :                                 tz->trips.active[i].temperature,
     662                 :          0 :                                 tz->kelvin_offset);
     663                 :          0 :                         return 0;
     664                 :            :                 }
     665                 :          0 :                 trip--;
     666                 :            :         }
     667                 :            : 
     668                 :            :         return -EINVAL;
     669                 :            : }
     670                 :            : 
     671                 :          0 : static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
     672                 :            :                                 int *temperature)
     673                 :            : {
     674                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     675                 :            : 
     676         [ #  # ]:          0 :         if (tz->trips.critical.flags.valid) {
     677                 :          0 :                 *temperature = deci_kelvin_to_millicelsius_with_offset(
     678                 :          0 :                                 tz->trips.critical.temperature,
     679                 :          0 :                                 tz->kelvin_offset);
     680                 :          0 :                 return 0;
     681                 :            :         } else
     682                 :            :                 return -EINVAL;
     683                 :            : }
     684                 :            : 
     685                 :          0 : static int thermal_get_trend(struct thermal_zone_device *thermal,
     686                 :            :                                 int trip, enum thermal_trend *trend)
     687                 :            : {
     688                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     689                 :          0 :         enum thermal_trip_type type;
     690                 :          0 :         int i;
     691                 :            : 
     692         [ #  # ]:          0 :         if (thermal_get_trip_type(thermal, trip, &type))
     693                 :            :                 return -EINVAL;
     694                 :            : 
     695         [ #  # ]:          0 :         if (type == THERMAL_TRIP_ACTIVE) {
     696                 :          0 :                 int trip_temp;
     697                 :          0 :                 int temp = deci_kelvin_to_millicelsius_with_offset(
     698                 :          0 :                                         tz->temperature, tz->kelvin_offset);
     699         [ #  # ]:          0 :                 if (thermal_get_trip_temp(thermal, trip, &trip_temp))
     700                 :            :                         return -EINVAL;
     701                 :            : 
     702         [ #  # ]:          0 :                 if (temp > trip_temp) {
     703                 :          0 :                         *trend = THERMAL_TREND_RAISING;
     704                 :          0 :                         return 0;
     705                 :            :                 } else {
     706                 :            :                         /* Fall back on default trend */
     707                 :            :                         return -EINVAL;
     708                 :            :                 }
     709                 :            :         }
     710                 :            : 
     711                 :            :         /*
     712                 :            :          * tz->temperature has already been updated by generic thermal layer,
     713                 :            :          * before this callback being invoked
     714                 :            :          */
     715                 :          0 :         i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
     716                 :          0 :                 + (tz->trips.passive.tc2
     717                 :          0 :                 * (tz->temperature - tz->trips.passive.temperature));
     718                 :            : 
     719         [ #  # ]:          0 :         if (i > 0)
     720                 :          0 :                 *trend = THERMAL_TREND_RAISING;
     721         [ #  # ]:          0 :         else if (i < 0)
     722                 :          0 :                 *trend = THERMAL_TREND_DROPPING;
     723                 :            :         else
     724                 :          0 :                 *trend = THERMAL_TREND_STABLE;
     725                 :            :         return 0;
     726                 :            : }
     727                 :            : 
     728                 :            : 
     729                 :          0 : static int thermal_notify(struct thermal_zone_device *thermal, int trip,
     730                 :            :                            enum thermal_trip_type trip_type)
     731                 :            : {
     732                 :          0 :         u8 type = 0;
     733                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     734                 :            : 
     735         [ #  # ]:          0 :         if (trip_type == THERMAL_TRIP_CRITICAL)
     736                 :            :                 type = ACPI_THERMAL_NOTIFY_CRITICAL;
     737         [ #  # ]:          0 :         else if (trip_type == THERMAL_TRIP_HOT)
     738                 :            :                 type = ACPI_THERMAL_NOTIFY_HOT;
     739                 :            :         else
     740                 :            :                 return 0;
     741                 :            : 
     742                 :          0 :         acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
     743         [ #  # ]:          0 :                                         dev_name(&tz->device->dev), type, 1);
     744                 :            : 
     745   [ #  #  #  # ]:          0 :         if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
     746                 :          0 :                 return 1;
     747                 :            : 
     748                 :            :         return 0;
     749                 :            : }
     750                 :            : 
     751                 :          0 : static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
     752                 :            :                                         struct thermal_cooling_device *cdev,
     753                 :            :                                         bool bind)
     754                 :            : {
     755                 :          0 :         struct acpi_device *device = cdev->devdata;
     756                 :          0 :         struct acpi_thermal *tz = thermal->devdata;
     757                 :          0 :         struct acpi_device *dev;
     758                 :          0 :         acpi_status status;
     759                 :          0 :         acpi_handle handle;
     760                 :          0 :         int i;
     761                 :          0 :         int j;
     762                 :          0 :         int trip = -1;
     763                 :          0 :         int result = 0;
     764                 :            : 
     765                 :          0 :         if (tz->trips.critical.flags.valid)
     766                 :            :                 trip++;
     767                 :            : 
     768         [ #  # ]:          0 :         if (tz->trips.hot.flags.valid)
     769                 :          0 :                 trip++;
     770                 :            : 
     771         [ #  # ]:          0 :         if (tz->trips.passive.flags.valid) {
     772                 :          0 :                 trip++;
     773         [ #  # ]:          0 :                 for (i = 0; i < tz->trips.passive.devices.count;
     774                 :          0 :                     i++) {
     775                 :          0 :                         handle = tz->trips.passive.devices.handles[i];
     776                 :          0 :                         status = acpi_bus_get_device(handle, &dev);
     777   [ #  #  #  # ]:          0 :                         if (ACPI_FAILURE(status) || dev != device)
     778                 :          0 :                                 continue;
     779         [ #  # ]:          0 :                         if (bind)
     780                 :          0 :                                 result =
     781                 :          0 :                                         thermal_zone_bind_cooling_device
     782                 :            :                                         (thermal, trip, cdev,
     783                 :            :                                          THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
     784                 :            :                                          THERMAL_WEIGHT_DEFAULT);
     785                 :            :                         else
     786                 :          0 :                                 result =
     787                 :          0 :                                         thermal_zone_unbind_cooling_device
     788                 :            :                                         (thermal, trip, cdev);
     789         [ #  # ]:          0 :                         if (result)
     790                 :          0 :                                 goto failed;
     791                 :            :                 }
     792                 :            :         }
     793                 :            : 
     794         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
     795         [ #  # ]:          0 :                 if (!tz->trips.active[i].flags.valid)
     796                 :            :                         break;
     797                 :          0 :                 trip++;
     798                 :          0 :                 for (j = 0;
     799         [ #  # ]:          0 :                     j < tz->trips.active[i].devices.count;
     800                 :          0 :                     j++) {
     801                 :          0 :                         handle = tz->trips.active[i].devices.handles[j];
     802                 :          0 :                         status = acpi_bus_get_device(handle, &dev);
     803   [ #  #  #  # ]:          0 :                         if (ACPI_FAILURE(status) || dev != device)
     804                 :          0 :                                 continue;
     805         [ #  # ]:          0 :                         if (bind)
     806                 :          0 :                                 result = thermal_zone_bind_cooling_device
     807                 :            :                                         (thermal, trip, cdev,
     808                 :            :                                          THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
     809                 :            :                                          THERMAL_WEIGHT_DEFAULT);
     810                 :            :                         else
     811                 :          0 :                                 result = thermal_zone_unbind_cooling_device
     812                 :            :                                         (thermal, trip, cdev);
     813         [ #  # ]:          0 :                         if (result)
     814                 :          0 :                                 goto failed;
     815                 :            :                 }
     816                 :            :         }
     817                 :            : 
     818         [ #  # ]:          0 :         for (i = 0; i < tz->devices.count; i++) {
     819                 :          0 :                 handle = tz->devices.handles[i];
     820                 :          0 :                 status = acpi_bus_get_device(handle, &dev);
     821   [ #  #  #  # ]:          0 :                 if (ACPI_SUCCESS(status) && (dev == device)) {
     822         [ #  # ]:          0 :                         if (bind)
     823                 :          0 :                                 result = thermal_zone_bind_cooling_device
     824                 :            :                                                 (thermal, THERMAL_TRIPS_NONE,
     825                 :            :                                                  cdev, THERMAL_NO_LIMIT,
     826                 :            :                                                  THERMAL_NO_LIMIT,
     827                 :            :                                                  THERMAL_WEIGHT_DEFAULT);
     828                 :            :                         else
     829                 :          0 :                                 result = thermal_zone_unbind_cooling_device
     830                 :            :                                                 (thermal, THERMAL_TRIPS_NONE,
     831                 :            :                                                  cdev);
     832         [ #  # ]:          0 :                         if (result)
     833                 :          0 :                                 goto failed;
     834                 :            :                 }
     835                 :            :         }
     836                 :            : 
     837                 :          0 : failed:
     838                 :          0 :         return result;
     839                 :            : }
     840                 :            : 
     841                 :            : static int
     842                 :          0 : acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
     843                 :            :                                         struct thermal_cooling_device *cdev)
     844                 :            : {
     845                 :          0 :         return acpi_thermal_cooling_device_cb(thermal, cdev, true);
     846                 :            : }
     847                 :            : 
     848                 :            : static int
     849                 :          0 : acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
     850                 :            :                                         struct thermal_cooling_device *cdev)
     851                 :            : {
     852                 :          0 :         return acpi_thermal_cooling_device_cb(thermal, cdev, false);
     853                 :            : }
     854                 :            : 
     855                 :            : static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
     856                 :            :         .bind = acpi_thermal_bind_cooling_device,
     857                 :            :         .unbind = acpi_thermal_unbind_cooling_device,
     858                 :            :         .get_temp = thermal_get_temp,
     859                 :            :         .get_mode = thermal_get_mode,
     860                 :            :         .set_mode = thermal_set_mode,
     861                 :            :         .get_trip_type = thermal_get_trip_type,
     862                 :            :         .get_trip_temp = thermal_get_trip_temp,
     863                 :            :         .get_crit_temp = thermal_get_crit_temp,
     864                 :            :         .get_trend = thermal_get_trend,
     865                 :            :         .notify = thermal_notify,
     866                 :            : };
     867                 :            : 
     868                 :          0 : static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
     869                 :            : {
     870                 :          0 :         int trips = 0;
     871                 :          0 :         int result;
     872                 :          0 :         acpi_status status;
     873                 :          0 :         int i;
     874                 :            : 
     875                 :          0 :         if (tz->trips.critical.flags.valid)
     876                 :            :                 trips++;
     877                 :            : 
     878         [ #  # ]:          0 :         if (tz->trips.hot.flags.valid)
     879                 :          0 :                 trips++;
     880                 :            : 
     881         [ #  # ]:          0 :         if (tz->trips.passive.flags.valid)
     882                 :          0 :                 trips++;
     883                 :            : 
     884         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
     885         [ #  # ]:          0 :                         tz->trips.active[i].flags.valid; i++, trips++);
     886                 :            : 
     887         [ #  # ]:          0 :         if (tz->trips.passive.flags.valid)
     888                 :          0 :                 tz->thermal_zone =
     889                 :          0 :                         thermal_zone_device_register("acpitz", trips, 0, tz,
     890                 :            :                                                 &acpi_thermal_zone_ops, NULL,
     891                 :          0 :                                                      tz->trips.passive.tsp*100,
     892                 :          0 :                                                      tz->polling_frequency*100);
     893                 :            :         else
     894                 :          0 :                 tz->thermal_zone =
     895                 :          0 :                         thermal_zone_device_register("acpitz", trips, 0, tz,
     896                 :            :                                                 &acpi_thermal_zone_ops, NULL,
     897                 :          0 :                                                 0, tz->polling_frequency*100);
     898         [ #  # ]:          0 :         if (IS_ERR(tz->thermal_zone))
     899                 :            :                 return -ENODEV;
     900                 :            : 
     901                 :          0 :         result = sysfs_create_link(&tz->device->dev.kobj,
     902                 :            :                                    &tz->thermal_zone->device.kobj, "thermal_zone");
     903         [ #  # ]:          0 :         if (result)
     904                 :            :                 return result;
     905                 :            : 
     906                 :          0 :         result = sysfs_create_link(&tz->thermal_zone->device.kobj,
     907                 :          0 :                                    &tz->device->dev.kobj, "device");
     908         [ #  # ]:          0 :         if (result)
     909                 :            :                 return result;
     910                 :            : 
     911                 :          0 :         status =  acpi_bus_attach_private_data(tz->device->handle,
     912                 :          0 :                                                tz->thermal_zone);
     913         [ #  # ]:          0 :         if (ACPI_FAILURE(status))
     914                 :            :                 return -ENODEV;
     915                 :            : 
     916                 :          0 :         tz->tz_enabled = 1;
     917                 :            : 
     918                 :          0 :         dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
     919                 :            :                  tz->thermal_zone->id);
     920                 :          0 :         return 0;
     921                 :            : }
     922                 :            : 
     923                 :          0 : static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
     924                 :            : {
     925                 :          0 :         sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
     926                 :          0 :         sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
     927                 :          0 :         thermal_zone_device_unregister(tz->thermal_zone);
     928                 :          0 :         tz->thermal_zone = NULL;
     929                 :          0 :         acpi_bus_detach_private_data(tz->device->handle);
     930                 :          0 : }
     931                 :            : 
     932                 :            : 
     933                 :            : /* --------------------------------------------------------------------------
     934                 :            :                                  Driver Interface
     935                 :            :    -------------------------------------------------------------------------- */
     936                 :            : 
     937                 :          0 : static void acpi_thermal_notify(struct acpi_device *device, u32 event)
     938                 :            : {
     939         [ #  # ]:          0 :         struct acpi_thermal *tz = acpi_driver_data(device);
     940                 :            : 
     941                 :            : 
     942         [ #  # ]:          0 :         if (!tz)
     943                 :            :                 return;
     944                 :            : 
     945   [ #  #  #  # ]:          0 :         switch (event) {
     946                 :            :         case ACPI_THERMAL_NOTIFY_TEMPERATURE:
     947         [ #  # ]:          0 :                 acpi_thermal_check(tz);
     948                 :            :                 break;
     949                 :          0 :         case ACPI_THERMAL_NOTIFY_THRESHOLDS:
     950                 :          0 :                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
     951         [ #  # ]:          0 :                 acpi_thermal_check(tz);
     952         [ #  # ]:          0 :                 acpi_bus_generate_netlink_event(device->pnp.device_class,
     953                 :            :                                                   dev_name(&device->dev), event, 0);
     954                 :          0 :                 break;
     955                 :          0 :         case ACPI_THERMAL_NOTIFY_DEVICES:
     956                 :          0 :                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
     957         [ #  # ]:          0 :                 acpi_thermal_check(tz);
     958         [ #  # ]:          0 :                 acpi_bus_generate_netlink_event(device->pnp.device_class,
     959                 :            :                                                   dev_name(&device->dev), event, 0);
     960                 :          0 :                 break;
     961                 :            :         default:
     962                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     963                 :            :                                   "Unsupported event [0x%x]\n", event));
     964                 :            :                 break;
     965                 :            :         }
     966                 :            : }
     967                 :            : 
     968                 :            : /*
     969                 :            :  * On some platforms, the AML code has dependency about
     970                 :            :  * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
     971                 :            :  * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
     972                 :            :  *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
     973                 :            :  * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
     974                 :            :  *    if _TMP has never been evaluated.
     975                 :            :  *
     976                 :            :  * As this dependency is totally transparent to OS, evaluate
     977                 :            :  * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
     978                 :            :  * _TMP, before they are actually used.
     979                 :            :  */
     980                 :          0 : static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
     981                 :            : {
     982                 :          0 :         acpi_handle handle = tz->device->handle;
     983                 :          0 :         unsigned long long value;
     984                 :          0 :         int i;
     985                 :            : 
     986                 :          0 :         acpi_evaluate_integer(handle, "_CRT", NULL, &value);
     987                 :          0 :         acpi_evaluate_integer(handle, "_HOT", NULL, &value);
     988                 :          0 :         acpi_evaluate_integer(handle, "_PSV", NULL, &value);
     989         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
     990                 :          0 :                 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
     991                 :          0 :                 acpi_status status;
     992                 :            : 
     993                 :          0 :                 status = acpi_evaluate_integer(handle, name, NULL, &value);
     994         [ #  # ]:          0 :                 if (status == AE_NOT_FOUND)
     995                 :            :                         break;
     996                 :            :         }
     997                 :          0 :         acpi_evaluate_integer(handle, "_TMP", NULL, &value);
     998                 :          0 : }
     999                 :            : 
    1000                 :          0 : static int acpi_thermal_get_info(struct acpi_thermal *tz)
    1001                 :            : {
    1002                 :          0 :         int result = 0;
    1003                 :            : 
    1004                 :            : 
    1005         [ #  # ]:          0 :         if (!tz)
    1006                 :            :                 return -EINVAL;
    1007                 :            : 
    1008                 :          0 :         acpi_thermal_aml_dependency_fix(tz);
    1009                 :            : 
    1010                 :            :         /* Get trip points [_CRT, _PSV, etc.] (required) */
    1011                 :          0 :         result = acpi_thermal_get_trip_points(tz);
    1012         [ #  # ]:          0 :         if (result)
    1013                 :            :                 return result;
    1014                 :            : 
    1015                 :            :         /* Get temperature [_TMP] (required) */
    1016                 :          0 :         result = acpi_thermal_get_temperature(tz);
    1017         [ #  # ]:          0 :         if (result)
    1018                 :            :                 return result;
    1019                 :            : 
    1020                 :            :         /* Set the cooling mode [_SCP] to active cooling (default) */
    1021                 :          0 :         result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
    1022                 :          0 :         if (!result)
    1023                 :          0 :                 tz->flags.cooling_mode = 1;
    1024                 :            : 
    1025                 :            :         /* Get default polling frequency [_TZP] (optional) */
    1026         [ #  # ]:          0 :         if (tzp)
    1027                 :          0 :                 tz->polling_frequency = tzp;
    1028                 :            :         else
    1029                 :          0 :                 acpi_thermal_get_polling_frequency(tz);
    1030                 :            : 
    1031                 :            :         return 0;
    1032                 :            : }
    1033                 :            : 
    1034                 :            : /*
    1035                 :            :  * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
    1036                 :            :  * handles temperature values with a single decimal place. As a consequence,
    1037                 :            :  * some implementations use an offset of 273.1 and others use an offset of
    1038                 :            :  * 273.2. Try to find out which one is being used, to present the most
    1039                 :            :  * accurate and visually appealing number.
    1040                 :            :  *
    1041                 :            :  * The heuristic below should work for all ACPI thermal zones which have a
    1042                 :            :  * critical trip point with a value being a multiple of 0.5 degree Celsius.
    1043                 :            :  */
    1044                 :          0 : static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
    1045                 :            : {
    1046                 :          0 :         if (tz->trips.critical.flags.valid &&
    1047         [ #  # ]:          0 :             (tz->trips.critical.temperature % 5) == 1)
    1048                 :          0 :                 tz->kelvin_offset = 273100;
    1049                 :            :         else
    1050                 :          0 :                 tz->kelvin_offset = 273200;
    1051                 :            : }
    1052                 :            : 
    1053                 :          0 : static void acpi_thermal_check_fn(struct work_struct *work)
    1054                 :            : {
    1055                 :          0 :         struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
    1056                 :            :                                                thermal_check_work);
    1057         [ #  # ]:          0 :         acpi_thermal_check(tz);
    1058                 :          0 : }
    1059                 :            : 
    1060                 :          0 : static int acpi_thermal_add(struct acpi_device *device)
    1061                 :            : {
    1062                 :          0 :         int result = 0;
    1063                 :          0 :         struct acpi_thermal *tz = NULL;
    1064                 :            : 
    1065                 :            : 
    1066         [ #  # ]:          0 :         if (!device)
    1067                 :            :                 return -EINVAL;
    1068                 :            : 
    1069                 :          0 :         tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
    1070         [ #  # ]:          0 :         if (!tz)
    1071                 :            :                 return -ENOMEM;
    1072                 :            : 
    1073                 :          0 :         tz->device = device;
    1074                 :          0 :         strcpy(tz->name, device->pnp.bus_id);
    1075                 :          0 :         strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
    1076                 :          0 :         strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
    1077                 :          0 :         device->driver_data = tz;
    1078                 :            : 
    1079                 :          0 :         result = acpi_thermal_get_info(tz);
    1080         [ #  # ]:          0 :         if (result)
    1081                 :          0 :                 goto free_memory;
    1082                 :            : 
    1083         [ #  # ]:          0 :         acpi_thermal_guess_offset(tz);
    1084                 :            : 
    1085                 :          0 :         result = acpi_thermal_register_thermal_zone(tz);
    1086         [ #  # ]:          0 :         if (result)
    1087                 :          0 :                 goto free_memory;
    1088                 :            : 
    1089         [ #  # ]:          0 :         INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
    1090                 :            : 
    1091         [ #  # ]:          0 :         pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
    1092                 :            :                 acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
    1093                 :          0 :         goto end;
    1094                 :            : 
    1095                 :          0 : free_memory:
    1096                 :          0 :         kfree(tz);
    1097                 :            : end:
    1098                 :            :         return result;
    1099                 :            : }
    1100                 :            : 
    1101                 :          0 : static int acpi_thermal_remove(struct acpi_device *device)
    1102                 :            : {
    1103                 :          0 :         struct acpi_thermal *tz = NULL;
    1104                 :            : 
    1105   [ #  #  #  # ]:          0 :         if (!device || !acpi_driver_data(device))
    1106                 :            :                 return -EINVAL;
    1107                 :            : 
    1108                 :          0 :         flush_workqueue(acpi_thermal_pm_queue);
    1109                 :          0 :         tz = acpi_driver_data(device);
    1110                 :            : 
    1111                 :          0 :         acpi_thermal_unregister_thermal_zone(tz);
    1112                 :          0 :         kfree(tz);
    1113                 :          0 :         return 0;
    1114                 :            : }
    1115                 :            : 
    1116                 :            : #ifdef CONFIG_PM_SLEEP
    1117                 :          0 : static int acpi_thermal_suspend(struct device *dev)
    1118                 :            : {
    1119                 :            :         /* Make sure the previously queued thermal check work has been done */
    1120                 :          0 :         flush_workqueue(acpi_thermal_pm_queue);
    1121                 :          0 :         return 0;
    1122                 :            : }
    1123                 :            : 
    1124                 :          0 : static int acpi_thermal_resume(struct device *dev)
    1125                 :            : {
    1126                 :          0 :         struct acpi_thermal *tz;
    1127                 :          0 :         int i, j, power_state, result;
    1128                 :            : 
    1129         [ #  # ]:          0 :         if (!dev)
    1130                 :            :                 return -EINVAL;
    1131                 :            : 
    1132         [ #  # ]:          0 :         tz = acpi_driver_data(to_acpi_device(dev));
    1133         [ #  # ]:          0 :         if (!tz)
    1134                 :            :                 return -EINVAL;
    1135                 :            : 
    1136         [ #  # ]:          0 :         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
    1137         [ #  # ]:          0 :                 if (!(&tz->trips.active[i]))
    1138                 :            :                         break;
    1139         [ #  # ]:          0 :                 if (!tz->trips.active[i].flags.valid)
    1140                 :            :                         break;
    1141                 :          0 :                 tz->trips.active[i].flags.enabled = 1;
    1142         [ #  # ]:          0 :                 for (j = 0; j < tz->trips.active[i].devices.count; j++) {
    1143                 :          0 :                         result = acpi_bus_update_power(
    1144                 :            :                                         tz->trips.active[i].devices.handles[j],
    1145                 :            :                                         &power_state);
    1146   [ #  #  #  # ]:          0 :                         if (result || (power_state != ACPI_STATE_D0)) {
    1147                 :          0 :                                 tz->trips.active[i].flags.enabled = 0;
    1148                 :          0 :                                 break;
    1149                 :            :                         }
    1150                 :            :                 }
    1151                 :          0 :                 tz->state.active |= tz->trips.active[i].flags.enabled;
    1152                 :            :         }
    1153                 :            : 
    1154                 :          0 :         queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
    1155                 :            : 
    1156                 :          0 :         return AE_OK;
    1157                 :            : }
    1158                 :            : #endif
    1159                 :            : 
    1160                 :          0 : static int thermal_act(const struct dmi_system_id *d) {
    1161                 :            : 
    1162         [ #  # ]:          0 :         if (act == 0) {
    1163                 :          0 :                 pr_notice(PREFIX "%s detected: "
    1164                 :            :                           "disabling all active thermal trip points\n", d->ident);
    1165                 :          0 :                 act = -1;
    1166                 :            :         }
    1167                 :          0 :         return 0;
    1168                 :            : }
    1169                 :          0 : static int thermal_nocrt(const struct dmi_system_id *d) {
    1170                 :            : 
    1171                 :          0 :         pr_notice(PREFIX "%s detected: "
    1172                 :            :                   "disabling all critical thermal trip point actions.\n", d->ident);
    1173                 :          0 :         nocrt = 1;
    1174                 :          0 :         return 0;
    1175                 :            : }
    1176                 :          0 : static int thermal_tzp(const struct dmi_system_id *d) {
    1177                 :            : 
    1178         [ #  # ]:          0 :         if (tzp == 0) {
    1179                 :          0 :                 pr_notice(PREFIX "%s detected: "
    1180                 :            :                           "enabling thermal zone polling\n", d->ident);
    1181                 :          0 :                 tzp = 300;      /* 300 dS = 30 Seconds */
    1182                 :            :         }
    1183                 :          0 :         return 0;
    1184                 :            : }
    1185                 :          0 : static int thermal_psv(const struct dmi_system_id *d) {
    1186                 :            : 
    1187         [ #  # ]:          0 :         if (psv == 0) {
    1188                 :          0 :                 pr_notice(PREFIX "%s detected: "
    1189                 :            :                           "disabling all passive thermal trip points\n", d->ident);
    1190                 :          0 :                 psv = -1;
    1191                 :            :         }
    1192                 :          0 :         return 0;
    1193                 :            : }
    1194                 :            : 
    1195                 :            : static const struct dmi_system_id thermal_dmi_table[] __initconst = {
    1196                 :            :         /*
    1197                 :            :          * Award BIOS on this AOpen makes thermal control almost worthless.
    1198                 :            :          * http://bugzilla.kernel.org/show_bug.cgi?id=8842
    1199                 :            :          */
    1200                 :            :         {
    1201                 :            :          .callback = thermal_act,
    1202                 :            :          .ident = "AOpen i915GMm-HFS",
    1203                 :            :          .matches = {
    1204                 :            :                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
    1205                 :            :                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
    1206                 :            :                 },
    1207                 :            :         },
    1208                 :            :         {
    1209                 :            :          .callback = thermal_psv,
    1210                 :            :          .ident = "AOpen i915GMm-HFS",
    1211                 :            :          .matches = {
    1212                 :            :                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
    1213                 :            :                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
    1214                 :            :                 },
    1215                 :            :         },
    1216                 :            :         {
    1217                 :            :          .callback = thermal_tzp,
    1218                 :            :          .ident = "AOpen i915GMm-HFS",
    1219                 :            :          .matches = {
    1220                 :            :                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
    1221                 :            :                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
    1222                 :            :                 },
    1223                 :            :         },
    1224                 :            :         {
    1225                 :            :          .callback = thermal_nocrt,
    1226                 :            :          .ident = "Gigabyte GA-7ZX",
    1227                 :            :          .matches = {
    1228                 :            :                 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
    1229                 :            :                 DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
    1230                 :            :                 },
    1231                 :            :         },
    1232                 :            :         {}
    1233                 :            : };
    1234                 :            : 
    1235                 :         28 : static int __init acpi_thermal_init(void)
    1236                 :            : {
    1237                 :         28 :         int result = 0;
    1238                 :            : 
    1239                 :         28 :         dmi_check_system(thermal_dmi_table);
    1240                 :            : 
    1241         [ -  + ]:         28 :         if (off) {
    1242                 :          0 :                 pr_notice(PREFIX "thermal control disabled\n");
    1243                 :          0 :                 return -ENODEV;
    1244                 :            :         }
    1245                 :            : 
    1246                 :         28 :         acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm",
    1247                 :            :                                                 WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
    1248         [ +  - ]:         28 :         if (!acpi_thermal_pm_queue)
    1249                 :            :                 return -ENODEV;
    1250                 :            : 
    1251                 :         28 :         result = acpi_bus_register_driver(&acpi_thermal_driver);
    1252         [ -  + ]:         28 :         if (result < 0) {
    1253                 :          0 :                 destroy_workqueue(acpi_thermal_pm_queue);
    1254                 :          0 :                 return -ENODEV;
    1255                 :            :         }
    1256                 :            : 
    1257                 :            :         return 0;
    1258                 :            : }
    1259                 :            : 
    1260                 :          0 : static void __exit acpi_thermal_exit(void)
    1261                 :            : {
    1262                 :          0 :         acpi_bus_unregister_driver(&acpi_thermal_driver);
    1263                 :          0 :         destroy_workqueue(acpi_thermal_pm_queue);
    1264                 :            : 
    1265                 :          0 :         return;
    1266                 :            : }
    1267                 :            : 
    1268                 :            : module_init(acpi_thermal_init);
    1269                 :            : module_exit(acpi_thermal_exit);

Generated by: LCOV version 1.14