xref: /OK3568_Linux_fs/kernel/drivers/thermal/thermal_sysfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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