diff mbox

[V4,04/13] Thermal: Introduce .get_trend() callback.

Message ID 1343292083-2047-5-git-send-email-rui.zhang@intel.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Zhang Rui July 26, 2012, 8:41 a.m. UTC
According to ACPI spec, tc1 and tc2 are used by OSPM
to anticipate the temperature trends.
We introduced the same concept to the generic thermal layer
for passive cooling, but now it seems that these values
are hard to be used on other platforms.

So We introduce .get_trend() as a more general solution.

For the platform thermal drivers that have their own way to
anticipate the temperature trends, they should provide
their own .get_trend() callback.
Or else, we will calculate the temperature trends by simply
comparing the current temperature and the cached previous
temperature reading.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/acpi/thermal.c        |   33 +++++++++++++++++++++++++++++++++
 drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
 include/linux/thermal.h       |    9 +++++++++
 3 files changed, 59 insertions(+), 2 deletions(-)

Comments

Rafael Wysocki July 26, 2012, 8:11 p.m. UTC | #1
On Thursday, July 26, 2012, Zhang Rui wrote:
> According to ACPI spec, tc1 and tc2 are used by OSPM
> to anticipate the temperature trends.
> We introduced the same concept to the generic thermal layer
> for passive cooling, but now it seems that these values
> are hard to be used on other platforms.
> 
> So We introduce .get_trend() as a more general solution.
> 
> For the platform thermal drivers that have their own way to
> anticipate the temperature trends, they should provide
> their own .get_trend() callback.
> Or else, we will calculate the temperature trends by simply
> comparing the current temperature and the cached previous
> temperature reading.

As far as the code is concerned:

Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>

I wonder, though, if there are any users of the thermal core currently in the
tree who should introduce their own .get_trend() callbacks?

Rafael


> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> ---
>  drivers/acpi/thermal.c        |   33 +++++++++++++++++++++++++++++++++
>  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
>  include/linux/thermal.h       |    9 +++++++++
>  3 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index b48ec3e..0c49e42 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -704,6 +704,38 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
>  		return -EINVAL;
>  }
>  
> +static int thermal_get_trend(struct thermal_zone_device *thermal,
> +				int trip, enum thermal_trend *trend)
> +{
> +	struct acpi_thermal *tz = thermal->devdata;
> +	enum thermal_trip_type type;
> +	int i;
> +
> +	if (thermal_get_trip_type(thermal, trip, &type))
> +		return -EINVAL;
> +
> +	/* Only PASSIVE trip points need TREND */
> +	if (type != THERMAL_TRIP_PASSIVE)
> +		return -EINVAL;
> +
> +	/*
> +	 * tz->temperature has already been updated by generic thermal layer,
> +	 * before this callback being invoked
> +	 */
> +	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> +		+ (tz->trips.passive.tc2
> +		* (tz->temperature - tz->trips.passive.temperature));
> +
> +	if (i > 0)
> +		*trend = THERMAL_TREND_RAISING;
> +	else if (i < 0)
> +		*trend = THERMAL_TREND_DROPPING;
> +	else
> +		*trend = THERMAL_TREND_STABLE;
> +	return 0;
> +}
> +
> +
>  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
>  			   enum thermal_trip_type trip_type)
>  {
> @@ -836,6 +868,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
>  	.get_trip_type = thermal_get_trip_type,
>  	.get_trip_temp = thermal_get_trip_temp,
>  	.get_crit_temp = thermal_get_crit_temp,
> +	.get_trend = thermal_get_trend,
>  	.notify = thermal_notify,
>  };
>  
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 62b4279..68c93d4 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -723,6 +723,20 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>  	struct thermal_cooling_device *cdev;
>  	long state, max_state;
>  
> +	if (!tz->ops->get_trend ||
> +	    tz->ops->get_trend(tz, trip, (enum thermal_trend *)&trend)) {
> +		/*
> +		 * compare the current temperature and previous temperature
> +		 * to get the thermal trend, if no special requirement
> +		 */
> +		if (tz->temperature > tz->last_temperature)
> +			trend = THERMAL_TREND_RAISING;
> +		else if (tz->temperature < tz->last_temperature)
> +			trend = THERMAL_TREND_DROPPING;
> +		else
> +			trend = THERMAL_TREND_STABLE;
> +	}
> +
>  	/*
>  	 * Above Trip?
>  	 * -----------
> @@ -1091,6 +1105,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  		goto leave;
>  	}
>  
> +	tz->last_temperature = tz->temperature;
> +	tz->temperature = temp;
> +
>  	for (count = 0; count < tz->trips; count++) {
>  		tz->ops->get_trip_type(tz, count, &trip_type);
>  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> @@ -1150,8 +1167,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>  		thermal_zone_device_passive(tz, temp, tz->forced_passive,
>  					    THERMAL_TRIPS_NONE);
>  
> -	tz->last_temperature = temp;
> -
>  leave:
>  	if (tz->passive)
>  		thermal_zone_device_set_polling(tz, tz->passive_delay);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index a43b12c..a01e3e6 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -44,6 +44,12 @@ enum thermal_trip_type {
>  	THERMAL_TRIP_CRITICAL,
>  };
>  
> +enum thermal_trend {
> +	THERMAL_TREND_STABLE, /* temperature is stable */
> +	THERMAL_TREND_RAISING, /* temperature is raising */
> +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> +};
> +
>  struct thermal_zone_device_ops {
>  	int (*bind) (struct thermal_zone_device *,
>  		     struct thermal_cooling_device *);
> @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
>  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
>  			      unsigned long);
>  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
> +	int (*get_trend) (struct thermal_zone_device *, int,
> +			  enum thermal_trend *);
>  	int (*notify) (struct thermal_zone_device *, int,
>  		       enum thermal_trip_type);
>  };
> @@ -111,6 +119,7 @@ struct thermal_zone_device {
>  	int tc2;
>  	int passive_delay;
>  	int polling_delay;
> +	int temperature;
>  	int last_temperature;
>  	bool passive;
>  	unsigned int forced_passive;
> 

--
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
Zhang Rui Aug. 1, 2012, 2:42 a.m. UTC | #2
On ?, 2012-07-26 at 22:11 +0200, Rafael J. Wysocki wrote:
> On Thursday, July 26, 2012, Zhang Rui wrote:
> > According to ACPI spec, tc1 and tc2 are used by OSPM
> > to anticipate the temperature trends.
> > We introduced the same concept to the generic thermal layer
> > for passive cooling, but now it seems that these values
> > are hard to be used on other platforms.
> > 
> > So We introduce .get_trend() as a more general solution.
> > 
> > For the platform thermal drivers that have their own way to
> > anticipate the temperature trends, they should provide
> > their own .get_trend() callback.
> > Or else, we will calculate the temperature trends by simply
> > comparing the current temperature and the cached previous
> > temperature reading.
> 
> As far as the code is concerned:
> 
> Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
> 
> I wonder, though, if there are any users of the thermal core currently in the
> tree who should introduce their own .get_trend() callbacks?
> 
No, for now.
But there will be soon. :)

thanks,
rui
> Rafael
> 
> 
> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
> > ---
> >  drivers/acpi/thermal.c        |   33 +++++++++++++++++++++++++++++++++
> >  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
> >  include/linux/thermal.h       |    9 +++++++++
> >  3 files changed, 59 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> > index b48ec3e..0c49e42 100644
> > --- a/drivers/acpi/thermal.c
> > +++ b/drivers/acpi/thermal.c
> > @@ -704,6 +704,38 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
> >  		return -EINVAL;
> >  }
> >  
> > +static int thermal_get_trend(struct thermal_zone_device *thermal,
> > +				int trip, enum thermal_trend *trend)
> > +{
> > +	struct acpi_thermal *tz = thermal->devdata;
> > +	enum thermal_trip_type type;
> > +	int i;
> > +
> > +	if (thermal_get_trip_type(thermal, trip, &type))
> > +		return -EINVAL;
> > +
> > +	/* Only PASSIVE trip points need TREND */
> > +	if (type != THERMAL_TRIP_PASSIVE)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * tz->temperature has already been updated by generic thermal layer,
> > +	 * before this callback being invoked
> > +	 */
> > +	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> > +		+ (tz->trips.passive.tc2
> > +		* (tz->temperature - tz->trips.passive.temperature));
> > +
> > +	if (i > 0)
> > +		*trend = THERMAL_TREND_RAISING;
> > +	else if (i < 0)
> > +		*trend = THERMAL_TREND_DROPPING;
> > +	else
> > +		*trend = THERMAL_TREND_STABLE;
> > +	return 0;
> > +}
> > +
> > +
> >  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
> >  			   enum thermal_trip_type trip_type)
> >  {
> > @@ -836,6 +868,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
> >  	.get_trip_type = thermal_get_trip_type,
> >  	.get_trip_temp = thermal_get_trip_temp,
> >  	.get_crit_temp = thermal_get_crit_temp,
> > +	.get_trend = thermal_get_trend,
> >  	.notify = thermal_notify,
> >  };
> >  
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index 62b4279..68c93d4 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -723,6 +723,20 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
> >  	struct thermal_cooling_device *cdev;
> >  	long state, max_state;
> >  
> > +	if (!tz->ops->get_trend ||
> > +	    tz->ops->get_trend(tz, trip, (enum thermal_trend *)&trend)) {
> > +		/*
> > +		 * compare the current temperature and previous temperature
> > +		 * to get the thermal trend, if no special requirement
> > +		 */
> > +		if (tz->temperature > tz->last_temperature)
> > +			trend = THERMAL_TREND_RAISING;
> > +		else if (tz->temperature < tz->last_temperature)
> > +			trend = THERMAL_TREND_DROPPING;
> > +		else
> > +			trend = THERMAL_TREND_STABLE;
> > +	}
> > +
> >  	/*
> >  	 * Above Trip?
> >  	 * -----------
> > @@ -1091,6 +1105,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> >  		goto leave;
> >  	}
> >  
> > +	tz->last_temperature = tz->temperature;
> > +	tz->temperature = temp;
> > +
> >  	for (count = 0; count < tz->trips; count++) {
> >  		tz->ops->get_trip_type(tz, count, &trip_type);
> >  		tz->ops->get_trip_temp(tz, count, &trip_temp);
> > @@ -1150,8 +1167,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
> >  		thermal_zone_device_passive(tz, temp, tz->forced_passive,
> >  					    THERMAL_TRIPS_NONE);
> >  
> > -	tz->last_temperature = temp;
> > -
> >  leave:
> >  	if (tz->passive)
> >  		thermal_zone_device_set_polling(tz, tz->passive_delay);
> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> > index a43b12c..a01e3e6 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -44,6 +44,12 @@ enum thermal_trip_type {
> >  	THERMAL_TRIP_CRITICAL,
> >  };
> >  
> > +enum thermal_trend {
> > +	THERMAL_TREND_STABLE, /* temperature is stable */
> > +	THERMAL_TREND_RAISING, /* temperature is raising */
> > +	THERMAL_TREND_DROPPING, /* temperature is dropping */
> > +};
> > +
> >  struct thermal_zone_device_ops {
> >  	int (*bind) (struct thermal_zone_device *,
> >  		     struct thermal_cooling_device *);
> > @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
> >  	int (*set_trip_hyst) (struct thermal_zone_device *, int,
> >  			      unsigned long);
> >  	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
> > +	int (*get_trend) (struct thermal_zone_device *, int,
> > +			  enum thermal_trend *);
> >  	int (*notify) (struct thermal_zone_device *, int,
> >  		       enum thermal_trip_type);
> >  };
> > @@ -111,6 +119,7 @@ struct thermal_zone_device {
> >  	int tc2;
> >  	int passive_delay;
> >  	int polling_delay;
> > +	int temperature;
> >  	int last_temperature;
> >  	bool passive;
> >  	unsigned int forced_passive;
> > 
> 


--
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
Eduardo Valentin Aug. 8, 2012, 1:44 p.m. UTC | #3
Hello,

On Thu, Jul 26, 2012 at 11:41 AM, Zhang Rui <rui.zhang@intel.com> wrote:
> According to ACPI spec, tc1 and tc2 are used by OSPM
> to anticipate the temperature trends.
> We introduced the same concept to the generic thermal layer
> for passive cooling, but now it seems that these values
> are hard to be used on other platforms.
>
> So We introduce .get_trend() as a more general solution.
>
> For the platform thermal drivers that have their own way to
> anticipate the temperature trends, they should provide
> their own .get_trend() callback.
> Or else, we will calculate the temperature trends by simply
> comparing the current temperature and the cached previous
> temperature reading.
>
> Signed-off-by: Zhang Rui <rui.zhang@intel.com>

Looks good to me.

Reviewed-by: Eduardo Valentin <eduardo.valentin@ti.com>

> ---
>  drivers/acpi/thermal.c        |   33 +++++++++++++++++++++++++++++++++
>  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
>  include/linux/thermal.h       |    9 +++++++++
>  3 files changed, 59 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index b48ec3e..0c49e42 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -704,6 +704,38 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
>                 return -EINVAL;
>  }
>
> +static int thermal_get_trend(struct thermal_zone_device *thermal,
> +                               int trip, enum thermal_trend *trend)
> +{
> +       struct acpi_thermal *tz = thermal->devdata;
> +       enum thermal_trip_type type;
> +       int i;
> +
> +       if (thermal_get_trip_type(thermal, trip, &type))
> +               return -EINVAL;
> +
> +       /* Only PASSIVE trip points need TREND */
> +       if (type != THERMAL_TRIP_PASSIVE)
> +               return -EINVAL;
> +
> +       /*
> +        * tz->temperature has already been updated by generic thermal layer,
> +        * before this callback being invoked
> +        */
> +       i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
> +               + (tz->trips.passive.tc2
> +               * (tz->temperature - tz->trips.passive.temperature));
> +
> +       if (i > 0)
> +               *trend = THERMAL_TREND_RAISING;
> +       else if (i < 0)
> +               *trend = THERMAL_TREND_DROPPING;
> +       else
> +               *trend = THERMAL_TREND_STABLE;
> +       return 0;
> +}
> +
> +
>  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
>                            enum thermal_trip_type trip_type)
>  {
> @@ -836,6 +868,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
>         .get_trip_type = thermal_get_trip_type,
>         .get_trip_temp = thermal_get_trip_temp,
>         .get_crit_temp = thermal_get_crit_temp,
> +       .get_trend = thermal_get_trend,
>         .notify = thermal_notify,
>  };
>
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 62b4279..68c93d4 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -723,6 +723,20 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>         struct thermal_cooling_device *cdev;
>         long state, max_state;
>
> +       if (!tz->ops->get_trend ||
> +           tz->ops->get_trend(tz, trip, (enum thermal_trend *)&trend)) {
> +               /*
> +                * compare the current temperature and previous temperature
> +                * to get the thermal trend, if no special requirement
> +                */
> +               if (tz->temperature > tz->last_temperature)
> +                       trend = THERMAL_TREND_RAISING;
> +               else if (tz->temperature < tz->last_temperature)
> +                       trend = THERMAL_TREND_DROPPING;
> +               else
> +                       trend = THERMAL_TREND_STABLE;
> +       }
> +
>         /*
>          * Above Trip?
>          * -----------
> @@ -1091,6 +1105,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>                 goto leave;
>         }
>
> +       tz->last_temperature = tz->temperature;
> +       tz->temperature = temp;
> +
>         for (count = 0; count < tz->trips; count++) {
>                 tz->ops->get_trip_type(tz, count, &trip_type);
>                 tz->ops->get_trip_temp(tz, count, &trip_temp);
> @@ -1150,8 +1167,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>                 thermal_zone_device_passive(tz, temp, tz->forced_passive,
>                                             THERMAL_TRIPS_NONE);
>
> -       tz->last_temperature = temp;
> -
>  leave:
>         if (tz->passive)
>                 thermal_zone_device_set_polling(tz, tz->passive_delay);
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index a43b12c..a01e3e6 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -44,6 +44,12 @@ enum thermal_trip_type {
>         THERMAL_TRIP_CRITICAL,
>  };
>
> +enum thermal_trend {
> +       THERMAL_TREND_STABLE, /* temperature is stable */
> +       THERMAL_TREND_RAISING, /* temperature is raising */
> +       THERMAL_TREND_DROPPING, /* temperature is dropping */
> +};
> +
>  struct thermal_zone_device_ops {
>         int (*bind) (struct thermal_zone_device *,
>                      struct thermal_cooling_device *);
> @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
>         int (*set_trip_hyst) (struct thermal_zone_device *, int,
>                               unsigned long);
>         int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
> +       int (*get_trend) (struct thermal_zone_device *, int,
> +                         enum thermal_trend *);
>         int (*notify) (struct thermal_zone_device *, int,
>                        enum thermal_trip_type);
>  };
> @@ -111,6 +119,7 @@ struct thermal_zone_device {
>         int tc2;
>         int passive_delay;
>         int polling_delay;
> +       int temperature;
>         int last_temperature;
>         bool passive;
>         unsigned int forced_passive;
> --
> 1.7.9.5
>
Eduardo Valentin Aug. 8, 2012, 1:46 p.m. UTC | #4
Hello Rui and Rafael,

On Wed, Aug 1, 2012 at 5:42 AM, Zhang Rui <rui.zhang@intel.com> wrote:
> On ?, 2012-07-26 at 22:11 +0200, Rafael J. Wysocki wrote:
>> On Thursday, July 26, 2012, Zhang Rui wrote:
>> > According to ACPI spec, tc1 and tc2 are used by OSPM
>> > to anticipate the temperature trends.
>> > We introduced the same concept to the generic thermal layer
>> > for passive cooling, but now it seems that these values
>> > are hard to be used on other platforms.
>> >
>> > So We introduce .get_trend() as a more general solution.
>> >
>> > For the platform thermal drivers that have their own way to
>> > anticipate the temperature trends, they should provide
>> > their own .get_trend() callback.
>> > Or else, we will calculate the temperature trends by simply
>> > comparing the current temperature and the cached previous
>> > temperature reading.
>>
>> As far as the code is concerned:
>>
>> Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
>>
>> I wonder, though, if there are any users of the thermal core currently in the
>> tree who should introduce their own .get_trend() callbacks?
>>
> No, for now.
> But there will be soon. :)

Yeah, one of them would be the OMAP5 thermal driver. But the code is
not implemented yet. Currently driver under staging area already
though: drivers/staging/omap-thermal/

>
> thanks,
> rui
>> Rafael
>>
>>
>> > Signed-off-by: Zhang Rui <rui.zhang@intel.com>
>> > ---
>> >  drivers/acpi/thermal.c        |   33 +++++++++++++++++++++++++++++++++
>> >  drivers/thermal/thermal_sys.c |   19 +++++++++++++++++--
>> >  include/linux/thermal.h       |    9 +++++++++
>> >  3 files changed, 59 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
>> > index b48ec3e..0c49e42 100644
>> > --- a/drivers/acpi/thermal.c
>> > +++ b/drivers/acpi/thermal.c
>> > @@ -704,6 +704,38 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
>> >             return -EINVAL;
>> >  }
>> >
>> > +static int thermal_get_trend(struct thermal_zone_device *thermal,
>> > +                           int trip, enum thermal_trend *trend)
>> > +{
>> > +   struct acpi_thermal *tz = thermal->devdata;
>> > +   enum thermal_trip_type type;
>> > +   int i;
>> > +
>> > +   if (thermal_get_trip_type(thermal, trip, &type))
>> > +           return -EINVAL;
>> > +
>> > +   /* Only PASSIVE trip points need TREND */
>> > +   if (type != THERMAL_TRIP_PASSIVE)
>> > +           return -EINVAL;
>> > +
>> > +   /*
>> > +    * tz->temperature has already been updated by generic thermal layer,
>> > +    * before this callback being invoked
>> > +    */
>> > +   i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
>> > +           + (tz->trips.passive.tc2
>> > +           * (tz->temperature - tz->trips.passive.temperature));
>> > +
>> > +   if (i > 0)
>> > +           *trend = THERMAL_TREND_RAISING;
>> > +   else if (i < 0)
>> > +           *trend = THERMAL_TREND_DROPPING;
>> > +   else
>> > +           *trend = THERMAL_TREND_STABLE;
>> > +   return 0;
>> > +}
>> > +
>> > +
>> >  static int thermal_notify(struct thermal_zone_device *thermal, int trip,
>> >                        enum thermal_trip_type trip_type)
>> >  {
>> > @@ -836,6 +868,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
>> >     .get_trip_type = thermal_get_trip_type,
>> >     .get_trip_temp = thermal_get_trip_temp,
>> >     .get_crit_temp = thermal_get_crit_temp,
>> > +   .get_trend = thermal_get_trend,
>> >     .notify = thermal_notify,
>> >  };
>> >
>> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
>> > index 62b4279..68c93d4 100644
>> > --- a/drivers/thermal/thermal_sys.c
>> > +++ b/drivers/thermal/thermal_sys.c
>> > @@ -723,6 +723,20 @@ static void thermal_zone_device_passive(struct thermal_zone_device *tz,
>> >     struct thermal_cooling_device *cdev;
>> >     long state, max_state;
>> >
>> > +   if (!tz->ops->get_trend ||
>> > +       tz->ops->get_trend(tz, trip, (enum thermal_trend *)&trend)) {
>> > +           /*
>> > +            * compare the current temperature and previous temperature
>> > +            * to get the thermal trend, if no special requirement
>> > +            */
>> > +           if (tz->temperature > tz->last_temperature)
>> > +                   trend = THERMAL_TREND_RAISING;
>> > +           else if (tz->temperature < tz->last_temperature)
>> > +                   trend = THERMAL_TREND_DROPPING;
>> > +           else
>> > +                   trend = THERMAL_TREND_STABLE;
>> > +   }
>> > +
>> >     /*
>> >      * Above Trip?
>> >      * -----------
>> > @@ -1091,6 +1105,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>> >             goto leave;
>> >     }
>> >
>> > +   tz->last_temperature = tz->temperature;
>> > +   tz->temperature = temp;
>> > +
>> >     for (count = 0; count < tz->trips; count++) {
>> >             tz->ops->get_trip_type(tz, count, &trip_type);
>> >             tz->ops->get_trip_temp(tz, count, &trip_temp);
>> > @@ -1150,8 +1167,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
>> >             thermal_zone_device_passive(tz, temp, tz->forced_passive,
>> >                                         THERMAL_TRIPS_NONE);
>> >
>> > -   tz->last_temperature = temp;
>> > -
>> >  leave:
>> >     if (tz->passive)
>> >             thermal_zone_device_set_polling(tz, tz->passive_delay);
>> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
>> > index a43b12c..a01e3e6 100644
>> > --- a/include/linux/thermal.h
>> > +++ b/include/linux/thermal.h
>> > @@ -44,6 +44,12 @@ enum thermal_trip_type {
>> >     THERMAL_TRIP_CRITICAL,
>> >  };
>> >
>> > +enum thermal_trend {
>> > +   THERMAL_TREND_STABLE, /* temperature is stable */
>> > +   THERMAL_TREND_RAISING, /* temperature is raising */
>> > +   THERMAL_TREND_DROPPING, /* temperature is dropping */
>> > +};
>> > +
>> >  struct thermal_zone_device_ops {
>> >     int (*bind) (struct thermal_zone_device *,
>> >                  struct thermal_cooling_device *);
>> > @@ -65,6 +71,8 @@ struct thermal_zone_device_ops {
>> >     int (*set_trip_hyst) (struct thermal_zone_device *, int,
>> >                           unsigned long);
>> >     int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
>> > +   int (*get_trend) (struct thermal_zone_device *, int,
>> > +                     enum thermal_trend *);
>> >     int (*notify) (struct thermal_zone_device *, int,
>> >                    enum thermal_trip_type);
>> >  };
>> > @@ -111,6 +119,7 @@ struct thermal_zone_device {
>> >     int tc2;
>> >     int passive_delay;
>> >     int polling_delay;
>> > +   int temperature;
>> >     int last_temperature;
>> >     bool passive;
>> >     unsigned int forced_passive;
>> >
>>
>
>
diff mbox

Patch

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index b48ec3e..0c49e42 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -704,6 +704,38 @@  static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 		return -EINVAL;
 }
 
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+				int trip, enum thermal_trend *trend)
+{
+	struct acpi_thermal *tz = thermal->devdata;
+	enum thermal_trip_type type;
+	int i;
+
+	if (thermal_get_trip_type(thermal, trip, &type))
+		return -EINVAL;
+
+	/* Only PASSIVE trip points need TREND */
+	if (type != THERMAL_TRIP_PASSIVE)
+		return -EINVAL;
+
+	/*
+	 * tz->temperature has already been updated by generic thermal layer,
+	 * before this callback being invoked
+	 */
+	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
+		+ (tz->trips.passive.tc2
+		* (tz->temperature - tz->trips.passive.temperature));
+
+	if (i > 0)
+		*trend = THERMAL_TREND_RAISING;
+	else if (i < 0)
+		*trend = THERMAL_TREND_DROPPING;
+	else
+		*trend = THERMAL_TREND_STABLE;
+	return 0;
+}
+
+
 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 			   enum thermal_trip_type trip_type)
 {
@@ -836,6 +868,7 @@  static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
 	.get_trip_type = thermal_get_trip_type,
 	.get_trip_temp = thermal_get_trip_temp,
 	.get_crit_temp = thermal_get_crit_temp,
+	.get_trend = thermal_get_trend,
 	.notify = thermal_notify,
 };
 
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 62b4279..68c93d4 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -723,6 +723,20 @@  static void thermal_zone_device_passive(struct thermal_zone_device *tz,
 	struct thermal_cooling_device *cdev;
 	long state, max_state;
 
+	if (!tz->ops->get_trend ||
+	    tz->ops->get_trend(tz, trip, (enum thermal_trend *)&trend)) {
+		/*
+		 * compare the current temperature and previous temperature
+		 * to get the thermal trend, if no special requirement
+		 */
+		if (tz->temperature > tz->last_temperature)
+			trend = THERMAL_TREND_RAISING;
+		else if (tz->temperature < tz->last_temperature)
+			trend = THERMAL_TREND_DROPPING;
+		else
+			trend = THERMAL_TREND_STABLE;
+	}
+
 	/*
 	 * Above Trip?
 	 * -----------
@@ -1091,6 +1105,9 @@  void thermal_zone_device_update(struct thermal_zone_device *tz)
 		goto leave;
 	}
 
+	tz->last_temperature = tz->temperature;
+	tz->temperature = temp;
+
 	for (count = 0; count < tz->trips; count++) {
 		tz->ops->get_trip_type(tz, count, &trip_type);
 		tz->ops->get_trip_temp(tz, count, &trip_temp);
@@ -1150,8 +1167,6 @@  void thermal_zone_device_update(struct thermal_zone_device *tz)
 		thermal_zone_device_passive(tz, temp, tz->forced_passive,
 					    THERMAL_TRIPS_NONE);
 
-	tz->last_temperature = temp;
-
 leave:
 	if (tz->passive)
 		thermal_zone_device_set_polling(tz, tz->passive_delay);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index a43b12c..a01e3e6 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -44,6 +44,12 @@  enum thermal_trip_type {
 	THERMAL_TRIP_CRITICAL,
 };
 
+enum thermal_trend {
+	THERMAL_TREND_STABLE, /* temperature is stable */
+	THERMAL_TREND_RAISING, /* temperature is raising */
+	THERMAL_TREND_DROPPING, /* temperature is dropping */
+};
+
 struct thermal_zone_device_ops {
 	int (*bind) (struct thermal_zone_device *,
 		     struct thermal_cooling_device *);
@@ -65,6 +71,8 @@  struct thermal_zone_device_ops {
 	int (*set_trip_hyst) (struct thermal_zone_device *, int,
 			      unsigned long);
 	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
+	int (*get_trend) (struct thermal_zone_device *, int,
+			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
 };
@@ -111,6 +119,7 @@  struct thermal_zone_device {
 	int tc2;
 	int passive_delay;
 	int polling_delay;
+	int temperature;
 	int last_temperature;
 	bool passive;
 	unsigned int forced_passive;