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