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