root/drivers/thermal/thermal_sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. type_show
  2. temp_show
  3. mode_show
  4. mode_store
  5. trip_point_type_show
  6. trip_point_temp_store
  7. trip_point_temp_show
  8. trip_point_hyst_store
  9. trip_point_hyst_show
  10. passive_store
  11. passive_show
  12. policy_store
  13. policy_show
  14. available_policies_show
  15. emul_temp_store
  16. sustainable_power_show
  17. sustainable_power_store
  18. thermal_zone_mode_is_visible
  19. thermal_zone_passive_is_visible
  20. create_trip_attrs
  21. destroy_trip_attrs
  22. thermal_zone_create_device_groups
  23. thermal_zone_destroy_device_groups
  24. cdev_type_show
  25. max_state_show
  26. cur_state_show
  27. cur_state_store
  28. update_time_in_state
  29. thermal_cooling_device_stats_update
  30. total_trans_show
  31. time_in_state_ms_show
  32. reset_store
  33. trans_table_show
  34. cooling_device_stats_setup
  35. cooling_device_stats_destroy
  36. cooling_device_stats_setup
  37. cooling_device_stats_destroy
  38. thermal_cooling_device_setup_sysfs
  39. thermal_cooling_device_destroy_sysfs
  40. trip_point_show
  41. weight_show
  42. weight_store

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  thermal.c - sysfs interface of thermal devices
   4  *
   5  *  Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
   6  *
   7  *  Highly based on original thermal_core.c
   8  *  Copyright (C) 2008 Intel Corp
   9  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
  10  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
  11  */
  12 
  13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14 
  15 #include <linux/sysfs.h>
  16 #include <linux/device.h>
  17 #include <linux/err.h>
  18 #include <linux/slab.h>
  19 #include <linux/string.h>
  20 #include <linux/jiffies.h>
  21 
  22 #include "thermal_core.h"
  23 
  24 /* sys I/F for thermal zone */
  25 
  26 static ssize_t
  27 type_show(struct device *dev, struct device_attribute *attr, char *buf)
  28 {
  29         struct thermal_zone_device *tz = to_thermal_zone(dev);
  30 
  31         return sprintf(buf, "%s\n", tz->type);
  32 }
  33 
  34 static ssize_t
  35 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
  36 {
  37         struct thermal_zone_device *tz = to_thermal_zone(dev);
  38         int temperature, ret;
  39 
  40         ret = thermal_zone_get_temp(tz, &temperature);
  41 
  42         if (ret)
  43                 return ret;
  44 
  45         return sprintf(buf, "%d\n", temperature);
  46 }
  47 
  48 static ssize_t
  49 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
  50 {
  51         struct thermal_zone_device *tz = to_thermal_zone(dev);
  52         enum thermal_device_mode mode;
  53         int result;
  54 
  55         if (!tz->ops->get_mode)
  56                 return -EPERM;
  57 
  58         result = tz->ops->get_mode(tz, &mode);
  59         if (result)
  60                 return result;
  61 
  62         return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
  63                        : "disabled");
  64 }
  65 
  66 static ssize_t
  67 mode_store(struct device *dev, struct device_attribute *attr,
  68            const char *buf, size_t count)
  69 {
  70         struct thermal_zone_device *tz = to_thermal_zone(dev);
  71         int result;
  72 
  73         if (!tz->ops->set_mode)
  74                 return -EPERM;
  75 
  76         if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
  77                 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
  78         else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
  79                 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
  80         else
  81                 result = -EINVAL;
  82 
  83         if (result)
  84                 return result;
  85 
  86         return count;
  87 }
  88 
  89 static ssize_t
  90 trip_point_type_show(struct device *dev, struct device_attribute *attr,
  91                      char *buf)
  92 {
  93         struct thermal_zone_device *tz = to_thermal_zone(dev);
  94         enum thermal_trip_type type;
  95         int trip, result;
  96 
  97         if (!tz->ops->get_trip_type)
  98                 return -EPERM;
  99 
 100         if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
 101                 return -EINVAL;
 102 
 103         result = tz->ops->get_trip_type(tz, trip, &type);
 104         if (result)
 105                 return result;
 106 
 107         switch (type) {
 108         case THERMAL_TRIP_CRITICAL:
 109                 return sprintf(buf, "critical\n");
 110         case THERMAL_TRIP_HOT:
 111                 return sprintf(buf, "hot\n");
 112         case THERMAL_TRIP_PASSIVE:
 113                 return sprintf(buf, "passive\n");
 114         case THERMAL_TRIP_ACTIVE:
 115                 return sprintf(buf, "active\n");
 116         default:
 117                 return sprintf(buf, "unknown\n");
 118         }
 119 }
 120 
 121 static ssize_t
 122 trip_point_temp_store(struct device *dev, struct device_attribute *attr,
 123                       const char *buf, size_t count)
 124 {
 125         struct thermal_zone_device *tz = to_thermal_zone(dev);
 126         int trip, ret;
 127         int temperature;
 128 
 129         if (!tz->ops->set_trip_temp)
 130                 return -EPERM;
 131 
 132         if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
 133                 return -EINVAL;
 134 
 135         if (kstrtoint(buf, 10, &temperature))
 136                 return -EINVAL;
 137 
 138         ret = tz->ops->set_trip_temp(tz, trip, temperature);
 139         if (ret)
 140                 return ret;
 141 
 142         thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 143 
 144         return count;
 145 }
 146 
 147 static ssize_t
 148 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
 149                      char *buf)
 150 {
 151         struct thermal_zone_device *tz = to_thermal_zone(dev);
 152         int trip, ret;
 153         int temperature;
 154 
 155         if (!tz->ops->get_trip_temp)
 156                 return -EPERM;
 157 
 158         if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
 159                 return -EINVAL;
 160 
 161         ret = tz->ops->get_trip_temp(tz, trip, &temperature);
 162 
 163         if (ret)
 164                 return ret;
 165 
 166         return sprintf(buf, "%d\n", temperature);
 167 }
 168 
 169 static ssize_t
 170 trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
 171                       const char *buf, size_t count)
 172 {
 173         struct thermal_zone_device *tz = to_thermal_zone(dev);
 174         int trip, ret;
 175         int temperature;
 176 
 177         if (!tz->ops->set_trip_hyst)
 178                 return -EPERM;
 179 
 180         if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
 181                 return -EINVAL;
 182 
 183         if (kstrtoint(buf, 10, &temperature))
 184                 return -EINVAL;
 185 
 186         /*
 187          * We are not doing any check on the 'temperature' value
 188          * here. The driver implementing 'set_trip_hyst' has to
 189          * take care of this.
 190          */
 191         ret = tz->ops->set_trip_hyst(tz, trip, temperature);
 192 
 193         if (!ret)
 194                 thermal_zone_set_trips(tz);
 195 
 196         return ret ? ret : count;
 197 }
 198 
 199 static ssize_t
 200 trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
 201                      char *buf)
 202 {
 203         struct thermal_zone_device *tz = to_thermal_zone(dev);
 204         int trip, ret;
 205         int temperature;
 206 
 207         if (!tz->ops->get_trip_hyst)
 208                 return -EPERM;
 209 
 210         if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
 211                 return -EINVAL;
 212 
 213         ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
 214 
 215         return ret ? ret : sprintf(buf, "%d\n", temperature);
 216 }
 217 
 218 static ssize_t
 219 passive_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         int state;
 224 
 225         if (sscanf(buf, "%d\n", &state) != 1)
 226                 return -EINVAL;
 227 
 228         /* sanity check: values below 1000 millicelcius don't make sense
 229          * and can cause the system to go into a thermal heart attack
 230          */
 231         if (state && state < 1000)
 232                 return -EINVAL;
 233 
 234         if (state && !tz->forced_passive) {
 235                 if (!tz->passive_delay)
 236                         tz->passive_delay = 1000;
 237                 thermal_zone_device_rebind_exception(tz, "Processor",
 238                                                      sizeof("Processor"));
 239         } else if (!state && tz->forced_passive) {
 240                 tz->passive_delay = 0;
 241                 thermal_zone_device_unbind_exception(tz, "Processor",
 242                                                      sizeof("Processor"));
 243         }
 244 
 245         tz->forced_passive = state;
 246 
 247         thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 248 
 249         return count;
 250 }
 251 
 252 static ssize_t
 253 passive_show(struct device *dev, struct device_attribute *attr,
 254              char *buf)
 255 {
 256         struct thermal_zone_device *tz = to_thermal_zone(dev);
 257 
 258         return sprintf(buf, "%d\n", tz->forced_passive);
 259 }
 260 
 261 static ssize_t
 262 policy_store(struct device *dev, struct device_attribute *attr,
 263              const char *buf, size_t count)
 264 {
 265         struct thermal_zone_device *tz = to_thermal_zone(dev);
 266         char name[THERMAL_NAME_LENGTH];
 267         int ret;
 268 
 269         snprintf(name, sizeof(name), "%s", buf);
 270 
 271         ret = thermal_zone_device_set_policy(tz, name);
 272         if (!ret)
 273                 ret = count;
 274 
 275         return ret;
 276 }
 277 
 278 static ssize_t
 279 policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
 280 {
 281         struct thermal_zone_device *tz = to_thermal_zone(dev);
 282 
 283         return sprintf(buf, "%s\n", tz->governor->name);
 284 }
 285 
 286 static ssize_t
 287 available_policies_show(struct device *dev, struct device_attribute *devattr,
 288                         char *buf)
 289 {
 290         return thermal_build_list_of_policies(buf);
 291 }
 292 
 293 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
 294 static ssize_t
 295 emul_temp_store(struct device *dev, struct device_attribute *attr,
 296                 const char *buf, size_t count)
 297 {
 298         struct thermal_zone_device *tz = to_thermal_zone(dev);
 299         int ret = 0;
 300         int temperature;
 301 
 302         if (kstrtoint(buf, 10, &temperature))
 303                 return -EINVAL;
 304 
 305         if (!tz->ops->set_emul_temp) {
 306                 mutex_lock(&tz->lock);
 307                 tz->emul_temperature = temperature;
 308                 mutex_unlock(&tz->lock);
 309         } else {
 310                 ret = tz->ops->set_emul_temp(tz, temperature);
 311         }
 312 
 313         if (!ret)
 314                 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 315 
 316         return ret ? ret : count;
 317 }
 318 static DEVICE_ATTR_WO(emul_temp);
 319 #endif
 320 
 321 static ssize_t
 322 sustainable_power_show(struct device *dev, struct device_attribute *devattr,
 323                        char *buf)
 324 {
 325         struct thermal_zone_device *tz = to_thermal_zone(dev);
 326 
 327         if (tz->tzp)
 328                 return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
 329         else
 330                 return -EIO;
 331 }
 332 
 333 static ssize_t
 334 sustainable_power_store(struct device *dev, struct device_attribute *devattr,
 335                         const char *buf, size_t count)
 336 {
 337         struct thermal_zone_device *tz = to_thermal_zone(dev);
 338         u32 sustainable_power;
 339 
 340         if (!tz->tzp)
 341                 return -EIO;
 342 
 343         if (kstrtou32(buf, 10, &sustainable_power))
 344                 return -EINVAL;
 345 
 346         tz->tzp->sustainable_power = sustainable_power;
 347 
 348         return count;
 349 }
 350 
 351 #define create_s32_tzp_attr(name)                                       \
 352         static ssize_t                                                  \
 353         name##_show(struct device *dev, struct device_attribute *devattr, \
 354                 char *buf)                                              \
 355         {                                                               \
 356         struct thermal_zone_device *tz = to_thermal_zone(dev);          \
 357                                                                         \
 358         if (tz->tzp)                                                    \
 359                 return sprintf(buf, "%d\n", tz->tzp->name);             \
 360         else                                                            \
 361                 return -EIO;                                            \
 362         }                                                               \
 363                                                                         \
 364         static ssize_t                                                  \
 365         name##_store(struct device *dev, struct device_attribute *devattr, \
 366                 const char *buf, size_t count)                          \
 367         {                                                               \
 368                 struct thermal_zone_device *tz = to_thermal_zone(dev);  \
 369                 s32 value;                                              \
 370                                                                         \
 371                 if (!tz->tzp)                                           \
 372                         return -EIO;                                    \
 373                                                                         \
 374                 if (kstrtos32(buf, 10, &value))                         \
 375                         return -EINVAL;                                 \
 376                                                                         \
 377                 tz->tzp->name = value;                                  \
 378                                                                         \
 379                 return count;                                           \
 380         }                                                               \
 381         static DEVICE_ATTR_RW(name)
 382 
 383 create_s32_tzp_attr(k_po);
 384 create_s32_tzp_attr(k_pu);
 385 create_s32_tzp_attr(k_i);
 386 create_s32_tzp_attr(k_d);
 387 create_s32_tzp_attr(integral_cutoff);
 388 create_s32_tzp_attr(slope);
 389 create_s32_tzp_attr(offset);
 390 #undef create_s32_tzp_attr
 391 
 392 /*
 393  * These are thermal zone device attributes that will always be present.
 394  * All the attributes created for tzp (create_s32_tzp_attr) also are always
 395  * present on the sysfs interface.
 396  */
 397 static DEVICE_ATTR_RO(type);
 398 static DEVICE_ATTR_RO(temp);
 399 static DEVICE_ATTR_RW(policy);
 400 static DEVICE_ATTR_RO(available_policies);
 401 static DEVICE_ATTR_RW(sustainable_power);
 402 
 403 /* These thermal zone device attributes are created based on conditions */
 404 static DEVICE_ATTR_RW(mode);
 405 static DEVICE_ATTR_RW(passive);
 406 
 407 /* These attributes are unconditionally added to a thermal zone */
 408 static struct attribute *thermal_zone_dev_attrs[] = {
 409         &dev_attr_type.attr,
 410         &dev_attr_temp.attr,
 411 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
 412         &dev_attr_emul_temp.attr,
 413 #endif
 414         &dev_attr_policy.attr,
 415         &dev_attr_available_policies.attr,
 416         &dev_attr_sustainable_power.attr,
 417         &dev_attr_k_po.attr,
 418         &dev_attr_k_pu.attr,
 419         &dev_attr_k_i.attr,
 420         &dev_attr_k_d.attr,
 421         &dev_attr_integral_cutoff.attr,
 422         &dev_attr_slope.attr,
 423         &dev_attr_offset.attr,
 424         NULL,
 425 };
 426 
 427 static struct attribute_group thermal_zone_attribute_group = {
 428         .attrs = thermal_zone_dev_attrs,
 429 };
 430 
 431 /* We expose mode only if .get_mode is present */
 432 static struct attribute *thermal_zone_mode_attrs[] = {
 433         &dev_attr_mode.attr,
 434         NULL,
 435 };
 436 
 437 static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
 438                                             struct attribute *attr,
 439                                             int attrno)
 440 {
 441         struct device *dev = container_of(kobj, struct device, kobj);
 442         struct thermal_zone_device *tz;
 443 
 444         tz = container_of(dev, struct thermal_zone_device, device);
 445 
 446         if (tz->ops->get_mode)
 447                 return attr->mode;
 448 
 449         return 0;
 450 }
 451 
 452 static struct attribute_group thermal_zone_mode_attribute_group = {
 453         .attrs = thermal_zone_mode_attrs,
 454         .is_visible = thermal_zone_mode_is_visible,
 455 };
 456 
 457 /* We expose passive only if passive trips are present */
 458 static struct attribute *thermal_zone_passive_attrs[] = {
 459         &dev_attr_passive.attr,
 460         NULL,
 461 };
 462 
 463 static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
 464                                                struct attribute *attr,
 465                                                int attrno)
 466 {
 467         struct device *dev = container_of(kobj, struct device, kobj);
 468         struct thermal_zone_device *tz;
 469         enum thermal_trip_type trip_type;
 470         int count, passive = 0;
 471 
 472         tz = container_of(dev, struct thermal_zone_device, device);
 473 
 474         for (count = 0; count < tz->trips && !passive; count++) {
 475                 tz->ops->get_trip_type(tz, count, &trip_type);
 476 
 477                 if (trip_type == THERMAL_TRIP_PASSIVE)
 478                         passive = 1;
 479         }
 480 
 481         if (!passive)
 482                 return attr->mode;
 483 
 484         return 0;
 485 }
 486 
 487 static struct attribute_group thermal_zone_passive_attribute_group = {
 488         .attrs = thermal_zone_passive_attrs,
 489         .is_visible = thermal_zone_passive_is_visible,
 490 };
 491 
 492 static const struct attribute_group *thermal_zone_attribute_groups[] = {
 493         &thermal_zone_attribute_group,
 494         &thermal_zone_mode_attribute_group,
 495         &thermal_zone_passive_attribute_group,
 496         /* This is not NULL terminated as we create the group dynamically */
 497 };
 498 
 499 /**
 500  * create_trip_attrs() - create attributes for trip points
 501  * @tz:         the thermal zone device
 502  * @mask:       Writeable trip point bitmap.
 503  *
 504  * helper function to instantiate sysfs entries for every trip
 505  * point and its properties of a struct thermal_zone_device.
 506  *
 507  * Return: 0 on success, the proper error value otherwise.
 508  */
 509 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 510 {
 511         struct attribute **attrs;
 512         int indx;
 513 
 514         /* This function works only for zones with at least one trip */
 515         if (tz->trips <= 0)
 516                 return -EINVAL;
 517 
 518         tz->trip_type_attrs = kcalloc(tz->trips, sizeof(*tz->trip_type_attrs),
 519                                       GFP_KERNEL);
 520         if (!tz->trip_type_attrs)
 521                 return -ENOMEM;
 522 
 523         tz->trip_temp_attrs = kcalloc(tz->trips, sizeof(*tz->trip_temp_attrs),
 524                                       GFP_KERNEL);
 525         if (!tz->trip_temp_attrs) {
 526                 kfree(tz->trip_type_attrs);
 527                 return -ENOMEM;
 528         }
 529 
 530         if (tz->ops->get_trip_hyst) {
 531                 tz->trip_hyst_attrs = kcalloc(tz->trips,
 532                                               sizeof(*tz->trip_hyst_attrs),
 533                                               GFP_KERNEL);
 534                 if (!tz->trip_hyst_attrs) {
 535                         kfree(tz->trip_type_attrs);
 536                         kfree(tz->trip_temp_attrs);
 537                         return -ENOMEM;
 538                 }
 539         }
 540 
 541         attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
 542         if (!attrs) {
 543                 kfree(tz->trip_type_attrs);
 544                 kfree(tz->trip_temp_attrs);
 545                 if (tz->ops->get_trip_hyst)
 546                         kfree(tz->trip_hyst_attrs);
 547                 return -ENOMEM;
 548         }
 549 
 550         for (indx = 0; indx < tz->trips; indx++) {
 551                 /* create trip type attribute */
 552                 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
 553                          "trip_point_%d_type", indx);
 554 
 555                 sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
 556                 tz->trip_type_attrs[indx].attr.attr.name =
 557                                                 tz->trip_type_attrs[indx].name;
 558                 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
 559                 tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
 560                 attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
 561 
 562                 /* create trip temp attribute */
 563                 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
 564                          "trip_point_%d_temp", indx);
 565 
 566                 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
 567                 tz->trip_temp_attrs[indx].attr.attr.name =
 568                                                 tz->trip_temp_attrs[indx].name;
 569                 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
 570                 tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
 571                 if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
 572                     mask & (1 << indx)) {
 573                         tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
 574                         tz->trip_temp_attrs[indx].attr.store =
 575                                                         trip_point_temp_store;
 576                 }
 577                 attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
 578 
 579                 /* create Optional trip hyst attribute */
 580                 if (!tz->ops->get_trip_hyst)
 581                         continue;
 582                 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
 583                          "trip_point_%d_hyst", indx);
 584 
 585                 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
 586                 tz->trip_hyst_attrs[indx].attr.attr.name =
 587                                         tz->trip_hyst_attrs[indx].name;
 588                 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
 589                 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
 590                 if (tz->ops->set_trip_hyst) {
 591                         tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
 592                         tz->trip_hyst_attrs[indx].attr.store =
 593                                         trip_point_hyst_store;
 594                 }
 595                 attrs[indx + tz->trips * 2] =
 596                                         &tz->trip_hyst_attrs[indx].attr.attr;
 597         }
 598         attrs[tz->trips * 3] = NULL;
 599 
 600         tz->trips_attribute_group.attrs = attrs;
 601 
 602         return 0;
 603 }
 604 
 605 /**
 606  * destroy_trip_attrs() - destroy attributes for trip points
 607  * @tz:         the thermal zone device
 608  *
 609  * helper function to free resources allocated by create_trip_attrs()
 610  */
 611 static void destroy_trip_attrs(struct thermal_zone_device *tz)
 612 {
 613         if (!tz)
 614                 return;
 615 
 616         kfree(tz->trip_type_attrs);
 617         kfree(tz->trip_temp_attrs);
 618         if (tz->ops->get_trip_hyst)
 619                 kfree(tz->trip_hyst_attrs);
 620         kfree(tz->trips_attribute_group.attrs);
 621 }
 622 
 623 int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
 624                                       int mask)
 625 {
 626         const struct attribute_group **groups;
 627         int i, size, result;
 628 
 629         /* we need one extra for trips and the NULL to terminate the array */
 630         size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
 631         /* This also takes care of API requirement to be NULL terminated */
 632         groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
 633         if (!groups)
 634                 return -ENOMEM;
 635 
 636         for (i = 0; i < size - 2; i++)
 637                 groups[i] = thermal_zone_attribute_groups[i];
 638 
 639         if (tz->trips) {
 640                 result = create_trip_attrs(tz, mask);
 641                 if (result) {
 642                         kfree(groups);
 643 
 644                         return result;
 645                 }
 646 
 647                 groups[size - 2] = &tz->trips_attribute_group;
 648         }
 649 
 650         tz->device.groups = groups;
 651 
 652         return 0;
 653 }
 654 
 655 void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
 656 {
 657         if (!tz)
 658                 return;
 659 
 660         if (tz->trips)
 661                 destroy_trip_attrs(tz);
 662 
 663         kfree(tz->device.groups);
 664 }
 665 
 666 /* sys I/F for cooling device */
 667 static ssize_t
 668 cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 669 {
 670         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 671 
 672         return sprintf(buf, "%s\n", cdev->type);
 673 }
 674 
 675 static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
 676                               char *buf)
 677 {
 678         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 679         unsigned long state;
 680         int ret;
 681 
 682         ret = cdev->ops->get_max_state(cdev, &state);
 683         if (ret)
 684                 return ret;
 685         return sprintf(buf, "%ld\n", state);
 686 }
 687 
 688 static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
 689                               char *buf)
 690 {
 691         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 692         unsigned long state;
 693         int ret;
 694 
 695         ret = cdev->ops->get_cur_state(cdev, &state);
 696         if (ret)
 697                 return ret;
 698         return sprintf(buf, "%ld\n", state);
 699 }
 700 
 701 static ssize_t
 702 cur_state_store(struct device *dev, struct device_attribute *attr,
 703                 const char *buf, size_t count)
 704 {
 705         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 706         unsigned long state;
 707         int result;
 708 
 709         if (sscanf(buf, "%ld\n", &state) != 1)
 710                 return -EINVAL;
 711 
 712         if ((long)state < 0)
 713                 return -EINVAL;
 714 
 715         mutex_lock(&cdev->lock);
 716 
 717         result = cdev->ops->set_cur_state(cdev, state);
 718         if (!result)
 719                 thermal_cooling_device_stats_update(cdev, state);
 720 
 721         mutex_unlock(&cdev->lock);
 722         return result ? result : count;
 723 }
 724 
 725 static struct device_attribute
 726 dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
 727 static DEVICE_ATTR_RO(max_state);
 728 static DEVICE_ATTR_RW(cur_state);
 729 
 730 static struct attribute *cooling_device_attrs[] = {
 731         &dev_attr_cdev_type.attr,
 732         &dev_attr_max_state.attr,
 733         &dev_attr_cur_state.attr,
 734         NULL,
 735 };
 736 
 737 static const struct attribute_group cooling_device_attr_group = {
 738         .attrs = cooling_device_attrs,
 739 };
 740 
 741 static const struct attribute_group *cooling_device_attr_groups[] = {
 742         &cooling_device_attr_group,
 743         NULL, /* Space allocated for cooling_device_stats_attr_group */
 744         NULL,
 745 };
 746 
 747 #ifdef CONFIG_THERMAL_STATISTICS
 748 struct cooling_dev_stats {
 749         spinlock_t lock;
 750         unsigned int total_trans;
 751         unsigned long state;
 752         unsigned long max_states;
 753         ktime_t last_time;
 754         ktime_t *time_in_state;
 755         unsigned int *trans_table;
 756 };
 757 
 758 static void update_time_in_state(struct cooling_dev_stats *stats)
 759 {
 760         ktime_t now = ktime_get(), delta;
 761 
 762         delta = ktime_sub(now, stats->last_time);
 763         stats->time_in_state[stats->state] =
 764                 ktime_add(stats->time_in_state[stats->state], delta);
 765         stats->last_time = now;
 766 }
 767 
 768 void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
 769                                          unsigned long new_state)
 770 {
 771         struct cooling_dev_stats *stats = cdev->stats;
 772 
 773         spin_lock(&stats->lock);
 774 
 775         if (stats->state == new_state)
 776                 goto unlock;
 777 
 778         update_time_in_state(stats);
 779         stats->trans_table[stats->state * stats->max_states + new_state]++;
 780         stats->state = new_state;
 781         stats->total_trans++;
 782 
 783 unlock:
 784         spin_unlock(&stats->lock);
 785 }
 786 
 787 static ssize_t total_trans_show(struct device *dev,
 788                                 struct device_attribute *attr, char *buf)
 789 {
 790         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 791         struct cooling_dev_stats *stats = cdev->stats;
 792         int ret;
 793 
 794         spin_lock(&stats->lock);
 795         ret = sprintf(buf, "%u\n", stats->total_trans);
 796         spin_unlock(&stats->lock);
 797 
 798         return ret;
 799 }
 800 
 801 static ssize_t
 802 time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
 803                       char *buf)
 804 {
 805         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 806         struct cooling_dev_stats *stats = cdev->stats;
 807         ssize_t len = 0;
 808         int i;
 809 
 810         spin_lock(&stats->lock);
 811         update_time_in_state(stats);
 812 
 813         for (i = 0; i < stats->max_states; i++) {
 814                 len += sprintf(buf + len, "state%u\t%llu\n", i,
 815                                ktime_to_ms(stats->time_in_state[i]));
 816         }
 817         spin_unlock(&stats->lock);
 818 
 819         return len;
 820 }
 821 
 822 static ssize_t
 823 reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
 824             size_t count)
 825 {
 826         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 827         struct cooling_dev_stats *stats = cdev->stats;
 828         int i, states = stats->max_states;
 829 
 830         spin_lock(&stats->lock);
 831 
 832         stats->total_trans = 0;
 833         stats->last_time = ktime_get();
 834         memset(stats->trans_table, 0,
 835                states * states * sizeof(*stats->trans_table));
 836 
 837         for (i = 0; i < stats->max_states; i++)
 838                 stats->time_in_state[i] = ktime_set(0, 0);
 839 
 840         spin_unlock(&stats->lock);
 841 
 842         return count;
 843 }
 844 
 845 static ssize_t trans_table_show(struct device *dev,
 846                                 struct device_attribute *attr, char *buf)
 847 {
 848         struct thermal_cooling_device *cdev = to_cooling_device(dev);
 849         struct cooling_dev_stats *stats = cdev->stats;
 850         ssize_t len = 0;
 851         int i, j;
 852 
 853         len += snprintf(buf + len, PAGE_SIZE - len, " From  :    To\n");
 854         len += snprintf(buf + len, PAGE_SIZE - len, "       : ");
 855         for (i = 0; i < stats->max_states; i++) {
 856                 if (len >= PAGE_SIZE)
 857                         break;
 858                 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u  ", i);
 859         }
 860         if (len >= PAGE_SIZE)
 861                 return PAGE_SIZE;
 862 
 863         len += snprintf(buf + len, PAGE_SIZE - len, "\n");
 864 
 865         for (i = 0; i < stats->max_states; i++) {
 866                 if (len >= PAGE_SIZE)
 867                         break;
 868 
 869                 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
 870 
 871                 for (j = 0; j < stats->max_states; j++) {
 872                         if (len >= PAGE_SIZE)
 873                                 break;
 874                         len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
 875                                 stats->trans_table[i * stats->max_states + j]);
 876                 }
 877                 if (len >= PAGE_SIZE)
 878                         break;
 879                 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
 880         }
 881 
 882         if (len >= PAGE_SIZE) {
 883                 pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
 884                 return -EFBIG;
 885         }
 886         return len;
 887 }
 888 
 889 static DEVICE_ATTR_RO(total_trans);
 890 static DEVICE_ATTR_RO(time_in_state_ms);
 891 static DEVICE_ATTR_WO(reset);
 892 static DEVICE_ATTR_RO(trans_table);
 893 
 894 static struct attribute *cooling_device_stats_attrs[] = {
 895         &dev_attr_total_trans.attr,
 896         &dev_attr_time_in_state_ms.attr,
 897         &dev_attr_reset.attr,
 898         &dev_attr_trans_table.attr,
 899         NULL
 900 };
 901 
 902 static const struct attribute_group cooling_device_stats_attr_group = {
 903         .attrs = cooling_device_stats_attrs,
 904         .name = "stats"
 905 };
 906 
 907 static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
 908 {
 909         struct cooling_dev_stats *stats;
 910         unsigned long states;
 911         int var;
 912 
 913         if (cdev->ops->get_max_state(cdev, &states))
 914                 return;
 915 
 916         states++; /* Total number of states is highest state + 1 */
 917 
 918         var = sizeof(*stats);
 919         var += sizeof(*stats->time_in_state) * states;
 920         var += sizeof(*stats->trans_table) * states * states;
 921 
 922         stats = kzalloc(var, GFP_KERNEL);
 923         if (!stats)
 924                 return;
 925 
 926         stats->time_in_state = (ktime_t *)(stats + 1);
 927         stats->trans_table = (unsigned int *)(stats->time_in_state + states);
 928         cdev->stats = stats;
 929         stats->last_time = ktime_get();
 930         stats->max_states = states;
 931 
 932         spin_lock_init(&stats->lock);
 933 
 934         /* Fill the empty slot left in cooling_device_attr_groups */
 935         var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
 936         cooling_device_attr_groups[var] = &cooling_device_stats_attr_group;
 937 }
 938 
 939 static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
 940 {
 941         kfree(cdev->stats);
 942         cdev->stats = NULL;
 943 }
 944 
 945 #else
 946 
 947 static inline void
 948 cooling_device_stats_setup(struct thermal_cooling_device *cdev) {}
 949 static inline void
 950 cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {}
 951 
 952 #endif /* CONFIG_THERMAL_STATISTICS */
 953 
 954 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
 955 {
 956         cooling_device_stats_setup(cdev);
 957         cdev->device.groups = cooling_device_attr_groups;
 958 }
 959 
 960 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
 961 {
 962         cooling_device_stats_destroy(cdev);
 963 }
 964 
 965 /* these helper will be used only at the time of bindig */
 966 ssize_t
 967 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
 968 {
 969         struct thermal_instance *instance;
 970 
 971         instance =
 972             container_of(attr, struct thermal_instance, attr);
 973 
 974         if (instance->trip == THERMAL_TRIPS_NONE)
 975                 return sprintf(buf, "-1\n");
 976         else
 977                 return sprintf(buf, "%d\n", instance->trip);
 978 }
 979 
 980 ssize_t
 981 weight_show(struct device *dev, struct device_attribute *attr, char *buf)
 982 {
 983         struct thermal_instance *instance;
 984 
 985         instance = container_of(attr, struct thermal_instance, weight_attr);
 986 
 987         return sprintf(buf, "%d\n", instance->weight);
 988 }
 989 
 990 ssize_t weight_store(struct device *dev, struct device_attribute *attr,
 991                      const char *buf, size_t count)
 992 {
 993         struct thermal_instance *instance;
 994         int ret, weight;
 995 
 996         ret = kstrtoint(buf, 0, &weight);
 997         if (ret)
 998                 return ret;
 999 
1000         instance = container_of(attr, struct thermal_instance, weight_attr);
1001         instance->weight = weight;
1002 
1003         return count;
1004 }

/* [<][>][^][v][top][bottom][index][help] */