linux/drivers/thermal/thermal_sys.c
<<
>>
Prefs
   1/*
   2 *  thermal.c - Generic Thermal Management Sysfs support.
   3 *
   4 *  Copyright (C) 2008 Intel Corp
   5 *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
   6 *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
   7 *
   8 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   9 *
  10 *  This program is free software; you can redistribute it and/or modify
  11 *  it under the terms of the GNU General Public License as published by
  12 *  the Free Software Foundation; version 2 of the License.
  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
  26#include <linux/module.h>
  27#include <linux/device.h>
  28#include <linux/err.h>
  29#include <linux/slab.h>
  30#include <linux/kdev_t.h>
  31#include <linux/idr.h>
  32#include <linux/thermal.h>
  33#include <linux/spinlock.h>
  34#include <linux/reboot.h>
  35
  36MODULE_AUTHOR("Zhang Rui");
  37MODULE_DESCRIPTION("Generic thermal management sysfs support");
  38MODULE_LICENSE("GPL");
  39
  40#define PREFIX "Thermal: "
  41
  42struct thermal_cooling_device_instance {
  43        int id;
  44        char name[THERMAL_NAME_LENGTH];
  45        struct thermal_zone_device *tz;
  46        struct thermal_cooling_device *cdev;
  47        int trip;
  48        char attr_name[THERMAL_NAME_LENGTH];
  49        struct device_attribute attr;
  50        struct list_head node;
  51};
  52
  53static DEFINE_IDR(thermal_tz_idr);
  54static DEFINE_IDR(thermal_cdev_idr);
  55static DEFINE_MUTEX(thermal_idr_lock);
  56
  57static LIST_HEAD(thermal_tz_list);
  58static LIST_HEAD(thermal_cdev_list);
  59static DEFINE_MUTEX(thermal_list_lock);
  60
  61static int get_idr(struct idr *idr, struct mutex *lock, int *id)
  62{
  63        int err;
  64
  65      again:
  66        if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
  67                return -ENOMEM;
  68
  69        if (lock)
  70                mutex_lock(lock);
  71        err = idr_get_new(idr, NULL, id);
  72        if (lock)
  73                mutex_unlock(lock);
  74        if (unlikely(err == -EAGAIN))
  75                goto again;
  76        else if (unlikely(err))
  77                return err;
  78
  79        *id = *id & MAX_ID_MASK;
  80        return 0;
  81}
  82
  83static void release_idr(struct idr *idr, struct mutex *lock, int id)
  84{
  85        if (lock)
  86                mutex_lock(lock);
  87        idr_remove(idr, id);
  88        if (lock)
  89                mutex_unlock(lock);
  90}
  91
  92/* sys I/F for thermal zone */
  93
  94#define to_thermal_zone(_dev) \
  95        container_of(_dev, struct thermal_zone_device, device)
  96
  97static ssize_t
  98type_show(struct device *dev, struct device_attribute *attr, char *buf)
  99{
 100        struct thermal_zone_device *tz = to_thermal_zone(dev);
 101
 102        return sprintf(buf, "%s\n", tz->type);
 103}
 104
 105static ssize_t
 106temp_show(struct device *dev, struct device_attribute *attr, char *buf)
 107{
 108        struct thermal_zone_device *tz = to_thermal_zone(dev);
 109        long temperature;
 110        int ret;
 111
 112        if (!tz->ops->get_temp)
 113                return -EPERM;
 114
 115        ret = tz->ops->get_temp(tz, &temperature);
 116
 117        if (ret)
 118                return ret;
 119
 120        return sprintf(buf, "%ld\n", temperature);
 121}
 122
 123static ssize_t
 124mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 125{
 126        struct thermal_zone_device *tz = to_thermal_zone(dev);
 127        enum thermal_device_mode mode;
 128        int result;
 129
 130        if (!tz->ops->get_mode)
 131                return -EPERM;
 132
 133        result = tz->ops->get_mode(tz, &mode);
 134        if (result)
 135                return result;
 136
 137        return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
 138                       : "disabled");
 139}
 140
 141static ssize_t
 142mode_store(struct device *dev, struct device_attribute *attr,
 143           const char *buf, size_t count)
 144{
 145        struct thermal_zone_device *tz = to_thermal_zone(dev);
 146        int result;
 147
 148        if (!tz->ops->set_mode)
 149                return -EPERM;
 150
 151        if (!strncmp(buf, "enabled", sizeof("enabled")))
 152                result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
 153        else if (!strncmp(buf, "disabled", sizeof("disabled")))
 154                result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
 155        else
 156                result = -EINVAL;
 157
 158        if (result)
 159                return result;
 160
 161        return count;
 162}
 163
 164static ssize_t
 165trip_point_type_show(struct device *dev, struct device_attribute *attr,
 166                     char *buf)
 167{
 168        struct thermal_zone_device *tz = to_thermal_zone(dev);
 169        enum thermal_trip_type type;
 170        int trip, result;
 171
 172        if (!tz->ops->get_trip_type)
 173                return -EPERM;
 174
 175        if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
 176                return -EINVAL;
 177
 178        result = tz->ops->get_trip_type(tz, trip, &type);
 179        if (result)
 180                return result;
 181
 182        switch (type) {
 183        case THERMAL_TRIP_CRITICAL:
 184                return sprintf(buf, "critical\n");
 185        case THERMAL_TRIP_HOT:
 186                return sprintf(buf, "hot\n");
 187        case THERMAL_TRIP_PASSIVE:
 188                return sprintf(buf, "passive\n");
 189        case THERMAL_TRIP_ACTIVE:
 190                return sprintf(buf, "active\n");
 191        default:
 192                return sprintf(buf, "unknown\n");
 193        }
 194}
 195
 196static ssize_t
 197trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 198                     char *buf)
 199{
 200        struct thermal_zone_device *tz = to_thermal_zone(dev);
 201        int trip, ret;
 202        long temperature;
 203
 204        if (!tz->ops->get_trip_temp)
 205                return -EPERM;
 206
 207        if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
 208                return -EINVAL;
 209
 210        ret = tz->ops->get_trip_temp(tz, trip, &temperature);
 211
 212        if (ret)
 213                return ret;
 214
 215        return sprintf(buf, "%ld\n", temperature);
 216}
 217
 218static ssize_t
 219passive_store(struct device *dev, struct device_attribute *attr,
 220                    const char *buf, size_t count)
 221{
 222        struct thermal_zone_device *tz = to_thermal_zone(dev);
 223        struct thermal_cooling_device *cdev = NULL;
 224        int state;
 225
 226        if (!sscanf(buf, "%d\n", &state))
 227                return -EINVAL;
 228
 229        /* sanity check: values below 1000 millicelcius don't make sense
 230         * and can cause the system to go into a thermal heart attack
 231         */
 232        if (state && state < 1000)
 233                return -EINVAL;
 234
 235        if (state && !tz->forced_passive) {
 236                mutex_lock(&thermal_list_lock);
 237                list_for_each_entry(cdev, &thermal_cdev_list, node) {
 238                        if (!strncmp("Processor", cdev->type,
 239                                     sizeof("Processor")))
 240                                thermal_zone_bind_cooling_device(tz,
 241                                                                 THERMAL_TRIPS_NONE,
 242                                                                 cdev);
 243                }
 244                mutex_unlock(&thermal_list_lock);
 245                if (!tz->passive_delay)
 246                        tz->passive_delay = 1000;
 247        } else if (!state && tz->forced_passive) {
 248                mutex_lock(&thermal_list_lock);
 249                list_for_each_entry(cdev, &thermal_cdev_list, node) {
 250                        if (!strncmp("Processor", cdev->type,
 251                                     sizeof("Processor")))
 252                                thermal_zone_unbind_cooling_device(tz,
 253                                                                   THERMAL_TRIPS_NONE,
 254                                                                   cdev);
 255                }
 256                mutex_unlock(&thermal_list_lock);
 257                tz->passive_delay = 0;
 258        }
 259
 260        tz->tc1 = 1;
 261        tz->tc2 = 1;
 262
 263        tz->forced_passive = state;
 264
 265        thermal_zone_device_update(tz);
 266
 267        return count;
 268}
 269
 270static ssize_t
 271passive_show(struct device *dev, struct device_attribute *attr,
 272                   char *buf)
 273{
 274        struct thermal_zone_device *tz = to_thermal_zone(dev);
 275
 276        return sprintf(buf, "%d\n", tz->forced_passive);
 277}
 278
 279static DEVICE_ATTR(type, 0444, type_show, NULL);
 280static DEVICE_ATTR(temp, 0444, temp_show, NULL);
 281static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 282static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \
 283                   passive_store);
 284
 285static struct device_attribute trip_point_attrs[] = {
 286        __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
 287        __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL),
 288        __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL),
 289        __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL),
 290        __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL),
 291        __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL),
 292        __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL),
 293        __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL),
 294        __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL),
 295        __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL),
 296        __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL),
 297        __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL),
 298        __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL),
 299        __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL),
 300        __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL),
 301        __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL),
 302        __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL),
 303        __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL),
 304        __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL),
 305        __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL),
 306        __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL),
 307        __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL),
 308        __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL),
 309        __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL),
 310};
 311
 312#define TRIP_POINT_ATTR_ADD(_dev, _index, result)     \
 313do {    \
 314        result = device_create_file(_dev,       \
 315                                &trip_point_attrs[_index * 2]); \
 316        if (result)     \
 317                break;  \
 318        result = device_create_file(_dev,       \
 319                        &trip_point_attrs[_index * 2 + 1]);     \
 320} while (0)
 321
 322#define TRIP_POINT_ATTR_REMOVE(_dev, _index)    \
 323do {    \
 324        device_remove_file(_dev, &trip_point_attrs[_index * 2]);        \
 325        device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);    \
 326} while (0)
 327
 328/* sys I/F for cooling device */
 329#define to_cooling_device(_dev) \
 330        container_of(_dev, struct thermal_cooling_device, device)
 331
 332static ssize_t
 333thermal_cooling_device_type_show(struct device *dev,
 334                                 struct device_attribute *attr, char *buf)
 335{
 336        struct thermal_cooling_device *cdev = to_cooling_device(dev);
 337
 338        return sprintf(buf, "%s\n", cdev->type);
 339}
 340
 341static ssize_t
 342thermal_cooling_device_max_state_show(struct device *dev,
 343                                      struct device_attribute *attr, char *buf)
 344{
 345        struct thermal_cooling_device *cdev = to_cooling_device(dev);
 346        unsigned long state;
 347        int ret;
 348
 349        ret = cdev->ops->get_max_state(cdev, &state);
 350        if (ret)
 351                return ret;
 352        return sprintf(buf, "%ld\n", state);
 353}
 354
 355static ssize_t
 356thermal_cooling_device_cur_state_show(struct device *dev,
 357                                      struct device_attribute *attr, char *buf)
 358{
 359        struct thermal_cooling_device *cdev = to_cooling_device(dev);
 360        unsigned long state;
 361        int ret;
 362
 363        ret = cdev->ops->get_cur_state(cdev, &state);
 364        if (ret)
 365                return ret;
 366        return sprintf(buf, "%ld\n", state);
 367}
 368
 369static ssize_t
 370thermal_cooling_device_cur_state_store(struct device *dev,
 371                                       struct device_attribute *attr,
 372                                       const char *buf, size_t count)
 373{
 374        struct thermal_cooling_device *cdev = to_cooling_device(dev);
 375        unsigned long state;
 376        int result;
 377
 378        if (!sscanf(buf, "%ld\n", &state))
 379                return -EINVAL;
 380
 381        if ((long)state < 0)
 382                return -EINVAL;
 383
 384        result = cdev->ops->set_cur_state(cdev, state);
 385        if (result)
 386                return result;
 387        return count;
 388}
 389
 390static struct device_attribute dev_attr_cdev_type =
 391__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
 392static DEVICE_ATTR(max_state, 0444,
 393                   thermal_cooling_device_max_state_show, NULL);
 394static DEVICE_ATTR(cur_state, 0644,
 395                   thermal_cooling_device_cur_state_show,
 396                   thermal_cooling_device_cur_state_store);
 397
 398static ssize_t
 399thermal_cooling_device_trip_point_show(struct device *dev,
 400                                       struct device_attribute *attr, char *buf)
 401{
 402        struct thermal_cooling_device_instance *instance;
 403
 404        instance =
 405            container_of(attr, struct thermal_cooling_device_instance, attr);
 406
 407        if (instance->trip == THERMAL_TRIPS_NONE)
 408                return sprintf(buf, "-1\n");
 409        else
 410                return sprintf(buf, "%d\n", instance->trip);
 411}
 412
 413/* Device management */
 414
 415#if defined(CONFIG_THERMAL_HWMON)
 416
 417/* hwmon sys I/F */
 418#include <linux/hwmon.h>
 419static LIST_HEAD(thermal_hwmon_list);
 420
 421static ssize_t
 422name_show(struct device *dev, struct device_attribute *attr, char *buf)
 423{
 424        struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev);
 425        return sprintf(buf, "%s\n", hwmon->type);
 426}
 427static DEVICE_ATTR(name, 0444, name_show, NULL);
 428
 429static ssize_t
 430temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
 431{
 432        long temperature;
 433        int ret;
 434        struct thermal_hwmon_attr *hwmon_attr
 435                        = container_of(attr, struct thermal_hwmon_attr, attr);
 436        struct thermal_zone_device *tz
 437                        = container_of(hwmon_attr, struct thermal_zone_device,
 438                                       temp_input);
 439
 440        ret = tz->ops->get_temp(tz, &temperature);
 441
 442        if (ret)
 443                return ret;
 444
 445        return sprintf(buf, "%ld\n", temperature);
 446}
 447
 448static ssize_t
 449temp_crit_show(struct device *dev, struct device_attribute *attr,
 450                char *buf)
 451{
 452        struct thermal_hwmon_attr *hwmon_attr
 453                        = container_of(attr, struct thermal_hwmon_attr, attr);
 454        struct thermal_zone_device *tz
 455                        = container_of(hwmon_attr, struct thermal_zone_device,
 456                                       temp_crit);
 457        long temperature;
 458        int ret;
 459
 460        ret = tz->ops->get_trip_temp(tz, 0, &temperature);
 461        if (ret)
 462                return ret;
 463
 464        return sprintf(buf, "%ld\n", temperature);
 465}
 466
 467
 468static int
 469thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
 470{
 471        struct thermal_hwmon_device *hwmon;
 472        int new_hwmon_device = 1;
 473        int result;
 474
 475        mutex_lock(&thermal_list_lock);
 476        list_for_each_entry(hwmon, &thermal_hwmon_list, node)
 477                if (!strcmp(hwmon->type, tz->type)) {
 478                        new_hwmon_device = 0;
 479                        mutex_unlock(&thermal_list_lock);
 480                        goto register_sys_interface;
 481                }
 482        mutex_unlock(&thermal_list_lock);
 483
 484        hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL);
 485        if (!hwmon)
 486                return -ENOMEM;
 487
 488        INIT_LIST_HEAD(&hwmon->tz_list);
 489        strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
 490        hwmon->device = hwmon_device_register(NULL);
 491        if (IS_ERR(hwmon->device)) {
 492                result = PTR_ERR(hwmon->device);
 493                goto free_mem;
 494        }
 495        dev_set_drvdata(hwmon->device, hwmon);
 496        result = device_create_file(hwmon->device, &dev_attr_name);
 497        if (result)
 498                goto unregister_hwmon_device;
 499
 500 register_sys_interface:
 501        tz->hwmon = hwmon;
 502        hwmon->count++;
 503
 504        snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH,
 505                 "temp%d_input", hwmon->count);
 506        tz->temp_input.attr.attr.name = tz->temp_input.name;
 507        tz->temp_input.attr.attr.mode = 0444;
 508        tz->temp_input.attr.show = temp_input_show;
 509        sysfs_attr_init(&tz->temp_input.attr.attr);
 510        result = device_create_file(hwmon->device, &tz->temp_input.attr);
 511        if (result)
 512                goto unregister_hwmon_device;
 513
 514        if (tz->ops->get_crit_temp) {
 515                unsigned long temperature;
 516                if (!tz->ops->get_crit_temp(tz, &temperature)) {
 517                        snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH,
 518                                "temp%d_crit", hwmon->count);
 519                        tz->temp_crit.attr.attr.name = tz->temp_crit.name;
 520                        tz->temp_crit.attr.attr.mode = 0444;
 521                        tz->temp_crit.attr.show = temp_crit_show;
 522                        sysfs_attr_init(&tz->temp_crit.attr.attr);
 523                        result = device_create_file(hwmon->device,
 524                                                    &tz->temp_crit.attr);
 525                        if (result)
 526                                goto unregister_hwmon_device;
 527                }
 528        }
 529
 530        mutex_lock(&thermal_list_lock);
 531        if (new_hwmon_device)
 532                list_add_tail(&hwmon->node, &thermal_hwmon_list);
 533        list_add_tail(&tz->hwmon_node, &hwmon->tz_list);
 534        mutex_unlock(&thermal_list_lock);
 535
 536        return 0;
 537
 538 unregister_hwmon_device:
 539        device_remove_file(hwmon->device, &tz->temp_crit.attr);
 540        device_remove_file(hwmon->device, &tz->temp_input.attr);
 541        if (new_hwmon_device) {
 542                device_remove_file(hwmon->device, &dev_attr_name);
 543                hwmon_device_unregister(hwmon->device);
 544        }
 545 free_mem:
 546        if (new_hwmon_device)
 547                kfree(hwmon);
 548
 549        return result;
 550}
 551
 552static void
 553thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 554{
 555        struct thermal_hwmon_device *hwmon = tz->hwmon;
 556
 557        tz->hwmon = NULL;
 558        device_remove_file(hwmon->device, &tz->temp_input.attr);
 559        device_remove_file(hwmon->device, &tz->temp_crit.attr);
 560
 561        mutex_lock(&thermal_list_lock);
 562        list_del(&tz->hwmon_node);
 563        if (!list_empty(&hwmon->tz_list)) {
 564                mutex_unlock(&thermal_list_lock);
 565                return;
 566        }
 567        list_del(&hwmon->node);
 568        mutex_unlock(&thermal_list_lock);
 569
 570        device_remove_file(hwmon->device, &dev_attr_name);
 571        hwmon_device_unregister(hwmon->device);
 572        kfree(hwmon);
 573}
 574#else
 575static int
 576thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
 577{
 578        return 0;
 579}
 580
 581static void
 582thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 583{
 584}
 585#endif
 586
 587static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
 588                                            int delay)
 589{
 590        cancel_delayed_work(&(tz->poll_queue));
 591
 592        if (!delay)
 593                return;
 594
 595        if (delay > 1000)
 596                schedule_delayed_work(&(tz->poll_queue),
 597                                      round_jiffies(msecs_to_jiffies(delay)));
 598        else
 599                schedule_delayed_work(&(tz->poll_queue),
 600                                      msecs_to_jiffies(delay));
 601}
 602
 603static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 604                                        int temp, int trip_temp, int trip)
 605{
 606        int trend = 0;
 607        struct thermal_cooling_device_instance *instance;
 608        struct thermal_cooling_device *cdev;
 609        long state, max_state;
 610
 611        /*
 612         * Above Trip?
 613         * -----------
 614         * Calculate the thermal trend (using the passive cooling equation)
 615         * and modify the performance limit for all passive cooling devices
 616         * accordingly.  Note that we assume symmetry.
 617         */
 618        if (temp >= trip_temp) {
 619                tz->passive = true;
 620
 621                trend = (tz->tc1 * (temp - tz->last_temperature)) +
 622                        (tz->tc2 * (temp - trip_temp));
 623
 624                /* Heating up? */
 625                if (trend > 0) {
 626                        list_for_each_entry(instance, &tz->cooling_devices,
 627                                            node) {
 628                                if (instance->trip != trip)
 629                                        continue;
 630                                cdev = instance->cdev;
 631                                cdev->ops->get_cur_state(cdev, &state);
 632                                cdev->ops->get_max_state(cdev, &max_state);
 633                                if (state++ < max_state)
 634                                        cdev->ops->set_cur_state(cdev, state);
 635                        }
 636                } else if (trend < 0) { /* Cooling off? */
 637                        list_for_each_entry(instance, &tz->cooling_devices,
 638                                            node) {
 639                                if (instance->trip != trip)
 640                                        continue;
 641                                cdev = instance->cdev;
 642                                cdev->ops->get_cur_state(cdev, &state);
 643                                cdev->ops->get_max_state(cdev, &max_state);
 644                                if (state > 0)
 645                                        cdev->ops->set_cur_state(cdev, --state);
 646                        }
 647                }
 648                return;
 649        }
 650
 651        /*
 652         * Below Trip?
 653         * -----------
 654         * Implement passive cooling hysteresis to slowly increase performance
 655         * and avoid thrashing around the passive trip point.  Note that we
 656         * assume symmetry.
 657         */
 658        list_for_each_entry(instance, &tz->cooling_devices, node) {
 659                if (instance->trip != trip)
 660                        continue;
 661                cdev = instance->cdev;
 662                cdev->ops->get_cur_state(cdev, &state);
 663                cdev->ops->get_max_state(cdev, &max_state);
 664                if (state > 0)
 665                        cdev->ops->set_cur_state(cdev, --state);
 666                if (state == 0)
 667                        tz->passive = false;
 668        }
 669}
 670
 671static void thermal_zone_device_check(struct work_struct *work)
 672{
 673        struct thermal_zone_device *tz = container_of(work, struct
 674                                                      thermal_zone_device,
 675                                                      poll_queue.work);
 676        thermal_zone_device_update(tz);
 677}
 678
 679/**
 680 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
 681 * @tz:         thermal zone device
 682 * @trip:       indicates which trip point the cooling devices is
 683 *              associated with in this thermal zone.
 684 * @cdev:       thermal cooling device
 685 *
 686 * This function is usually called in the thermal zone device .bind callback.
 687 */
 688int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 689                                     int trip,
 690                                     struct thermal_cooling_device *cdev)
 691{
 692        struct thermal_cooling_device_instance *dev;
 693        struct thermal_cooling_device_instance *pos;
 694        struct thermal_zone_device *pos1;
 695        struct thermal_cooling_device *pos2;
 696        int result;
 697
 698        if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
 699                return -EINVAL;
 700
 701        list_for_each_entry(pos1, &thermal_tz_list, node) {
 702                if (pos1 == tz)
 703                        break;
 704        }
 705        list_for_each_entry(pos2, &thermal_cdev_list, node) {
 706                if (pos2 == cdev)
 707                        break;
 708        }
 709
 710        if (tz != pos1 || cdev != pos2)
 711                return -EINVAL;
 712
 713        dev =
 714            kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL);
 715        if (!dev)
 716                return -ENOMEM;
 717        dev->tz = tz;
 718        dev->cdev = cdev;
 719        dev->trip = trip;
 720        result = get_idr(&tz->idr, &tz->lock, &dev->id);
 721        if (result)
 722                goto free_mem;
 723
 724        sprintf(dev->name, "cdev%d", dev->id);
 725        result =
 726            sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
 727        if (result)
 728                goto release_idr;
 729
 730        sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
 731        sysfs_attr_init(&dev->attr.attr);
 732        dev->attr.attr.name = dev->attr_name;
 733        dev->attr.attr.mode = 0444;
 734        dev->attr.show = thermal_cooling_device_trip_point_show;
 735        result = device_create_file(&tz->device, &dev->attr);
 736        if (result)
 737                goto remove_symbol_link;
 738
 739        mutex_lock(&tz->lock);
 740        list_for_each_entry(pos, &tz->cooling_devices, node)
 741            if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 742                result = -EEXIST;
 743                break;
 744        }
 745        if (!result)
 746                list_add_tail(&dev->node, &tz->cooling_devices);
 747        mutex_unlock(&tz->lock);
 748
 749        if (!result)
 750                return 0;
 751
 752        device_remove_file(&tz->device, &dev->attr);
 753      remove_symbol_link:
 754        sysfs_remove_link(&tz->device.kobj, dev->name);
 755      release_idr:
 756        release_idr(&tz->idr, &tz->lock, dev->id);
 757      free_mem:
 758        kfree(dev);
 759        return result;
 760}
 761
 762EXPORT_SYMBOL(thermal_zone_bind_cooling_device);
 763
 764/**
 765 * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone
 766 * @tz:         thermal zone device
 767 * @trip:       indicates which trip point the cooling devices is
 768 *              associated with in this thermal zone.
 769 * @cdev:       thermal cooling device
 770 *
 771 * This function is usually called in the thermal zone device .unbind callback.
 772 */
 773int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 774                                       int trip,
 775                                       struct thermal_cooling_device *cdev)
 776{
 777        struct thermal_cooling_device_instance *pos, *next;
 778
 779        mutex_lock(&tz->lock);
 780        list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) {
 781                if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
 782                        list_del(&pos->node);
 783                        mutex_unlock(&tz->lock);
 784                        goto unbind;
 785                }
 786        }
 787        mutex_unlock(&tz->lock);
 788
 789        return -ENODEV;
 790
 791      unbind:
 792        device_remove_file(&tz->device, &pos->attr);
 793        sysfs_remove_link(&tz->device.kobj, pos->name);
 794        release_idr(&tz->idr, &tz->lock, pos->id);
 795        kfree(pos);
 796        return 0;
 797}
 798
 799EXPORT_SYMBOL(thermal_zone_unbind_cooling_device);
 800
 801static void thermal_release(struct device *dev)
 802{
 803        struct thermal_zone_device *tz;
 804        struct thermal_cooling_device *cdev;
 805
 806        if (!strncmp(dev_name(dev), "thermal_zone", sizeof "thermal_zone" - 1)) {
 807                tz = to_thermal_zone(dev);
 808                kfree(tz);
 809        } else {
 810                cdev = to_cooling_device(dev);
 811                kfree(cdev);
 812        }
 813}
 814
 815static struct class thermal_class = {
 816        .name = "thermal",
 817        .dev_release = thermal_release,
 818};
 819
 820/**
 821 * thermal_cooling_device_register - register a new thermal cooling device
 822 * @type:       the thermal cooling device type.
 823 * @devdata:    device private data.
 824 * @ops:                standard thermal cooling devices callbacks.
 825 */
 826struct thermal_cooling_device *thermal_cooling_device_register(char *type,
 827                                                               void *devdata,
 828                                                               struct
 829                                                               thermal_cooling_device_ops
 830                                                               *ops)
 831{
 832        struct thermal_cooling_device *cdev;
 833        struct thermal_zone_device *pos;
 834        int result;
 835
 836        if (strlen(type) >= THERMAL_NAME_LENGTH)
 837                return ERR_PTR(-EINVAL);
 838
 839        if (!ops || !ops->get_max_state || !ops->get_cur_state ||
 840            !ops->set_cur_state)
 841                return ERR_PTR(-EINVAL);
 842
 843        cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
 844        if (!cdev)
 845                return ERR_PTR(-ENOMEM);
 846
 847        result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id);
 848        if (result) {
 849                kfree(cdev);
 850                return ERR_PTR(result);
 851        }
 852
 853        strcpy(cdev->type, type);
 854        cdev->ops = ops;
 855        cdev->device.class = &thermal_class;
 856        cdev->devdata = devdata;
 857        dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
 858        result = device_register(&cdev->device);
 859        if (result) {
 860                release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
 861                kfree(cdev);
 862                return ERR_PTR(result);
 863        }
 864
 865        /* sys I/F */
 866        if (type) {
 867                result = device_create_file(&cdev->device, &dev_attr_cdev_type);
 868                if (result)
 869                        goto unregister;
 870        }
 871
 872        result = device_create_file(&cdev->device, &dev_attr_max_state);
 873        if (result)
 874                goto unregister;
 875
 876        result = device_create_file(&cdev->device, &dev_attr_cur_state);
 877        if (result)
 878                goto unregister;
 879
 880        mutex_lock(&thermal_list_lock);
 881        list_add(&cdev->node, &thermal_cdev_list);
 882        list_for_each_entry(pos, &thermal_tz_list, node) {
 883                if (!pos->ops->bind)
 884                        continue;
 885                result = pos->ops->bind(pos, cdev);
 886                if (result)
 887                        break;
 888
 889        }
 890        mutex_unlock(&thermal_list_lock);
 891
 892        if (!result)
 893                return cdev;
 894
 895      unregister:
 896        release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
 897        device_unregister(&cdev->device);
 898        return ERR_PTR(result);
 899}
 900
 901EXPORT_SYMBOL(thermal_cooling_device_register);
 902
 903/**
 904 * thermal_cooling_device_unregister - removes the registered thermal cooling device
 905 * @cdev:       the thermal cooling device to remove.
 906 *
 907 * thermal_cooling_device_unregister() must be called when the device is no
 908 * longer needed.
 909 */
 910void thermal_cooling_device_unregister(struct
 911                                       thermal_cooling_device
 912                                       *cdev)
 913{
 914        struct thermal_zone_device *tz;
 915        struct thermal_cooling_device *pos = NULL;
 916
 917        if (!cdev)
 918                return;
 919
 920        mutex_lock(&thermal_list_lock);
 921        list_for_each_entry(pos, &thermal_cdev_list, node)
 922            if (pos == cdev)
 923                break;
 924        if (pos != cdev) {
 925                /* thermal cooling device not found */
 926                mutex_unlock(&thermal_list_lock);
 927                return;
 928        }
 929        list_del(&cdev->node);
 930        list_for_each_entry(tz, &thermal_tz_list, node) {
 931                if (!tz->ops->unbind)
 932                        continue;
 933                tz->ops->unbind(tz, cdev);
 934        }
 935        mutex_unlock(&thermal_list_lock);
 936        if (cdev->type[0])
 937                device_remove_file(&cdev->device, &dev_attr_cdev_type);
 938        device_remove_file(&cdev->device, &dev_attr_max_state);
 939        device_remove_file(&cdev->device, &dev_attr_cur_state);
 940
 941        release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
 942        device_unregister(&cdev->device);
 943        return;
 944}
 945
 946EXPORT_SYMBOL(thermal_cooling_device_unregister);
 947
 948/**
 949 * thermal_zone_device_update - force an update of a thermal zone's state
 950 * @ttz:        the thermal zone to update
 951 */
 952
 953void thermal_zone_device_update(struct thermal_zone_device *tz)
 954{
 955        int count, ret = 0;
 956        long temp, trip_temp;
 957        enum thermal_trip_type trip_type;
 958        struct thermal_cooling_device_instance *instance;
 959        struct thermal_cooling_device *cdev;
 960
 961        mutex_lock(&tz->lock);
 962
 963        if (tz->ops->get_temp(tz, &temp)) {
 964                /* get_temp failed - retry it later */
 965                printk(KERN_WARNING PREFIX "failed to read out thermal zone "
 966                       "%d\n", tz->id);
 967                goto leave;
 968        }
 969
 970        for (count = 0; count < tz->trips; count++) {
 971                tz->ops->get_trip_type(tz, count, &trip_type);
 972                tz->ops->get_trip_temp(tz, count, &trip_temp);
 973
 974                switch (trip_type) {
 975                case THERMAL_TRIP_CRITICAL:
 976                        if (temp >= trip_temp) {
 977                                if (tz->ops->notify)
 978                                        ret = tz->ops->notify(tz, count,
 979                                                              trip_type);
 980                                if (!ret) {
 981                                        printk(KERN_EMERG
 982                                               "Critical temperature reached (%ld C), shutting down.\n",
 983                                               temp/1000);
 984                                        orderly_poweroff(true);
 985                                }
 986                        }
 987                        break;
 988                case THERMAL_TRIP_HOT:
 989                        if (temp >= trip_temp)
 990                                if (tz->ops->notify)
 991                                        tz->ops->notify(tz, count, trip_type);
 992                        break;
 993                case THERMAL_TRIP_ACTIVE:
 994                        list_for_each_entry(instance, &tz->cooling_devices,
 995                                            node) {
 996                                if (instance->trip != count)
 997                                        continue;
 998
 999                                cdev = instance->cdev;
1000
1001                                if (temp >= trip_temp)
1002                                        cdev->ops->set_cur_state(cdev, 1);
1003                                else
1004                                        cdev->ops->set_cur_state(cdev, 0);
1005                        }
1006                        break;
1007                case THERMAL_TRIP_PASSIVE:
1008                        if (temp >= trip_temp || tz->passive)
1009                                thermal_zone_device_passive(tz, temp,
1010                                                            trip_temp, count);
1011                        break;
1012                }
1013        }
1014
1015        if (tz->forced_passive)
1016                thermal_zone_device_passive(tz, temp, tz->forced_passive,
1017                                            THERMAL_TRIPS_NONE);
1018
1019        tz->last_temperature = temp;
1020
1021      leave:
1022        if (tz->passive)
1023                thermal_zone_device_set_polling(tz, tz->passive_delay);
1024        else if (tz->polling_delay)
1025                thermal_zone_device_set_polling(tz, tz->polling_delay);
1026        else
1027                thermal_zone_device_set_polling(tz, 0);
1028        mutex_unlock(&tz->lock);
1029}
1030EXPORT_SYMBOL(thermal_zone_device_update);
1031
1032/**
1033 * thermal_zone_device_register - register a new thermal zone device
1034 * @type:       the thermal zone device type
1035 * @trips:      the number of trip points the thermal zone support
1036 * @devdata:    private device data
1037 * @ops:        standard thermal zone device callbacks
1038 * @tc1:        thermal coefficient 1 for passive calculations
1039 * @tc2:        thermal coefficient 2 for passive calculations
1040 * @passive_delay: number of milliseconds to wait between polls when
1041 *                 performing passive cooling
1042 * @polling_delay: number of milliseconds to wait between polls when checking
1043 *                 whether trip points have been crossed (0 for interrupt
1044 *                 driven systems)
1045 *
1046 * thermal_zone_device_unregister() must be called when the device is no
1047 * longer needed. The passive cooling formula uses tc1 and tc2 as described in
1048 * section 11.1.5.1 of the ACPI specification 3.0.
1049 */
1050struct thermal_zone_device *thermal_zone_device_register(char *type,
1051                                                         int trips,
1052                                                         void *devdata, struct
1053                                                         thermal_zone_device_ops
1054                                                         *ops, int tc1, int
1055                                                         tc2,
1056                                                         int passive_delay,
1057                                                         int polling_delay)
1058{
1059        struct thermal_zone_device *tz;
1060        struct thermal_cooling_device *pos;
1061        enum thermal_trip_type trip_type;
1062        int result;
1063        int count;
1064        int passive = 0;
1065
1066        if (strlen(type) >= THERMAL_NAME_LENGTH)
1067                return ERR_PTR(-EINVAL);
1068
1069        if (trips > THERMAL_MAX_TRIPS || trips < 0)
1070                return ERR_PTR(-EINVAL);
1071
1072        if (!ops || !ops->get_temp)
1073                return ERR_PTR(-EINVAL);
1074
1075        tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
1076        if (!tz)
1077                return ERR_PTR(-ENOMEM);
1078
1079        INIT_LIST_HEAD(&tz->cooling_devices);
1080        idr_init(&tz->idr);
1081        mutex_init(&tz->lock);
1082        result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id);
1083        if (result) {
1084                kfree(tz);
1085                return ERR_PTR(result);
1086        }
1087
1088        strcpy(tz->type, type);
1089        tz->ops = ops;
1090        tz->device.class = &thermal_class;
1091        tz->devdata = devdata;
1092        tz->trips = trips;
1093        tz->tc1 = tc1;
1094        tz->tc2 = tc2;
1095        tz->passive_delay = passive_delay;
1096        tz->polling_delay = polling_delay;
1097
1098        dev_set_name(&tz->device, "thermal_zone%d", tz->id);
1099        result = device_register(&tz->device);
1100        if (result) {
1101                release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
1102                kfree(tz);
1103                return ERR_PTR(result);
1104        }
1105
1106        /* sys I/F */
1107        if (type) {
1108                result = device_create_file(&tz->device, &dev_attr_type);
1109                if (result)
1110                        goto unregister;
1111        }
1112
1113        result = device_create_file(&tz->device, &dev_attr_temp);
1114        if (result)
1115                goto unregister;
1116
1117        if (ops->get_mode) {
1118                result = device_create_file(&tz->device, &dev_attr_mode);
1119                if (result)
1120                        goto unregister;
1121        }
1122
1123        for (count = 0; count < trips; count++) {
1124                TRIP_POINT_ATTR_ADD(&tz->device, count, result);
1125                if (result)
1126                        goto unregister;
1127                tz->ops->get_trip_type(tz, count, &trip_type);
1128                if (trip_type == THERMAL_TRIP_PASSIVE)
1129                        passive = 1;
1130        }
1131
1132        if (!passive)
1133                result = device_create_file(&tz->device,
1134                                            &dev_attr_passive);
1135
1136        if (result)
1137                goto unregister;
1138
1139        result = thermal_add_hwmon_sysfs(tz);
1140        if (result)
1141                goto unregister;
1142
1143        mutex_lock(&thermal_list_lock);
1144        list_add_tail(&tz->node, &thermal_tz_list);
1145        if (ops->bind)
1146                list_for_each_entry(pos, &thermal_cdev_list, node) {
1147                result = ops->bind(tz, pos);
1148                if (result)
1149                        break;
1150                }
1151        mutex_unlock(&thermal_list_lock);
1152
1153        INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
1154
1155        thermal_zone_device_update(tz);
1156
1157        if (!result)
1158                return tz;
1159
1160      unregister:
1161        release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
1162        device_unregister(&tz->device);
1163        return ERR_PTR(result);
1164}
1165
1166EXPORT_SYMBOL(thermal_zone_device_register);
1167
1168/**
1169 * thermal_device_unregister - removes the registered thermal zone device
1170 * @tz: the thermal zone device to remove
1171 */
1172void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1173{
1174        struct thermal_cooling_device *cdev;
1175        struct thermal_zone_device *pos = NULL;
1176        int count;
1177
1178        if (!tz)
1179                return;
1180
1181        mutex_lock(&thermal_list_lock);
1182        list_for_each_entry(pos, &thermal_tz_list, node)
1183            if (pos == tz)
1184                break;
1185        if (pos != tz) {
1186                /* thermal zone device not found */
1187                mutex_unlock(&thermal_list_lock);
1188                return;
1189        }
1190        list_del(&tz->node);
1191        if (tz->ops->unbind)
1192                list_for_each_entry(cdev, &thermal_cdev_list, node)
1193                    tz->ops->unbind(tz, cdev);
1194        mutex_unlock(&thermal_list_lock);
1195
1196        thermal_zone_device_set_polling(tz, 0);
1197
1198        if (tz->type[0])
1199                device_remove_file(&tz->device, &dev_attr_type);
1200        device_remove_file(&tz->device, &dev_attr_temp);
1201        if (tz->ops->get_mode)
1202                device_remove_file(&tz->device, &dev_attr_mode);
1203
1204        for (count = 0; count < tz->trips; count++)
1205                TRIP_POINT_ATTR_REMOVE(&tz->device, count);
1206
1207        thermal_remove_hwmon_sysfs(tz);
1208        release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
1209        idr_destroy(&tz->idr);
1210        mutex_destroy(&tz->lock);
1211        device_unregister(&tz->device);
1212        return;
1213}
1214
1215EXPORT_SYMBOL(thermal_zone_device_unregister);
1216
1217static int __init thermal_init(void)
1218{
1219        int result = 0;
1220
1221        result = class_register(&thermal_class);
1222        if (result) {
1223                idr_destroy(&thermal_tz_idr);
1224                idr_destroy(&thermal_cdev_idr);
1225                mutex_destroy(&thermal_idr_lock);
1226                mutex_destroy(&thermal_list_lock);
1227        }
1228        return result;
1229}
1230
1231static void __exit thermal_exit(void)
1232{
1233        class_unregister(&thermal_class);
1234        idr_destroy(&thermal_tz_idr);
1235        idr_destroy(&thermal_cdev_idr);
1236        mutex_destroy(&thermal_idr_lock);
1237        mutex_destroy(&thermal_list_lock);
1238}
1239
1240subsys_initcall(thermal_init);
1241module_exit(thermal_exit);
1242
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.