summaryrefslogtreecommitdiff
path: root/drivers/thermal/thermal_core.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2023-01-23 20:52:53 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2023-01-23 20:52:53 +0300
commita2c81dc59d41e92362ab7d41d0c15471ea50637d (patch)
tree1141751d023d11a7ed3494f998662944e7c6265e /drivers/thermal/thermal_core.c
parent6c54b7bc8a31ce0f7cc7f8deef05067df414f1d8 (diff)
parent976cb655c940bd76c76c7925cc2740357e2f6803 (diff)
downloadlinux-a2c81dc59d41e92362ab7d41d0c15471ea50637d.tar.xz
Merge back thermal control material for 6.3.
Diffstat (limited to 'drivers/thermal/thermal_core.c')
-rw-r--r--drivers/thermal/thermal_core.c154
1 files changed, 131 insertions, 23 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 77bd47d976a2..c686da8b4c68 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -344,35 +344,31 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
tz->ops->critical(tz);
}
-static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id)
{
- enum thermal_trip_type type;
- int trip_temp, hyst = 0;
+ struct thermal_trip trip;
/* Ignore disabled trip points */
- if (test_bit(trip, &tz->trips_disabled))
+ if (test_bit(trip_id, &tz->trips_disabled))
return;
- tz->ops->get_trip_temp(tz, trip, &trip_temp);
- tz->ops->get_trip_type(tz, trip, &type);
- if (tz->ops->get_trip_hyst)
- tz->ops->get_trip_hyst(tz, trip, &hyst);
+ __thermal_zone_get_trip(tz, trip_id, &trip);
if (tz->last_temperature != THERMAL_TEMP_INVALID) {
- if (tz->last_temperature < trip_temp &&
- tz->temperature >= trip_temp)
- thermal_notify_tz_trip_up(tz->id, trip,
+ if (tz->last_temperature < trip.temperature &&
+ tz->temperature >= trip.temperature)
+ thermal_notify_tz_trip_up(tz->id, trip_id,
tz->temperature);
- if (tz->last_temperature >= trip_temp &&
- tz->temperature < (trip_temp - hyst))
- thermal_notify_tz_trip_down(tz->id, trip,
+ if (tz->last_temperature >= trip.temperature &&
+ tz->temperature < (trip.temperature - trip.hysteresis))
+ thermal_notify_tz_trip_down(tz->id, trip_id,
tz->temperature);
}
- if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
- handle_critical_trips(tz, trip, trip_temp, type);
+ if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT)
+ handle_critical_trips(tz, trip_id, trip.temperature, trip.type);
else
- handle_non_critical_trips(tz, trip);
+ handle_non_critical_trips(tz, trip_id);
}
static void update_temperature(struct thermal_zone_device *tz)
@@ -1166,6 +1162,119 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms
*delay_jiffies = round_jiffies(*delay_jiffies);
}
+int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
+{
+ return tz->num_trips;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
+
+int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp)
+{
+ int i, ret = -EINVAL;
+
+ if (tz->ops->get_crit_temp)
+ return tz->ops->get_crit_temp(tz, temp);
+
+ if (!tz->trips)
+ return -EINVAL;
+
+ mutex_lock(&tz->lock);
+
+ for (i = 0; i < tz->num_trips; i++) {
+ if (tz->trips[i].type == THERMAL_TRIP_CRITICAL) {
+ *temp = tz->trips[i].temperature;
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&tz->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
+
+int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
+ struct thermal_trip *trip)
+{
+ int ret;
+
+ if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip)
+ return -EINVAL;
+
+ if (tz->trips) {
+ *trip = tz->trips[trip_id];
+ return 0;
+ }
+
+ if (tz->ops->get_trip_hyst) {
+ ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis);
+ if (ret)
+ return ret;
+ } else {
+ trip->hysteresis = 0;
+ }
+
+ ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature);
+ if (ret)
+ return ret;
+
+ return tz->ops->get_trip_type(tz, trip_id, &trip->type);
+}
+EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);
+
+int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
+ struct thermal_trip *trip)
+{
+ int ret;
+
+ mutex_lock(&tz->lock);
+ ret = __thermal_zone_get_trip(tz, trip_id, trip);
+ mutex_unlock(&tz->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_trip);
+
+int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
+ const struct thermal_trip *trip)
+{
+ struct thermal_trip t;
+ int ret;
+
+ if (!tz->ops->set_trip_temp && !tz->ops->set_trip_hyst && !tz->trips)
+ return -EINVAL;
+
+ ret = __thermal_zone_get_trip(tz, trip_id, &t);
+ if (ret)
+ return ret;
+
+ if (t.type != trip->type)
+ return -EINVAL;
+
+ if (t.temperature != trip->temperature && tz->ops->set_trip_temp) {
+ ret = tz->ops->set_trip_temp(tz, trip_id, trip->temperature);
+ if (ret)
+ return ret;
+ }
+
+ if (t.hysteresis != trip->hysteresis && tz->ops->set_trip_hyst) {
+ ret = tz->ops->set_trip_hyst(tz, trip_id, trip->hysteresis);
+ if (ret)
+ return ret;
+ }
+
+ if (tz->trips && (t.temperature != trip->temperature || t.hysteresis != trip->hysteresis))
+ tz->trips[trip_id] = *trip;
+
+ thermal_notify_tz_trip_change(tz->id, trip_id, trip->type,
+ trip->temperature, trip->hysteresis);
+
+ __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+
+ return 0;
+}
+
/**
* thermal_zone_device_register_with_trips() - register a new thermal zone device
* @type: the thermal zone device type
@@ -1198,8 +1307,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
int polling_delay)
{
struct thermal_zone_device *tz;
- enum thermal_trip_type trip_type;
- int trip_temp;
int id;
int result;
int count;
@@ -1239,7 +1346,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
return ERR_PTR(-EINVAL);
}
- if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
+ if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips)
return ERR_PTR(-EINVAL);
tz = kzalloc(sizeof(*tz), GFP_KERNEL);
@@ -1290,9 +1397,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
goto release_device;
for (count = 0; count < num_trips; count++) {
- if (tz->ops->get_trip_type(tz, count, &trip_type) ||
- tz->ops->get_trip_temp(tz, count, &trip_temp) ||
- !trip_temp)
+ struct thermal_trip trip;
+
+ result = thermal_zone_get_trip(tz, count, &trip);
+ if (result)
set_bit(count, &tz->trips_disabled);
}