* Update the 'temp' attr of a thermal_zone sysfs node, when the temperature goes above\below a trip point. Use sysfs_notify to send the notifications. * Send the notification only if the temperature notifications are enabled. Use the hysteresis property to avoid sending too many notifications when the temperatures are bouncing around. * Add ops that will allow thermal framework to: * find out if a temperature notification can be sent when a given trip point has been crossed. * get/set the trip state. * Add a new state type for the trip points. A trip point can either be 'TRIPPED' or 'NOT_TRIPPED'. Change-Id: If5b530b4045cdb2840eef855dc158cbce239ce79 Signed-off-by: Srikar Srimath Tirumala <srikars@xxxxxxxxxx> --- drivers/thermal/thermal_core.c | 28 ++++++++++++++++++++++++++++ include/linux/thermal.h | 12 ++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b09fff1..37bdc32 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -419,6 +419,32 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); } +static void handle_temp_notify(struct thermal_zone_device *tz, int trip) +{ + int trip_temp, hyst = 0; + enum thermal_trip_state s, ns; + + s = ns = THERMAL_TRIP_NOT_TRIPPED; + tz->ops->get_trip_temp(tz, trip, &trip_temp); + tz->ops->get_trip_hyst(tz, trip, &hyst); + + if (tz->ops->get_trip_state) + tz->ops->get_trip_state(tz, trip, &s); + + if (s == THERMAL_TRIP_TRIPPED && tz->temperature < trip_temp - hyst) + ns = THERMAL_TRIP_NOT_TRIPPED; + else if (s == THERMAL_TRIP_NOT_TRIPPED && tz->temperature >= trip_temp) + ns = THERMAL_TRIP_TRIPPED; + + if (tz->ops->set_trip_state) + tz->ops->set_trip_state(tz, trip, ns); + + /* send if notifications are enabled and state has changed */ + if (s != ns && tz->ops->enb_temp_notify && + tz->ops->enb_temp_notify(tz, trip)) + sysfs_notify(&tz->device.kobj, NULL, "temp"); +} + static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip, enum thermal_trip_type trip_type) { @@ -464,6 +490,8 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) handle_critical_trips(tz, trip, type); else handle_non_critical_trips(tz, trip, type); + + handle_temp_notify(tz, trip); /* * Alright, we handled this trip successfully. * So, start monitoring again. diff --git a/include/linux/thermal.h b/include/linux/thermal.h index a55d052..9182e36 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -84,6 +84,11 @@ enum thermal_trip_type { THERMAL_TRIP_CRITICAL, }; +enum thermal_trip_state { + THERMAL_TRIP_NOT_TRIPPED = 0, + THERMAL_TRIP_TRIPPED +}; + enum thermal_trend { THERMAL_TREND_STABLE, /* temperature is stable */ THERMAL_TREND_RAISING, /* temperature is raising */ @@ -114,6 +119,11 @@ struct thermal_zone_device_ops { enum thermal_trend *); int (*notify) (struct thermal_zone_device *, int, enum thermal_trip_type); + int (*get_trip_state)(struct thermal_zone_device *, int, + enum thermal_trip_state *); + int (*set_trip_state)(struct thermal_zone_device *, int, + enum thermal_trip_state); + bool (*enb_temp_notify)(struct thermal_zone_device *, int); }; struct thermal_cooling_device_ops { @@ -348,6 +358,7 @@ struct thermal_zone_of_device_ops { * @temperature: temperature value in miliCelsius * @hysteresis: relative hysteresis in miliCelsius * @type: trip point type + * @state: trip point state */ struct thermal_trip { @@ -355,6 +366,7 @@ struct thermal_trip { unsigned long int temperature; unsigned long int hysteresis; enum thermal_trip_type type; + enum thermal_trip_state state; }; /* Function declarations */ -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html