@@ -75,6 +75,58 @@ static struct thermal_governor *__find_governor(const char *name)
75
75
return NULL ;
76
76
}
77
77
78
+ /**
79
+ * bind_previous_governor() - bind the previous governor of the thermal zone
80
+ * @tz: a valid pointer to a struct thermal_zone_device
81
+ * @failed_gov_name: the name of the governor that failed to register
82
+ *
83
+ * Register the previous governor of the thermal zone after a new
84
+ * governor has failed to be bound.
85
+ */
86
+ static void bind_previous_governor (struct thermal_zone_device * tz ,
87
+ const char * failed_gov_name )
88
+ {
89
+ if (tz -> governor && tz -> governor -> bind_to_tz ) {
90
+ if (tz -> governor -> bind_to_tz (tz )) {
91
+ dev_err (& tz -> device ,
92
+ "governor %s failed to bind and the previous one (%s) failed to bind again, thermal zone %s has no governor\n" ,
93
+ failed_gov_name , tz -> governor -> name , tz -> type );
94
+ tz -> governor = NULL ;
95
+ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * thermal_set_governor() - Switch to another governor
101
+ * @tz: a valid pointer to a struct thermal_zone_device
102
+ * @new_gov: pointer to the new governor
103
+ *
104
+ * Change the governor of thermal zone @tz.
105
+ *
106
+ * Return: 0 on success, an error if the new governor's bind_to_tz() failed.
107
+ */
108
+ static int thermal_set_governor (struct thermal_zone_device * tz ,
109
+ struct thermal_governor * new_gov )
110
+ {
111
+ int ret = 0 ;
112
+
113
+ if (tz -> governor && tz -> governor -> unbind_from_tz )
114
+ tz -> governor -> unbind_from_tz (tz );
115
+
116
+ if (new_gov && new_gov -> bind_to_tz ) {
117
+ ret = new_gov -> bind_to_tz (tz );
118
+ if (ret ) {
119
+ bind_previous_governor (tz , new_gov -> name );
120
+
121
+ return ret ;
122
+ }
123
+ }
124
+
125
+ tz -> governor = new_gov ;
126
+
127
+ return ret ;
128
+ }
129
+
78
130
int thermal_register_governor (struct thermal_governor * governor )
79
131
{
80
132
int err ;
@@ -107,8 +159,15 @@ int thermal_register_governor(struct thermal_governor *governor)
107
159
108
160
name = pos -> tzp -> governor_name ;
109
161
110
- if (!strncasecmp (name , governor -> name , THERMAL_NAME_LENGTH ))
111
- pos -> governor = governor ;
162
+ if (!strncasecmp (name , governor -> name , THERMAL_NAME_LENGTH )) {
163
+ int ret ;
164
+
165
+ ret = thermal_set_governor (pos , governor );
166
+ if (ret )
167
+ dev_err (& pos -> device ,
168
+ "Failed to set governor %s for thermal zone %s: %d\n" ,
169
+ governor -> name , pos -> type , ret );
170
+ }
112
171
}
113
172
114
173
mutex_unlock (& thermal_list_lock );
@@ -134,7 +193,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)
134
193
list_for_each_entry (pos , & thermal_tz_list , node ) {
135
194
if (!strncasecmp (pos -> governor -> name , governor -> name ,
136
195
THERMAL_NAME_LENGTH ))
137
- pos -> governor = NULL ;
196
+ thermal_set_governor ( pos , NULL ) ;
138
197
}
139
198
140
199
mutex_unlock (& thermal_list_lock );
@@ -770,8 +829,9 @@ policy_store(struct device *dev, struct device_attribute *attr,
770
829
if (!gov )
771
830
goto exit ;
772
831
773
- tz -> governor = gov ;
774
- ret = count ;
832
+ ret = thermal_set_governor (tz , gov );
833
+ if (!ret )
834
+ ret = count ;
775
835
776
836
exit :
777
837
mutex_unlock (& tz -> lock );
@@ -1512,6 +1572,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1512
1572
int result ;
1513
1573
int count ;
1514
1574
int passive = 0 ;
1575
+ struct thermal_governor * governor ;
1515
1576
1516
1577
if (type && strlen (type ) >= THERMAL_NAME_LENGTH )
1517
1578
return ERR_PTR (- EINVAL );
@@ -1602,9 +1663,15 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1602
1663
mutex_lock (& thermal_governor_lock );
1603
1664
1604
1665
if (tz -> tzp )
1605
- tz -> governor = __find_governor (tz -> tzp -> governor_name );
1666
+ governor = __find_governor (tz -> tzp -> governor_name );
1606
1667
else
1607
- tz -> governor = def_governor ;
1668
+ governor = def_governor ;
1669
+
1670
+ result = thermal_set_governor (tz , governor );
1671
+ if (result ) {
1672
+ mutex_unlock (& thermal_governor_lock );
1673
+ goto unregister ;
1674
+ }
1608
1675
1609
1676
mutex_unlock (& thermal_governor_lock );
1610
1677
@@ -1693,7 +1760,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1693
1760
device_remove_file (& tz -> device , & dev_attr_mode );
1694
1761
device_remove_file (& tz -> device , & dev_attr_policy );
1695
1762
remove_trip_attrs (tz );
1696
- tz -> governor = NULL ;
1763
+ thermal_set_governor ( tz , NULL ) ;
1697
1764
1698
1765
thermal_remove_hwmon_sysfs (tz );
1699
1766
release_idr (& thermal_tz_idr , & thermal_idr_lock , tz -> id );
0 commit comments