From: Durgadoss R <hidden> Date: 2012-08-27 04:28:56
This patch series is a v2 of the series submitted here:
http://www.spinics.net/lists/linux-acpi/msg37375.html
These patches are based on Rui's tree here: (branch - thermal)
git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
Changes since v1:
* Created thermal_core.h
* Removed get_cdev_by_name API, as it is no longer needed
* Introduced thermal_bind_params inside thermal_zone_params
* Use a single arbitrator by making thermal_cdev_update global
* Added more documentation on EXPORT_SYMBOL APIs in thermal_sys.c
* Various minor fixes based on comments from Rui and Eduardo.
The function pointer based implementation for various throttling
policies is not done here. I tried and it altered the structure of
the patch set a lot, and hence I shall take it up after this code
gets in.
Durgadoss R (14):
Thermal: Refactor thermal.h file
Thermal: Move thermal_instance to thermal_core.h
Thermal: Add get trend, get instance API's to thermal_sys
Thermal: Add platform level information to thermal.h
Thermal: Obtain platform data for thermal zone
Thermal: Add a policy sysfs attribute
Thermal: Update binding logic based on platform data
Thermal: Make thermal_cdev_update as a global function
Thermal: Introduce fair_share thermal governor
Thermal: Introduce a step_wise thermal governor
Thermal: Remove throttling logic out of thermal_sys.c
Thermal: Add a notification API
Thermal: Add documentation for platform layer data
Thermal: Platform layer changes to provide thermal data
Documentation/thermal/sysfs-api.txt | 51 +++
arch/x86/platform/mrst/mrst.c | 49 +++
drivers/thermal/Kconfig | 12 +
drivers/thermal/Makefile | 4 +-
drivers/thermal/fair_share.c | 113 ++++++
drivers/thermal/step_wise.c | 173 ++++++++++
drivers/thermal/thermal_core.h | 53 +++
drivers/thermal/thermal_sys.c | 647 ++++++++++++++++++++++-------------
include/linux/thermal.h | 145 ++++++--
9 files changed, 969 insertions(+), 278 deletions(-)
create mode 100644 drivers/thermal/fair_share.c
create mode 100644 drivers/thermal/step_wise.c
create mode 100644 drivers/thermal/thermal_core.h
--
1.7.9.5
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:07
This patch rearranges the code in thermal.h file,
in the following order, so that it is easy to
read/maintain.
1. All #defines
2. All enums
3. All fops structures
4. All device structures
5. All function declarations
Signed-off-by: Durgadoss R <redacted>
---
include/linux/thermal.h | 78 ++++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 35 deletions(-)
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:08
This patch creates a thermal_core.h file which can contain
all defines used by the core thermal framework files. For
now, move the thermal_instance structure to thermal_core.h
This structure is used by files under drivers/thermal/.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_core.h | 53 ++++++++++++++++++++++++++++++++++++++++
drivers/thermal/thermal_sys.c | 23 ++---------------
2 files changed, 55 insertions(+), 21 deletions(-)
create mode 100644 drivers/thermal/thermal_core.h
@@ -0,0 +1,53 @@+/*+*thermal_core.h+*+*Copyright(C)2012IntelCorp+*Author:DurgadossR<durgadoss.r@intel.com>+*+*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby+*theFreeSoftwareFoundation;version2oftheLicense.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,but+*WITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.SeetheGNU+*GeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicensealong+*withthisprogram;ifnot,writetotheFreeSoftwareFoundation,Inc.,+*59TemplePlace,Suite330,Boston,MA02111-1307USA.+*+*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+*/++#ifndef __THERMAL_CORE_H__+#define __THERMAL_CORE_H__++#include<linux/device.h>+#include<linux/thermal.h>++/* Initial state of a cooling device during binding */+#define THERMAL_NO_TARGET -1UL++/*+*Thisstructureisusedtodescribethebehaviorof+*acertaincoolingdeviceonacertaintrippoint+*inacertainthermalzone+*/+structthermal_instance{+intid;+charname[THERMAL_NAME_LENGTH];+structthermal_zone_device*tz;+structthermal_cooling_device*cdev;+inttrip;+unsignedlongupper;/* Highest cooling state for this trip point */+unsignedlonglower;/* Lowest cooling state for this trip point */+unsignedlongtarget;/* expected cooling state */+charattr_name[THERMAL_NAME_LENGTH];+structdevice_attributeattr;+structlist_headtz_node;/* node in tz->thermal_instances */+structlist_headcdev_node;/* node in cdev->thermal_instances */+};++#endif /* __THERMAL_CORE_H__ */
@@ -37,31 +37,12 @@#include<net/netlink.h>#include<net/genetlink.h>+#include"thermal_core.h"+MODULE_AUTHOR("Zhang Rui");MODULE_DESCRIPTION("Generic thermal management sysfs support");MODULE_LICENSE("GPL");-#define THERMAL_NO_TARGET -1UL-/*-*Thisstructureisusedtodescribethebehaviorof-*acertaincoolingdeviceonacertaintrippoint-*inacertainthermalzone-*/-structthermal_instance{-intid;-charname[THERMAL_NAME_LENGTH];-structthermal_zone_device*tz;-structthermal_cooling_device*cdev;-inttrip;-unsignedlongupper;/* Highest cooling state for this trip point */-unsignedlonglower;/* Lowest cooling state for this trip point */-unsignedlongtarget;/* expected cooling state */-charattr_name[THERMAL_NAME_LENGTH];-structdevice_attributeattr;-structlist_headtz_node;/* node in tz->thermal_instances */-structlist_headcdev_node;/* node in cdev->thermal_instances */-};-staticDEFINE_IDR(thermal_tz_idr);staticDEFINE_IDR(thermal_cdev_idr);staticDEFINE_MUTEX(thermal_idr_lock);
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:10
This patch adds the following API's to thermal_sys.c, that
can be used by other Thermal drivers.
* get_tz_trend: obtain the trend of the given thermal zone
* get_thermal_instance: obtain the instance corresponding
to the given tz, cdev and the trip point.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 4 ++++
2 files changed, 44 insertions(+)
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:12
This patch creates two structures; one to hold bind
bind parameters for a thermal zone, and another to
store platform layer data for a thermal zone, and
defines an extern function to retrieve these
parameters from thermal_sys.c. This patch also
defines an enum that describes various policies
for thermal throttling.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 3 +++
include/linux/thermal.h | 46 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
@@ -67,6 +67,12 @@ enum thermal_trend {THERMAL_TREND_DROPPING,/* temperature is dropping */};+enumthermal_throttle_policy{+THERMAL_USER_SPACE,+THERMAL_FAIR_SHARE,+THERMAL_STEP_WISE,+};+/* Events supported by Thermal Netlink */enumevents{THERMAL_AUX0,
@@ -162,6 +168,37 @@ struct thermal_zone_device {structmutexlock;/* protect thermal_instances list */structlist_headnode;structdelayed_workpoll_queue;+structthermal_zone_params*tzp;+};++/* Structure that holds binding parameters for a zone */+structthermal_bind_params{+structthermal_cooling_device*cdev;++/*+*Thisisameasureof'howeffectivelythesedevicescan+*cool'this'thermalzone.Theshallbedeterminedbyplatform+*characterization.Thisisona'percentage'scale.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+intweight;++/*+*Thisisabitmaskthatgivesthebindingrelationbetweenthis+*thermalzoneandcdev,foraparticulartrippoint.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+inttrip_mask;+int(*match)(structthermal_zone_device*tz,+structthermal_cooling_device*cdev);+};++/* Structure to define Thermal Zone parameters */+structthermal_zone_params{+constchar*zone_name;+enumthermal_throttle_policythrottle_policy;+intnum_tbps;/* Number of tbp entries */+structthermal_bind_params*tbp;};structthermal_genl_event{
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:14
This patch retrieves the platform level data for
a zone during its registration. It is not an error
to not have any platform data.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
@@ -1339,6 +1339,22 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)kfree(tz->trip_hyst_attrs);}+staticintretrieve_zone_params(structthermal_zone_device*tz)+{+intret;++/* Check whether the platform data pointer is defined */+if(!get_platform_thermal_params)+return0;++/* It is not an error to not have any platform data */+ret=get_platform_thermal_params(tz);+if(ret)+tz->tzp=NULL;++return0;+}+/***thermal_zone_device_register-registeranewthermalzonedevice*@type:thethermalzonedevicetype
@@ -1443,6 +1459,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,if(result)gotounregister;+/* Retrieve platform level parameters for this zone */+result=retrieve_zone_params(tz);+if(result)+gotounregister;+mutex_lock(&thermal_list_lock);list_add_tail(&tz->node,&thermal_tz_list);if(ops->bind)
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:16
This patch adds a policy sysfs attribute to a thermal zone.
This attribute will give us the throttling policy used
for the zone. This is a RO attribute.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct thermal_zone_device *tz)/* It is not an error to not have any platform data */ret=get_platform_thermal_params(tz);-if(ret)+if(ret){tz->tzp=NULL;+return0;+}-return0;+ret=device_create_file(&tz->device,&dev_attr_throttle_policy);+if(ret)+dev_err(&tz->device,"creating policy attr failed:%d\n",ret);++returnret;}/**
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:18
This patch updates the binding logic in thermal_sys.c
It uses the platform layer data to bind a thermal zone
to a cdev for a particular trip point.
* If we do not have platform data and do not have
.bind defined, do not bind.
* If we do not have platform data but .bind is
defined, then use tz->ops->bind.
* If we have platform data, use it to create binding.
The same logic sequence is followed for unbind also.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 184 +++++++++++++++++++++++++++++++++++------
1 file changed, 158 insertions(+), 26 deletions(-)
@@ -125,6 +125,111 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,}EXPORT_SYMBOL(get_thermal_instance);+staticvoidprint_bind_err_msg(structthermal_zone_device*tz,+structthermal_cooling_device*cdev,intret)+{+dev_err(&tz->device,"binding zone %s with cdev %s failed:%d\n",+tz->type,cdev->type,ret);+}++staticvoid__bind(structthermal_zone_device*tz,intmask,+structthermal_cooling_device*cdev)+{+inti,ret;++for(i=0;i<tz->trips;i++){+if(mask&(1<<i)){+ret=thermal_zone_bind_cooling_device(tz,i,cdev,+THERMAL_NO_LIMIT,THERMAL_NO_LIMIT);+if(ret)+print_bind_err_msg(tz,cdev,ret);+}+}+}++staticvoid__unbind(structthermal_zone_device*tz,intmask,+structthermal_cooling_device*cdev)+{+inti;++for(i=0;i<tz->trips;i++)+if(mask&(1<<i))+thermal_zone_unbind_cooling_device(tz,i,cdev);+}++staticvoidupdate_bind_info(structthermal_cooling_device*cdev)+{+inti,ret;+structthermal_zone_params*tzp;+structthermal_zone_device*pos=NULL;++mutex_lock(&thermal_list_lock);++list_for_each_entry(pos,&thermal_tz_list,node){+if(!pos->tzp&&!pos->ops->bind)+continue;++if(!pos->tzp&&pos->ops->bind){+ret=pos->ops->bind(pos,cdev);+if(ret)+print_bind_err_msg(pos,cdev,ret);+}++tzp=pos->tzp;+if(!tzp->tbp)+return;++for(i=0;i<tzp->num_tbps;i++){+if(tzp->tbp[i].cdev||!tzp->tbp[i].match)+continue;+if(tzp->tbp[i].match(pos,cdev))+continue;+tzp->tbp[i].cdev=cdev;+__bind(pos,tzp->tbp[i].trip_mask,cdev);+}+}++mutex_unlock(&thermal_list_lock);+}++staticvoiddo_binding(structthermal_zone_device*tz)+{+inti,ret;+structthermal_cooling_device*pos=NULL;+structthermal_zone_params*tzp=tz->tzp;++if(!tzp&&!tz->ops->bind)+return;++mutex_lock(&thermal_list_lock);++/* If there is no platform data, try to use ops->bind */+if(!tzp&&tz->ops->bind){+list_for_each_entry(pos,&thermal_cdev_list,node){+ret=tz->ops->bind(tz,pos);+if(ret)+print_bind_err_msg(tz,pos,ret);+}+gotoexit;+}++if(!tzp->tbp)+gotoexit;++list_for_each_entry(pos,&thermal_cdev_list,node){+for(i=0;i<tzp->num_tbps;i++){+if(tzp->tbp[i].cdev||!tzp->tbp[i].match)+continue;+if(tzp->tbp[i].match(tz,pos))+continue;+tzp->tbp[i].cdev=pos;+__bind(tz,tzp->tbp[i].trip_mask,pos);+}+}+exit:+mutex_unlock(&thermal_list_lock);+}+/* sys I/F for thermal zone */#define to_thermal_zone(_dev) \
@@ -993,20 +1097,15 @@ thermal_cooling_device_register(char *type, void *devdata,if(result)gotounregister;+/* Add 'this' new cdev to the global cdev list */mutex_lock(&thermal_list_lock);list_add(&cdev->node,&thermal_cdev_list);-list_for_each_entry(pos,&thermal_tz_list,node){-if(!pos->ops->bind)-continue;-result=pos->ops->bind(pos,cdev);-if(result)-break;--}mutex_unlock(&thermal_list_lock);-if(!result)-returncdev;+/* Update binding information for 'this' new cdev */+update_bind_info(cdev);++returncdev;unregister:release_idr(&thermal_cdev_idr,&thermal_idr_lock,cdev->id);
@@ -1042,12 +1141,28 @@ void thermal_cooling_device_unregister(structreturn;}list_del(&cdev->node);++/* Unbind all thermal zones associated with 'this' cdev */list_for_each_entry(tz,&thermal_tz_list,node){-if(!tz->ops->unbind)+if(tz->ops->unbind){+tz->ops->unbind(tz,cdev);continue;-tz->ops->unbind(tz,cdev);+}++if(!tz->tzp||!tz->tzp->tbp)+continue;++tzp=tz->tzp;+for(i=0;i<tzp->num_tbps;i++){+if(tzp->tbp[i].cdev==cdev){+__unbind(tz,tzp->tbp[i].trip_mask,cdev);+tzp->tbp[i].cdev=NULL;+}+}}+mutex_unlock(&thermal_list_lock);+if(cdev->type[0])device_remove_file(&cdev->device,&dev_attr_cdev_type);device_remove_file(&cdev->device,&dev_attr_max_state);
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:20
This patch makes the thermal_cdev_update function as a
global one, so that other files can use it. This function
serves as a single arbitrator to set the state of a cooling
device.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 5 +++--
include/linux/thermal.h | 2 ++
2 files changed, 5 insertions(+), 2 deletions(-)
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:22
This patch introduces a simple 'weight' based
governor named fair_share governor. Whenever the
thermal framework gets notified of the trip point
violation, this governor (if configured), throttles
the cooling devices associated with a thermal zone.
This mapping between a thermal zone and a cooling device
and the effectiveness of cooling are provided in the
platform layer.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/Kconfig | 6 +++
drivers/thermal/Makefile | 3 +-
drivers/thermal/fair_share.c | 113 ++++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 9 ++++
4 files changed, 130 insertions(+), 1 deletion(-)
create mode 100644 drivers/thermal/fair_share.c
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:24
This patch adds a simple step_wise governor to the
generic thermal layer. This algorithm throttles the
cooling devices in a linear fashion. If the 'trend'
is heating, it throttles by one step. And if the
thermal trend is cooling it de-throttles by one step.
This actually moves the throttling logic from thermal_sys.c
and puts inside step_wise.c, without any change.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/Kconfig | 6 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/step_wise.c | 173 +++++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 9 +++
4 files changed, 189 insertions(+)
create mode 100644 drivers/thermal/step_wise.c
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:26
This patch removes the throttling logic out of
thermal_sys.c; also refactors the code into smaller
functions so that are easy to read/maintain.
* Seperates the handling of critical and non-critical trips
* Re-arranges the set_polling and device_check methods, so
that all related functions are arranged in one place.
* Removes the 'do_update' and 'trip_update' method, as part
of moving the throttling logic out of thermal_sys.c
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 337 +++++++++++++++++------------------------
1 file changed, 136 insertions(+), 201 deletions(-)
@@ -230,6 +230,142 @@ exit:mutex_unlock(&thermal_list_lock);}+staticvoidthermal_zone_device_set_polling(structthermal_zone_device*tz,+intdelay)+{+cancel_delayed_work(&(tz->poll_queue));++if(!delay)+return;++if(delay>1000)+queue_delayed_work(system_freezable_wq,&(tz->poll_queue),+round_jiffies(msecs_to_jiffies(delay)));+else+queue_delayed_work(system_freezable_wq,&(tz->poll_queue),+msecs_to_jiffies(delay));+}++staticvoidmonitor_thermal_zone(structthermal_zone_device*tz)+{+mutex_lock(&tz->lock);++if(tz->passive)+thermal_zone_device_set_polling(tz,tz->passive_delay);+elseif(tz->polling_delay)+thermal_zone_device_set_polling(tz,tz->polling_delay);+else+thermal_zone_device_set_polling(tz,0);++mutex_unlock(&tz->lock);+}++staticvoidnotify_user_space(structthermal_zone_device*tz,inttrip)+{+mutex_lock(&tz->lock);++kobject_uevent(&tz->device.kobj,KOBJ_CHANGE);++mutex_unlock(&tz->lock);+}++staticvoidhandle_non_critical_trips(structthermal_zone_device*tz,+inttrip,enumthermal_trip_typetrip_type)+{+intthrottle_policy=THERMAL_STEP_WISE;++if(tz->tzp)+throttle_policy=tz->tzp->throttle_policy;++switch(throttle_policy){+caseTHERMAL_FAIR_SHARE:+fair_share_throttle(tz,trip);+break;+caseTHERMAL_STEP_WISE:+step_wise_throttle(tz,trip);+break;+caseTHERMAL_USER_SPACE:+notify_user_space(tz,trip);+break;+}+}++staticvoidhandle_critical_trips(structthermal_zone_device*tz,+inttrip,enumthermal_trip_typetrip_type)+{+longtrip_temp;++tz->ops->get_trip_temp(tz,trip,&trip_temp);++/* If we have not crossed the trip_temp, we do not care. */+if(tz->temperature<trip_temp)+return;++if(tz->ops->notify)+tz->ops->notify(tz,trip,trip_type);++if(trip_type==THERMAL_TRIP_CRITICAL){+pr_emerg("Critical temperature reached(%d C),shutting down\n",+tz->temperature/1000);+orderly_poweroff(true);+}+}++staticvoidhandle_thermal_trip(structthermal_zone_device*tz,inttrip)+{+enumthermal_trip_typetype;++tz->ops->get_trip_type(tz,trip,&type);++if(type==THERMAL_TRIP_CRITICAL||type==THERMAL_TRIP_HOT)+handle_critical_trips(tz,trip,type);+else+handle_non_critical_trips(tz,trip,type);+/*+*Alright,wehandledthistripsuccessfully.+*So,startmonitoringagain.+*/+monitor_thermal_zone(tz);+}++staticvoidupdate_temperature(structthermal_zone_device*tz)+{+longtemp;+intret;++mutex_lock(&tz->lock);++ret=tz->ops->get_temp(tz,&temp);+if(ret){+pr_warn("failed to read out thermal zone %d\n",tz->id);+return;+}++tz->last_temperature=tz->temperature;+tz->temperature=temp;++mutex_unlock(&tz->lock);+}++voidthermal_zone_device_update(structthermal_zone_device*tz)+{+intcount;++update_temperature(tz);++for(count=0;count<tz->trips;count++)+handle_thermal_trip(tz,count);+}+EXPORT_SYMBOL(thermal_zone_device_update);++staticvoidthermal_zone_device_check(structwork_struct*work)+{+structthermal_zone_device*tz=container_of(work,struct+thermal_zone_device,+poll_queue.work);+thermal_zone_device_update(tz);+}+/* sys I/F for thermal zone */#define to_thermal_zone(_dev) \
@@ -1197,183 +1309,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)}EXPORT_SYMBOL(thermal_cdev_update);-staticvoidthermal_zone_do_update(structthermal_zone_device*tz)-{-structthermal_instance*instance;--list_for_each_entry(instance,&tz->thermal_instances,tz_node)-thermal_cdev_update(instance->cdev);-}--/*-*Coolingalgorithmforbothactiveandpassivecooling-*-*1.ifthetemperatureishigherthanatrippoint,-*a.ifthetrendisTHERMAL_TREND_RAISING,usehighercooling-*stateforthistrippoint-*b.ifthetrendisTHERMAL_TREND_DROPPING,uselowercooling-*stateforthistrippoint-*-*2.ifthetemperatureislowerthanatrippoint,uselower-*coolingstateforthistrippoint-*-*Notethatthisbehavesthesameasthepreviouspassivecooling-*algorithm.-*/--staticvoidthermal_zone_trip_update(structthermal_zone_device*tz,-inttrip,longtemp)-{-structthermal_instance*instance;-structthermal_cooling_device*cdev=NULL;-unsignedlongcur_state,max_state;-longtrip_temp;-enumthermal_trip_typetrip_type;-enumthermal_trendtrend;--if(trip==THERMAL_TRIPS_NONE){-trip_temp=tz->forced_passive;-trip_type=THERMAL_TRIPS_NONE;-}else{-tz->ops->get_trip_temp(tz,trip,&trip_temp);-tz->ops->get_trip_type(tz,trip,&trip_type);-}--if(!tz->ops->get_trend||tz->ops->get_trend(tz,trip,&trend)){-/*-*comparethecurrenttemperatureandprevioustemperature-*togetthethermaltrend,ifnospecialrequirement-*/-if(tz->temperature>tz->last_temperature)-trend=THERMAL_TREND_RAISING;-elseif(tz->temperature<tz->last_temperature)-trend=THERMAL_TREND_DROPPING;-else-trend=THERMAL_TREND_STABLE;-}--if(temp>=trip_temp){-list_for_each_entry(instance,&tz->thermal_instances,tz_node){-if(instance->trip!=trip)-continue;--cdev=instance->cdev;--cdev->ops->get_cur_state(cdev,&cur_state);-cdev->ops->get_max_state(cdev,&max_state);--if(trend==THERMAL_TREND_RAISING){-cur_state=cur_state<instance->upper?-(cur_state+1):instance->upper;-}elseif(trend==THERMAL_TREND_DROPPING){-cur_state=cur_state>instance->lower?-(cur_state-1):instance->lower;-}--/* activate a passive thermal instance */-if((trip_type==THERMAL_TRIP_PASSIVE||-trip_type==THERMAL_TRIPS_NONE)&&-instance->target==THERMAL_NO_TARGET)-tz->passive++;--instance->target=cur_state;-cdev->updated=false;/* cooling device needs update */-}-}else{/* below trip */-list_for_each_entry(instance,&tz->thermal_instances,tz_node){-if(instance->trip!=trip)-continue;--/* Do not use the inactive thermal instance */-if(instance->target==THERMAL_NO_TARGET)-continue;-cdev=instance->cdev;-cdev->ops->get_cur_state(cdev,&cur_state);--cur_state=cur_state>instance->lower?-(cur_state-1):THERMAL_NO_TARGET;--/* deactivate a passive thermal instance */-if((trip_type==THERMAL_TRIP_PASSIVE||-trip_type==THERMAL_TRIPS_NONE)&&-cur_state==THERMAL_NO_TARGET)-tz->passive--;-instance->target=cur_state;-cdev->updated=false;/* cooling device needs update */-}-}--return;-}-/**-*thermal_zone_device_update-forceanupdateofathermalzone'sstate-*@ttz:thethermalzonetoupdate-*/--voidthermal_zone_device_update(structthermal_zone_device*tz)-{-intcount,ret=0;-longtemp,trip_temp;-enumthermal_trip_typetrip_type;--mutex_lock(&tz->lock);--if(tz->ops->get_temp(tz,&temp)){-/* get_temp failed - retry it later */-pr_warn("failed to read out thermal zone %d\n",tz->id);-gotoleave;-}--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);--switch(trip_type){-caseTHERMAL_TRIP_CRITICAL:-if(temp>=trip_temp){-if(tz->ops->notify)-ret=tz->ops->notify(tz,count,-trip_type);-if(!ret){-pr_emerg("Critical temperature reached (%ld C), shutting down\n",-temp/1000);-orderly_poweroff(true);-}-}-break;-caseTHERMAL_TRIP_HOT:-if(temp>=trip_temp)-if(tz->ops->notify)-tz->ops->notify(tz,count,trip_type);-break;-caseTHERMAL_TRIP_ACTIVE:-thermal_zone_trip_update(tz,count,temp);-break;-caseTHERMAL_TRIP_PASSIVE:-if(temp>=trip_temp||tz->passive)-thermal_zone_trip_update(tz,count,temp);-break;-}-}--if(tz->forced_passive)-thermal_zone_trip_update(tz,THERMAL_TRIPS_NONE,temp);-thermal_zone_do_update(tz);--leave:-if(tz->passive)-thermal_zone_device_set_polling(tz,tz->passive_delay);-elseif(tz->polling_delay)-thermal_zone_device_set_polling(tz,tz->polling_delay);-else-thermal_zone_device_set_polling(tz,0);-mutex_unlock(&tz->lock);-}-EXPORT_SYMBOL(thermal_zone_device_update);-/***create_trip_attrs-createattributesfortrippoints*@tz:thethermalzonedevice
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:28
This patch adds a notification API which the sensor drivers'
can use to notify the framework. The framework then takes
care of the throttling according to the configured policy.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 18 ++++++++++++++++++
include/linux/thermal.h | 1 +
2 files changed, 19 insertions(+)
@@ -112,6 +112,30 @@ temperature) and throttle appropriate devices. trip: indicates which trip point the cooling devices is associated with in this thermal zone.+1.4 Thermal Zone Parameters+1.4.1 struct thermal_bind_params+ This structure defines the following parameters that are used to bind+ a zone with a cooling device for a particular trip point.+ .cdev: The cooling device pointer+ .weight: The 'influence' of a particular cooling device on this zone.+ This is on a percentage scale. The sum of all these weights+ (for a particular zone) cannot exceed 100.+ .trip_mask:This is a bit mask that gives the binding relation between+ this thermal zone and cdev, for a particular trip point.+ If nth bit is set, then the cdev and thermal zone are bound+ for trip point n.+1.4.2 struct thermal_zone_params+ This structure defines the platform level parameters for a thermal zone.+ This data, for each thermal zone should come from the platform layer.+ This is an optional feature where some platforms can choose not to+ provide this data.+ .throttle_policy: One of the throttling policies from enum+ thermal_throttle_policy+ .zone_name: Name of the thermal zone, for which these parameters+ are being defined.+ .num_tbps: Number of thermal_bind_params entries for this zone+ .tbp: thermal_bind_params entries+ 2. sysfs attributes structure RO read only value
@@ -305,3 +329,30 @@ to a thermal_zone_device when it registers itself with the framework. The event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL, THERMAL_DEV_FAULT}. Notification can be sent when the current temperature crosses any of the configured thresholds.++5. Export Symbol APIs:++5.1: get_tz_trend:+This function returns the trend of a thermal zone, i.e the rate of change+of temperature of the thermal zone. Ideally, the thermal sensor drivers+are supposed to implement the callback. If they don't, the thermal+framework calculated the trend by comparing the previous and the current+temperature values.++5.2:get_thermal_instance:+This function returns the thermal_instance corresponding to a given+{thermal_zone, cooling_device, trip_point} combination. Returns NULL+if such an instance does not exist.++5.3:notify_thermal_framework:+This function handles the trip events from sensor drivers. It starts+throttling the cooling devices according to the policy configured.+For CRITICAL and HOT trip points, this notifies the respective drivers,+and does actual throttling for other trip points i.e ACTIVE and PASSIVE.+The throttling policy is based on the configured platform data; if no+platform data is provided, this uses the step_wise throttling policy.++5.4:thermal_cdev_update:+This function serves as an arbitrator to set the state of a cooling+device. It sets the cooling device to the deepest cooling state if+possible.
From: Durgadoss R <hidden> Date: 2012-08-27 04:29:32
This patch shows how can we add platform specific thermal data
required by the thermal framework. This is just an example
patch, and _not_ for merge.
Signed-off-by: Durgadoss R <redacted>
---
arch/x86/platform/mrst/mrst.c | 49 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 03/14] Thermal: Add get trend, get instance API's to
thermal_sys
Importance: High
This patch adds the following API's to thermal_sys.c, that can be used
by other Thermal drivers.
* get_tz_trend: obtain the trend of the given thermal zone
* get_thermal_instance: obtain the instance corresponding
to the given tz, cdev and the trip point.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 40
++++++++++++++++++++++++++++++++++++++++
include/linux/thermal.h | 4 ++++
2 files changed, 44 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 0e71b00..5e141b5 100644
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 04/14] Thermal: Add platform level information to
thermal.h
Importance: High
This patch creates two structures; one to hold bind bind parameters for
a thermal zone, and another to store platform layer data for a thermal
zone, and defines an extern function to retrieve these parameters from
thermal_sys.c. This patch also defines an enum that describes various
policies for thermal throttling.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 3 +++
include/linux/thermal.h | 46
+++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 5e141b5..92a187c 100644
If this function is used by the thermal layer, and provided by the platform thermal driver, why not make it mandatory when registering a thermal zone?
Say,
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ int trips,
+ int mask,
+ struct thermal_zone_device_ops *ops;
+ enum thermal_throttle_policy throttle_policy;
+ int num_tbps; /* Number of tbp entries */
+ struct thermal_bind_params *tbp;
};
And modify thermal_zone_device_register to
Struct thermal_zone_device *thermal_zone_device_register(const char *type, struct thermal_zone_params *params);
The first 3 fields are necessary for registering a zone, the thermal_bind_params can either be filled by platform thermal driver, or be NULL and filled by thermal layer later, when user invokes thermal_zone_bind_cooling_devices.
In this way, we do not need this API at all.
Thanks,
rui
quoted hunk
static int get_idr(struct idr *idr, struct mutex *lock, int *id) {
int err;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index
@@ -67,6 +67,12 @@ enum thermal_trend {THERMAL_TREND_DROPPING,/* temperature is dropping */};+enumthermal_throttle_policy{+THERMAL_USER_SPACE,+THERMAL_FAIR_SHARE,+THERMAL_STEP_WISE,+};+/* Events supported by Thermal Netlink */enumevents{THERMAL_AUX0,
@@ -162,6 +168,37 @@ struct thermal_zone_device {structmutexlock;/* protect thermal_instances list */structlist_headnode;structdelayed_workpoll_queue;+structthermal_zone_params*tzp;+};++/* Structure that holds binding parameters for a zone */struct+thermal_bind_params{+structthermal_cooling_device*cdev;++/*+*Thisisameasureof'howeffectivelythesedevicescan+*cool'this'thermalzone.Theshallbedeterminedbyplatform+*characterization.Thisisona'percentage'scale.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+intweight;++/*+*Thisisabitmaskthatgivesthebindingrelationbetween
this
+ * thermal zone and cdev, for a particular trip point.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int trip_mask;
+ int (*match) (struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev); };
You should start a new line here.
+
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ const char *zone_name;
What is this zone_name used for?
quoted hunk
+ enum thermal_throttle_policy throttle_policy;
+ int num_tbps; /* Number of tbp entries */
+ struct thermal_bind_params *tbp;
};
struct thermal_genl_event {
thermal_cooling_device *); int get_tz_trend(struct thermal_zone_device
*, int); struct thermal_instance *get_thermal_instance(struct
thermal_zone_device *,
struct thermal_cooling_device *, int);
+/*
+ * The platform layer shall define a 'function' that provides the
+ * parameters for all thermal zones in the platform. This pointer
+ * should point to that 'function'.
+ *
+ * In thermal_zone_device_register() we update the parameters
+ * for the particular thermal zone.
+ */
+extern int (*get_platform_thermal_params)(struct thermal_zone_device
+*);
#ifdef CONFIG_NET
extern int thermal_generate_netlink_event(u32 orig, enum events event);
--
1.7.9.5
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 05/14] Thermal: Obtain platform data for thermal zone
Importance: High
This patch retrieves the platform level data for a zone during its
registration. It is not an error to not have any platform data.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 92a187c..6adda39 100644
thermal_zone_device *tz)
kfree(tz->trip_hyst_attrs);
}
+static int retrieve_zone_params(struct thermal_zone_device *tz) {
+ int ret;
+
+ /* Check whether the platform data pointer is defined */
+ if (!get_platform_thermal_params)
+ return 0;
+
+ /* It is not an error to not have any platform data */
+ ret = get_platform_thermal_params(tz);
+ if (ret)
+ tz->tzp = NULL;
+
+ return 0;
+}
+
/**
* thermal_zone_device_register - register a new thermal zone device
* @type: the thermal zone device type
@@ -1443,6 +1459,11 @@ struct thermal_zone_device
*thermal_zone_device_register(const char *type,
if (result)
goto unregister;
+ /* Retrieve platform level parameters for this zone */
+ result = retrieve_zone_params(tz);
+ if (result)
+ goto unregister;
+
As I said, if we need it, we should ask user to provide it during registration. What do you think?
Thanks,
rui
mutex_lock(&thermal_list_lock);
list_add_tail(&tz->node, &thermal_tz_list);
if (ops->bind)
--
1.7.9.5
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 06/14] Thermal: Add a policy sysfs attribute
Importance: High
This patch adds a policy sysfs attribute to a thermal zone.
This attribute will give us the throttling policy used for the zone.
This is a RO attribute.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 6adda39..8aa4200a6 100644
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
What does this mean?
We will not create "policy" attributes if there is no thermal_zone_params?
What if platform thermal drivers chooses to provide .bind() and invoke thermal_zone_bind_cooling_device manually?
Thanks,
rui
If this function is used by the thermal layer, and provided by the platform
thermal driver, why not make it mandatory when registering a thermal zone?
Say,
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ int trips,
+ int mask,
+ struct thermal_zone_device_ops *ops;
+ enum thermal_throttle_policy throttle_policy;
+ int num_tbps; /* Number of tbp entries */
+ struct thermal_bind_params *tbp;
};
And modify thermal_zone_device_register to
Struct thermal_zone_device *thermal_zone_device_register(const char
*type, struct thermal_zone_params *params);
The first 3 fields are necessary for registering a zone, the
thermal_bind_params can either be filled by platform thermal driver, or be
NULL and filled by thermal layer later, when user invokes
thermal_zone_bind_cooling_devices.
In this way, we do not need this API at all.
We can do it either ways. In this case, we need to modify all the tzd_register
calls. If we are Ok doing that, I am happy to change.
Just that we are adding one more to the already existing 7 args :-)
quoted
static int get_idr(struct idr *idr, struct mutex *lock, int *id) {
int err;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index
@@ -67,6 +67,12 @@ enum thermal_trend {THERMAL_TREND_DROPPING,/* temperature is dropping */};+enumthermal_throttle_policy{+THERMAL_USER_SPACE,+THERMAL_FAIR_SHARE,+THERMAL_STEP_WISE,+};+/* Events supported by Thermal Netlink */enumevents{THERMAL_AUX0,
@@ -162,6 +168,37 @@ struct thermal_zone_device {structmutexlock;/* protect thermal_instances list */structlist_headnode;structdelayed_workpoll_queue;+structthermal_zone_params*tzp;+};++/* Structure that holds binding parameters for a zone */struct+thermal_bind_params{+structthermal_cooling_device*cdev;++/*+*Thisisameasureof'howeffectivelythesedevicescan+*cool'this'thermalzone.Theshallbedeterminedbyplatform+*characterization.Thisisona'percentage'scale.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+intweight;++/*+*Thisisabitmaskthatgivesthebindingrelationbetween
this
+ * thermal zone and cdev, for a particular trip point.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int trip_mask;
+ int (*match) (struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev); };
You should start a new line here.
Again, not sure what you meant here. The new line is already there.
quoted
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ const char *zone_name;
What is this zone_name used for?
This is required when we retrieve platform data from framework layer.
Now, that we make it as an argument in tzd_register, we don't need this.
Thanks,
Durga
/**
* thermal_zone_device_register - register a new thermal zone device
* @type: the thermal zone device type
@@ -1443,6 +1459,11 @@ struct thermal_zone_device
*thermal_zone_device_register(const char *type,
if (result)
goto unregister;
+ /* Retrieve platform level parameters for this zone */
+ result = retrieve_zone_params(tz);
+ if (result)
+ goto unregister;
+
As I said, if we need it, we should ask user to provide it during registration.
What do you think?
That's Fine, we can provide it through tzd_register function call.
Thanks,
Durga
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
What does this mean?
We will not create "policy" attributes if there is no thermal_zone_params?
Yes, that's what I thought initially. Because if there is no 'throttle_policy'
we assume that it is (by default) step_wise.
But, if we make tz_params be provided through tzd_register function call,
it makes sense for this to be a mandatory attribute, showing 'step_wise"
if there is no thermal_zone_params.
This needs a clean fix, will make it in v3.
Thanks,
Durga
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 11:47 AM
To: Zhang, Rui; lenb@kernel.org
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
Subject: RE: [PATCHv2 03/14] Thermal: Add get trend, get instance API's
to thermal_sys
Importance: High
Hi Rui,
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 11:57 AM
To: Zhang, Rui; lenb@kernel.org
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
Subject: RE: [PATCHv2 04/14] Thermal: Add platform level information to
thermal.h
Importance: High
Hi Rui,
[cut.]
If this function is used by the thermal layer, and provided by the
platform thermal driver, why not make it mandatory when registering a
thermal zone?
quoted
Say,
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ int trips,
+ int mask,
+ struct thermal_zone_device_ops *ops;
+ enum thermal_throttle_policy throttle_policy;
+ int num_tbps; /* Number of tbp entries */
+ struct thermal_bind_params *tbp;
};
And modify thermal_zone_device_register to Struct thermal_zone_device
*thermal_zone_device_register(const char *type, struct
thermal_zone_params *params);
The first 3 fields are necessary for registering a zone, the
thermal_bind_params can either be filled by platform thermal driver,
or be NULL and filled by thermal layer later, when user invokes
thermal_zone_bind_cooling_devices.
In this way, we do not need this API at all.
We can do it either ways. In this case, we need to modify all the
tzd_register calls. If we are Ok doing that, I am happy to change.
Just that we are adding one more to the already existing 7 args :-)
No, we are trying to reducing the args by moving them into thermal_zone_params.
quoted
quoted
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
@@ -67,6 +67,12 @@ enum thermal_trend {THERMAL_TREND_DROPPING,/* temperature is dropping */};+enumthermal_throttle_policy{+THERMAL_USER_SPACE,+THERMAL_FAIR_SHARE,+THERMAL_STEP_WISE,+};+/* Events supported by Thermal Netlink */enumevents{THERMAL_AUX0,
@@ -162,6 +168,37 @@ struct thermal_zone_device {structmutexlock;/* protect thermal_instances list */structlist_headnode;structdelayed_workpoll_queue;+structthermal_zone_params*tzp;+};++/* Structure that holds binding parameters for a zone */struct+thermal_bind_params{+structthermal_cooling_device*cdev;++/*+*Thisisameasureof'howeffectivelythesedevicescan+*cool'this'thermalzone.Theshallbedeterminedbyplatform+*characterization.Thisisona'percentage'scale.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+intweight;++/*+*Thisisabitmaskthatgivesthebindingrelationbetween
this
+ * thermal zone and cdev, for a particular trip point.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int trip_mask;
+ int (*match) (struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev); };
You should start a new line here.
Again, not sure what you meant here. The new line is already there.
struct thermal_cooling_device *cdev);
};
I'm not sure what it is in your original patch, but I see something like
"struct thermal_cooling_device *cdev); };"
May be this is because I'm using outlook?
thanks,
rui
quoted
quoted
+/* Structure to define Thermal Zone parameters */ struct
+thermal_zone_params {
+ const char *zone_name;
What is this zone_name used for?
This is required when we retrieve platform data from framework layer.
Now, that we make it as an argument in tzd_register, we don't need this.
Thanks,
Durga
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
What does this mean?
We will not create "policy" attributes if there is no
thermal_zone_params?
Yes, that's what I thought initially. Because if there is no
'throttle_policy'
we assume that it is (by default) step_wise.
But, if we make tz_params be provided through tzd_register function
call, it makes sense for this to be a mandatory attribute, showing
'step_wise"
if there is no thermal_zone_params.
IMO, every thermal zone should have a policy. And they can be changed anytime if user wants to.
Thanks,
rui
*thermal_zone_device_register(const char *type, struct
thermal_zone_params *params);
The first 3 fields are necessary for registering a zone, the
thermal_bind_params can either be filled by platform thermal driver,
or be NULL and filled by thermal layer later, when user invokes
thermal_zone_bind_cooling_devices.
In this way, we do not need this API at all.
We can do it either ways. In this case, we need to modify all the
tzd_register calls. If we are Ok doing that, I am happy to change.
Just that we are adding one more to the already existing 7 args :-)
No, we are trying to reducing the args by moving them into
thermal_zone_params.
quoted
quoted
quoted
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
@@ -67,6 +67,12 @@ enum thermal_trend {THERMAL_TREND_DROPPING,/* temperature is dropping */};+enumthermal_throttle_policy{+THERMAL_USER_SPACE,+THERMAL_FAIR_SHARE,+THERMAL_STEP_WISE,+};+/* Events supported by Thermal Netlink */enumevents{THERMAL_AUX0,
@@ -162,6 +168,37 @@ struct thermal_zone_device {structmutexlock;/* protect thermal_instances list */structlist_headnode;structdelayed_workpoll_queue;+structthermal_zone_params*tzp;+};++/* Structure that holds binding parameters for a zone */struct+thermal_bind_params{+structthermal_cooling_device*cdev;++/*+*Thisisameasureof'howeffectivelythesedevicescan+*cool'this'thermalzone.Theshallbedeterminedbyplatform+*characterization.Thisisona'percentage'scale.+*SeeDocumentation/thermal/sysfs-api.txtformoreinformation.+*/+intweight;++/*+*Thisisabitmaskthatgivesthebindingrelationbetween
this
+ * thermal zone and cdev, for a particular trip point.
+ * See Documentation/thermal/sysfs-api.txt for more information.
+ */
+ int trip_mask;
+ int (*match) (struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev); };
You should start a new line here.
Again, not sure what you meant here. The new line is already there.
struct thermal_cooling_device *cdev);
};
I'm not sure what it is in your original patch, but I see something like
"struct thermal_cooling_device *cdev); };"
May be this is because I'm using outlook?
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 06/14] Thermal: Add a policy sysfs attribute
Importance: High
This patch adds a policy sysfs attribute to a thermal zone.
This attribute will give us the throttling policy used for the zone.
This is a RO attribute.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 6adda39..8aa4200a6 100644
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
/**
We should remove this attribute in thermal_zone_device_unregister();
Thanks.
rui
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 7:28 AM
To: lenb@kernel.org; Zhang, Rui
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com; R, Durgadoss
Subject: [PATCHv2 07/14] Thermal: Update binding logic based on
platform data
Importance: High
This patch updates the binding logic in thermal_sys.c It uses the
platform layer data to bind a thermal zone to a cdev for a particular
trip point.
* If we do not have platform data and do not have
.bind defined, do not bind.
* If we do not have platform data but .bind is
defined, then use tz->ops->bind.
* If we have platform data, use it to create binding.
The same logic sequence is followed for unbind also.
Signed-off-by: Durgadoss R <redacted>
---
drivers/thermal/thermal_sys.c | 184
+++++++++++++++++++++++++++++++++++------
1 file changed, 158 insertions(+), 26 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c
b/drivers/thermal/thermal_sys.c index 8aa4200a6..5d38501 100644
*get_thermal_instance(struct thermal_zone_device *tz, }
EXPORT_SYMBOL(get_thermal_instance);
+static void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret) {
+ dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+ tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev) {
+ int i, ret;
+
+ for (i = 0; i < tz->trips; i++) {
+ if (mask & (1 << i)) {
+ ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+ THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+ if (ret)
+ print_bind_err_msg(tz, cdev, ret);
+ }
+ }
+}
+
+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev) {
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev); }
+
+static void update_bind_info(struct thermal_cooling_device *cdev) {
I do not think this function name is accurate.
Update_bind_info is called when a new cooling device comes
and do_binding is called when a new zone is registered, right?
I think we should reflect this in the function name.
Maybe something like this:
Int do_bind(tz, cdev) {
If (tz->ops->bind)
Tz->ops->bind(tz, cdev);
Else {
Blabla
...
}
}
Bind_cdev(cdev) {
List_for_each_entry(tz, thermal_tz_list) {
Do_bind(tz, cdev);
}
}
Bind_tz(tz) {
List_for_each_entry(cdev, thermal_cdev_list) {
Do_bind(tz, cdev);
}
}
Thanks,
rui
quoted hunk
+ int i, ret;
+ struct thermal_zone_params *tzp;
+ struct thermal_zone_device *pos = NULL;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!pos->tzp && !pos->ops->bind)
+ continue;
+
+ if (!pos->tzp && pos->ops->bind) {
+ ret = pos->ops->bind(pos, cdev);
+ if (ret)
+ print_bind_err_msg(pos, cdev, ret);
+ }
+
+ tzp = pos->tzp;
+ if (!tzp->tbp)
+ return;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(pos, cdev))
+ continue;
+ tzp->tbp[i].cdev = cdev;
+ __bind(pos, tzp->tbp[i].trip_mask, cdev);
+ }
+ }
+
+ mutex_unlock(&thermal_list_lock);
+}
+
+static void do_binding(struct thermal_zone_device *tz) {
+ int i, ret;
+ struct thermal_cooling_device *pos = NULL;
+ struct thermal_zone_params *tzp = tz->tzp;
+
+ if (!tzp && !tz->ops->bind)
+ return;
+
+ mutex_lock(&thermal_list_lock);
+
+ /* If there is no platform data, try to use ops->bind */
+ if (!tzp && tz->ops->bind) {
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ ret = tz->ops->bind(tz, pos);
+ if (ret)
+ print_bind_err_msg(tz, pos, ret);
+ }
+ goto exit;
+ }
+
+ if (!tzp->tbp)
+ goto exit;
+
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(tz, pos))
+ continue;
+ tzp->tbp[i].cdev = pos;
+ __bind(tz, tzp->tbp[i].trip_mask, pos);
+ }
+ }
+exit:
+ mutex_unlock(&thermal_list_lock);
+}
+
/* sys I/F for thermal zone */
#define to_thermal_zone(_dev) \
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
What does this mean?
We will not create "policy" attributes if there is no
thermal_zone_params?
Yes, that's what I thought initially. Because if there is no
'throttle_policy'
we assume that it is (by default) step_wise.
But, if we make tz_params be provided through tzd_register function
call, it makes sense for this to be a mandatory attribute, showing
'step_wise"
if there is no thermal_zone_params.
IMO, every thermal zone should have a policy. And they can be changed
anytime if user wants to.
Agree with you on the first part. Not sure if we want this to be writable.
Thanks,
Durga
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device, &dev_attr_throttle_policy);
+ if (ret)
+ dev_err(&tz->device, "creating policy attr failed:%d\n",
ret);
+
+ return ret;
}
/**
We should remove this attribute in thermal_zone_device_unregister();
Oh yes, missed it :-(
Will fix in v3..
Thanks for the catch,
Durga
+
+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev) {
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev); }
+
+static void update_bind_info(struct thermal_cooling_device *cdev) {
I do not think this function name is accurate.
Update_bind_info is called when a new cooling device comes
and do_binding is called when a new zone is registered, right?
I think we should reflect this in the function name.
Maybe something like this:
Int do_bind(tz, cdev) {
If (tz->ops->bind)
Tz->ops->bind(tz, cdev);
Else {
Blabla
...
}
}
Bind_cdev(cdev) {
List_for_each_entry(tz, thermal_tz_list) {
Do_bind(tz, cdev);
}
}
Bind_tz(tz) {
List_for_each_entry(cdev, thermal_cdev_list) {
Do_bind(tz, cdev);
}
}
Will see how I can rename/make this patch cleaner..
Thanks,
Durga
-----Original Message-----
From: R, Durgadoss
Sent: Monday, August 27, 2012 1:24 PM
To: Zhang, Rui; lenb@kernel.org
Cc: linux-acpi@vger.kernel.org; eduardo.valentin@ti.com
Subject: RE: [PATCHv2 06/14] Thermal: Add a policy sysfs attribute
Importance: High
quoted
quoted
quoted
quoted
#define to_cooling_device(_dev) \
@@ -1349,10 +1371,16 @@ static int retrieve_zone_params(struct
thermal_zone_device *tz)
/* It is not an error to not have any platform data */
ret = get_platform_thermal_params(tz);
- if (ret)
+ if (ret) {
tz->tzp = NULL;
+ return 0;
+ }
- return 0;
+ ret = device_create_file(&tz->device,
&dev_attr_throttle_policy);
quoted
quoted
quoted
quoted
+ if (ret)
+ dev_err(&tz->device, "creating policy attr
failed:%d\n",
quoted
quoted
quoted
quoted
ret);
+
+ return ret;
}
What does this mean?
We will not create "policy" attributes if there is no
thermal_zone_params?
Yes, that's what I thought initially. Because if there is no
'throttle_policy'
we assume that it is (by default) step_wise.
But, if we make tz_params be provided through tzd_register function
call, it makes sense for this to be a mandatory attribute, showing
'step_wise"
if there is no thermal_zone_params.
IMO, every thermal zone should have a policy. And they can be changed
anytime if user wants to.
Agree with you on the first part. Not sure if we want this to be
writable.
Say, what if a user space application is loaded and want to take control of the thermal management from kernel?
It should set the policy to "userspace" to stop the kernel actions first.
BTW, just like the cpufreq governors, they can be changed any time.