diff mbox

[v3,2/4] thermal: send notifications for tz temperature

Message ID 1459298497-29481-3-git-send-email-srikars@nvidia.com (mailing list archive)
State Changes Requested
Delegated to: Eduardo Valentin
Headers show

Commit Message

Srikar Srimath Tirumala March 30, 2016, 12:41 a.m. UTC
* 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@nvidia.com>
---
 drivers/thermal/thermal_core.c | 28 ++++++++++++++++++++++++++++
 include/linux/thermal.h        | 12 ++++++++++++
 2 files changed, 40 insertions(+)

Comments

Matthew Longnecker March 30, 2016, 4:43 p.m. UTC | #1
On 03/29/2016 05:41 PM, Srikar Srimath Tirumala wrote:
> * 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.
Rather than notifying temp, would it make sense to notify 
trip_pointX_temp when temperature crosses the trip point going up and 
trip_pointX_hyst when temperature crosses the trip point going down? 
That would allow userspace to watch for only a subset of events by 
polling/selecting on the relevant nodes.

>   
>   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;
This looks vestigial. Remove it?


--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Matthew Longnecker March 30, 2016, 4:53 p.m. UTC | #2
On 03/30/2016 09:43 AM, Matt Longnecker wrote:
>
>
> On 03/29/2016 05:41 PM, Srikar Srimath Tirumala wrote:
>>     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;
> This looks vestigial. Remove it?
>
>
nevermind. I see that it's used in the next patch. And it really does 
belong here, not in the next patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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 */