• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
policy_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)221 policy_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 	char name[THERMAL_NAME_LENGTH];
226 	int ret;
227 
228 	snprintf(name, sizeof(name), "%s", buf);
229 
230 	ret = thermal_zone_device_set_policy(tz, name);
231 	if (!ret)
232 		ret = count;
233 
234 	return ret;
235 }
236 
237 static ssize_t
policy_show(struct device * dev,struct device_attribute * devattr,char * buf)238 policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
239 {
240 	struct thermal_zone_device *tz = to_thermal_zone(dev);
241 
242 	return sprintf(buf, "%s\n", tz->governor->name);
243 }
244 
245 static ssize_t
available_policies_show(struct device * dev,struct device_attribute * devattr,char * buf)246 available_policies_show(struct device *dev, struct device_attribute *devattr,
247 			char *buf)
248 {
249 	return thermal_build_list_of_policies(buf);
250 }
251 
252 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
253 static ssize_t
emul_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)254 emul_temp_store(struct device *dev, struct device_attribute *attr,
255 		const char *buf, size_t count)
256 {
257 	struct thermal_zone_device *tz = to_thermal_zone(dev);
258 	int ret = 0;
259 	int temperature;
260 
261 	if (kstrtoint(buf, 10, &temperature))
262 		return -EINVAL;
263 
264 	if (!tz->ops->set_emul_temp) {
265 		mutex_lock(&tz->lock);
266 		tz->emul_temperature = temperature;
267 		mutex_unlock(&tz->lock);
268 	} else {
269 		ret = tz->ops->set_emul_temp(tz, temperature);
270 	}
271 
272 	if (!ret)
273 		thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
274 
275 	return ret ? ret : count;
276 }
277 static DEVICE_ATTR_WO(emul_temp);
278 #endif
279 
280 static ssize_t
sustainable_power_show(struct device * dev,struct device_attribute * devattr,char * buf)281 sustainable_power_show(struct device *dev, struct device_attribute *devattr,
282 		       char *buf)
283 {
284 	struct thermal_zone_device *tz = to_thermal_zone(dev);
285 
286 	if (tz->tzp)
287 		return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
288 	else
289 		return -EIO;
290 }
291 
292 static ssize_t
sustainable_power_store(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)293 sustainable_power_store(struct device *dev, struct device_attribute *devattr,
294 			const char *buf, size_t count)
295 {
296 	struct thermal_zone_device *tz = to_thermal_zone(dev);
297 	u32 sustainable_power;
298 
299 	if (!tz->tzp)
300 		return -EIO;
301 
302 	if (kstrtou32(buf, 10, &sustainable_power))
303 		return -EINVAL;
304 
305 	tz->tzp->sustainable_power = sustainable_power;
306 
307 	return count;
308 }
309 
310 #define create_s32_tzp_attr(name)					\
311 	static ssize_t							\
312 	name##_show(struct device *dev, struct device_attribute *devattr, \
313 		char *buf)						\
314 	{								\
315 	struct thermal_zone_device *tz = to_thermal_zone(dev);		\
316 									\
317 	if (tz->tzp)							\
318 		return sprintf(buf, "%d\n", tz->tzp->name);		\
319 	else								\
320 		return -EIO;						\
321 	}								\
322 									\
323 	static ssize_t							\
324 	name##_store(struct device *dev, struct device_attribute *devattr, \
325 		const char *buf, size_t count)				\
326 	{								\
327 		struct thermal_zone_device *tz = to_thermal_zone(dev);	\
328 		s32 value;						\
329 									\
330 		if (!tz->tzp)						\
331 			return -EIO;					\
332 									\
333 		if (kstrtos32(buf, 10, &value))				\
334 			return -EINVAL;					\
335 									\
336 		tz->tzp->name = value;					\
337 									\
338 		return count;						\
339 	}								\
340 	static DEVICE_ATTR_RW(name)
341 
342 create_s32_tzp_attr(k_po);
343 create_s32_tzp_attr(k_pu);
344 create_s32_tzp_attr(k_i);
345 create_s32_tzp_attr(k_d);
346 create_s32_tzp_attr(integral_cutoff);
347 create_s32_tzp_attr(slope);
348 create_s32_tzp_attr(offset);
349 #undef create_s32_tzp_attr
350 
351 /*
352  * These are thermal zone device attributes that will always be present.
353  * All the attributes created for tzp (create_s32_tzp_attr) also are always
354  * present on the sysfs interface.
355  */
356 static DEVICE_ATTR_RO(type);
357 static DEVICE_ATTR_RO(temp);
358 static DEVICE_ATTR_RW(policy);
359 static DEVICE_ATTR_RO(available_policies);
360 static DEVICE_ATTR_RW(sustainable_power);
361 
362 /* These thermal zone device attributes are created based on conditions */
363 static DEVICE_ATTR_RW(mode);
364 
365 /* These attributes are unconditionally added to a thermal zone */
366 static struct attribute *thermal_zone_dev_attrs[] = {
367 	&dev_attr_type.attr,
368 	&dev_attr_temp.attr,
369 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
370 	&dev_attr_emul_temp.attr,
371 #endif
372 	&dev_attr_policy.attr,
373 	&dev_attr_available_policies.attr,
374 	&dev_attr_sustainable_power.attr,
375 	&dev_attr_k_po.attr,
376 	&dev_attr_k_pu.attr,
377 	&dev_attr_k_i.attr,
378 	&dev_attr_k_d.attr,
379 	&dev_attr_integral_cutoff.attr,
380 	&dev_attr_slope.attr,
381 	&dev_attr_offset.attr,
382 	NULL,
383 };
384 
385 static const struct attribute_group thermal_zone_attribute_group = {
386 	.attrs = thermal_zone_dev_attrs,
387 };
388 
389 static struct attribute *thermal_zone_mode_attrs[] = {
390 	&dev_attr_mode.attr,
391 	NULL,
392 };
393 
394 static const struct attribute_group thermal_zone_mode_attribute_group = {
395 	.attrs = thermal_zone_mode_attrs,
396 };
397 
398 static const struct attribute_group *thermal_zone_attribute_groups[] = {
399 	&thermal_zone_attribute_group,
400 	&thermal_zone_mode_attribute_group,
401 	/* This is not NULL terminated as we create the group dynamically */
402 };
403 
404 /**
405  * create_trip_attrs() - create attributes for trip points
406  * @tz:		the thermal zone device
407  * @mask:	Writeable trip point bitmap.
408  *
409  * helper function to instantiate sysfs entries for every trip
410  * point and its properties of a struct thermal_zone_device.
411  *
412  * Return: 0 on success, the proper error value otherwise.
413  */
create_trip_attrs(struct thermal_zone_device * tz,int mask)414 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
415 {
416 	struct attribute **attrs;
417 	int indx;
418 
419 	/* This function works only for zones with at least one trip */
420 	if (tz->num_trips <= 0)
421 		return -EINVAL;
422 
423 	tz->trip_type_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_type_attrs),
424 				      GFP_KERNEL);
425 	if (!tz->trip_type_attrs)
426 		return -ENOMEM;
427 
428 	tz->trip_temp_attrs = kcalloc(tz->num_trips, sizeof(*tz->trip_temp_attrs),
429 				      GFP_KERNEL);
430 	if (!tz->trip_temp_attrs) {
431 		kfree(tz->trip_type_attrs);
432 		return -ENOMEM;
433 	}
434 
435 	if (tz->ops->get_trip_hyst) {
436 		tz->trip_hyst_attrs = kcalloc(tz->num_trips,
437 					      sizeof(*tz->trip_hyst_attrs),
438 					      GFP_KERNEL);
439 		if (!tz->trip_hyst_attrs) {
440 			kfree(tz->trip_type_attrs);
441 			kfree(tz->trip_temp_attrs);
442 			return -ENOMEM;
443 		}
444 	}
445 
446 	attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
447 	if (!attrs) {
448 		kfree(tz->trip_type_attrs);
449 		kfree(tz->trip_temp_attrs);
450 		if (tz->ops->get_trip_hyst)
451 			kfree(tz->trip_hyst_attrs);
452 		return -ENOMEM;
453 	}
454 
455 	for (indx = 0; indx < tz->num_trips; indx++) {
456 		/* create trip type attribute */
457 		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
458 			 "trip_point_%d_type", indx);
459 
460 		sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
461 		tz->trip_type_attrs[indx].attr.attr.name =
462 						tz->trip_type_attrs[indx].name;
463 		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
464 		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
465 		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
466 
467 		/* create trip temp attribute */
468 		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
469 			 "trip_point_%d_temp", indx);
470 
471 		sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
472 		tz->trip_temp_attrs[indx].attr.attr.name =
473 						tz->trip_temp_attrs[indx].name;
474 		tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
475 		tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
476 		if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
477 		    mask & (1 << indx)) {
478 			tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
479 			tz->trip_temp_attrs[indx].attr.store =
480 							trip_point_temp_store;
481 		}
482 		attrs[indx + tz->num_trips] = &tz->trip_temp_attrs[indx].attr.attr;
483 
484 		/* create Optional trip hyst attribute */
485 		if (!tz->ops->get_trip_hyst)
486 			continue;
487 		snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
488 			 "trip_point_%d_hyst", indx);
489 
490 		sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
491 		tz->trip_hyst_attrs[indx].attr.attr.name =
492 					tz->trip_hyst_attrs[indx].name;
493 		tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
494 		tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
495 		if (tz->ops->set_trip_hyst) {
496 			tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
497 			tz->trip_hyst_attrs[indx].attr.store =
498 					trip_point_hyst_store;
499 		}
500 		attrs[indx + tz->num_trips * 2] =
501 					&tz->trip_hyst_attrs[indx].attr.attr;
502 	}
503 	attrs[tz->num_trips * 3] = NULL;
504 
505 	tz->trips_attribute_group.attrs = attrs;
506 
507 	return 0;
508 }
509 
510 /**
511  * destroy_trip_attrs() - destroy attributes for trip points
512  * @tz:		the thermal zone device
513  *
514  * helper function to free resources allocated by create_trip_attrs()
515  */
destroy_trip_attrs(struct thermal_zone_device * tz)516 static void destroy_trip_attrs(struct thermal_zone_device *tz)
517 {
518 	if (!tz)
519 		return;
520 
521 	kfree(tz->trip_type_attrs);
522 	kfree(tz->trip_temp_attrs);
523 	if (tz->ops->get_trip_hyst)
524 		kfree(tz->trip_hyst_attrs);
525 	kfree(tz->trips_attribute_group.attrs);
526 }
527 
thermal_zone_create_device_groups(struct thermal_zone_device * tz,int mask)528 int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
529 				      int mask)
530 {
531 	const struct attribute_group **groups;
532 	int i, size, result;
533 
534 	/* we need one extra for trips and the NULL to terminate the array */
535 	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
536 	/* This also takes care of API requirement to be NULL terminated */
537 	groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
538 	if (!groups)
539 		return -ENOMEM;
540 
541 	for (i = 0; i < size - 2; i++)
542 		groups[i] = thermal_zone_attribute_groups[i];
543 
544 	if (tz->num_trips) {
545 		result = create_trip_attrs(tz, mask);
546 		if (result) {
547 			kfree(groups);
548 
549 			return result;
550 		}
551 
552 		groups[size - 2] = &tz->trips_attribute_group;
553 	}
554 
555 	tz->device.groups = groups;
556 
557 	return 0;
558 }
559 
thermal_zone_destroy_device_groups(struct thermal_zone_device * tz)560 void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
561 {
562 	if (!tz)
563 		return;
564 
565 	if (tz->num_trips)
566 		destroy_trip_attrs(tz);
567 
568 	kfree(tz->device.groups);
569 }
570 
571 /* sys I/F for cooling device */
572 static ssize_t
cdev_type_show(struct device * dev,struct device_attribute * attr,char * buf)573 cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
574 {
575 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
576 
577 	return sprintf(buf, "%s\n", cdev->type);
578 }
579 
max_state_show(struct device * dev,struct device_attribute * attr,char * buf)580 static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
581 			      char *buf)
582 {
583 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
584 
585 	return sprintf(buf, "%ld\n", cdev->max_state);
586 }
587 
cur_state_show(struct device * dev,struct device_attribute * attr,char * buf)588 static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
589 			      char *buf)
590 {
591 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
592 	unsigned long state;
593 	int ret;
594 
595 	ret = cdev->ops->get_cur_state(cdev, &state);
596 	if (ret)
597 		return ret;
598 	return sprintf(buf, "%ld\n", state);
599 }
600 
601 static ssize_t
cur_state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)602 cur_state_store(struct device *dev, struct device_attribute *attr,
603 		const char *buf, size_t count)
604 {
605 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
606 	unsigned long state;
607 	int result;
608 
609 	if (sscanf(buf, "%ld\n", &state) != 1)
610 		return -EINVAL;
611 
612 	if ((long)state < 0)
613 		return -EINVAL;
614 
615 	/* Requested state should be less than max_state + 1 */
616 	if (state > cdev->max_state)
617 		return -EINVAL;
618 
619 	mutex_lock(&cdev->lock);
620 
621 	result = cdev->ops->set_cur_state(cdev, state);
622 	if (!result)
623 		thermal_cooling_device_stats_update(cdev, state);
624 
625 	mutex_unlock(&cdev->lock);
626 	return result ? result : count;
627 }
628 
629 static struct device_attribute
630 dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
631 static DEVICE_ATTR_RO(max_state);
632 static DEVICE_ATTR_RW(cur_state);
633 
634 static struct attribute *cooling_device_attrs[] = {
635 	&dev_attr_cdev_type.attr,
636 	&dev_attr_max_state.attr,
637 	&dev_attr_cur_state.attr,
638 	NULL,
639 };
640 
641 static const struct attribute_group cooling_device_attr_group = {
642 	.attrs = cooling_device_attrs,
643 };
644 
645 static const struct attribute_group *cooling_device_attr_groups[] = {
646 	&cooling_device_attr_group,
647 	NULL, /* Space allocated for cooling_device_stats_attr_group */
648 	NULL,
649 };
650 
651 #ifdef CONFIG_THERMAL_STATISTICS
652 struct cooling_dev_stats {
653 	spinlock_t lock;
654 	unsigned int total_trans;
655 	unsigned long state;
656 	unsigned long max_states;
657 	ktime_t last_time;
658 	ktime_t *time_in_state;
659 	unsigned int *trans_table;
660 };
661 
update_time_in_state(struct cooling_dev_stats * stats)662 static void update_time_in_state(struct cooling_dev_stats *stats)
663 {
664 	ktime_t now = ktime_get(), delta;
665 
666 	delta = ktime_sub(now, stats->last_time);
667 	stats->time_in_state[stats->state] =
668 		ktime_add(stats->time_in_state[stats->state], delta);
669 	stats->last_time = now;
670 }
671 
thermal_cooling_device_stats_update(struct thermal_cooling_device * cdev,unsigned long new_state)672 void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
673 					 unsigned long new_state)
674 {
675 	struct cooling_dev_stats *stats = cdev->stats;
676 
677 	if (!stats)
678 		return;
679 
680 	spin_lock(&stats->lock);
681 
682 	if (stats->state == new_state)
683 		goto unlock;
684 
685 	update_time_in_state(stats);
686 	stats->trans_table[stats->state * stats->max_states + new_state]++;
687 	stats->state = new_state;
688 	stats->total_trans++;
689 
690 unlock:
691 	spin_unlock(&stats->lock);
692 }
693 
total_trans_show(struct device * dev,struct device_attribute * attr,char * buf)694 static ssize_t total_trans_show(struct device *dev,
695 				struct device_attribute *attr, char *buf)
696 {
697 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
698 	struct cooling_dev_stats *stats = cdev->stats;
699 	int ret;
700 
701 	spin_lock(&stats->lock);
702 	ret = sprintf(buf, "%u\n", stats->total_trans);
703 	spin_unlock(&stats->lock);
704 
705 	return ret;
706 }
707 
708 static ssize_t
time_in_state_ms_show(struct device * dev,struct device_attribute * attr,char * buf)709 time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
710 		      char *buf)
711 {
712 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
713 	struct cooling_dev_stats *stats = cdev->stats;
714 	ssize_t len = 0;
715 	int i;
716 
717 	spin_lock(&stats->lock);
718 	update_time_in_state(stats);
719 
720 	for (i = 0; i < stats->max_states; i++) {
721 		len += sprintf(buf + len, "state%u\t%llu\n", i,
722 			       ktime_to_ms(stats->time_in_state[i]));
723 	}
724 	spin_unlock(&stats->lock);
725 
726 	return len;
727 }
728 
729 static ssize_t
reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)730 reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
731 	    size_t count)
732 {
733 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
734 	struct cooling_dev_stats *stats = cdev->stats;
735 	int i, states = stats->max_states;
736 
737 	spin_lock(&stats->lock);
738 
739 	stats->total_trans = 0;
740 	stats->last_time = ktime_get();
741 	memset(stats->trans_table, 0,
742 	       states * states * sizeof(*stats->trans_table));
743 
744 	for (i = 0; i < stats->max_states; i++)
745 		stats->time_in_state[i] = ktime_set(0, 0);
746 
747 	spin_unlock(&stats->lock);
748 
749 	return count;
750 }
751 
trans_table_show(struct device * dev,struct device_attribute * attr,char * buf)752 static ssize_t trans_table_show(struct device *dev,
753 				struct device_attribute *attr, char *buf)
754 {
755 	struct thermal_cooling_device *cdev = to_cooling_device(dev);
756 	struct cooling_dev_stats *stats = cdev->stats;
757 	ssize_t len = 0;
758 	int i, j;
759 
760 	len += snprintf(buf + len, PAGE_SIZE - len, " From  :    To\n");
761 	len += snprintf(buf + len, PAGE_SIZE - len, "       : ");
762 	for (i = 0; i < stats->max_states; i++) {
763 		if (len >= PAGE_SIZE)
764 			break;
765 		len += snprintf(buf + len, PAGE_SIZE - len, "state%2u  ", i);
766 	}
767 	if (len >= PAGE_SIZE)
768 		return PAGE_SIZE;
769 
770 	len += snprintf(buf + len, PAGE_SIZE - len, "\n");
771 
772 	for (i = 0; i < stats->max_states; i++) {
773 		if (len >= PAGE_SIZE)
774 			break;
775 
776 		len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
777 
778 		for (j = 0; j < stats->max_states; j++) {
779 			if (len >= PAGE_SIZE)
780 				break;
781 			len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
782 				stats->trans_table[i * stats->max_states + j]);
783 		}
784 		if (len >= PAGE_SIZE)
785 			break;
786 		len += snprintf(buf + len, PAGE_SIZE - len, "\n");
787 	}
788 
789 	if (len >= PAGE_SIZE) {
790 		pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
791 		return -EFBIG;
792 	}
793 	return len;
794 }
795 
796 static DEVICE_ATTR_RO(total_trans);
797 static DEVICE_ATTR_RO(time_in_state_ms);
798 static DEVICE_ATTR_WO(reset);
799 static DEVICE_ATTR_RO(trans_table);
800 
801 static struct attribute *cooling_device_stats_attrs[] = {
802 	&dev_attr_total_trans.attr,
803 	&dev_attr_time_in_state_ms.attr,
804 	&dev_attr_reset.attr,
805 	&dev_attr_trans_table.attr,
806 	NULL
807 };
808 
809 static const struct attribute_group cooling_device_stats_attr_group = {
810 	.attrs = cooling_device_stats_attrs,
811 	.name = "stats"
812 };
813 
cooling_device_stats_setup(struct thermal_cooling_device * cdev)814 static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
815 {
816 	const struct attribute_group *stats_attr_group = NULL;
817 	struct cooling_dev_stats *stats;
818 	unsigned long states;
819 	int var;
820 	int disable_cdev_stats = 0;
821 
822 	trace_android_vh_disable_thermal_cooling_stats(cdev,
823 						&disable_cdev_stats);
824 	if (disable_cdev_stats) {
825 		var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
826 		cooling_device_attr_groups[var] = NULL;
827 		return;
828 	}
829 
830 	if (cdev->ops->get_max_state(cdev, &states))
831 		goto out;
832 
833 	states++; /* Total number of states is highest state + 1 */
834 
835 	var = sizeof(*stats);
836 	var += sizeof(*stats->time_in_state) * states;
837 	var += sizeof(*stats->trans_table) * states * states;
838 
839 	stats = kzalloc(var, GFP_KERNEL);
840 	if (!stats)
841 		goto out;
842 
843 	stats->time_in_state = (ktime_t *)(stats + 1);
844 	stats->trans_table = (unsigned int *)(stats->time_in_state + states);
845 	cdev->stats = stats;
846 	stats->last_time = ktime_get();
847 	stats->max_states = states;
848 
849 	spin_lock_init(&stats->lock);
850 
851 	stats_attr_group = &cooling_device_stats_attr_group;
852 
853 out:
854 	/* Fill the empty slot left in cooling_device_attr_groups */
855 	var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
856 	cooling_device_attr_groups[var] = stats_attr_group;
857 }
858 
cooling_device_stats_destroy(struct thermal_cooling_device * cdev)859 static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
860 {
861 	kfree(cdev->stats);
862 	cdev->stats = NULL;
863 }
864 
865 #else
866 
867 static inline void
cooling_device_stats_setup(struct thermal_cooling_device * cdev)868 cooling_device_stats_setup(struct thermal_cooling_device *cdev) {}
869 static inline void
cooling_device_stats_destroy(struct thermal_cooling_device * cdev)870 cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {}
871 
872 #endif /* CONFIG_THERMAL_STATISTICS */
873 
thermal_cooling_device_setup_sysfs(struct thermal_cooling_device * cdev)874 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
875 {
876 	cooling_device_stats_setup(cdev);
877 	cdev->device.groups = cooling_device_attr_groups;
878 }
879 
thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device * cdev)880 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
881 {
882 	cooling_device_stats_destroy(cdev);
883 }
884 
885 /* these helper will be used only at the time of bindig */
886 ssize_t
trip_point_show(struct device * dev,struct device_attribute * attr,char * buf)887 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
888 {
889 	struct thermal_instance *instance;
890 
891 	instance =
892 	    container_of(attr, struct thermal_instance, attr);
893 
894 	return sprintf(buf, "%d\n", instance->trip);
895 }
896 
897 ssize_t
weight_show(struct device * dev,struct device_attribute * attr,char * buf)898 weight_show(struct device *dev, struct device_attribute *attr, char *buf)
899 {
900 	struct thermal_instance *instance;
901 
902 	instance = container_of(attr, struct thermal_instance, weight_attr);
903 
904 	return sprintf(buf, "%d\n", instance->weight);
905 }
906 
weight_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)907 ssize_t weight_store(struct device *dev, struct device_attribute *attr,
908 		     const char *buf, size_t count)
909 {
910 	struct thermal_instance *instance;
911 	int ret, weight;
912 
913 	ret = kstrtoint(buf, 0, &weight);
914 	if (ret)
915 		return ret;
916 
917 	instance = container_of(attr, struct thermal_instance, weight_attr);
918 	instance->weight = weight;
919 
920 	return count;
921 }
922