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