0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0014
0015 #include <linux/sysfs.h>
0016 #include <linux/device.h>
0017 #include <linux/err.h>
0018 #include <linux/slab.h>
0019 #include <linux/string.h>
0020 #include <linux/jiffies.h>
0021
0022 #include "thermal_core.h"
0023
0024
0025
0026 static ssize_t
0027 type_show(struct device *dev, struct device_attribute *attr, char *buf)
0028 {
0029 struct thermal_zone_device *tz = to_thermal_zone(dev);
0030
0031 return sprintf(buf, "%s\n", tz->type);
0032 }
0033
0034 static ssize_t
0035 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
0036 {
0037 struct thermal_zone_device *tz = to_thermal_zone(dev);
0038 int temperature, ret;
0039
0040 ret = thermal_zone_get_temp(tz, &temperature);
0041
0042 if (ret)
0043 return ret;
0044
0045 return sprintf(buf, "%d\n", temperature);
0046 }
0047
0048 static ssize_t
0049 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
0050 {
0051 struct thermal_zone_device *tz = to_thermal_zone(dev);
0052 int enabled = thermal_zone_device_is_enabled(tz);
0053
0054 return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled");
0055 }
0056
0057 static ssize_t
0058 mode_store(struct device *dev, struct device_attribute *attr,
0059 const char *buf, size_t count)
0060 {
0061 struct thermal_zone_device *tz = to_thermal_zone(dev);
0062 int result;
0063
0064 if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
0065 result = thermal_zone_device_enable(tz);
0066 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
0067 result = thermal_zone_device_disable(tz);
0068 else
0069 result = -EINVAL;
0070
0071 if (result)
0072 return result;
0073
0074 return count;
0075 }
0076
0077 static ssize_t
0078 trip_point_type_show(struct device *dev, struct device_attribute *attr,
0079 char *buf)
0080 {
0081 struct thermal_zone_device *tz = to_thermal_zone(dev);
0082 enum thermal_trip_type type;
0083 int trip, result;
0084
0085 if (!tz->ops->get_trip_type)
0086 return -EPERM;
0087
0088 if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
0089 return -EINVAL;
0090
0091 result = tz->ops->get_trip_type(tz, trip, &type);
0092 if (result)
0093 return result;
0094
0095 switch (type) {
0096 case THERMAL_TRIP_CRITICAL:
0097 return sprintf(buf, "critical\n");
0098 case THERMAL_TRIP_HOT:
0099 return sprintf(buf, "hot\n");
0100 case THERMAL_TRIP_PASSIVE:
0101 return sprintf(buf, "passive\n");
0102 case THERMAL_TRIP_ACTIVE:
0103 return sprintf(buf, "active\n");
0104 default:
0105 return sprintf(buf, "unknown\n");
0106 }
0107 }
0108
0109 static ssize_t
0110 trip_point_temp_store(struct device *dev, struct device_attribute *attr,
0111 const char *buf, size_t count)
0112 {
0113 struct thermal_zone_device *tz = to_thermal_zone(dev);
0114 int trip, ret;
0115 int temperature, hyst = 0;
0116 enum thermal_trip_type type;
0117
0118 if (!tz->ops->set_trip_temp)
0119 return -EPERM;
0120
0121 if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
0122 return -EINVAL;
0123
0124 if (kstrtoint(buf, 10, &temperature))
0125 return -EINVAL;
0126
0127 ret = tz->ops->set_trip_temp(tz, trip, temperature);
0128 if (ret)
0129 return ret;
0130
0131 if (tz->ops->get_trip_hyst) {
0132 ret = tz->ops->get_trip_hyst(tz, trip, &hyst);
0133 if (ret)
0134 return ret;
0135 }
0136
0137 ret = tz->ops->get_trip_type(tz, trip, &type);
0138 if (ret)
0139 return ret;
0140
0141 thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst);
0142
0143 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
0144
0145 return count;
0146 }
0147
0148 static ssize_t
0149 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
0150 char *buf)
0151 {
0152 struct thermal_zone_device *tz = to_thermal_zone(dev);
0153 int trip, ret;
0154 int temperature;
0155
0156 if (!tz->ops->get_trip_temp)
0157 return -EPERM;
0158
0159 if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
0160 return -EINVAL;
0161
0162 ret = tz->ops->get_trip_temp(tz, trip, &temperature);
0163
0164 if (ret)
0165 return ret;
0166
0167 return sprintf(buf, "%d\n", temperature);
0168 }
0169
0170 static ssize_t
0171 trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
0172 const char *buf, size_t count)
0173 {
0174 struct thermal_zone_device *tz = to_thermal_zone(dev);
0175 int trip, ret;
0176 int temperature;
0177
0178 if (!tz->ops->set_trip_hyst)
0179 return -EPERM;
0180
0181 if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
0182 return -EINVAL;
0183
0184 if (kstrtoint(buf, 10, &temperature))
0185 return -EINVAL;
0186
0187
0188
0189
0190
0191
0192 ret = tz->ops->set_trip_hyst(tz, trip, temperature);
0193
0194 if (!ret)
0195 thermal_zone_set_trips(tz);
0196
0197 return ret ? ret : count;
0198 }
0199
0200 static ssize_t
0201 trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
0202 char *buf)
0203 {
0204 struct thermal_zone_device *tz = to_thermal_zone(dev);
0205 int trip, ret;
0206 int temperature;
0207
0208 if (!tz->ops->get_trip_hyst)
0209 return -EPERM;
0210
0211 if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
0212 return -EINVAL;
0213
0214 ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
0215
0216 return ret ? ret : sprintf(buf, "%d\n", temperature);
0217 }
0218
0219 static ssize_t
0220 policy_store(struct device *dev, struct device_attribute *attr,
0221 const char *buf, size_t count)
0222 {
0223 struct thermal_zone_device *tz = to_thermal_zone(dev);
0224 char name[THERMAL_NAME_LENGTH];
0225 int ret;
0226
0227 snprintf(name, sizeof(name), "%s", buf);
0228
0229 ret = thermal_zone_device_set_policy(tz, name);
0230 if (!ret)
0231 ret = count;
0232
0233 return ret;
0234 }
0235
0236 static ssize_t
0237 policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
0238 {
0239 struct thermal_zone_device *tz = to_thermal_zone(dev);
0240
0241 return sprintf(buf, "%s\n", tz->governor->name);
0242 }
0243
0244 static ssize_t
0245 available_policies_show(struct device *dev, struct device_attribute *devattr,
0246 char *buf)
0247 {
0248 return thermal_build_list_of_policies(buf);
0249 }
0250
0251 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
0252 static ssize_t
0253 emul_temp_store(struct device *dev, struct device_attribute *attr,
0254 const char *buf, size_t count)
0255 {
0256 struct thermal_zone_device *tz = to_thermal_zone(dev);
0257 int ret = 0;
0258 int temperature;
0259
0260 if (kstrtoint(buf, 10, &temperature))
0261 return -EINVAL;
0262
0263 if (!tz->ops->set_emul_temp) {
0264 mutex_lock(&tz->lock);
0265 tz->emul_temperature = temperature;
0266 mutex_unlock(&tz->lock);
0267 } else {
0268 ret = tz->ops->set_emul_temp(tz, temperature);
0269 }
0270
0271 if (!ret)
0272 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
0273
0274 return ret ? ret : count;
0275 }
0276 static DEVICE_ATTR_WO(emul_temp);
0277 #endif
0278
0279 static ssize_t
0280 sustainable_power_show(struct device *dev, struct device_attribute *devattr,
0281 char *buf)
0282 {
0283 struct thermal_zone_device *tz = to_thermal_zone(dev);
0284
0285 if (tz->tzp)
0286 return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
0287 else
0288 return -EIO;
0289 }
0290
0291 static ssize_t
0292 sustainable_power_store(struct device *dev, struct device_attribute *devattr,
0293 const char *buf, size_t count)
0294 {
0295 struct thermal_zone_device *tz = to_thermal_zone(dev);
0296 u32 sustainable_power;
0297
0298 if (!tz->tzp)
0299 return -EIO;
0300
0301 if (kstrtou32(buf, 10, &sustainable_power))
0302 return -EINVAL;
0303
0304 tz->tzp->sustainable_power = sustainable_power;
0305
0306 return count;
0307 }
0308
0309 #define create_s32_tzp_attr(name) \
0310 static ssize_t \
0311 name##_show(struct device *dev, struct device_attribute *devattr, \
0312 char *buf) \
0313 { \
0314 struct thermal_zone_device *tz = to_thermal_zone(dev); \
0315 \
0316 if (tz->tzp) \
0317 return sprintf(buf, "%d\n", tz->tzp->name); \
0318 else \
0319 return -EIO; \
0320 } \
0321 \
0322 static ssize_t \
0323 name##_store(struct device *dev, struct device_attribute *devattr, \
0324 const char *buf, size_t count) \
0325 { \
0326 struct thermal_zone_device *tz = to_thermal_zone(dev); \
0327 s32 value; \
0328 \
0329 if (!tz->tzp) \
0330 return -EIO; \
0331 \
0332 if (kstrtos32(buf, 10, &value)) \
0333 return -EINVAL; \
0334 \
0335 tz->tzp->name = value; \
0336 \
0337 return count; \
0338 } \
0339 static DEVICE_ATTR_RW(name)
0340
0341 create_s32_tzp_attr(k_po);
0342 create_s32_tzp_attr(k_pu);
0343 create_s32_tzp_attr(k_i);
0344 create_s32_tzp_attr(k_d);
0345 create_s32_tzp_attr(integral_cutoff);
0346 create_s32_tzp_attr(slope);
0347 create_s32_tzp_attr(offset);
0348 #undef create_s32_tzp_attr
0349
0350
0351
0352
0353
0354
0355 static DEVICE_ATTR_RO(type);
0356 static DEVICE_ATTR_RO(temp);
0357 static DEVICE_ATTR_RW(policy);
0358 static DEVICE_ATTR_RO(available_policies);
0359 static DEVICE_ATTR_RW(sustainable_power);
0360
0361
0362 static DEVICE_ATTR_RW(mode);
0363
0364
0365 static struct attribute *thermal_zone_dev_attrs[] = {
0366 &dev_attr_type.attr,
0367 &dev_attr_temp.attr,
0368 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
0369 &dev_attr_emul_temp.attr,
0370 #endif
0371 &dev_attr_policy.attr,
0372 &dev_attr_available_policies.attr,
0373 &dev_attr_sustainable_power.attr,
0374 &dev_attr_k_po.attr,
0375 &dev_attr_k_pu.attr,
0376 &dev_attr_k_i.attr,
0377 &dev_attr_k_d.attr,
0378 &dev_attr_integral_cutoff.attr,
0379 &dev_attr_slope.attr,
0380 &dev_attr_offset.attr,
0381 NULL,
0382 };
0383
0384 static const struct attribute_group thermal_zone_attribute_group = {
0385 .attrs = thermal_zone_dev_attrs,
0386 };
0387
0388 static struct attribute *thermal_zone_mode_attrs[] = {
0389 &dev_attr_mode.attr,
0390 NULL,
0391 };
0392
0393 static const struct attribute_group thermal_zone_mode_attribute_group = {
0394 .attrs = thermal_zone_mode_attrs,
0395 };
0396
0397 static const struct attribute_group *thermal_zone_attribute_groups[] = {
0398 &thermal_zone_attribute_group,
0399 &thermal_zone_mode_attribute_group,
0400
0401 };
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
0414 {
0415 struct attribute **attrs;
0416 int indx;
0417
0418
0419 if (tz->num_trips <= 0)
0420 return -EINVAL;
0421
0422 tz->trip_type_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_type_attrs),
0423 GFP_KERNEL);
0424 if (!tz->trip_type_attrs)
0425 return -ENOMEM;
0426
0427 tz->trip_temp_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_temp_attrs),
0428 GFP_KERNEL);
0429 if (!tz->trip_temp_attrs) {
0430 kfree(tz->trip_type_attrs);
0431 return -ENOMEM;
0432 }
0433
0434 if (tz->ops->get_trip_hyst) {
0435 tz->trip_hyst_attrs = kcalloc(tz->num_trips,
0436 sizeof(*tz->trip_hyst_attrs),
0437 GFP_KERNEL);
0438 if (!tz->trip_hyst_attrs) {
0439 kfree(tz->trip_type_attrs);
0440 kfree(tz->trip_temp_attrs);
0441 return -ENOMEM;
0442 }
0443 }
0444
0445 attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
0446 if (!attrs) {
0447 kfree(tz->trip_type_attrs);
0448 kfree(tz->trip_temp_attrs);
0449 if (tz->ops->get_trip_hyst)
0450 kfree(tz->trip_hyst_attrs);
0451 return -ENOMEM;
0452 }
0453
0454 for (indx = 0; indx < tz->num_trips; indx++) {
0455
0456 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
0457 "trip_point_%d_type", indx);
0458
0459 sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
0460 tz->trip_type_attrs[indx].attr.attr.name =
0461 tz->trip_type_attrs[indx].name;
0462 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
0463 tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
0464 attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
0465
0466
0467 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
0468 "trip_point_%d_temp", indx);
0469
0470 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
0471 tz->trip_temp_attrs[indx].attr.attr.name =
0472 tz->trip_temp_attrs[indx].name;
0473 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
0474 tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
0475 if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
0476 mask & (1 << indx)) {
0477 tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
0478 tz->trip_temp_attrs[indx].attr.store =
0479 trip_point_temp_store;
0480 }
0481 attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr;
0482
0483
0484 if (!tz->ops->get_trip_hyst)
0485 continue;
0486 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
0487 "trip_point_%d_hyst", indx);
0488
0489 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
0490 tz->trip_hyst_attrs[indx].attr.attr.name =
0491 tz->trip_hyst_attrs[indx].name;
0492 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
0493 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
0494 if (tz->ops->set_trip_hyst) {
0495 tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
0496 tz->trip_hyst_attrs[indx].attr.store =
0497 trip_point_hyst_store;
0498 }
0499 attrs[indx + tz->num_trips * 2] =
0500 &tz->trip_hyst_attrs[indx].attr.attr;
0501 }
0502 attrs[tz->num_trips * 3] = NULL;
0503
0504 tz->trips_attribute_group.attrs = attrs;
0505
0506 return 0;
0507 }
0508
0509
0510
0511
0512
0513
0514
0515 static void destroy_trip_attrs(struct thermal_zone_device *tz)
0516 {
0517 if (!tz)
0518 return;
0519
0520 kfree(tz->trip_type_attrs);
0521 kfree(tz->trip_temp_attrs);
0522 if (tz->ops->get_trip_hyst)
0523 kfree(tz->trip_hyst_attrs);
0524 kfree(tz->trips_attribute_group.attrs);
0525 }
0526
0527 int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
0528 int mask)
0529 {
0530 const struct attribute_group **groups;
0531 int i, size, result;
0532
0533
0534 size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
0535
0536 groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
0537 if (!groups)
0538 return -ENOMEM;
0539
0540 for (i = 0; i < size - 2; i++)
0541 groups[i] = thermal_zone_attribute_groups[i];
0542
0543 if (tz->num_trips) {
0544 result = create_trip_attrs(tz, mask);
0545 if (result) {
0546 kfree(groups);
0547
0548 return result;
0549 }
0550
0551 groups[size - 2] = &tz->trips_attribute_group;
0552 }
0553
0554 tz->device.groups = groups;
0555
0556 return 0;
0557 }
0558
0559 void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
0560 {
0561 if (!tz)
0562 return;
0563
0564 if (tz->num_trips)
0565 destroy_trip_attrs(tz);
0566
0567 kfree(tz->device.groups);
0568 }
0569
0570
0571 static ssize_t
0572 cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
0573 {
0574 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0575
0576 return sprintf(buf, "%s\n", cdev->type);
0577 }
0578
0579 static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
0580 char *buf)
0581 {
0582 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0583 unsigned long state;
0584 int ret;
0585
0586 ret = cdev->ops->get_max_state(cdev, &state);
0587 if (ret)
0588 return ret;
0589 return sprintf(buf, "%ld\n", state);
0590 }
0591
0592 static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
0593 char *buf)
0594 {
0595 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0596 unsigned long state;
0597 int ret;
0598
0599 ret = cdev->ops->get_cur_state(cdev, &state);
0600 if (ret)
0601 return ret;
0602 return sprintf(buf, "%ld\n", state);
0603 }
0604
0605 static ssize_t
0606 cur_state_store(struct device *dev, struct device_attribute *attr,
0607 const char *buf, size_t count)
0608 {
0609 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0610 unsigned long state;
0611 int result;
0612
0613 if (sscanf(buf, "%ld\n", &state) != 1)
0614 return -EINVAL;
0615
0616 if ((long)state < 0)
0617 return -EINVAL;
0618
0619 mutex_lock(&cdev->lock);
0620
0621 result = cdev->ops->set_cur_state(cdev, state);
0622 if (!result)
0623 thermal_cooling_device_stats_update(cdev, state);
0624
0625 mutex_unlock(&cdev->lock);
0626 return result ? result : count;
0627 }
0628
0629 static struct device_attribute
0630 dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
0631 static DEVICE_ATTR_RO(max_state);
0632 static DEVICE_ATTR_RW(cur_state);
0633
0634 static struct attribute *cooling_device_attrs[] = {
0635 &dev_attr_cdev_type.attr,
0636 &dev_attr_max_state.attr,
0637 &dev_attr_cur_state.attr,
0638 NULL,
0639 };
0640
0641 static const struct attribute_group cooling_device_attr_group = {
0642 .attrs = cooling_device_attrs,
0643 };
0644
0645 static const struct attribute_group *cooling_device_attr_groups[] = {
0646 &cooling_device_attr_group,
0647 NULL,
0648 NULL,
0649 };
0650
0651 #ifdef CONFIG_THERMAL_STATISTICS
0652 struct cooling_dev_stats {
0653 spinlock_t lock;
0654 unsigned int total_trans;
0655 unsigned long state;
0656 unsigned long max_states;
0657 ktime_t last_time;
0658 ktime_t *time_in_state;
0659 unsigned int *trans_table;
0660 };
0661
0662 static void update_time_in_state(struct cooling_dev_stats *stats)
0663 {
0664 ktime_t now = ktime_get(), delta;
0665
0666 delta = ktime_sub(now, stats->last_time);
0667 stats->time_in_state[stats->state] =
0668 ktime_add(stats->time_in_state[stats->state], delta);
0669 stats->last_time = now;
0670 }
0671
0672 void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
0673 unsigned long new_state)
0674 {
0675 struct cooling_dev_stats *stats = cdev->stats;
0676
0677 if (!stats)
0678 return;
0679
0680 spin_lock(&stats->lock);
0681
0682 if (stats->state == new_state)
0683 goto unlock;
0684
0685 update_time_in_state(stats);
0686 stats->trans_table[stats->state * stats->max_states + new_state]++;
0687 stats->state = new_state;
0688 stats->total_trans++;
0689
0690 unlock:
0691 spin_unlock(&stats->lock);
0692 }
0693
0694 static ssize_t total_trans_show(struct device *dev,
0695 struct device_attribute *attr, char *buf)
0696 {
0697 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0698 struct cooling_dev_stats *stats = cdev->stats;
0699 int ret;
0700
0701 spin_lock(&stats->lock);
0702 ret = sprintf(buf, "%u\n", stats->total_trans);
0703 spin_unlock(&stats->lock);
0704
0705 return ret;
0706 }
0707
0708 static ssize_t
0709 time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
0710 char *buf)
0711 {
0712 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0713 struct cooling_dev_stats *stats = cdev->stats;
0714 ssize_t len = 0;
0715 int i;
0716
0717 spin_lock(&stats->lock);
0718 update_time_in_state(stats);
0719
0720 for (i = 0; i < stats->max_states; i++) {
0721 len += sprintf(buf + len, "state%u\t%llu\n", i,
0722 ktime_to_ms(stats->time_in_state[i]));
0723 }
0724 spin_unlock(&stats->lock);
0725
0726 return len;
0727 }
0728
0729 static ssize_t
0730 reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
0731 size_t count)
0732 {
0733 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0734 struct cooling_dev_stats *stats = cdev->stats;
0735 int i, states = stats->max_states;
0736
0737 spin_lock(&stats->lock);
0738
0739 stats->total_trans = 0;
0740 stats->last_time = ktime_get();
0741 memset(stats->trans_table, 0,
0742 states * states * sizeof(*stats->trans_table));
0743
0744 for (i = 0; i < stats->max_states; i++)
0745 stats->time_in_state[i] = ktime_set(0, 0);
0746
0747 spin_unlock(&stats->lock);
0748
0749 return count;
0750 }
0751
0752 static ssize_t trans_table_show(struct device *dev,
0753 struct device_attribute *attr, char *buf)
0754 {
0755 struct thermal_cooling_device *cdev = to_cooling_device(dev);
0756 struct cooling_dev_stats *stats = cdev->stats;
0757 ssize_t len = 0;
0758 int i, j;
0759
0760 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
0761 len += snprintf(buf + len, PAGE_SIZE - len, " : ");
0762 for (i = 0; i < stats->max_states; i++) {
0763 if (len >= PAGE_SIZE)
0764 break;
0765 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u ", i);
0766 }
0767 if (len >= PAGE_SIZE)
0768 return PAGE_SIZE;
0769
0770 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
0771
0772 for (i = 0; i < stats->max_states; i++) {
0773 if (len >= PAGE_SIZE)
0774 break;
0775
0776 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
0777
0778 for (j = 0; j < stats->max_states; j++) {
0779 if (len >= PAGE_SIZE)
0780 break;
0781 len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
0782 stats->trans_table[i * stats->max_states + j]);
0783 }
0784 if (len >= PAGE_SIZE)
0785 break;
0786 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
0787 }
0788
0789 if (len >= PAGE_SIZE) {
0790 pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
0791 return -EFBIG;
0792 }
0793 return len;
0794 }
0795
0796 static DEVICE_ATTR_RO(total_trans);
0797 static DEVICE_ATTR_RO(time_in_state_ms);
0798 static DEVICE_ATTR_WO(reset);
0799 static DEVICE_ATTR_RO(trans_table);
0800
0801 static struct attribute *cooling_device_stats_attrs[] = {
0802 &dev_attr_total_trans.attr,
0803 &dev_attr_time_in_state_ms.attr,
0804 &dev_attr_reset.attr,
0805 &dev_attr_trans_table.attr,
0806 NULL
0807 };
0808
0809 static const struct attribute_group cooling_device_stats_attr_group = {
0810 .attrs = cooling_device_stats_attrs,
0811 .name = "stats"
0812 };
0813
0814 static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
0815 {
0816 const struct attribute_group *stats_attr_group = NULL;
0817 struct cooling_dev_stats *stats;
0818 unsigned long states;
0819 int var;
0820
0821 if (cdev->ops->get_max_state(cdev, &states))
0822 goto out;
0823
0824 states++;
0825
0826 var = sizeof(*stats);
0827 var += sizeof(*stats->time_in_state) * states;
0828 var += sizeof(*stats->trans_table) * states * states;
0829
0830 stats = kzalloc(var, GFP_KERNEL);
0831 if (!stats)
0832 goto out;
0833
0834 stats->time_in_state = (ktime_t *)(stats + 1);
0835 stats->trans_table = (unsigned int *)(stats->time_in_state + states);
0836 cdev->stats = stats;
0837 stats->last_time = ktime_get();
0838 stats->max_states = states;
0839
0840 spin_lock_init(&stats->lock);
0841
0842 stats_attr_group = &cooling_device_stats_attr_group;
0843
0844 out:
0845
0846 var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
0847 cooling_device_attr_groups[var] = stats_attr_group;
0848 }
0849
0850 static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
0851 {
0852 kfree(cdev->stats);
0853 cdev->stats = NULL;
0854 }
0855
0856 #else
0857
0858 static inline void
0859 cooling_device_stats_setup(struct thermal_cooling_device *cdev) {}
0860 static inline void
0861 cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {}
0862
0863 #endif
0864
0865 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
0866 {
0867 cooling_device_stats_setup(cdev);
0868 cdev->device.groups = cooling_device_attr_groups;
0869 }
0870
0871 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
0872 {
0873 cooling_device_stats_destroy(cdev);
0874 }
0875
0876
0877 ssize_t
0878 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
0879 {
0880 struct thermal_instance *instance;
0881
0882 instance =
0883 container_of(attr, struct thermal_instance, attr);
0884
0885 return sprintf(buf, "%d\n", instance->trip);
0886 }
0887
0888 ssize_t
0889 weight_show(struct device *dev, struct device_attribute *attr, char *buf)
0890 {
0891 struct thermal_instance *instance;
0892
0893 instance = container_of(attr, struct thermal_instance, weight_attr);
0894
0895 return sprintf(buf, "%d\n", instance->weight);
0896 }
0897
0898 ssize_t weight_store(struct device *dev, struct device_attribute *attr,
0899 const char *buf, size_t count)
0900 {
0901 struct thermal_instance *instance;
0902 int ret, weight;
0903
0904 ret = kstrtoint(buf, 0, &weight);
0905 if (ret)
0906 return ret;
0907
0908 instance = container_of(attr, struct thermal_instance, weight_attr);
0909 instance->weight = weight;
0910
0911 return count;
0912 }