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