Linux Audio

Check our new training course

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