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