Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  *
0008  *  This driver fully implements the ACPI thermal policy as described in the
0009  *  ACPI 2.0 Specification.
0010  *
0011  *  TBD: 1. Implement passive cooling hysteresis.
0012  *       2. Enhance passive cooling (CPU) states/limit interface to support
0013  *          concepts of 'multiple limiters', upper/lower limits, etc.
0014  */
0015 
0016 #define pr_fmt(fmt) "ACPI: thermal: " fmt
0017 
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/dmi.h>
0021 #include <linux/init.h>
0022 #include <linux/slab.h>
0023 #include <linux/types.h>
0024 #include <linux/jiffies.h>
0025 #include <linux/kmod.h>
0026 #include <linux/reboot.h>
0027 #include <linux/device.h>
0028 #include <linux/thermal.h>
0029 #include <linux/acpi.h>
0030 #include <linux/workqueue.h>
0031 #include <linux/uaccess.h>
0032 #include <linux/units.h>
0033 
0034 #define ACPI_THERMAL_CLASS      "thermal_zone"
0035 #define ACPI_THERMAL_DEVICE_NAME    "Thermal Zone"
0036 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
0037 #define ACPI_THERMAL_NOTIFY_THRESHOLDS  0x81
0038 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
0039 #define ACPI_THERMAL_NOTIFY_CRITICAL    0xF0
0040 #define ACPI_THERMAL_NOTIFY_HOT     0xF1
0041 #define ACPI_THERMAL_MODE_ACTIVE    0x00
0042 
0043 #define ACPI_THERMAL_MAX_ACTIVE 10
0044 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
0045 
0046 MODULE_AUTHOR("Paul Diefenbaugh");
0047 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
0048 MODULE_LICENSE("GPL");
0049 
0050 static int act;
0051 module_param(act, int, 0644);
0052 MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
0053 
0054 static int crt;
0055 module_param(crt, int, 0644);
0056 MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
0057 
0058 static int tzp;
0059 module_param(tzp, int, 0444);
0060 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
0061 
0062 static int nocrt;
0063 module_param(nocrt, int, 0);
0064 MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
0065 
0066 static int off;
0067 module_param(off, int, 0);
0068 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
0069 
0070 static int psv;
0071 module_param(psv, int, 0644);
0072 MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
0073 
0074 static struct workqueue_struct *acpi_thermal_pm_queue;
0075 
0076 static int acpi_thermal_add(struct acpi_device *device);
0077 static int acpi_thermal_remove(struct acpi_device *device);
0078 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
0079 
0080 static const struct acpi_device_id  thermal_device_ids[] = {
0081     {ACPI_THERMAL_HID, 0},
0082     {"", 0},
0083 };
0084 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
0085 
0086 #ifdef CONFIG_PM_SLEEP
0087 static int acpi_thermal_suspend(struct device *dev);
0088 static int acpi_thermal_resume(struct device *dev);
0089 #else
0090 #define acpi_thermal_suspend NULL
0091 #define acpi_thermal_resume NULL
0092 #endif
0093 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
0094 
0095 static struct acpi_driver acpi_thermal_driver = {
0096     .name = "thermal",
0097     .class = ACPI_THERMAL_CLASS,
0098     .ids = thermal_device_ids,
0099     .ops = {
0100         .add = acpi_thermal_add,
0101         .remove = acpi_thermal_remove,
0102         .notify = acpi_thermal_notify,
0103         },
0104     .drv.pm = &acpi_thermal_pm,
0105 };
0106 
0107 struct acpi_thermal_state {
0108     u8 critical:1;
0109     u8 hot:1;
0110     u8 passive:1;
0111     u8 active:1;
0112     u8 reserved:4;
0113     int active_index;
0114 };
0115 
0116 struct acpi_thermal_state_flags {
0117     u8 valid:1;
0118     u8 enabled:1;
0119     u8 reserved:6;
0120 };
0121 
0122 struct acpi_thermal_critical {
0123     struct acpi_thermal_state_flags flags;
0124     unsigned long temperature;
0125 };
0126 
0127 struct acpi_thermal_hot {
0128     struct acpi_thermal_state_flags flags;
0129     unsigned long temperature;
0130 };
0131 
0132 struct acpi_thermal_passive {
0133     struct acpi_thermal_state_flags flags;
0134     unsigned long temperature;
0135     unsigned long tc1;
0136     unsigned long tc2;
0137     unsigned long tsp;
0138     struct acpi_handle_list devices;
0139 };
0140 
0141 struct acpi_thermal_active {
0142     struct acpi_thermal_state_flags flags;
0143     unsigned long temperature;
0144     struct acpi_handle_list devices;
0145 };
0146 
0147 struct acpi_thermal_trips {
0148     struct acpi_thermal_critical critical;
0149     struct acpi_thermal_hot hot;
0150     struct acpi_thermal_passive passive;
0151     struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
0152 };
0153 
0154 struct acpi_thermal_flags {
0155     u8 cooling_mode:1;  /* _SCP */
0156     u8 devices:1;       /* _TZD */
0157     u8 reserved:6;
0158 };
0159 
0160 struct acpi_thermal {
0161     struct acpi_device * device;
0162     acpi_bus_id name;
0163     unsigned long temperature;
0164     unsigned long last_temperature;
0165     unsigned long polling_frequency;
0166     volatile u8 zombie;
0167     struct acpi_thermal_flags flags;
0168     struct acpi_thermal_state state;
0169     struct acpi_thermal_trips trips;
0170     struct acpi_handle_list devices;
0171     struct thermal_zone_device *thermal_zone;
0172     int kelvin_offset;  /* in millidegrees */
0173     struct work_struct thermal_check_work;
0174     struct mutex thermal_check_lock;
0175     refcount_t thermal_check_count;
0176 };
0177 
0178 /* --------------------------------------------------------------------------
0179                              Thermal Zone Management
0180    -------------------------------------------------------------------------- */
0181 
0182 static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
0183 {
0184     acpi_status status = AE_OK;
0185     unsigned long long tmp;
0186 
0187     if (!tz)
0188         return -EINVAL;
0189 
0190     tz->last_temperature = tz->temperature;
0191 
0192     status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
0193     if (ACPI_FAILURE(status))
0194         return -ENODEV;
0195 
0196     tz->temperature = tmp;
0197 
0198     acpi_handle_debug(tz->device->handle, "Temperature is %lu dK\n",
0199               tz->temperature);
0200 
0201     return 0;
0202 }
0203 
0204 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
0205 {
0206     acpi_status status = AE_OK;
0207     unsigned long long tmp;
0208 
0209     if (!tz)
0210         return -EINVAL;
0211 
0212     status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
0213     if (ACPI_FAILURE(status))
0214         return -ENODEV;
0215 
0216     tz->polling_frequency = tmp;
0217     acpi_handle_debug(tz->device->handle, "Polling frequency is %lu dS\n",
0218               tz->polling_frequency);
0219 
0220     return 0;
0221 }
0222 
0223 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
0224 {
0225     if (!tz)
0226         return -EINVAL;
0227 
0228     if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
0229                             "_SCP", mode)))
0230         return -ENODEV;
0231 
0232     return 0;
0233 }
0234 
0235 #define ACPI_TRIPS_CRITICAL 0x01
0236 #define ACPI_TRIPS_HOT      0x02
0237 #define ACPI_TRIPS_PASSIVE  0x04
0238 #define ACPI_TRIPS_ACTIVE   0x08
0239 #define ACPI_TRIPS_DEVICES  0x10
0240 
0241 #define ACPI_TRIPS_REFRESH_THRESHOLDS   (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
0242 #define ACPI_TRIPS_REFRESH_DEVICES  ACPI_TRIPS_DEVICES
0243 
0244 #define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |    \
0245                   ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
0246                   ACPI_TRIPS_DEVICES)
0247 
0248 /*
0249  * This exception is thrown out in two cases:
0250  * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
0251  *   when re-evaluating the AML code.
0252  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
0253  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
0254  */
0255 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str)    \
0256 do {    \
0257     if (flags != ACPI_TRIPS_INIT)   \
0258         acpi_handle_info(tz->device->handle,    \
0259         "ACPI thermal trip point %s changed\n"  \
0260         "Please report to linux-acpi@vger.kernel.org\n", str); \
0261 } while (0)
0262 
0263 static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
0264 {
0265     acpi_status status = AE_OK;
0266     unsigned long long tmp;
0267     struct acpi_handle_list devices;
0268     int valid = 0;
0269     int i;
0270 
0271     /* Critical Shutdown */
0272     if (flag & ACPI_TRIPS_CRITICAL) {
0273         status = acpi_evaluate_integer(tz->device->handle,
0274                 "_CRT", NULL, &tmp);
0275         tz->trips.critical.temperature = tmp;
0276         /*
0277          * Treat freezing temperatures as invalid as well; some
0278          * BIOSes return really low values and cause reboots at startup.
0279          * Below zero (Celsius) values clearly aren't right for sure..
0280          * ... so lets discard those as invalid.
0281          */
0282         if (ACPI_FAILURE(status)) {
0283             tz->trips.critical.flags.valid = 0;
0284             acpi_handle_debug(tz->device->handle,
0285                       "No critical threshold\n");
0286         } else if (tmp <= 2732) {
0287             pr_info(FW_BUG "Invalid critical threshold (%llu)\n",
0288                 tmp);
0289             tz->trips.critical.flags.valid = 0;
0290         } else {
0291             tz->trips.critical.flags.valid = 1;
0292             acpi_handle_debug(tz->device->handle,
0293                       "Found critical threshold [%lu]\n",
0294                       tz->trips.critical.temperature);
0295         }
0296         if (tz->trips.critical.flags.valid == 1) {
0297             if (crt == -1) {
0298                 tz->trips.critical.flags.valid = 0;
0299             } else if (crt > 0) {
0300                 unsigned long crt_k = celsius_to_deci_kelvin(crt);
0301 
0302                 /*
0303                  * Allow override critical threshold
0304                  */
0305                 if (crt_k > tz->trips.critical.temperature)
0306                     pr_info("Critical threshold %d C\n", crt);
0307 
0308                 tz->trips.critical.temperature = crt_k;
0309             }
0310         }
0311     }
0312 
0313     /* Critical Sleep (optional) */
0314     if (flag & ACPI_TRIPS_HOT) {
0315         status = acpi_evaluate_integer(tz->device->handle,
0316                 "_HOT", NULL, &tmp);
0317         if (ACPI_FAILURE(status)) {
0318             tz->trips.hot.flags.valid = 0;
0319             acpi_handle_debug(tz->device->handle,
0320                       "No hot threshold\n");
0321         } else {
0322             tz->trips.hot.temperature = tmp;
0323             tz->trips.hot.flags.valid = 1;
0324             acpi_handle_debug(tz->device->handle,
0325                       "Found hot threshold [%lu]\n",
0326                       tz->trips.hot.temperature);
0327         }
0328     }
0329 
0330     /* Passive (optional) */
0331     if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
0332         (flag == ACPI_TRIPS_INIT)) {
0333         valid = tz->trips.passive.flags.valid;
0334         if (psv == -1) {
0335             status = AE_SUPPORT;
0336         } else if (psv > 0) {
0337             tmp = celsius_to_deci_kelvin(psv);
0338             status = AE_OK;
0339         } else {
0340             status = acpi_evaluate_integer(tz->device->handle,
0341                 "_PSV", NULL, &tmp);
0342         }
0343 
0344         if (ACPI_FAILURE(status))
0345             tz->trips.passive.flags.valid = 0;
0346         else {
0347             tz->trips.passive.temperature = tmp;
0348             tz->trips.passive.flags.valid = 1;
0349             if (flag == ACPI_TRIPS_INIT) {
0350                 status = acpi_evaluate_integer(
0351                         tz->device->handle, "_TC1",
0352                         NULL, &tmp);
0353                 if (ACPI_FAILURE(status))
0354                     tz->trips.passive.flags.valid = 0;
0355                 else
0356                     tz->trips.passive.tc1 = tmp;
0357                 status = acpi_evaluate_integer(
0358                         tz->device->handle, "_TC2",
0359                         NULL, &tmp);
0360                 if (ACPI_FAILURE(status))
0361                     tz->trips.passive.flags.valid = 0;
0362                 else
0363                     tz->trips.passive.tc2 = tmp;
0364                 status = acpi_evaluate_integer(
0365                         tz->device->handle, "_TSP",
0366                         NULL, &tmp);
0367                 if (ACPI_FAILURE(status))
0368                     tz->trips.passive.flags.valid = 0;
0369                 else
0370                     tz->trips.passive.tsp = tmp;
0371             }
0372         }
0373     }
0374     if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
0375         memset(&devices, 0, sizeof(struct acpi_handle_list));
0376         status = acpi_evaluate_reference(tz->device->handle, "_PSL",
0377                             NULL, &devices);
0378         if (ACPI_FAILURE(status)) {
0379             acpi_handle_info(tz->device->handle,
0380                      "Invalid passive threshold\n");
0381             tz->trips.passive.flags.valid = 0;
0382         }
0383         else
0384             tz->trips.passive.flags.valid = 1;
0385 
0386         if (memcmp(&tz->trips.passive.devices, &devices,
0387                 sizeof(struct acpi_handle_list))) {
0388             memcpy(&tz->trips.passive.devices, &devices,
0389                 sizeof(struct acpi_handle_list));
0390             ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
0391         }
0392     }
0393     if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
0394         if (valid != tz->trips.passive.flags.valid)
0395                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
0396     }
0397 
0398     /* Active (optional) */
0399     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
0400         char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
0401         valid = tz->trips.active[i].flags.valid;
0402 
0403         if (act == -1)
0404             break; /* disable all active trip points */
0405 
0406         if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
0407             tz->trips.active[i].flags.valid)) {
0408             status = acpi_evaluate_integer(tz->device->handle,
0409                             name, NULL, &tmp);
0410             if (ACPI_FAILURE(status)) {
0411                 tz->trips.active[i].flags.valid = 0;
0412                 if (i == 0)
0413                     break;
0414                 if (act <= 0)
0415                     break;
0416                 if (i == 1)
0417                     tz->trips.active[0].temperature =
0418                         celsius_to_deci_kelvin(act);
0419                 else
0420                     /*
0421                      * Don't allow override higher than
0422                      * the next higher trip point
0423                      */
0424                     tz->trips.active[i - 1].temperature =
0425                         (tz->trips.active[i - 2].temperature <
0426                         celsius_to_deci_kelvin(act) ?
0427                         tz->trips.active[i - 2].temperature :
0428                         celsius_to_deci_kelvin(act));
0429                 break;
0430             } else {
0431                 tz->trips.active[i].temperature = tmp;
0432                 tz->trips.active[i].flags.valid = 1;
0433             }
0434         }
0435 
0436         name[2] = 'L';
0437         if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
0438             memset(&devices, 0, sizeof(struct acpi_handle_list));
0439             status = acpi_evaluate_reference(tz->device->handle,
0440                         name, NULL, &devices);
0441             if (ACPI_FAILURE(status)) {
0442                 acpi_handle_info(tz->device->handle,
0443                          "Invalid active%d threshold\n", i);
0444                 tz->trips.active[i].flags.valid = 0;
0445             }
0446             else
0447                 tz->trips.active[i].flags.valid = 1;
0448 
0449             if (memcmp(&tz->trips.active[i].devices, &devices,
0450                     sizeof(struct acpi_handle_list))) {
0451                 memcpy(&tz->trips.active[i].devices, &devices,
0452                     sizeof(struct acpi_handle_list));
0453                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
0454             }
0455         }
0456         if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
0457             if (valid != tz->trips.active[i].flags.valid)
0458                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
0459 
0460         if (!tz->trips.active[i].flags.valid)
0461             break;
0462     }
0463 
0464     if (flag & ACPI_TRIPS_DEVICES) {
0465         memset(&devices, 0, sizeof(devices));
0466         status = acpi_evaluate_reference(tz->device->handle, "_TZD",
0467                         NULL, &devices);
0468         if (ACPI_SUCCESS(status)
0469             && memcmp(&tz->devices, &devices, sizeof(devices))) {
0470             tz->devices = devices;
0471             ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
0472         }
0473     }
0474 
0475     return 0;
0476 }
0477 
0478 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
0479 {
0480     int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
0481 
0482     if (ret)
0483         return ret;
0484 
0485     valid = tz->trips.critical.flags.valid |
0486         tz->trips.hot.flags.valid |
0487         tz->trips.passive.flags.valid;
0488 
0489     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
0490         valid |= tz->trips.active[i].flags.valid;
0491 
0492     if (!valid) {
0493         pr_warn(FW_BUG "No valid trip found\n");
0494         return -ENODEV;
0495     }
0496     return 0;
0497 }
0498 
0499 /* sys I/F for generic thermal sysfs support */
0500 
0501 static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
0502 {
0503     struct acpi_thermal *tz = thermal->devdata;
0504     int result;
0505 
0506     if (!tz)
0507         return -EINVAL;
0508 
0509     result = acpi_thermal_get_temperature(tz);
0510     if (result)
0511         return result;
0512 
0513     *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature,
0514                             tz->kelvin_offset);
0515     return 0;
0516 }
0517 
0518 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
0519                  int trip, enum thermal_trip_type *type)
0520 {
0521     struct acpi_thermal *tz = thermal->devdata;
0522     int i;
0523 
0524     if (!tz || trip < 0)
0525         return -EINVAL;
0526 
0527     if (tz->trips.critical.flags.valid) {
0528         if (!trip) {
0529             *type = THERMAL_TRIP_CRITICAL;
0530             return 0;
0531         }
0532         trip--;
0533     }
0534 
0535     if (tz->trips.hot.flags.valid) {
0536         if (!trip) {
0537             *type = THERMAL_TRIP_HOT;
0538             return 0;
0539         }
0540         trip--;
0541     }
0542 
0543     if (tz->trips.passive.flags.valid) {
0544         if (!trip) {
0545             *type = THERMAL_TRIP_PASSIVE;
0546             return 0;
0547         }
0548         trip--;
0549     }
0550 
0551     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
0552         tz->trips.active[i].flags.valid; i++) {
0553         if (!trip) {
0554             *type = THERMAL_TRIP_ACTIVE;
0555             return 0;
0556         }
0557         trip--;
0558     }
0559 
0560     return -EINVAL;
0561 }
0562 
0563 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
0564                  int trip, int *temp)
0565 {
0566     struct acpi_thermal *tz = thermal->devdata;
0567     int i;
0568 
0569     if (!tz || trip < 0)
0570         return -EINVAL;
0571 
0572     if (tz->trips.critical.flags.valid) {
0573         if (!trip) {
0574             *temp = deci_kelvin_to_millicelsius_with_offset(
0575                 tz->trips.critical.temperature,
0576                 tz->kelvin_offset);
0577             return 0;
0578         }
0579         trip--;
0580     }
0581 
0582     if (tz->trips.hot.flags.valid) {
0583         if (!trip) {
0584             *temp = deci_kelvin_to_millicelsius_with_offset(
0585                 tz->trips.hot.temperature,
0586                 tz->kelvin_offset);
0587             return 0;
0588         }
0589         trip--;
0590     }
0591 
0592     if (tz->trips.passive.flags.valid) {
0593         if (!trip) {
0594             *temp = deci_kelvin_to_millicelsius_with_offset(
0595                 tz->trips.passive.temperature,
0596                 tz->kelvin_offset);
0597             return 0;
0598         }
0599         trip--;
0600     }
0601 
0602     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
0603         tz->trips.active[i].flags.valid; i++) {
0604         if (!trip) {
0605             *temp = deci_kelvin_to_millicelsius_with_offset(
0606                 tz->trips.active[i].temperature,
0607                 tz->kelvin_offset);
0608             return 0;
0609         }
0610         trip--;
0611     }
0612 
0613     return -EINVAL;
0614 }
0615 
0616 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
0617                 int *temperature)
0618 {
0619     struct acpi_thermal *tz = thermal->devdata;
0620 
0621     if (tz->trips.critical.flags.valid) {
0622         *temperature = deci_kelvin_to_millicelsius_with_offset(
0623                 tz->trips.critical.temperature,
0624                 tz->kelvin_offset);
0625         return 0;
0626     } else
0627         return -EINVAL;
0628 }
0629 
0630 static int thermal_get_trend(struct thermal_zone_device *thermal,
0631                 int trip, enum thermal_trend *trend)
0632 {
0633     struct acpi_thermal *tz = thermal->devdata;
0634     enum thermal_trip_type type;
0635     int i;
0636 
0637     if (thermal_get_trip_type(thermal, trip, &type))
0638         return -EINVAL;
0639 
0640     if (type == THERMAL_TRIP_ACTIVE) {
0641         int trip_temp;
0642         int temp = deci_kelvin_to_millicelsius_with_offset(
0643                     tz->temperature, tz->kelvin_offset);
0644         if (thermal_get_trip_temp(thermal, trip, &trip_temp))
0645             return -EINVAL;
0646 
0647         if (temp > trip_temp) {
0648             *trend = THERMAL_TREND_RAISING;
0649             return 0;
0650         } else {
0651             /* Fall back on default trend */
0652             return -EINVAL;
0653         }
0654     }
0655 
0656     /*
0657      * tz->temperature has already been updated by generic thermal layer,
0658      * before this callback being invoked
0659      */
0660     i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
0661         + (tz->trips.passive.tc2
0662         * (tz->temperature - tz->trips.passive.temperature));
0663 
0664     if (i > 0)
0665         *trend = THERMAL_TREND_RAISING;
0666     else if (i < 0)
0667         *trend = THERMAL_TREND_DROPPING;
0668     else
0669         *trend = THERMAL_TREND_STABLE;
0670     return 0;
0671 }
0672 
0673 static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal)
0674 {
0675     struct acpi_thermal *tz = thermal->devdata;
0676 
0677     acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
0678                     dev_name(&tz->device->dev),
0679                     ACPI_THERMAL_NOTIFY_HOT, 1);
0680 }
0681 
0682 static void acpi_thermal_zone_device_critical(struct thermal_zone_device *thermal)
0683 {
0684     struct acpi_thermal *tz = thermal->devdata;
0685 
0686     acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
0687                     dev_name(&tz->device->dev),
0688                     ACPI_THERMAL_NOTIFY_CRITICAL, 1);
0689 
0690     thermal_zone_device_critical(thermal);
0691 }
0692 
0693 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
0694                     struct thermal_cooling_device *cdev,
0695                     bool bind)
0696 {
0697     struct acpi_device *device = cdev->devdata;
0698     struct acpi_thermal *tz = thermal->devdata;
0699     struct acpi_device *dev;
0700     acpi_handle handle;
0701     int i;
0702     int j;
0703     int trip = -1;
0704     int result = 0;
0705 
0706     if (tz->trips.critical.flags.valid)
0707         trip++;
0708 
0709     if (tz->trips.hot.flags.valid)
0710         trip++;
0711 
0712     if (tz->trips.passive.flags.valid) {
0713         trip++;
0714         for (i = 0; i < tz->trips.passive.devices.count;
0715             i++) {
0716             handle = tz->trips.passive.devices.handles[i];
0717             dev = acpi_fetch_acpi_dev(handle);
0718             if (dev != device)
0719                 continue;
0720             if (bind)
0721                 result =
0722                     thermal_zone_bind_cooling_device
0723                     (thermal, trip, cdev,
0724                      THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
0725                      THERMAL_WEIGHT_DEFAULT);
0726             else
0727                 result =
0728                     thermal_zone_unbind_cooling_device
0729                     (thermal, trip, cdev);
0730             if (result)
0731                 goto failed;
0732         }
0733     }
0734 
0735     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
0736         if (!tz->trips.active[i].flags.valid)
0737             break;
0738         trip++;
0739         for (j = 0;
0740             j < tz->trips.active[i].devices.count;
0741             j++) {
0742             handle = tz->trips.active[i].devices.handles[j];
0743             dev = acpi_fetch_acpi_dev(handle);
0744             if (dev != device)
0745                 continue;
0746             if (bind)
0747                 result = thermal_zone_bind_cooling_device
0748                     (thermal, trip, cdev,
0749                      THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
0750                      THERMAL_WEIGHT_DEFAULT);
0751             else
0752                 result = thermal_zone_unbind_cooling_device
0753                     (thermal, trip, cdev);
0754             if (result)
0755                 goto failed;
0756         }
0757     }
0758 
0759 failed:
0760     return result;
0761 }
0762 
0763 static int
0764 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
0765                     struct thermal_cooling_device *cdev)
0766 {
0767     return acpi_thermal_cooling_device_cb(thermal, cdev, true);
0768 }
0769 
0770 static int
0771 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
0772                     struct thermal_cooling_device *cdev)
0773 {
0774     return acpi_thermal_cooling_device_cb(thermal, cdev, false);
0775 }
0776 
0777 static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
0778     .bind = acpi_thermal_bind_cooling_device,
0779     .unbind = acpi_thermal_unbind_cooling_device,
0780     .get_temp = thermal_get_temp,
0781     .get_trip_type = thermal_get_trip_type,
0782     .get_trip_temp = thermal_get_trip_temp,
0783     .get_crit_temp = thermal_get_crit_temp,
0784     .get_trend = thermal_get_trend,
0785     .hot = acpi_thermal_zone_device_hot,
0786     .critical = acpi_thermal_zone_device_critical,
0787 };
0788 
0789 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
0790 {
0791     int trips = 0;
0792     int result;
0793     acpi_status status;
0794     int i;
0795 
0796     if (tz->trips.critical.flags.valid)
0797         trips++;
0798 
0799     if (tz->trips.hot.flags.valid)
0800         trips++;
0801 
0802     if (tz->trips.passive.flags.valid)
0803         trips++;
0804 
0805     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
0806             tz->trips.active[i].flags.valid; i++, trips++);
0807 
0808     if (tz->trips.passive.flags.valid)
0809         tz->thermal_zone =
0810             thermal_zone_device_register("acpitz", trips, 0, tz,
0811                         &acpi_thermal_zone_ops, NULL,
0812                              tz->trips.passive.tsp*100,
0813                              tz->polling_frequency*100);
0814     else
0815         tz->thermal_zone =
0816             thermal_zone_device_register("acpitz", trips, 0, tz,
0817                         &acpi_thermal_zone_ops, NULL,
0818                         0, tz->polling_frequency*100);
0819     if (IS_ERR(tz->thermal_zone))
0820         return -ENODEV;
0821 
0822     result = sysfs_create_link(&tz->device->dev.kobj,
0823                    &tz->thermal_zone->device.kobj, "thermal_zone");
0824     if (result)
0825         goto unregister_tzd;
0826 
0827     result = sysfs_create_link(&tz->thermal_zone->device.kobj,
0828                    &tz->device->dev.kobj, "device");
0829     if (result)
0830         goto remove_tz_link;
0831 
0832     status =  acpi_bus_attach_private_data(tz->device->handle,
0833                            tz->thermal_zone);
0834     if (ACPI_FAILURE(status)) {
0835         result = -ENODEV;
0836         goto remove_dev_link;
0837     }
0838 
0839     result = thermal_zone_device_enable(tz->thermal_zone);
0840     if (result)
0841         goto acpi_bus_detach;
0842 
0843     dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
0844          tz->thermal_zone->id);
0845 
0846     return 0;
0847 
0848 acpi_bus_detach:
0849     acpi_bus_detach_private_data(tz->device->handle);
0850 remove_dev_link:
0851     sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
0852 remove_tz_link:
0853     sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
0854 unregister_tzd:
0855     thermal_zone_device_unregister(tz->thermal_zone);
0856 
0857     return result;
0858 }
0859 
0860 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
0861 {
0862     sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
0863     sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
0864     thermal_zone_device_unregister(tz->thermal_zone);
0865     tz->thermal_zone = NULL;
0866     acpi_bus_detach_private_data(tz->device->handle);
0867 }
0868 
0869 
0870 /* --------------------------------------------------------------------------
0871                                  Driver Interface
0872    -------------------------------------------------------------------------- */
0873 
0874 static void acpi_queue_thermal_check(struct acpi_thermal *tz)
0875 {
0876     if (!work_pending(&tz->thermal_check_work))
0877         queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
0878 }
0879 
0880 static void acpi_thermal_notify(struct acpi_device *device, u32 event)
0881 {
0882     struct acpi_thermal *tz = acpi_driver_data(device);
0883 
0884 
0885     if (!tz)
0886         return;
0887 
0888     switch (event) {
0889     case ACPI_THERMAL_NOTIFY_TEMPERATURE:
0890         acpi_queue_thermal_check(tz);
0891         break;
0892     case ACPI_THERMAL_NOTIFY_THRESHOLDS:
0893         acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
0894         acpi_queue_thermal_check(tz);
0895         acpi_bus_generate_netlink_event(device->pnp.device_class,
0896                           dev_name(&device->dev), event, 0);
0897         break;
0898     case ACPI_THERMAL_NOTIFY_DEVICES:
0899         acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
0900         acpi_queue_thermal_check(tz);
0901         acpi_bus_generate_netlink_event(device->pnp.device_class,
0902                           dev_name(&device->dev), event, 0);
0903         break;
0904     default:
0905         acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
0906                   event);
0907         break;
0908     }
0909 }
0910 
0911 /*
0912  * On some platforms, the AML code has dependency about
0913  * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
0914  * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
0915  *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
0916  * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
0917  *    if _TMP has never been evaluated.
0918  *
0919  * As this dependency is totally transparent to OS, evaluate
0920  * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
0921  * _TMP, before they are actually used.
0922  */
0923 static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
0924 {
0925     acpi_handle handle = tz->device->handle;
0926     unsigned long long value;
0927     int i;
0928 
0929     acpi_evaluate_integer(handle, "_CRT", NULL, &value);
0930     acpi_evaluate_integer(handle, "_HOT", NULL, &value);
0931     acpi_evaluate_integer(handle, "_PSV", NULL, &value);
0932     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
0933         char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
0934         acpi_status status;
0935 
0936         status = acpi_evaluate_integer(handle, name, NULL, &value);
0937         if (status == AE_NOT_FOUND)
0938             break;
0939     }
0940     acpi_evaluate_integer(handle, "_TMP", NULL, &value);
0941 }
0942 
0943 static int acpi_thermal_get_info(struct acpi_thermal *tz)
0944 {
0945     int result = 0;
0946 
0947 
0948     if (!tz)
0949         return -EINVAL;
0950 
0951     acpi_thermal_aml_dependency_fix(tz);
0952 
0953     /* Get trip points [_CRT, _PSV, etc.] (required) */
0954     result = acpi_thermal_get_trip_points(tz);
0955     if (result)
0956         return result;
0957 
0958     /* Get temperature [_TMP] (required) */
0959     result = acpi_thermal_get_temperature(tz);
0960     if (result)
0961         return result;
0962 
0963     /* Set the cooling mode [_SCP] to active cooling (default) */
0964     result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
0965     if (!result)
0966         tz->flags.cooling_mode = 1;
0967 
0968     /* Get default polling frequency [_TZP] (optional) */
0969     if (tzp)
0970         tz->polling_frequency = tzp;
0971     else
0972         acpi_thermal_get_polling_frequency(tz);
0973 
0974     return 0;
0975 }
0976 
0977 /*
0978  * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
0979  * handles temperature values with a single decimal place. As a consequence,
0980  * some implementations use an offset of 273.1 and others use an offset of
0981  * 273.2. Try to find out which one is being used, to present the most
0982  * accurate and visually appealing number.
0983  *
0984  * The heuristic below should work for all ACPI thermal zones which have a
0985  * critical trip point with a value being a multiple of 0.5 degree Celsius.
0986  */
0987 static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
0988 {
0989     if (tz->trips.critical.flags.valid &&
0990         (tz->trips.critical.temperature % 5) == 1)
0991         tz->kelvin_offset = 273100;
0992     else
0993         tz->kelvin_offset = 273200;
0994 }
0995 
0996 static void acpi_thermal_check_fn(struct work_struct *work)
0997 {
0998     struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
0999                            thermal_check_work);
1000 
1001     /*
1002      * In general, it is not sufficient to check the pending bit, because
1003      * subsequent instances of this function may be queued after one of them
1004      * has started running (e.g. if _TMP sleeps).  Avoid bailing out if just
1005      * one of them is running, though, because it may have done the actual
1006      * check some time ago, so allow at least one of them to block on the
1007      * mutex while another one is running the update.
1008      */
1009     if (!refcount_dec_not_one(&tz->thermal_check_count))
1010         return;
1011 
1012     mutex_lock(&tz->thermal_check_lock);
1013 
1014     thermal_zone_device_update(tz->thermal_zone, THERMAL_EVENT_UNSPECIFIED);
1015 
1016     refcount_inc(&tz->thermal_check_count);
1017 
1018     mutex_unlock(&tz->thermal_check_lock);
1019 }
1020 
1021 static int acpi_thermal_add(struct acpi_device *device)
1022 {
1023     int result = 0;
1024     struct acpi_thermal *tz = NULL;
1025 
1026 
1027     if (!device)
1028         return -EINVAL;
1029 
1030     tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1031     if (!tz)
1032         return -ENOMEM;
1033 
1034     tz->device = device;
1035     strcpy(tz->name, device->pnp.bus_id);
1036     strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1037     strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1038     device->driver_data = tz;
1039 
1040     result = acpi_thermal_get_info(tz);
1041     if (result)
1042         goto free_memory;
1043 
1044     acpi_thermal_guess_offset(tz);
1045 
1046     result = acpi_thermal_register_thermal_zone(tz);
1047     if (result)
1048         goto free_memory;
1049 
1050     refcount_set(&tz->thermal_check_count, 3);
1051     mutex_init(&tz->thermal_check_lock);
1052     INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
1053 
1054     pr_info("%s [%s] (%ld C)\n", acpi_device_name(device),
1055         acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
1056     goto end;
1057 
1058 free_memory:
1059     kfree(tz);
1060 end:
1061     return result;
1062 }
1063 
1064 static int acpi_thermal_remove(struct acpi_device *device)
1065 {
1066     struct acpi_thermal *tz = NULL;
1067 
1068     if (!device || !acpi_driver_data(device))
1069         return -EINVAL;
1070 
1071     flush_workqueue(acpi_thermal_pm_queue);
1072     tz = acpi_driver_data(device);
1073 
1074     acpi_thermal_unregister_thermal_zone(tz);
1075     kfree(tz);
1076     return 0;
1077 }
1078 
1079 #ifdef CONFIG_PM_SLEEP
1080 static int acpi_thermal_suspend(struct device *dev)
1081 {
1082     /* Make sure the previously queued thermal check work has been done */
1083     flush_workqueue(acpi_thermal_pm_queue);
1084     return 0;
1085 }
1086 
1087 static int acpi_thermal_resume(struct device *dev)
1088 {
1089     struct acpi_thermal *tz;
1090     int i, j, power_state, result;
1091 
1092     if (!dev)
1093         return -EINVAL;
1094 
1095     tz = acpi_driver_data(to_acpi_device(dev));
1096     if (!tz)
1097         return -EINVAL;
1098 
1099     for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1100         if (!tz->trips.active[i].flags.valid)
1101             break;
1102         tz->trips.active[i].flags.enabled = 1;
1103         for (j = 0; j < tz->trips.active[i].devices.count; j++) {
1104             result = acpi_bus_update_power(
1105                     tz->trips.active[i].devices.handles[j],
1106                     &power_state);
1107             if (result || (power_state != ACPI_STATE_D0)) {
1108                 tz->trips.active[i].flags.enabled = 0;
1109                 break;
1110             }
1111         }
1112         tz->state.active |= tz->trips.active[i].flags.enabled;
1113     }
1114 
1115     acpi_queue_thermal_check(tz);
1116 
1117     return AE_OK;
1118 }
1119 #endif
1120 
1121 static int thermal_act(const struct dmi_system_id *d) {
1122 
1123     if (act == 0) {
1124         pr_notice("%s detected: disabling all active thermal trip points\n",
1125               d->ident);
1126         act = -1;
1127     }
1128     return 0;
1129 }
1130 static int thermal_nocrt(const struct dmi_system_id *d) {
1131 
1132     pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
1133           d->ident);
1134     nocrt = 1;
1135     return 0;
1136 }
1137 static int thermal_tzp(const struct dmi_system_id *d) {
1138 
1139     if (tzp == 0) {
1140         pr_notice("%s detected: enabling thermal zone polling\n",
1141               d->ident);
1142         tzp = 300;  /* 300 dS = 30 Seconds */
1143     }
1144     return 0;
1145 }
1146 static int thermal_psv(const struct dmi_system_id *d) {
1147 
1148     if (psv == 0) {
1149         pr_notice("%s detected: disabling all passive thermal trip points\n",
1150               d->ident);
1151         psv = -1;
1152     }
1153     return 0;
1154 }
1155 
1156 static const struct dmi_system_id thermal_dmi_table[] __initconst = {
1157     /*
1158      * Award BIOS on this AOpen makes thermal control almost worthless.
1159      * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1160      */
1161     {
1162      .callback = thermal_act,
1163      .ident = "AOpen i915GMm-HFS",
1164      .matches = {
1165         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1166         DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1167         },
1168     },
1169     {
1170      .callback = thermal_psv,
1171      .ident = "AOpen i915GMm-HFS",
1172      .matches = {
1173         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1174         DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1175         },
1176     },
1177     {
1178      .callback = thermal_tzp,
1179      .ident = "AOpen i915GMm-HFS",
1180      .matches = {
1181         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1182         DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1183         },
1184     },
1185     {
1186      .callback = thermal_nocrt,
1187      .ident = "Gigabyte GA-7ZX",
1188      .matches = {
1189         DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
1190         DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
1191         },
1192     },
1193     {}
1194 };
1195 
1196 static int __init acpi_thermal_init(void)
1197 {
1198     int result = 0;
1199 
1200     dmi_check_system(thermal_dmi_table);
1201 
1202     if (off) {
1203         pr_notice("thermal control disabled\n");
1204         return -ENODEV;
1205     }
1206 
1207     acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm",
1208                         WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
1209     if (!acpi_thermal_pm_queue)
1210         return -ENODEV;
1211 
1212     result = acpi_bus_register_driver(&acpi_thermal_driver);
1213     if (result < 0) {
1214         destroy_workqueue(acpi_thermal_pm_queue);
1215         return -ENODEV;
1216     }
1217 
1218     return 0;
1219 }
1220 
1221 static void __exit acpi_thermal_exit(void)
1222 {
1223     acpi_bus_unregister_driver(&acpi_thermal_driver);
1224     destroy_workqueue(acpi_thermal_pm_queue);
1225 
1226     return;
1227 }
1228 
1229 module_init(acpi_thermal_init);
1230 module_exit(acpi_thermal_exit);