1 // SPDX-License-Identifier: GPL-2.0
3 * thermal.c - sysfs interface of thermal devices
5 * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
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>
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
23 #include "thermal_core.h"
25 /* sys I/F for thermal zone */
28 type_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
30 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
32 return sprintf(buf
, "%s\n", tz
->type
);
36 temp_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
38 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
41 ret
= thermal_zone_get_temp(tz
, &temperature
);
46 return sprintf(buf
, "%d\n", temperature
);
50 mode_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
52 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
54 guard(thermal_zone
)(tz
);
56 if (tz
->mode
== THERMAL_DEVICE_ENABLED
)
57 return sprintf(buf
, "enabled\n");
59 return sprintf(buf
, "disabled\n");
63 mode_store(struct device
*dev
, struct device_attribute
*attr
,
64 const char *buf
, size_t count
)
66 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
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
);
82 #define thermal_trip_of_attr(_ptr_, _attr_) \
84 struct thermal_trip_desc *td; \
86 td = container_of(_ptr_, struct thermal_trip_desc, \
87 trip_attrs._attr_.attr); \
92 trip_point_type_show(struct device
*dev
, struct device_attribute
*attr
,
95 struct thermal_trip
*trip
= thermal_trip_of_attr(attr
, type
);
97 return sprintf(buf
, "%s\n", thermal_trip_type_name(trip
->type
));
101 trip_point_temp_store(struct device
*dev
, struct device_attribute
*attr
,
102 const char *buf
, size_t count
)
104 struct thermal_trip
*trip
= thermal_trip_of_attr(attr
, temp
);
105 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
108 if (kstrtoint(buf
, 10, &temp
))
111 guard(thermal_zone
)(tz
);
113 if (temp
== trip
->temperature
)
116 /* Arrange the condition to avoid integer overflows. */
117 if (temp
!= THERMAL_TEMP_INVALID
&&
118 temp
<= trip
->hysteresis
+ THERMAL_TEMP_INVALID
)
121 if (tz
->ops
.set_trip_temp
) {
124 ret
= tz
->ops
.set_trip_temp(tz
, trip
, temp
);
129 thermal_zone_set_trip_temp(tz
, trip
, temp
);
131 __thermal_zone_device_update(tz
, THERMAL_TRIP_CHANGED
);
137 trip_point_temp_show(struct device
*dev
, struct device_attribute
*attr
,
140 struct thermal_trip
*trip
= thermal_trip_of_attr(attr
, temp
);
142 return sprintf(buf
, "%d\n", READ_ONCE(trip
->temperature
));
146 trip_point_hyst_store(struct device
*dev
, struct device_attribute
*attr
,
147 const char *buf
, size_t count
)
149 struct thermal_trip
*trip
= thermal_trip_of_attr(attr
, hyst
);
150 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
153 if (kstrtoint(buf
, 10, &hyst
) || hyst
< 0)
156 guard(thermal_zone
)(tz
);
158 if (hyst
== trip
->hysteresis
)
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.
167 if (trip
->temperature
== THERMAL_TEMP_INVALID
) {
168 WRITE_ONCE(trip
->hysteresis
, hyst
);
172 if (trip
->temperature
- hyst
<= THERMAL_TEMP_INVALID
)
175 thermal_zone_set_trip_hyst(tz
, trip
, hyst
);
177 __thermal_zone_device_update(tz
, THERMAL_TRIP_CHANGED
);
183 trip_point_hyst_show(struct device
*dev
, struct device_attribute
*attr
,
186 struct thermal_trip
*trip
= thermal_trip_of_attr(attr
, hyst
);
188 return sprintf(buf
, "%d\n", READ_ONCE(trip
->hysteresis
));
192 policy_store(struct device
*dev
, struct device_attribute
*attr
,
193 const char *buf
, size_t count
)
195 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
196 char name
[THERMAL_NAME_LENGTH
];
199 snprintf(name
, sizeof(name
), "%s", buf
);
201 ret
= thermal_zone_device_set_policy(tz
, name
);
209 policy_show(struct device
*dev
, struct device_attribute
*devattr
, char *buf
)
211 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
213 return sprintf(buf
, "%s\n", tz
->governor
->name
);
217 available_policies_show(struct device
*dev
, struct device_attribute
*devattr
,
220 return thermal_build_list_of_policies(buf
);
223 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
225 emul_temp_store(struct device
*dev
, struct device_attribute
*attr
,
226 const char *buf
, size_t count
)
228 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
231 if (kstrtoint(buf
, 10, &temperature
))
234 guard(thermal_zone
)(tz
);
236 if (tz
->ops
.set_emul_temp
) {
239 ret
= tz
->ops
.set_emul_temp(tz
, temperature
);
243 tz
->emul_temperature
= temperature
;
246 __thermal_zone_device_update(tz
, THERMAL_EVENT_UNSPECIFIED
);
250 static DEVICE_ATTR_WO(emul_temp
);
254 sustainable_power_show(struct device
*dev
, struct device_attribute
*devattr
,
257 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
260 return sprintf(buf
, "%u\n", tz
->tzp
->sustainable_power
);
266 sustainable_power_store(struct device
*dev
, struct device_attribute
*devattr
,
267 const char *buf
, size_t count
)
269 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
270 u32 sustainable_power
;
275 if (kstrtou32(buf
, 10, &sustainable_power
))
278 tz
->tzp
->sustainable_power
= sustainable_power
;
283 #define create_s32_tzp_attr(name) \
285 name##_show(struct device *dev, struct device_attribute *devattr, \
288 struct thermal_zone_device *tz = to_thermal_zone(dev); \
291 return sprintf(buf, "%d\n", tz->tzp->name); \
297 name##_store(struct device *dev, struct device_attribute *devattr, \
298 const char *buf, size_t count) \
300 struct thermal_zone_device *tz = to_thermal_zone(dev); \
306 if (kstrtos32(buf, 10, &value)) \
309 tz->tzp->name = value; \
313 static DEVICE_ATTR_RW(name)
315 create_s32_tzp_attr(k_po
);
316 create_s32_tzp_attr(k_pu
);
317 create_s32_tzp_attr(k_i
);
318 create_s32_tzp_attr(k_d
);
319 create_s32_tzp_attr(integral_cutoff
);
320 create_s32_tzp_attr(slope
);
321 create_s32_tzp_attr(offset
);
322 #undef create_s32_tzp_attr
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.
329 static DEVICE_ATTR_RO(type
);
330 static DEVICE_ATTR_RO(temp
);
331 static DEVICE_ATTR_RW(policy
);
332 static DEVICE_ATTR_RO(available_policies
);
333 static DEVICE_ATTR_RW(sustainable_power
);
335 /* These thermal zone device attributes are created based on conditions */
336 static DEVICE_ATTR_RW(mode
);
338 /* These attributes are unconditionally added to a thermal zone */
339 static struct attribute
*thermal_zone_dev_attrs
[] = {
342 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
343 &dev_attr_emul_temp
.attr
,
345 &dev_attr_policy
.attr
,
346 &dev_attr_available_policies
.attr
,
347 &dev_attr_sustainable_power
.attr
,
352 &dev_attr_integral_cutoff
.attr
,
353 &dev_attr_slope
.attr
,
354 &dev_attr_offset
.attr
,
358 static const struct attribute_group thermal_zone_attribute_group
= {
359 .attrs
= thermal_zone_dev_attrs
,
362 static struct attribute
*thermal_zone_mode_attrs
[] = {
367 static const struct attribute_group thermal_zone_mode_attribute_group
= {
368 .attrs
= thermal_zone_mode_attrs
,
371 static 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 */
378 * create_trip_attrs() - create attributes for trip points
379 * @tz: the thermal zone device
381 * helper function to instantiate sysfs entries for every trip
382 * point and its properties of a struct thermal_zone_device.
384 * Return: 0 on success, the proper error value otherwise.
386 static int create_trip_attrs(struct thermal_zone_device
*tz
)
388 struct thermal_trip_desc
*td
;
389 struct attribute
**attrs
;
392 attrs
= kcalloc(tz
->num_trips
* 3 + 1, sizeof(*attrs
), GFP_KERNEL
);
397 for_each_trip_desc(tz
, td
) {
398 struct thermal_trip_attrs
*trip_attrs
= &td
->trip_attrs
;
400 /* create trip type attribute */
401 snprintf(trip_attrs
->type
.name
, THERMAL_NAME_LENGTH
,
402 "trip_point_%d_type", i
);
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
;
410 /* create trip temp attribute */
411 snprintf(trip_attrs
->temp
.name
, THERMAL_NAME_LENGTH
,
412 "trip_point_%d_temp", i
);
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
;
422 attrs
[i
+ tz
->num_trips
] = &trip_attrs
->temp
.attr
.attr
;
424 snprintf(trip_attrs
->hyst
.name
, THERMAL_NAME_LENGTH
,
425 "trip_point_%d_hyst", i
);
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
;
435 attrs
[i
+ 2 * tz
->num_trips
] = &trip_attrs
->hyst
.attr
.attr
;
438 attrs
[tz
->num_trips
* 3] = NULL
;
440 tz
->trips_attribute_group
.attrs
= attrs
;
446 * destroy_trip_attrs() - destroy attributes for trip points
447 * @tz: the thermal zone device
449 * helper function to free resources allocated by create_trip_attrs()
451 static void destroy_trip_attrs(struct thermal_zone_device
*tz
)
454 kfree(tz
->trips_attribute_group
.attrs
);
457 int thermal_zone_create_device_groups(struct thermal_zone_device
*tz
)
459 const struct attribute_group
**groups
;
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
);
469 for (i
= 0; i
< size
- 2; i
++)
470 groups
[i
] = thermal_zone_attribute_groups
[i
];
473 result
= create_trip_attrs(tz
);
480 groups
[size
- 2] = &tz
->trips_attribute_group
;
483 tz
->device
.groups
= groups
;
488 void thermal_zone_destroy_device_groups(struct thermal_zone_device
*tz
)
494 destroy_trip_attrs(tz
);
496 kfree(tz
->device
.groups
);
499 /* sys I/F for cooling device */
501 cdev_type_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
503 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
505 return sprintf(buf
, "%s\n", cdev
->type
);
508 static ssize_t
max_state_show(struct device
*dev
, struct device_attribute
*attr
,
511 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
513 return sprintf(buf
, "%ld\n", cdev
->max_state
);
516 static ssize_t
cur_state_show(struct device
*dev
, struct device_attribute
*attr
,
519 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
523 ret
= cdev
->ops
->get_cur_state(cdev
, &state
);
526 return sprintf(buf
, "%ld\n", state
);
530 cur_state_store(struct device
*dev
, struct device_attribute
*attr
,
531 const char *buf
, size_t count
)
533 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
537 if (sscanf(buf
, "%ld\n", &state
) != 1)
543 /* Requested state should be less than max_state + 1 */
544 if (state
> cdev
->max_state
)
547 guard(cooling_dev
)(cdev
);
549 result
= cdev
->ops
->set_cur_state(cdev
, state
);
553 thermal_cooling_device_stats_update(cdev
, state
);
558 static struct device_attribute
559 dev_attr_cdev_type
= __ATTR(type
, 0444, cdev_type_show
, NULL
);
560 static DEVICE_ATTR_RO(max_state
);
561 static DEVICE_ATTR_RW(cur_state
);
563 static struct attribute
*cooling_device_attrs
[] = {
564 &dev_attr_cdev_type
.attr
,
565 &dev_attr_max_state
.attr
,
566 &dev_attr_cur_state
.attr
,
570 static const struct attribute_group cooling_device_attr_group
= {
571 .attrs
= cooling_device_attrs
,
574 static const struct attribute_group
*cooling_device_attr_groups
[] = {
575 &cooling_device_attr_group
,
576 NULL
, /* Space allocated for cooling_device_stats_attr_group */
580 #ifdef CONFIG_THERMAL_STATISTICS
581 struct cooling_dev_stats
{
583 unsigned int total_trans
;
586 ktime_t
*time_in_state
;
587 unsigned int *trans_table
;
590 static void update_time_in_state(struct cooling_dev_stats
*stats
)
592 ktime_t now
= ktime_get(), delta
;
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
;
600 void thermal_cooling_device_stats_update(struct thermal_cooling_device
*cdev
,
601 unsigned long new_state
)
603 struct cooling_dev_stats
*stats
= cdev
->stats
;
605 lockdep_assert_held(&cdev
->lock
);
610 spin_lock(&stats
->lock
);
612 if (stats
->state
== new_state
)
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
++;
621 spin_unlock(&stats
->lock
);
624 static ssize_t
total_trans_show(struct device
*dev
,
625 struct device_attribute
*attr
, char *buf
)
627 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
628 struct cooling_dev_stats
*stats
;
631 guard(cooling_dev
)(cdev
);
637 spin_lock(&stats
->lock
);
638 ret
= sprintf(buf
, "%u\n", stats
->total_trans
);
639 spin_unlock(&stats
->lock
);
645 time_in_state_ms_show(struct device
*dev
, struct device_attribute
*attr
,
648 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
649 struct cooling_dev_stats
*stats
;
653 guard(cooling_dev
)(cdev
);
659 spin_lock(&stats
->lock
);
661 update_time_in_state(stats
);
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
]));
667 spin_unlock(&stats
->lock
);
673 reset_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
,
676 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
677 struct cooling_dev_stats
*stats
;
680 guard(cooling_dev
)(cdev
);
686 states
= cdev
->max_state
+ 1;
688 spin_lock(&stats
->lock
);
690 stats
->total_trans
= 0;
691 stats
->last_time
= ktime_get();
692 memset(stats
->trans_table
, 0,
693 states
* states
* sizeof(*stats
->trans_table
));
695 for (i
= 0; i
< states
; i
++)
696 stats
->time_in_state
[i
] = ktime_set(0, 0);
698 spin_unlock(&stats
->lock
);
703 static ssize_t
trans_table_show(struct device
*dev
,
704 struct device_attribute
*attr
, char *buf
)
706 struct thermal_cooling_device
*cdev
= to_cooling_device(dev
);
707 struct cooling_dev_stats
*stats
;
711 guard(cooling_dev
)(cdev
);
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
)
722 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "state%2u ", i
);
724 if (len
>= PAGE_SIZE
)
727 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "\n");
729 for (i
= 0; i
<= cdev
->max_state
; i
++) {
730 if (len
>= PAGE_SIZE
)
733 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "state%2u:", i
);
735 for (j
= 0; j
<= cdev
->max_state
; j
++) {
736 if (len
>= PAGE_SIZE
)
738 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "%8u ",
739 stats
->trans_table
[i
* (cdev
->max_state
+ 1) + j
]);
741 if (len
>= PAGE_SIZE
)
743 len
+= snprintf(buf
+ len
, PAGE_SIZE
- len
, "\n");
746 if (len
>= PAGE_SIZE
) {
747 pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
754 static DEVICE_ATTR_RO(total_trans
);
755 static DEVICE_ATTR_RO(time_in_state_ms
);
756 static DEVICE_ATTR_WO(reset
);
757 static DEVICE_ATTR_RO(trans_table
);
759 static 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
,
767 static const struct attribute_group cooling_device_stats_attr_group
= {
768 .attrs
= cooling_device_stats_attrs
,
772 static void cooling_device_stats_setup(struct thermal_cooling_device
*cdev
)
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;
780 var
= sizeof(*stats
);
781 var
+= sizeof(*stats
->time_in_state
) * states
;
782 var
+= sizeof(*stats
->trans_table
) * states
* states
;
784 stats
= kzalloc(var
, GFP_KERNEL
);
788 stats
->time_in_state
= (ktime_t
*)(stats
+ 1);
789 stats
->trans_table
= (unsigned int *)(stats
->time_in_state
+ states
);
791 stats
->last_time
= ktime_get();
793 spin_lock_init(&stats
->lock
);
795 stats_attr_group
= &cooling_device_stats_attr_group
;
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
;
803 static void cooling_device_stats_destroy(struct thermal_cooling_device
*cdev
)
812 cooling_device_stats_setup(struct thermal_cooling_device
*cdev
) {}
814 cooling_device_stats_destroy(struct thermal_cooling_device
*cdev
) {}
816 #endif /* CONFIG_THERMAL_STATISTICS */
818 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device
*cdev
)
820 cooling_device_stats_setup(cdev
);
821 cdev
->device
.groups
= cooling_device_attr_groups
;
824 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device
*cdev
)
826 cooling_device_stats_destroy(cdev
);
829 void thermal_cooling_device_stats_reinit(struct thermal_cooling_device
*cdev
)
831 lockdep_assert_held(&cdev
->lock
);
833 cooling_device_stats_destroy(cdev
);
834 cooling_device_stats_setup(cdev
);
837 /* these helper will be used only at the time of bindig */
839 trip_point_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
841 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
842 struct thermal_instance
*instance
;
844 instance
= container_of(attr
, struct thermal_instance
, attr
);
846 return sprintf(buf
, "%d\n", thermal_zone_trip_id(tz
, instance
->trip
));
850 weight_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
852 struct thermal_instance
*instance
;
854 instance
= container_of(attr
, struct thermal_instance
, weight_attr
);
856 return sprintf(buf
, "%d\n", instance
->weight
);
859 ssize_t
weight_store(struct device
*dev
, struct device_attribute
*attr
,
860 const char *buf
, size_t count
)
862 struct thermal_zone_device
*tz
= to_thermal_zone(dev
);
863 struct thermal_instance
*instance
;
866 ret
= kstrtoint(buf
, 0, &weight
);
870 instance
= container_of(attr
, struct thermal_instance
, weight_attr
);
872 /* Don't race with governors using the 'weight' value */
873 guard(thermal_zone
)(tz
);
875 instance
->weight
= weight
;
877 thermal_governor_update_tz(tz
, THERMAL_INSTANCE_WEIGHT_CHANGED
);