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/container_of.h>
16 #include <linux/sysfs.h>
17 #include <linux/device.h>
18 #include <linux/err.h>
19 #include <linux/slab.h>
20 #include <linux/string.h>
21 #include <linux/jiffies.h>
22
23 #include "thermal_core.h"
24
25 /* sys I/F for thermal zone */
26
27 static ssize_t
type_show(struct device * dev,struct device_attribute * attr,char * buf)28 type_show(struct device *dev, struct device_attribute *attr, char *buf)
29 {
30 struct thermal_zone_device *tz = to_thermal_zone(dev);
31
32 return sprintf(buf, "%s\n", tz->type);
33 }
34
35 static ssize_t
temp_show(struct device * dev,struct device_attribute * attr,char * buf)36 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
37 {
38 struct thermal_zone_device *tz = to_thermal_zone(dev);
39 int temperature, ret;
40
41 ret = thermal_zone_get_temp(tz, &temperature);
42
43 if (!ret)
44 return sprintf(buf, "%d\n", temperature);
45
46 if (ret == -EAGAIN)
47 return -ENODATA;
48
49 return ret;
50 }
51
52 static ssize_t
mode_show(struct device * dev,struct device_attribute * attr,char * buf)53 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
54 {
55 struct thermal_zone_device *tz = to_thermal_zone(dev);
56
57 guard(thermal_zone)(tz);
58
59 if (tz->mode == THERMAL_DEVICE_ENABLED)
60 return sprintf(buf, "enabled\n");
61
62 return sprintf(buf, "disabled\n");
63 }
64
65 static ssize_t
mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)66 mode_store(struct device *dev, struct device_attribute *attr,
67 const char *buf, size_t count)
68 {
69 struct thermal_zone_device *tz = to_thermal_zone(dev);
70 int result;
71
72 if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
73 result = thermal_zone_device_enable(tz);
74 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
75 result = thermal_zone_device_disable(tz);
76 else
77 result = -EINVAL;
78
79 if (result)
80 return result;
81
82 return count;
83 }
84
85 #define thermal_trip_of_attr(_ptr_, _attr_) \
86 ({ \
87 struct thermal_trip_desc *td; \
88 \
89 td = container_of(_ptr_, struct thermal_trip_desc, \
90 trip_attrs._attr_.attr); \
91 &td->trip; \
92 })
93
94 static ssize_t
trip_point_type_show(struct device * dev,struct device_attribute * attr,char * buf)95 trip_point_type_show(struct device *dev, struct device_attribute *attr,
96 char *buf)
97 {
98 struct thermal_trip *trip = thermal_trip_of_attr(attr, type);
99
100 return sprintf(buf, "%s\n", thermal_trip_type_name(trip->type));
101 }
102
103 static ssize_t
trip_point_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)104 trip_point_temp_store(struct device *dev, struct device_attribute *attr,
105 const char *buf, size_t count)
106 {
107 struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
108 struct thermal_zone_device *tz = to_thermal_zone(dev);
109 int temp;
110
111 if (kstrtoint(buf, 10, &temp))
112 return -EINVAL;
113
114 guard(thermal_zone)(tz);
115
116 if (temp == trip->temperature)
117 return count;
118
119 /* Arrange the condition to avoid integer overflows. */
120 if (temp != THERMAL_TEMP_INVALID &&
121 temp <= trip->hysteresis + THERMAL_TEMP_INVALID)
122 return -EINVAL;
123
124 if (tz->ops.set_trip_temp) {
125 int ret;
126
127 ret = tz->ops.set_trip_temp(tz, trip, temp);
128 if (ret)
129 return ret;
130 }
131
132 thermal_zone_set_trip_temp(tz, trip, temp);
133
134 __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
135
136 return count;
137 }
138
139 static ssize_t
trip_point_temp_show(struct device * dev,struct device_attribute * attr,char * buf)140 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
141 char *buf)
142 {
143 struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
144
145 return sprintf(buf, "%d\n", READ_ONCE(trip->temperature));
146 }
147
148 static ssize_t
trip_point_hyst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)149 trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
150 const char *buf, size_t count)
151 {
152 struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
153 struct thermal_zone_device *tz = to_thermal_zone(dev);
154 int hyst;
155
156 if (kstrtoint(buf, 10, &hyst) || hyst < 0)
157 return -EINVAL;
158
159 guard(thermal_zone)(tz);
160
161 if (hyst == trip->hysteresis)
162 return count;
163
164 /*
165 * Allow the hysteresis to be updated when the temperature is invalid
166 * to allow user space to avoid having to adjust hysteresis after a
167 * valid temperature has been set, but in that case just change the
168 * value and do nothing else.
169 */
170 if (trip->temperature == THERMAL_TEMP_INVALID) {
171 WRITE_ONCE(trip->hysteresis, hyst);
172 return count;
173 }
174
175 if (trip->temperature - hyst <= THERMAL_TEMP_INVALID)
176 return -EINVAL;
177
178 thermal_zone_set_trip_hyst(tz, trip, hyst);
179
180 __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
181
182 return count;
183 }
184
185 static ssize_t
trip_point_hyst_show(struct device * dev,struct device_attribute * attr,char * buf)186 trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
187 char *buf)
188 {
189 struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
190
191 return sprintf(buf, "%d\n", READ_ONCE(trip->hysteresis));
192 }
193
194 static ssize_t
policy_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)195 policy_store(struct device *dev, struct device_attribute *attr,
196 const char *buf, size_t count)
197 {
198 struct thermal_zone_device *tz = to_thermal_zone(dev);
199 char name[THERMAL_NAME_LENGTH];
200 int ret;
201
202 snprintf(name, sizeof(name), "%s", buf);
203
204 ret = thermal_zone_device_set_policy(tz, name);
205 if (!ret)
206 ret = count;
207
208 return ret;
209 }
210
211 static ssize_t
policy_show(struct device * dev,struct device_attribute * devattr,char * buf)212 policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
213 {
214 struct thermal_zone_device *tz = to_thermal_zone(dev);
215
216 return sprintf(buf, "%s\n", tz->governor->name);
217 }
218
219 static ssize_t
available_policies_show(struct device * dev,struct device_attribute * devattr,char * buf)220 available_policies_show(struct device *dev, struct device_attribute *devattr,
221 char *buf)
222 {
223 return thermal_build_list_of_policies(buf);
224 }
225
226 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
227 static ssize_t
emul_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)228 emul_temp_store(struct device *dev, struct device_attribute *attr,
229 const char *buf, size_t count)
230 {
231 struct thermal_zone_device *tz = to_thermal_zone(dev);
232 int temperature;
233
234 if (kstrtoint(buf, 10, &temperature))
235 return -EINVAL;
236
237 guard(thermal_zone)(tz);
238
239 if (tz->ops.set_emul_temp) {
240 int ret;
241
242 ret = tz->ops.set_emul_temp(tz, temperature);
243 if (ret)
244 return ret;
245 } else {
246 tz->emul_temperature = temperature;
247 }
248
249 __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
250
251 return count;
252 }
253 static DEVICE_ATTR_WO(emul_temp);
254 #endif
255
256 static ssize_t
sustainable_power_show(struct device * dev,struct device_attribute * devattr,char * buf)257 sustainable_power_show(struct device *dev, struct device_attribute *devattr,
258 char *buf)
259 {
260 struct thermal_zone_device *tz = to_thermal_zone(dev);
261
262 if (tz->tzp)
263 return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
264 else
265 return -EIO;
266 }
267
268 static ssize_t
sustainable_power_store(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)269 sustainable_power_store(struct device *dev, struct device_attribute *devattr,
270 const char *buf, size_t count)
271 {
272 struct thermal_zone_device *tz = to_thermal_zone(dev);
273 u32 sustainable_power;
274
275 if (!tz->tzp)
276 return -EIO;
277
278 if (kstrtou32(buf, 10, &sustainable_power))
279 return -EINVAL;
280
281 tz->tzp->sustainable_power = sustainable_power;
282
283 return count;
284 }
285
286 #define create_s32_tzp_attr(name) \
287 static ssize_t \
288 name##_show(struct device *dev, struct device_attribute *devattr, \
289 char *buf) \
290 { \
291 struct thermal_zone_device *tz = to_thermal_zone(dev); \
292 \
293 if (tz->tzp) \
294 return sprintf(buf, "%d\n", tz->tzp->name); \
295 else \
296 return -EIO; \
297 } \
298 \
299 static ssize_t \
300 name##_store(struct device *dev, struct device_attribute *devattr, \
301 const char *buf, size_t count) \
302 { \
303 struct thermal_zone_device *tz = to_thermal_zone(dev); \
304 s32 value; \
305 \
306 if (!tz->tzp) \
307 return -EIO; \
308 \
309 if (kstrtos32(buf, 10, &value)) \
310 return -EINVAL; \
311 \
312 tz->tzp->name = value; \
313 \
314 return count; \
315 } \
316 static DEVICE_ATTR_RW(name)
317
318 create_s32_tzp_attr(k_po);
319 create_s32_tzp_attr(k_pu);
320 create_s32_tzp_attr(k_i);
321 create_s32_tzp_attr(k_d);
322 create_s32_tzp_attr(integral_cutoff);
323 create_s32_tzp_attr(slope);
324 create_s32_tzp_attr(offset);
325 #undef create_s32_tzp_attr
326
327 /*
328 * These are thermal zone device attributes that will always be present.
329 * All the attributes created for tzp (create_s32_tzp_attr) also are always
330 * present on the sysfs interface.
331 */
332 static DEVICE_ATTR_RO(type);
333 static DEVICE_ATTR_RO(temp);
334 static DEVICE_ATTR_RW(policy);
335 static DEVICE_ATTR_RO(available_policies);
336 static DEVICE_ATTR_RW(sustainable_power);
337
338 /* These thermal zone device attributes are created based on conditions */
339 static DEVICE_ATTR_RW(mode);
340
341 /* These attributes are unconditionally added to a thermal zone */
342 static struct attribute *thermal_zone_dev_attrs[] = {
343 &dev_attr_type.attr,
344 &dev_attr_temp.attr,
345 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
346 &dev_attr_emul_temp.attr,
347 #endif
348 &dev_attr_policy.attr,
349 &dev_attr_available_policies.attr,
350 &dev_attr_sustainable_power.attr,
351 &dev_attr_k_po.attr,
352 &dev_attr_k_pu.attr,
353 &dev_attr_k_i.attr,
354 &dev_attr_k_d.attr,
355 &dev_attr_integral_cutoff.attr,
356 &dev_attr_slope.attr,
357 &dev_attr_offset.attr,
358 NULL,
359 };
360
361 static const struct attribute_group thermal_zone_attribute_group = {
362 .attrs = thermal_zone_dev_attrs,
363 };
364
365 static struct attribute *thermal_zone_mode_attrs[] = {
366 &dev_attr_mode.attr,
367 NULL,
368 };
369
370 static const struct attribute_group thermal_zone_mode_attribute_group = {
371 .attrs = thermal_zone_mode_attrs,
372 };
373
374 static const struct attribute_group *thermal_zone_attribute_groups[] = {
375 &thermal_zone_attribute_group,
376 &thermal_zone_mode_attribute_group,
377 /* This is not NULL terminated as we create the group dynamically */
378 };
379
380 /**
381 * create_trip_attrs() - create attributes for trip points
382 * @tz: the thermal zone device
383 *
384 * helper function to instantiate sysfs entries for every trip
385 * point and its properties of a struct thermal_zone_device.
386 *
387 * Return: 0 on success, the proper error value otherwise.
388 */
create_trip_attrs(struct thermal_zone_device * tz)389 static int create_trip_attrs(struct thermal_zone_device *tz)
390 {
391 struct thermal_trip_desc *td;
392 struct attribute **attrs;
393 int i;
394
395 attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
396 if (!attrs)
397 return -ENOMEM;
398
399 i = 0;
400 for_each_trip_desc(tz, td) {
401 struct thermal_trip_attrs *trip_attrs = &td->trip_attrs;
402
403 /* create trip type attribute */
404 snprintf(trip_attrs->type.name, THERMAL_NAME_LENGTH,
405 "trip_point_%d_type", i);
406
407 sysfs_attr_init(&trip_attrs->type.attr.attr);
408 trip_attrs->type.attr.attr.name = trip_attrs->type.name;
409 trip_attrs->type.attr.attr.mode = S_IRUGO;
410 trip_attrs->type.attr.show = trip_point_type_show;
411 attrs[i] = &trip_attrs->type.attr.attr;
412
413 /* create trip temp attribute */
414 snprintf(trip_attrs->temp.name, THERMAL_NAME_LENGTH,
415 "trip_point_%d_temp", i);
416
417 sysfs_attr_init(&trip_attrs->temp.attr.attr);
418 trip_attrs->temp.attr.attr.name = trip_attrs->temp.name;
419 trip_attrs->temp.attr.attr.mode = S_IRUGO;
420 trip_attrs->temp.attr.show = trip_point_temp_show;
421 if (td->trip.flags & THERMAL_TRIP_FLAG_RW_TEMP) {
422 trip_attrs->temp.attr.attr.mode |= S_IWUSR;
423 trip_attrs->temp.attr.store = trip_point_temp_store;
424 }
425 attrs[i + tz->num_trips] = &trip_attrs->temp.attr.attr;
426
427 snprintf(trip_attrs->hyst.name, THERMAL_NAME_LENGTH,
428 "trip_point_%d_hyst", i);
429
430 sysfs_attr_init(&trip_attrs->hyst.attr.attr);
431 trip_attrs->hyst.attr.attr.name = trip_attrs->hyst.name;
432 trip_attrs->hyst.attr.attr.mode = S_IRUGO;
433 trip_attrs->hyst.attr.show = trip_point_hyst_show;
434 if (td->trip.flags & THERMAL_TRIP_FLAG_RW_HYST) {
435 trip_attrs->hyst.attr.attr.mode |= S_IWUSR;
436 trip_attrs->hyst.attr.store = trip_point_hyst_store;
437 }
438 attrs[i + 2 * tz->num_trips] = &trip_attrs->hyst.attr.attr;
439 i++;
440 }
441 attrs[tz->num_trips * 3] = NULL;
442
443 tz->trips_attribute_group.attrs = attrs;
444
445 return 0;
446 }
447
448 /**
449 * destroy_trip_attrs() - destroy attributes for trip points
450 * @tz: the thermal zone device
451 *
452 * helper function to free resources allocated by create_trip_attrs()
453 */
destroy_trip_attrs(struct thermal_zone_device * tz)454 static void destroy_trip_attrs(struct thermal_zone_device *tz)
455 {
456 if (tz)
457 kfree(tz->trips_attribute_group.attrs);
458 }
459
thermal_zone_create_device_groups(struct thermal_zone_device * tz)460 int thermal_zone_create_device_groups(struct thermal_zone_device *tz)
461 {
462 const struct attribute_group **groups;
463 int i, size, result;
464
465 /* we need one extra for trips and the NULL to terminate the array */
466 size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
467 /* This also takes care of API requirement to be NULL terminated */
468 groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
469 if (!groups)
470 return -ENOMEM;
471
472 for (i = 0; i < size - 2; i++)
473 groups[i] = thermal_zone_attribute_groups[i];
474
475 if (tz->num_trips) {
476 result = create_trip_attrs(tz);
477 if (result) {
478 kfree(groups);
479
480 return result;
481 }
482
483 groups[size - 2] = &tz->trips_attribute_group;
484 }
485
486 tz->device.groups = groups;
487
488 return 0;
489 }
490
thermal_zone_destroy_device_groups(struct thermal_zone_device * tz)491 void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
492 {
493 if (!tz)
494 return;
495
496 if (tz->num_trips)
497 destroy_trip_attrs(tz);
498
499 kfree(tz->device.groups);
500 }
501
502 /* sys I/F for cooling device */
503 static ssize_t
cdev_type_show(struct device * dev,struct device_attribute * attr,char * buf)504 cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
505 {
506 struct thermal_cooling_device *cdev = to_cooling_device(dev);
507
508 return sprintf(buf, "%s\n", cdev->type);
509 }
510
max_state_show(struct device * dev,struct device_attribute * attr,char * buf)511 static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
512 char *buf)
513 {
514 struct thermal_cooling_device *cdev = to_cooling_device(dev);
515
516 return sprintf(buf, "%ld\n", cdev->max_state);
517 }
518
cur_state_show(struct device * dev,struct device_attribute * attr,char * buf)519 static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
520 char *buf)
521 {
522 struct thermal_cooling_device *cdev = to_cooling_device(dev);
523 unsigned long state;
524 int ret;
525
526 ret = cdev->ops->get_cur_state(cdev, &state);
527 if (ret)
528 return ret;
529 return sprintf(buf, "%ld\n", state);
530 }
531
532 static ssize_t
cur_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)533 cur_state_store(struct device *dev, struct device_attribute *attr,
534 const char *buf, size_t count)
535 {
536 struct thermal_cooling_device *cdev = to_cooling_device(dev);
537 unsigned long state;
538 int result;
539
540 if (sscanf(buf, "%ld\n", &state) != 1)
541 return -EINVAL;
542
543 if ((long)state < 0)
544 return -EINVAL;
545
546 /* Requested state should be less than max_state + 1 */
547 if (state > cdev->max_state)
548 return -EINVAL;
549
550 guard(cooling_dev)(cdev);
551
552 result = cdev->ops->set_cur_state(cdev, state);
553 if (result)
554 return result;
555
556 thermal_cooling_device_stats_update(cdev, state);
557
558 return count;
559 }
560
561 static struct device_attribute
562 dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
563 static DEVICE_ATTR_RO(max_state);
564 static DEVICE_ATTR_RW(cur_state);
565
566 static struct attribute *cooling_device_attrs[] = {
567 &dev_attr_cdev_type.attr,
568 &dev_attr_max_state.attr,
569 &dev_attr_cur_state.attr,
570 NULL,
571 };
572
573 static const struct attribute_group cooling_device_attr_group = {
574 .attrs = cooling_device_attrs,
575 };
576
577 static const struct attribute_group *cooling_device_attr_groups[] = {
578 &cooling_device_attr_group,
579 NULL, /* Space allocated for cooling_device_stats_attr_group */
580 NULL,
581 };
582
583 #ifdef CONFIG_THERMAL_STATISTICS
584 struct cooling_dev_stats {
585 spinlock_t lock;
586 unsigned int total_trans;
587 unsigned long state;
588 ktime_t last_time;
589 ktime_t *time_in_state;
590 unsigned int *trans_table;
591 };
592
update_time_in_state(struct cooling_dev_stats * stats)593 static void update_time_in_state(struct cooling_dev_stats *stats)
594 {
595 ktime_t now = ktime_get(), delta;
596
597 delta = ktime_sub(now, stats->last_time);
598 stats->time_in_state[stats->state] =
599 ktime_add(stats->time_in_state[stats->state], delta);
600 stats->last_time = now;
601 }
602
thermal_cooling_device_stats_update(struct thermal_cooling_device * cdev,unsigned long new_state)603 void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
604 unsigned long new_state)
605 {
606 struct cooling_dev_stats *stats = cdev->stats;
607
608 lockdep_assert_held(&cdev->lock);
609
610 if (!stats)
611 return;
612
613 spin_lock(&stats->lock);
614
615 if (stats->state == new_state)
616 goto unlock;
617
618 update_time_in_state(stats);
619 stats->trans_table[stats->state * (cdev->max_state + 1) + new_state]++;
620 stats->state = new_state;
621 stats->total_trans++;
622
623 unlock:
624 spin_unlock(&stats->lock);
625 }
626
total_trans_show(struct device * dev,struct device_attribute * attr,char * buf)627 static ssize_t total_trans_show(struct device *dev,
628 struct device_attribute *attr, char *buf)
629 {
630 struct thermal_cooling_device *cdev = to_cooling_device(dev);
631 struct cooling_dev_stats *stats;
632 int ret;
633
634 guard(cooling_dev)(cdev);
635
636 stats = cdev->stats;
637 if (!stats)
638 return 0;
639
640 spin_lock(&stats->lock);
641 ret = sprintf(buf, "%u\n", stats->total_trans);
642 spin_unlock(&stats->lock);
643
644 return ret;
645 }
646
647 static ssize_t
time_in_state_ms_show(struct device * dev,struct device_attribute * attr,char * buf)648 time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
649 char *buf)
650 {
651 struct thermal_cooling_device *cdev = to_cooling_device(dev);
652 struct cooling_dev_stats *stats;
653 ssize_t len = 0;
654 int i;
655
656 guard(cooling_dev)(cdev);
657
658 stats = cdev->stats;
659 if (!stats)
660 return 0;
661
662 spin_lock(&stats->lock);
663
664 update_time_in_state(stats);
665
666 for (i = 0; i <= cdev->max_state; i++) {
667 len += sprintf(buf + len, "state%u\t%llu\n", i,
668 ktime_to_ms(stats->time_in_state[i]));
669 }
670 spin_unlock(&stats->lock);
671
672 return len;
673 }
674
675 static ssize_t
reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)676 reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
677 size_t count)
678 {
679 struct thermal_cooling_device *cdev = to_cooling_device(dev);
680 struct cooling_dev_stats *stats;
681 int i, states;
682
683 guard(cooling_dev)(cdev);
684
685 stats = cdev->stats;
686 if (!stats)
687 return count;
688
689 states = cdev->max_state + 1;
690
691 spin_lock(&stats->lock);
692
693 stats->total_trans = 0;
694 stats->last_time = ktime_get();
695 memset(stats->trans_table, 0,
696 states * states * sizeof(*stats->trans_table));
697
698 for (i = 0; i < states; i++)
699 stats->time_in_state[i] = ktime_set(0, 0);
700
701 spin_unlock(&stats->lock);
702
703 return count;
704 }
705
trans_table_show(struct device * dev,struct device_attribute * attr,char * buf)706 static ssize_t trans_table_show(struct device *dev,
707 struct device_attribute *attr, char *buf)
708 {
709 struct thermal_cooling_device *cdev = to_cooling_device(dev);
710 struct cooling_dev_stats *stats;
711 ssize_t len = 0;
712 int i, j;
713
714 guard(cooling_dev)(cdev);
715
716 stats = cdev->stats;
717 if (!stats)
718 return -ENODATA;
719
720 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
721 len += snprintf(buf + len, PAGE_SIZE - len, " : ");
722 for (i = 0; i <= cdev->max_state; i++) {
723 if (len >= PAGE_SIZE)
724 break;
725 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u ", i);
726 }
727 if (len >= PAGE_SIZE)
728 return PAGE_SIZE;
729
730 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
731
732 for (i = 0; i <= cdev->max_state; i++) {
733 if (len >= PAGE_SIZE)
734 break;
735
736 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
737
738 for (j = 0; j <= cdev->max_state; j++) {
739 if (len >= PAGE_SIZE)
740 break;
741 len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
742 stats->trans_table[i * (cdev->max_state + 1) + j]);
743 }
744 if (len >= PAGE_SIZE)
745 break;
746 len += snprintf(buf + len, PAGE_SIZE - len, "\n");
747 }
748
749 if (len >= PAGE_SIZE) {
750 pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
751 len = -EFBIG;
752 }
753
754 return len;
755 }
756
757 static DEVICE_ATTR_RO(total_trans);
758 static DEVICE_ATTR_RO(time_in_state_ms);
759 static DEVICE_ATTR_WO(reset);
760 static DEVICE_ATTR_RO(trans_table);
761
762 static struct attribute *cooling_device_stats_attrs[] = {
763 &dev_attr_total_trans.attr,
764 &dev_attr_time_in_state_ms.attr,
765 &dev_attr_reset.attr,
766 &dev_attr_trans_table.attr,
767 NULL
768 };
769
770 static const struct attribute_group cooling_device_stats_attr_group = {
771 .attrs = cooling_device_stats_attrs,
772 .name = "stats"
773 };
774
cooling_device_stats_setup(struct thermal_cooling_device * cdev)775 static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
776 {
777 const struct attribute_group *stats_attr_group = NULL;
778 struct cooling_dev_stats *stats;
779 /* Total number of states is highest state + 1 */
780 unsigned long states = cdev->max_state + 1;
781 int var;
782
783 var = sizeof(*stats);
784 var += sizeof(*stats->time_in_state) * states;
785 var += sizeof(*stats->trans_table) * states * states;
786
787 stats = kzalloc(var, GFP_KERNEL);
788 if (!stats)
789 goto out;
790
791 stats->time_in_state = (ktime_t *)(stats + 1);
792 stats->trans_table = (unsigned int *)(stats->time_in_state + states);
793 cdev->stats = stats;
794 stats->last_time = ktime_get();
795
796 spin_lock_init(&stats->lock);
797
798 stats_attr_group = &cooling_device_stats_attr_group;
799
800 out:
801 /* Fill the empty slot left in cooling_device_attr_groups */
802 var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
803 cooling_device_attr_groups[var] = stats_attr_group;
804 }
805
cooling_device_stats_destroy(struct thermal_cooling_device * cdev)806 static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
807 {
808 kfree(cdev->stats);
809 cdev->stats = NULL;
810 }
811
812 #else
813
814 static inline void
cooling_device_stats_setup(struct thermal_cooling_device * cdev)815 cooling_device_stats_setup(struct thermal_cooling_device *cdev) {}
816 static inline void
cooling_device_stats_destroy(struct thermal_cooling_device * cdev)817 cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {}
818
819 #endif /* CONFIG_THERMAL_STATISTICS */
820
thermal_cooling_device_setup_sysfs(struct thermal_cooling_device * cdev)821 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
822 {
823 cooling_device_stats_setup(cdev);
824 cdev->device.groups = cooling_device_attr_groups;
825 }
826
thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device * cdev)827 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
828 {
829 cooling_device_stats_destroy(cdev);
830 }
831
thermal_cooling_device_stats_reinit(struct thermal_cooling_device * cdev)832 void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev)
833 {
834 lockdep_assert_held(&cdev->lock);
835
836 cooling_device_stats_destroy(cdev);
837 cooling_device_stats_setup(cdev);
838 }
839
840 /* these helper will be used only at the time of bindig */
841 ssize_t
trip_point_show(struct device * dev,struct device_attribute * attr,char * buf)842 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
843 {
844 struct thermal_zone_device *tz = to_thermal_zone(dev);
845 struct thermal_instance *instance;
846
847 instance = container_of(attr, struct thermal_instance, attr);
848
849 return sprintf(buf, "%d\n", thermal_zone_trip_id(tz, instance->trip));
850 }
851
852 ssize_t
weight_show(struct device * dev,struct device_attribute * attr,char * buf)853 weight_show(struct device *dev, struct device_attribute *attr, char *buf)
854 {
855 struct thermal_instance *instance;
856
857 instance = container_of(attr, struct thermal_instance, weight_attr);
858
859 return sprintf(buf, "%d\n", instance->weight);
860 }
861
weight_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)862 ssize_t weight_store(struct device *dev, struct device_attribute *attr,
863 const char *buf, size_t count)
864 {
865 struct thermal_zone_device *tz = to_thermal_zone(dev);
866 struct thermal_instance *instance;
867 int ret, weight;
868
869 ret = kstrtoint(buf, 0, &weight);
870 if (ret)
871 return ret;
872
873 instance = container_of(attr, struct thermal_instance, weight_attr);
874
875 /* Don't race with governors using the 'weight' value */
876 guard(thermal_zone)(tz);
877
878 instance->weight = weight;
879
880 thermal_governor_update_tz(tz, THERMAL_INSTANCE_WEIGHT_CHANGED);
881
882 return count;
883 }
884