diff mbox

[07/13] Thermal: Update binding logic based on platform data

Message ID 1344516365-7230-8-git-send-email-durgadoss.r@intel.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

durgadoss.r@intel.com Aug. 9, 2012, 12:45 p.m. UTC
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 <durgadoss.r@intel.com>
---
 drivers/thermal/thermal_sys.c |  170 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 144 insertions(+), 26 deletions(-)

Comments

Zhang Rui Aug. 13, 2012, 6:41 a.m. UTC | #1
On ?, 2012-08-09 at 18:15 +0530, Durgadoss R wrote:
> 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 <durgadoss.r@intel.com>
> ---
>  drivers/thermal/thermal_sys.c |  170 ++++++++++++++++++++++++++++++++++-------
>  1 file changed, 144 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> index 195e529..748b12f 100644
> --- a/drivers/thermal/thermal_sys.c
> +++ b/drivers/thermal/thermal_sys.c
> @@ -158,6 +158,107 @@ static void retrieve_zone_params(struct thermal_zone_device *tz)
>  	}
>  }
>  
> +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)
> +{
> +	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;
> +		for (i = 0; i < tzp->num_cdevs; i++) {
> +			if (!strcmp(tzp->cdevs_name[i], cdev->type)) {
> +				__bind(pos, tzp->trip_mask[i], cdev);
> +				break;
> +			}
> +		}
> +	}
> +	mutex_unlock(&thermal_list_lock);
> +}

I still do not understand why we need this kind of bind.
Say, the platform thermal driver knows the platform data, i.e. it knows
which cooling devices should be bound to which trip points.
why we can not move this kind of logic to the .bind() callback, offered
by the platform thermal driver?
say, in .bind() callback,
the platform thermal driver has the pointer of the platform data, right?
the .cdev parameter can be used to find the cooling device name,
and we can make the comparison there. instead of introducing new binding
functions in the generic thermal layer.

> +
> +static void do_binding(struct thermal_zone_device *tz)
> +{
> +	int i, ret;
> +	char *name;
> +	struct thermal_cooling_device *pos = NULL;
> +	struct thermal_zone_params *tzp = tz->tzp;
> +
> +	if (!tzp && !tz->ops->bind)
> +		return;
> +
> +	/* If there is no platform data, try to use ops->bind */
> +	if (!tzp && tz->ops->bind) {
> +		mutex_lock(&thermal_list_lock);
> +
> +		list_for_each_entry(pos, &thermal_cdev_list, node) {
> +			ret = tz->ops->bind(tz, pos);
> +			if (ret)
> +				print_bind_err_msg(tz, pos, ret);
> +		}
> +
> +		mutex_unlock(&thermal_list_lock);
> +		return;
> +	}
> +
> +	/* If platform data is available, use it to create binding */
> +	for (i = 0; i < tzp->num_cdevs; i++) {
> +		name = tzp->cdevs_name[i];
> +		pos = get_cdev_by_name(name);
> +
> +		if (!pos) {
> +			dev_err(&tz->device, "cannot find cdev %s\n", name);
> +			continue;
> +		}
> +
> +		mutex_lock(&thermal_list_lock);
> +		__bind(tz, tzp->trip_mask[i], pos);
> +		mutex_unlock(&thermal_list_lock);
> +	}
> +}
> +
>  /* sys I/F for thermal zone */
>  
>  #define to_thermal_zone(_dev) \
> @@ -975,7 +1076,6 @@ thermal_cooling_device_register(char *type, void *devdata,
>  				const struct thermal_cooling_device_ops *ops)
>  {
>  	struct thermal_cooling_device *cdev;
> -	struct thermal_zone_device *pos;
>  	int result;
>  
>  	if (strlen(type) >= THERMAL_NAME_LENGTH)
> @@ -1025,20 +1125,15 @@ thermal_cooling_device_register(char *type, void *devdata,
>  	if (result)
>  		goto unregister;
>  
> +	/* 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)
> -		return cdev;
> +	/* Update binding information for 'this' new cdev */
> +	update_bind_info(cdev);
> +
> +	return cdev;
>  
>  unregister:
>  	release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
> @@ -1054,10 +1149,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register);
>   * thermal_cooling_device_unregister() must be called when the device is no
>   * longer needed.
>   */
> -void thermal_cooling_device_unregister(struct
> -				       thermal_cooling_device
> -				       *cdev)
> +void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
>  {
> +	int i;
> +	struct thermal_zone_params *tzp;
>  	struct thermal_zone_device *tz;
>  	struct thermal_cooling_device *pos = NULL;
>  
> @@ -1074,12 +1169,23 @@ void thermal_cooling_device_unregister(struct
>  		return;
>  	}
>  	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)
> +		tzp = tz->tzp;
> +		if (!tzp && !tz->ops->unbind)
>  			continue;
> -		tz->ops->unbind(tz, cdev);
> +
> +		if (!tzp && tz->ops->unbind)
> +			tz->ops->unbind(tz, cdev);
> +
> +		for (i = 0; i < tzp->num_cdevs; i++)
> +			if (!strcmp(cdev->type, tzp->cdevs_name[i]))
> +				__unbind(tz, tzp->trip_mask[i], cdev);
>  	}
> +
>  	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);
> @@ -1424,7 +1530,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
>  	int passive_delay, int polling_delay)
>  {
>  	struct thermal_zone_device *tz;
> -	struct thermal_cooling_device *pos;
>  	enum thermal_trip_type trip_type;
>  	int result;
>  	int count;
> @@ -1519,14 +1624,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
>  
>  	mutex_lock(&thermal_list_lock);
>  	list_add_tail(&tz->node, &thermal_tz_list);
> -	if (ops->bind)
> -		list_for_each_entry(pos, &thermal_cdev_list, node) {
> -		result = ops->bind(tz, pos);
> -		if (result)
> -			break;
> -		}
>  	mutex_unlock(&thermal_list_lock);
>  
> +	/* Bind cooling devices for this zone */
> +	do_binding(tz);
> +
> +
>  	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
>  
>  	thermal_zone_device_update(tz);
> @@ -1547,12 +1650,16 @@ EXPORT_SYMBOL(thermal_zone_device_register);
>   */
>  void thermal_zone_device_unregister(struct thermal_zone_device *tz)
>  {
> +	int i;
> +	struct thermal_zone_params *tzp;
>  	struct thermal_cooling_device *cdev;
>  	struct thermal_zone_device *pos = NULL;
>  
>  	if (!tz)
>  		return;
>  
> +	tzp = tz->tzp;
> +
>  	mutex_lock(&thermal_list_lock);
>  	list_for_each_entry(pos, &thermal_tz_list, node)
>  	    if (pos == tz)
> @@ -1563,9 +1670,20 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
>  		return;
>  	}
>  	list_del(&tz->node);
> -	if (tz->ops->unbind)
> -		list_for_each_entry(cdev, &thermal_cdev_list, node)
> -		    tz->ops->unbind(tz, cdev);
> +
> +	/* Unbind all cdevs associated with 'this' thermal zone */
> +	list_for_each_entry(cdev, &thermal_cdev_list, node) {
> +		if (!tzp && !tz->ops->unbind)
> +			break;
> +
> +		if (!tzp && tz->ops->unbind)
> +			tz->ops->unbind(tz, cdev);
> +
> +		for (i = 0; i < tzp->num_cdevs; i++)
> +			if (!strcmp(cdev->type, tzp->cdevs_name[i]))
> +				__unbind(tz, tzp->trip_mask[i], cdev);
> +	}
> +
>  	mutex_unlock(&thermal_list_lock);
>  
>  	thermal_zone_device_set_polling(tz, 0);


--
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
durgadoss.r@intel.com Aug. 13, 2012, 3:41 p.m. UTC | #2
Hi Rui,

> -----Original Message-----

> From: Zhang, Rui

> Sent: Monday, August 13, 2012 12:11 PM

> To: R, Durgadoss

> Cc: lenb@kernel.org; rjw@sisk.pl; linux-acpi@vger.kernel.org; linux-

> pm@vger.kernel.org; eduardo.valentin@ti.com; amit.kachhap@linaro.org;

> wni@nvidia.com

> Subject: Re: [PATCH 07/13] Thermal: Update binding logic based on platform data

> 

> On ?, 2012-08-09 at 18:15 +0530, Durgadoss R wrote:

> > 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 <durgadoss.r@intel.com>

> > ---

> >  drivers/thermal/thermal_sys.c |  170

> ++++++++++++++++++++++++++++++++++-------

> >  1 file changed, 144 insertions(+), 26 deletions(-)

> >

> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c

> > index 195e529..748b12f 100644

> > --- a/drivers/thermal/thermal_sys.c

> > +++ b/drivers/thermal/thermal_sys.c

> > @@ -158,6 +158,107 @@ static void retrieve_zone_params(struct

> thermal_zone_device *tz)

> >  	}

> >  }

> >

> > +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)

> > +{

> > +	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;

> > +		for (i = 0; i < tzp->num_cdevs; i++) {

> > +			if (!strcmp(tzp->cdevs_name[i], cdev->type)) {

> > +				__bind(pos, tzp->trip_mask[i], cdev);

> > +				break;

> > +			}

> > +		}

> > +	}

> > +	mutex_unlock(&thermal_list_lock);

> > +}

> 

> I still do not understand why we need this kind of bind.

> Say, the platform thermal driver knows the platform data, i.e. it knows

> which cooling devices should be bound to which trip points.

> why we can not move this kind of logic to the .bind() callback, offered

> by the platform thermal driver?

> say, in .bind() callback,

> the platform thermal driver has the pointer of the platform data, right?

> the .cdev parameter can be used to find the cooling device name,

> and we can make the comparison there. instead of introducing new binding

> functions in the generic thermal layer.


For once, I got little confused between the generic platform thermal sensor
drivers (the chip drivers) and the platform level driver (not specific for chip,
but for a platform). So, yes we can put this in the platform level driver.

On the other hand, I believe we will have more and more platform thermal
drivers, as new devices arrive. And in each of the drivers, we are going to
do the 'looping, finding cdev and then binding' part. I was wondering wouldn't
it be better to move the common code to the framework, so that the same
code does not get duplicated, over several places.

So, please give a second thought on this and let me know your opinion.

Thanks,
Durga
Zhang Rui Aug. 15, 2012, 6:53 a.m. UTC | #3
On ?, 2012-08-13 at 09:41 -0600, R, Durgadoss wrote:
> Hi Rui,
> 
> > -----Original Message-----
> > From: Zhang, Rui
> > Sent: Monday, August 13, 2012 12:11 PM
> > To: R, Durgadoss
> > Cc: lenb@kernel.org; rjw@sisk.pl; linux-acpi@vger.kernel.org; linux-
> > pm@vger.kernel.org; eduardo.valentin@ti.com; amit.kachhap@linaro.org;
> > wni@nvidia.com
> > Subject: Re: [PATCH 07/13] Thermal: Update binding logic based on platform data
> > 
> > On ?, 2012-08-09 at 18:15 +0530, Durgadoss R wrote:
> > > 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 <durgadoss.r@intel.com>
> > > ---
> > >  drivers/thermal/thermal_sys.c |  170
> > ++++++++++++++++++++++++++++++++++-------
> > >  1 file changed, 144 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > > index 195e529..748b12f 100644
> > > --- a/drivers/thermal/thermal_sys.c
> > > +++ b/drivers/thermal/thermal_sys.c
> > > @@ -158,6 +158,107 @@ static void retrieve_zone_params(struct
> > thermal_zone_device *tz)
> > >  	}
> > >  }
> > >
> > > +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)
> > > +{
> > > +	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;
> > > +		for (i = 0; i < tzp->num_cdevs; i++) {
> > > +			if (!strcmp(tzp->cdevs_name[i], cdev->type)) {
> > > +				__bind(pos, tzp->trip_mask[i], cdev);
> > > +				break;
> > > +			}
> > > +		}
> > > +	}
> > > +	mutex_unlock(&thermal_list_lock);
> > > +}
> > 
> > I still do not understand why we need this kind of bind.
> > Say, the platform thermal driver knows the platform data, i.e. it knows
> > which cooling devices should be bound to which trip points.
> > why we can not move this kind of logic to the .bind() callback, offered
> > by the platform thermal driver?
> > say, in .bind() callback,
> > the platform thermal driver has the pointer of the platform data, right?
> > the .cdev parameter can be used to find the cooling device name,
> > and we can make the comparison there. instead of introducing new binding
> > functions in the generic thermal layer.
> 
> For once, I got little confused between the generic platform thermal sensor
> drivers (the chip drivers) and the platform level driver (not specific for chip,
> but for a platform). So, yes we can put this in the platform level driver.
> 
Hmm,
I'm not clear about the difference between these two drivers.
what is supposed to be done in the platform thermal sensor drivers and
what is supposed to be done in the platform level driver?

At least for now, all the thermal drivers are both thermal sensor driver
and platform level driver, right?

thanks,
rui
> On the other hand, I believe we will have more and more platform thermal
> drivers, as new devices arrive. And in each of the drivers, we are going to
> do the 'looping, finding cdev and then binding' part. I was wondering wouldn't
> it be better to move the common code to the framework, so that the same
> code does not get duplicated, over several places.
> 
> 
> 
> So, please give a second thought on this and let me know your opinion.

> Thanks,
> Durga


--
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
durgadoss.r@intel.com Aug. 15, 2012, 9:17 a.m. UTC | #4
SGkgUnVpLA0KDQo+ID4gPiA+ICtzdGF0aWMgdm9pZCB1cGRhdGVfYmluZF9pbmZvKHN0cnVjdCB0
aGVybWFsX2Nvb2xpbmdfZGV2aWNlICpjZGV2KQ0KPiA+ID4gPiArew0KPiA+ID4gPiArCWludCBp
LCByZXQ7DQo+ID4gPiA+ICsJc3RydWN0IHRoZXJtYWxfem9uZV9wYXJhbXMgKnR6cDsNCj4gPiA+
ID4gKwlzdHJ1Y3QgdGhlcm1hbF96b25lX2RldmljZSAqcG9zID0gTlVMTDsNCj4gPiA+ID4gKw0K
PiA+ID4gPiArCW11dGV4X2xvY2soJnRoZXJtYWxfbGlzdF9sb2NrKTsNCj4gPiA+ID4gKw0KPiA+
ID4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnkocG9zLCAmdGhlcm1hbF90el9saXN0LCBub2RlKSB7
DQo+ID4gPiA+ICsJCWlmICghcG9zLT50enAgJiYgIXBvcy0+b3BzLT5iaW5kKQ0KPiA+ID4gPiAr
CQkJY29udGludWU7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwkJaWYgKCFwb3MtPnR6cCAmJiBwb3Mt
Pm9wcy0+YmluZCkgew0KPiA+ID4gPiArCQkJcmV0ID0gcG9zLT5vcHMtPmJpbmQocG9zLCBjZGV2
KTsNCj4gPiA+ID4gKwkJCWlmIChyZXQpDQo+ID4gPiA+ICsJCQkJcHJpbnRfYmluZF9lcnJfbXNn
KHBvcywgY2RldiwgcmV0KTsNCj4gPiA+ID4gKwkJfQ0KPiA+ID4gPiArDQo+ID4gPiA+ICsJCXR6
cCA9IHBvcy0+dHpwOw0KPiA+ID4gPiArCQlmb3IgKGkgPSAwOyBpIDwgdHpwLT5udW1fY2RldnM7
IGkrKykgew0KPiA+ID4gPiArCQkJaWYgKCFzdHJjbXAodHpwLT5jZGV2c19uYW1lW2ldLCBjZGV2
LT50eXBlKSkgew0KPiA+ID4gPiArCQkJCV9fYmluZChwb3MsIHR6cC0+dHJpcF9tYXNrW2ldLCBj
ZGV2KTsNCj4gPiA+ID4gKwkJCQlicmVhazsNCj4gPiA+ID4gKwkJCX0NCj4gPiA+ID4gKwkJfQ0K
PiA+ID4gPiArCX0NCj4gPiA+ID4gKwltdXRleF91bmxvY2soJnRoZXJtYWxfbGlzdF9sb2NrKTsN
Cj4gPiA+ID4gK30NCj4gPiA+DQo+ID4gPiBJIHN0aWxsIGRvIG5vdCB1bmRlcnN0YW5kIHdoeSB3
ZSBuZWVkIHRoaXMga2luZCBvZiBiaW5kLg0KPiA+ID4gU2F5LCB0aGUgcGxhdGZvcm0gdGhlcm1h
bCBkcml2ZXIga25vd3MgdGhlIHBsYXRmb3JtIGRhdGEsIGkuZS4gaXQga25vd3MNCj4gPiA+IHdo
aWNoIGNvb2xpbmcgZGV2aWNlcyBzaG91bGQgYmUgYm91bmQgdG8gd2hpY2ggdHJpcCBwb2ludHMu
DQo+ID4gPiB3aHkgd2UgY2FuIG5vdCBtb3ZlIHRoaXMga2luZCBvZiBsb2dpYyB0byB0aGUgLmJp
bmQoKSBjYWxsYmFjaywgb2ZmZXJlZA0KPiA+ID4gYnkgdGhlIHBsYXRmb3JtIHRoZXJtYWwgZHJp
dmVyPw0KPiA+ID4gc2F5LCBpbiAuYmluZCgpIGNhbGxiYWNrLA0KPiA+ID4gdGhlIHBsYXRmb3Jt
IHRoZXJtYWwgZHJpdmVyIGhhcyB0aGUgcG9pbnRlciBvZiB0aGUgcGxhdGZvcm0gZGF0YSwgcmln
aHQ/DQo+ID4gPiB0aGUgLmNkZXYgcGFyYW1ldGVyIGNhbiBiZSB1c2VkIHRvIGZpbmQgdGhlIGNv
b2xpbmcgZGV2aWNlIG5hbWUsDQo+ID4gPiBhbmQgd2UgY2FuIG1ha2UgdGhlIGNvbXBhcmlzb24g
dGhlcmUuIGluc3RlYWQgb2YgaW50cm9kdWNpbmcgbmV3IGJpbmRpbmcNCj4gPiA+IGZ1bmN0aW9u
cyBpbiB0aGUgZ2VuZXJpYyB0aGVybWFsIGxheWVyLg0KPiA+DQo+ID4gRm9yIG9uY2UsIEkgZ290
IGxpdHRsZSBjb25mdXNlZCBiZXR3ZWVuIHRoZSBnZW5lcmljIHBsYXRmb3JtIHRoZXJtYWwgc2Vu
c29yDQo+ID4gZHJpdmVycyAodGhlIGNoaXAgZHJpdmVycykgYW5kIHRoZSBwbGF0Zm9ybSBsZXZl
bCBkcml2ZXIgKG5vdCBzcGVjaWZpYyBmb3IgY2hpcCwNCj4gPiBidXQgZm9yIGEgcGxhdGZvcm0p
LiBTbywgeWVzIHdlIGNhbiBwdXQgdGhpcyBpbiB0aGUgcGxhdGZvcm0gbGV2ZWwgZHJpdmVyLg0K
PiA+DQo+IEhtbSwNCj4gSSdtIG5vdCBjbGVhciBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVu
IHRoZXNlIHR3byBkcml2ZXJzLg0KPiB3aGF0IGlzIHN1cHBvc2VkIHRvIGJlIGRvbmUgaW4gdGhl
IHBsYXRmb3JtIHRoZXJtYWwgc2Vuc29yIGRyaXZlcnMgYW5kDQo+IHdoYXQgaXMgc3VwcG9zZWQg
dG8gYmUgZG9uZSBpbiB0aGUgcGxhdGZvcm0gbGV2ZWwgZHJpdmVyPw0KDQpBIHNlbnNvciBkcml2
ZXIgY2FuIGJlIGEgZ2VuZXJpYyBjaGlwIGRyaXZlciBsaWtlIGVtYzE0MDMgKHRoaXMgaXMgdGhl
IG9uZQ0KdGhhdCBJIGhhdmUgd29ya2VkIG9uLi4pIG9yIGNvcmV0ZW1wICh0aGUgQ1BVIERUUyBk
cml2ZXIgZm9yIHg4NikuIFRoZXkgc2l0DQppbiBkaWZmZXJlbnQgc3ViIHN5c3RlbXMgKHRoZXNl
IHR3byBpbiBod21vbikuIFdlIG1pZ2h0IG5vdCBiZSBhbGxvd2VkIHRvDQphZGQgYW55IHRoZXJt
YWwgZnJhbWV3b3JrIHNwZWNpZmljIGNvZGUgaW4gdGhlc2UgZHJpdmVycy4gVGhlIHNhbWUgZHJp
dmVyDQp3b3JrcyBvbiBhbGwgcGxhdGZvcm1zLg0KDQpBIHBsYXRmb3JtIGxldmVsIHRoZXJtYWwg
ZHJpdmVyIGtub3dzIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0aGVybWFsIHNlbnNvcnMsDQphbmQg
dGhlaXIgem9uZXMgb24gdGhlIHBsYXRmb3JtOyBhbmQgaXMgc3BlY2lmaWMgdG8gdGhlIHBsYXRm
b3JtLg0KRm9yIHg4NiwgdGhpcyB3aWxsIGJlIGluIGRyaXZlcnMveDg2L3BsYXRmb3JtLyB3aGVy
ZWFzIG1pZ2h0IGJlIGluIHNvbWUgb3RoZXINCnBsYWNlIGZvciBvdGhlciBhcmNoaXRlY3R1cmVz
LiBBbiBleGFtcGxlIGlzIGludGVsX21pZF90aGVybWFsLmMgd2hpY2ggc2l0cw0KaW4gZHJpdmVy
cy94ODYvcGxhdGZvcm0uIFdlIGNhbiBhZGQgb3VyIHRoZXJtYWwgZnJhbWV3b3JrIHNwZWNpZmlj
IGNvZGUNCnRvIHRoaXMgZHJpdmVyLg0KDQo+IA0KPiBBdCBsZWFzdCBmb3Igbm93LCBhbGwgdGhl
IHRoZXJtYWwgZHJpdmVycyBhcmUgYm90aCB0aGVybWFsIHNlbnNvciBkcml2ZXINCj4gYW5kIHBs
YXRmb3JtIGxldmVsIGRyaXZlciwgcmlnaHQ/DQogDQpOb3QgYWxsIHRoZSB0aW1lcywgYWx0aG91
Z2ggdGhlcmUgYXJlIHNvbWUgaW5zdGFuY2VzIHdoZXJlIGJvdGggYXJlIHNhbWUuDQpXZSB1c2Ug
Y29yZXRlbXAuYyBhbmQgaW50ZWxfbWlkX3RoZXJtYWwuYyAod2hpY2ggYXJlIGRpZmZlcmVudCks
IGZvciB0aGUNCng4NiBtaWQgcGxhdGZvcm1zLg0KDQpJIGhvcGUgdGhpcyBleHBsYW5hdGlvbiBo
ZWxwcyB5b3UuLg0KDQpUaGFua3MsDQpEdXJnYQ0K
--
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. 16, 2012, 3:30 a.m. UTC | #5
On ?, 2012-08-15 at 03:17 -0600, R, Durgadoss wrote:
> Hi Rui,
> 
> > > > > +static void update_bind_info(struct thermal_cooling_device *cdev)
> > > > > +{
> > > > > +	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;
> > > > > +		for (i = 0; i < tzp->num_cdevs; i++) {
> > > > > +			if (!strcmp(tzp->cdevs_name[i], cdev->type)) {
> > > > > +				__bind(pos, tzp->trip_mask[i], cdev);
> > > > > +				break;
> > > > > +			}
> > > > > +		}
> > > > > +	}
> > > > > +	mutex_unlock(&thermal_list_lock);
> > > > > +}
> > > >
> > > > I still do not understand why we need this kind of bind.
> > > > Say, the platform thermal driver knows the platform data, i.e. it knows
> > > > which cooling devices should be bound to which trip points.
> > > > why we can not move this kind of logic to the .bind() callback, offered
> > > > by the platform thermal driver?
> > > > say, in .bind() callback,
> > > > the platform thermal driver has the pointer of the platform data, right?
> > > > the .cdev parameter can be used to find the cooling device name,
> > > > and we can make the comparison there. instead of introducing new binding
> > > > functions in the generic thermal layer.
> > >
> > > For once, I got little confused between the generic platform thermal sensor
> > > drivers (the chip drivers) and the platform level driver (not specific for chip,
> > > but for a platform). So, yes we can put this in the platform level driver.
> > >
> > Hmm,
> > I'm not clear about the difference between these two drivers.
> > what is supposed to be done in the platform thermal sensor drivers and
> > what is supposed to be done in the platform level driver?
> 
> A sensor driver can be a generic chip driver like emc1403 (this is the one
> that I have worked on..) or coretemp (the CPU DTS driver for x86). They sit
> in different sub systems (these two in hwmon). We might not be allowed to
> add any thermal framework specific code in these drivers. The same driver
> works on all platforms.

does the sensor know anything about the "policy"?
Say, does it have any trip points? does it know which device can be
throttled to cool itself?
I think the answer is "no", right?

> 
> A platform level thermal driver knows information about the thermal sensors,
> and their zones on the platform; and is specific to the platform.
> For x86, this will be in drivers/x86/platform/ whereas might be in some other
> place for other architectures. An example is intel_mid_thermal.c which sits
> in drivers/x86/platform. We can add our thermal framework specific code
> to this driver.
> 
but I think intel_mide_thermal driver is also a platform thermal sensor
driver at the same time.

> > 
> > At least for now, all the thermal drivers are both thermal sensor driver
> > and platform level driver, right?
>  
> Not all the times, although there are some instances where both are same.
> We use coretemp.c and intel_mid_thermal.c (which are different), for the
> x86 mid platforms.
> 
so you want to use coretemp.c as a temperature sensor, and then bind
your own cooling devices to it in your platform level thermal driver?

thanks,
rui

--
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
durgadoss.r@intel.com Aug. 16, 2012, 3:31 a.m. UTC | #6
SGkgUnVpLA0KDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogWmhhbmcs
IFJ1aQ0KPiBTZW50OiBUaHVyc2RheSwgQXVndXN0IDE2LCAyMDEyIDk6MDAgQU0NCj4gVG86IFIs
IER1cmdhZG9zcw0KPiBDYzogbGVuYkBrZXJuZWwub3JnOyByandAc2lzay5wbDsgbGludXgtYWNw
aUB2Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LQ0KPiBwbUB2Z2VyLmtlcm5lbC5vcmc7IGVkdWFyZG8u
dmFsZW50aW5AdGkuY29tOyBhbWl0LmthY2hoYXBAbGluYXJvLm9yZzsNCj4gd25pQG52aWRpYS5j
b20NCj4gU3ViamVjdDogUkU6IFtQQVRDSCAwNy8xM10gVGhlcm1hbDogVXBkYXRlIGJpbmRpbmcg
bG9naWMgYmFzZWQgb24gcGxhdGZvcm0NCj4gZGF0YQ0KPiANCj4gT24g5LiJLCAyMDEyLTA4LTE1
IGF0IDAzOjE3IC0wNjAwLCBSLCBEdXJnYWRvc3Mgd3JvdGU6DQo+ID4gSGkgUnVpLA0KPiA+DQo+
ID4gPiA+ID4gPiArc3RhdGljIHZvaWQgdXBkYXRlX2JpbmRfaW5mbyhzdHJ1Y3QgdGhlcm1hbF9j
b29saW5nX2RldmljZQ0KPiAqY2RldikNCj4gPiA+ID4gPiA+ICt7DQo+ID4gPiA+ID4gPiArCWlu
dCBpLCByZXQ7DQo+ID4gPiA+ID4gPiArCXN0cnVjdCB0aGVybWFsX3pvbmVfcGFyYW1zICp0enA7
DQo+ID4gPiA+ID4gPiArCXN0cnVjdCB0aGVybWFsX3pvbmVfZGV2aWNlICpwb3MgPSBOVUxMOw0K
PiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gKwltdXRleF9sb2NrKCZ0aGVybWFsX2xpc3RfbG9j
ayk7DQo+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnkocG9z
LCAmdGhlcm1hbF90el9saXN0LCBub2RlKSB7DQo+ID4gPiA+ID4gPiArCQlpZiAoIXBvcy0+dHpw
ICYmICFwb3MtPm9wcy0+YmluZCkNCj4gPiA+ID4gPiA+ICsJCQljb250aW51ZTsNCj4gPiA+ID4g
PiA+ICsNCj4gPiA+ID4gPiA+ICsJCWlmICghcG9zLT50enAgJiYgcG9zLT5vcHMtPmJpbmQpIHsN
Cj4gPiA+ID4gPiA+ICsJCQlyZXQgPSBwb3MtPm9wcy0+YmluZChwb3MsIGNkZXYpOw0KPiA+ID4g
PiA+ID4gKwkJCWlmIChyZXQpDQo+ID4gPiA+ID4gPiArCQkJCXByaW50X2JpbmRfZXJyX21zZyhw
b3MsIGNkZXYsIHJldCk7DQo+ID4gPiA+ID4gPiArCQl9DQo+ID4gPiA+ID4gPiArDQo+ID4gPiA+
ID4gPiArCQl0enAgPSBwb3MtPnR6cDsNCj4gPiA+ID4gPiA+ICsJCWZvciAoaSA9IDA7IGkgPCB0
enAtPm51bV9jZGV2czsgaSsrKSB7DQo+ID4gPiA+ID4gPiArCQkJaWYgKCFzdHJjbXAodHpwLT5j
ZGV2c19uYW1lW2ldLCBjZGV2LT50eXBlKSkNCj4gew0KPiA+ID4gPiA+ID4gKwkJCQlfX2JpbmQo
cG9zLCB0enAtPnRyaXBfbWFza1tpXSwgY2Rldik7DQo+ID4gPiA+ID4gPiArCQkJCWJyZWFrOw0K
PiA+ID4gPiA+ID4gKwkJCX0NCj4gPiA+ID4gPiA+ICsJCX0NCj4gPiA+ID4gPiA+ICsJfQ0KPiA+
ID4gPiA+ID4gKwltdXRleF91bmxvY2soJnRoZXJtYWxfbGlzdF9sb2NrKTsNCj4gPiA+ID4gPiA+
ICt9DQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBJIHN0aWxsIGRvIG5vdCB1bmRlcnN0YW5kIHdoeSB3
ZSBuZWVkIHRoaXMga2luZCBvZiBiaW5kLg0KPiA+ID4gPiA+IFNheSwgdGhlIHBsYXRmb3JtIHRo
ZXJtYWwgZHJpdmVyIGtub3dzIHRoZSBwbGF0Zm9ybSBkYXRhLCBpLmUuIGl0DQo+IGtub3dzDQo+
ID4gPiA+ID4gd2hpY2ggY29vbGluZyBkZXZpY2VzIHNob3VsZCBiZSBib3VuZCB0byB3aGljaCB0
cmlwIHBvaW50cy4NCj4gPiA+ID4gPiB3aHkgd2UgY2FuIG5vdCBtb3ZlIHRoaXMga2luZCBvZiBs
b2dpYyB0byB0aGUgLmJpbmQoKSBjYWxsYmFjaywgb2ZmZXJlZA0KPiA+ID4gPiA+IGJ5IHRoZSBw
bGF0Zm9ybSB0aGVybWFsIGRyaXZlcj8NCj4gPiA+ID4gPiBzYXksIGluIC5iaW5kKCkgY2FsbGJh
Y2ssDQo+ID4gPiA+ID4gdGhlIHBsYXRmb3JtIHRoZXJtYWwgZHJpdmVyIGhhcyB0aGUgcG9pbnRl
ciBvZiB0aGUgcGxhdGZvcm0gZGF0YSwNCj4gcmlnaHQ/DQo+ID4gPiA+ID4gdGhlIC5jZGV2IHBh
cmFtZXRlciBjYW4gYmUgdXNlZCB0byBmaW5kIHRoZSBjb29saW5nIGRldmljZSBuYW1lLA0KPiA+
ID4gPiA+IGFuZCB3ZSBjYW4gbWFrZSB0aGUgY29tcGFyaXNvbiB0aGVyZS4gaW5zdGVhZCBvZiBp
bnRyb2R1Y2luZyBuZXcNCj4gYmluZGluZw0KPiA+ID4gPiA+IGZ1bmN0aW9ucyBpbiB0aGUgZ2Vu
ZXJpYyB0aGVybWFsIGxheWVyLg0KPiA+ID4gPg0KPiA+ID4gPiBGb3Igb25jZSwgSSBnb3QgbGl0
dGxlIGNvbmZ1c2VkIGJldHdlZW4gdGhlIGdlbmVyaWMgcGxhdGZvcm0gdGhlcm1hbA0KPiBzZW5z
b3INCj4gPiA+ID4gZHJpdmVycyAodGhlIGNoaXAgZHJpdmVycykgYW5kIHRoZSBwbGF0Zm9ybSBs
ZXZlbCBkcml2ZXIgKG5vdCBzcGVjaWZpYyBmb3INCj4gY2hpcCwNCj4gPiA+ID4gYnV0IGZvciBh
IHBsYXRmb3JtKS4gU28sIHllcyB3ZSBjYW4gcHV0IHRoaXMgaW4gdGhlIHBsYXRmb3JtIGxldmVs
IGRyaXZlci4NCj4gPiA+ID4NCj4gPiA+IEhtbSwNCj4gPiA+IEknbSBub3QgY2xlYXIgYWJvdXQg
dGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGVzZSB0d28gZHJpdmVycy4NCj4gPiA+IHdoYXQgaXMg
c3VwcG9zZWQgdG8gYmUgZG9uZSBpbiB0aGUgcGxhdGZvcm0gdGhlcm1hbCBzZW5zb3IgZHJpdmVy
cyBhbmQNCj4gPiA+IHdoYXQgaXMgc3VwcG9zZWQgdG8gYmUgZG9uZSBpbiB0aGUgcGxhdGZvcm0g
bGV2ZWwgZHJpdmVyPw0KPiA+DQo+ID4gQSBzZW5zb3IgZHJpdmVyIGNhbiBiZSBhIGdlbmVyaWMg
Y2hpcCBkcml2ZXIgbGlrZSBlbWMxNDAzICh0aGlzIGlzIHRoZSBvbmUNCj4gPiB0aGF0IEkgaGF2
ZSB3b3JrZWQgb24uLikgb3IgY29yZXRlbXAgKHRoZSBDUFUgRFRTIGRyaXZlciBmb3IgeDg2KS4g
VGhleSBzaXQNCj4gPiBpbiBkaWZmZXJlbnQgc3ViIHN5c3RlbXMgKHRoZXNlIHR3byBpbiBod21v
bikuIFdlIG1pZ2h0IG5vdCBiZSBhbGxvd2VkDQo+IHRvDQo+ID4gYWRkIGFueSB0aGVybWFsIGZy
YW1ld29yayBzcGVjaWZpYyBjb2RlIGluIHRoZXNlIGRyaXZlcnMuIFRoZSBzYW1lIGRyaXZlcg0K
PiA+IHdvcmtzIG9uIGFsbCBwbGF0Zm9ybXMuDQo+IA0KPiBkb2VzIHRoZSBzZW5zb3Iga25vdyBh
bnl0aGluZyBhYm91dCB0aGUgInBvbGljeSI/DQo+IFNheSwgZG9lcyBpdCBoYXZlIGFueSB0cmlw
IHBvaW50cz8gZG9lcyBpdCBrbm93IHdoaWNoIGRldmljZSBjYW4gYmUNCj4gdGhyb3R0bGVkIHRv
IGNvb2wgaXRzZWxmPw0KPiBJIHRoaW5rIHRoZSBhbnN3ZXIgaXMgIm5vIiwgcmlnaHQ/DQoNClll
cy4gWW91IGFyZSByaWdodCA6LSkNClRoZSBhbnN3ZXIgaXMgJ05vJy4NCg0KPiA+DQo+ID4gQSBw
bGF0Zm9ybSBsZXZlbCB0aGVybWFsIGRyaXZlciBrbm93cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUg
dGhlcm1hbA0KPiBzZW5zb3JzLA0KPiA+IGFuZCB0aGVpciB6b25lcyBvbiB0aGUgcGxhdGZvcm07
IGFuZCBpcyBzcGVjaWZpYyB0byB0aGUgcGxhdGZvcm0uDQo+ID4gRm9yIHg4NiwgdGhpcyB3aWxs
IGJlIGluIGRyaXZlcnMveDg2L3BsYXRmb3JtLyB3aGVyZWFzIG1pZ2h0IGJlIGluIHNvbWUNCj4g
b3RoZXINCj4gPiBwbGFjZSBmb3Igb3RoZXIgYXJjaGl0ZWN0dXJlcy4gQW4gZXhhbXBsZSBpcyBp
bnRlbF9taWRfdGhlcm1hbC5jIHdoaWNoIHNpdHMNCj4gPiBpbiBkcml2ZXJzL3g4Ni9wbGF0Zm9y
bS4gV2UgY2FuIGFkZCBvdXIgdGhlcm1hbCBmcmFtZXdvcmsgc3BlY2lmaWMgY29kZQ0KPiA+IHRv
IHRoaXMgZHJpdmVyLg0KPiA+DQo+IGJ1dCBJIHRoaW5rIGludGVsX21pZGVfdGhlcm1hbCBkcml2
ZXIgaXMgYWxzbyBhIHBsYXRmb3JtIHRoZXJtYWwgc2Vuc29yDQo+IGRyaXZlciBhdCB0aGUgc2Ft
ZSB0aW1lLg0KDQpZZXMgdG9kYXkgaXQgaXMgYm90aC4uDQoNCj4gPiA+DQo+ID4gPiBBdCBsZWFz
dCBmb3Igbm93LCBhbGwgdGhlIHRoZXJtYWwgZHJpdmVycyBhcmUgYm90aCB0aGVybWFsIHNlbnNv
ciBkcml2ZXINCj4gPiA+IGFuZCBwbGF0Zm9ybSBsZXZlbCBkcml2ZXIsIHJpZ2h0Pw0KPiA+DQo+
ID4gTm90IGFsbCB0aGUgdGltZXMsIGFsdGhvdWdoIHRoZXJlIGFyZSBzb21lIGluc3RhbmNlcyB3
aGVyZSBib3RoIGFyZSBzYW1lLg0KPiA+IFdlIHVzZSBjb3JldGVtcC5jIGFuZCBpbnRlbF9taWRf
dGhlcm1hbC5jICh3aGljaCBhcmUgZGlmZmVyZW50KSwgZm9yIHRoZQ0KPiA+IHg4NiBtaWQgcGxh
dGZvcm1zLg0KPiA+DQo+IHNvIHlvdSB3YW50IHRvIHVzZSBjb3JldGVtcC5jIGFzIGEgdGVtcGVy
YXR1cmUgc2Vuc29yLCBhbmQgdGhlbiBiaW5kDQo+IHlvdXIgb3duIGNvb2xpbmcgZGV2aWNlcyB0
byBpdCBpbiB5b3VyIHBsYXRmb3JtIGxldmVsIHRoZXJtYWwgZHJpdmVyPw0KDQpZZXMsIGNvcmV0
ZW1wIGlzIG9uZSBmaW5lIGV4YW1wbGUuDQpBdCBsZWFzdCBJIHdvdWxkIGxpa2UgdG8gZ2V0IHRo
ZSBzYW1lIHRoaW5nIGRvbmUgZm9yIGVtYzE0MDMuYw0KKGFuZCBmZXcgaHdtb24gZHJpdmVycyku
Lg0KDQpUaGFua3MsDQpEdXJnYQ0K
--
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. 20, 2012, 6:11 p.m. UTC | #7
Hello,

On Thu, Aug 16, 2012 at 03:31:55AM +0000, R, Durgadoss wrote:
> Hi Rui,
> 
> 
> > -----Original Message-----
> > From: Zhang, Rui
> > Sent: Thursday, August 16, 2012 9:00 AM
> > To: R, Durgadoss
> > Cc: lenb@kernel.org; rjw@sisk.pl; linux-acpi@vger.kernel.org; linux-
> > pm@vger.kernel.org; eduardo.valentin@ti.com; amit.kachhap@linaro.org;
> > wni@nvidia.com
> > Subject: RE: [PATCH 07/13] Thermal: Update binding logic based on platform
> > data
> > 
> > On ?, 2012-08-15 at 03:17 -0600, R, Durgadoss wrote:
> > > Hi Rui,
> > >
> > > > > > > +static void update_bind_info(struct thermal_cooling_device
> > *cdev)
> > > > > > > +{
> > > > > > > +	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;
> > > > > > > +		for (i = 0; i < tzp->num_cdevs; i++) {
> > > > > > > +			if (!strcmp(tzp->cdevs_name[i], cdev->type))
> > {
> > > > > > > +				__bind(pos, tzp->trip_mask[i], cdev);
> > > > > > > +				break;
> > > > > > > +			}
> > > > > > > +		}
> > > > > > > +	}
> > > > > > > +	mutex_unlock(&thermal_list_lock);
> > > > > > > +}
> > > > > >
> > > > > > I still do not understand why we need this kind of bind.
> > > > > > Say, the platform thermal driver knows the platform data, i.e. it
> > knows
> > > > > > which cooling devices should be bound to which trip points.
> > > > > > why we can not move this kind of logic to the .bind() callback, offered
> > > > > > by the platform thermal driver?
> > > > > > say, in .bind() callback,
> > > > > > the platform thermal driver has the pointer of the platform data,
> > right?
> > > > > > the .cdev parameter can be used to find the cooling device name,
> > > > > > and we can make the comparison there. instead of introducing new
> > binding
> > > > > > functions in the generic thermal layer.
> > > > >
> > > > > For once, I got little confused between the generic platform thermal
> > sensor
> > > > > drivers (the chip drivers) and the platform level driver (not specific for
> > chip,
> > > > > but for a platform). So, yes we can put this in the platform level driver.
> > > > >
> > > > Hmm,
> > > > I'm not clear about the difference between these two drivers.
> > > > what is supposed to be done in the platform thermal sensor drivers and
> > > > what is supposed to be done in the platform level driver?
> > >
> > > A sensor driver can be a generic chip driver like emc1403 (this is the one
> > > that I have worked on..) or coretemp (the CPU DTS driver for x86). They sit
> > > in different sub systems (these two in hwmon). We might not be allowed
> > to
> > > add any thermal framework specific code in these drivers. The same driver
> > > works on all platforms.
> > 
> > does the sensor know anything about the "policy"?
> > Say, does it have any trip points? does it know which device can be
> > throttled to cool itself?
> > I think the answer is "no", right?
> 
> Yes. You are right :-)
> The answer is 'No'.
> 
> > >
> > > A platform level thermal driver knows information about the thermal
> > sensors,
> > > and their zones on the platform; and is specific to the platform.
> > > For x86, this will be in drivers/x86/platform/ whereas might be in some
> > other
> > > place for other architectures. An example is intel_mid_thermal.c which sits
> > > in drivers/x86/platform. We can add our thermal framework specific code
> > > to this driver.
> > >
> > but I think intel_mide_thermal driver is also a platform thermal sensor
> > driver at the same time.
> 
> Yes today it is both..

So, what is the conclusion from above? I think we need to have a call here as
it will drive how driver code is going to look like. So far, the way I am
designing the OMAP thermal support is that the temp sensor drivers would
know about how to cool the zones, at SoC level. But the cooling of a platform/end-product
level would require another driver, which would require knowledge of availability
of sensors and cooling devices, in order to define the board policy.

> 
> > > >
> > > > At least for now, all the thermal drivers are both thermal sensor driver
> > > > and platform level driver, right?
> > >
> > > Not all the times, although there are some instances where both are same.
> > > We use coretemp.c and intel_mid_thermal.c (which are different), for the
> > > x86 mid platforms.
> > >
> > so you want to use coretemp.c as a temperature sensor, and then bind
> > your own cooling devices to it in your platform level thermal driver?
> 
> Yes, coretemp is one fine example.
> At least I would like to get the same thing done for emc1403.c
> (and few hwmon drivers)..
> 
> Thanks,
> Durga
--
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_sys.c b/drivers/thermal/thermal_sys.c
index 195e529..748b12f 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -158,6 +158,107 @@  static void retrieve_zone_params(struct thermal_zone_device *tz)
 	}
 }
 
+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)
+{
+	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;
+		for (i = 0; i < tzp->num_cdevs; i++) {
+			if (!strcmp(tzp->cdevs_name[i], cdev->type)) {
+				__bind(pos, tzp->trip_mask[i], cdev);
+				break;
+			}
+		}
+	}
+	mutex_unlock(&thermal_list_lock);
+}
+
+static void do_binding(struct thermal_zone_device *tz)
+{
+	int i, ret;
+	char *name;
+	struct thermal_cooling_device *pos = NULL;
+	struct thermal_zone_params *tzp = tz->tzp;
+
+	if (!tzp && !tz->ops->bind)
+		return;
+
+	/* If there is no platform data, try to use ops->bind */
+	if (!tzp && tz->ops->bind) {
+		mutex_lock(&thermal_list_lock);
+
+		list_for_each_entry(pos, &thermal_cdev_list, node) {
+			ret = tz->ops->bind(tz, pos);
+			if (ret)
+				print_bind_err_msg(tz, pos, ret);
+		}
+
+		mutex_unlock(&thermal_list_lock);
+		return;
+	}
+
+	/* If platform data is available, use it to create binding */
+	for (i = 0; i < tzp->num_cdevs; i++) {
+		name = tzp->cdevs_name[i];
+		pos = get_cdev_by_name(name);
+
+		if (!pos) {
+			dev_err(&tz->device, "cannot find cdev %s\n", name);
+			continue;
+		}
+
+		mutex_lock(&thermal_list_lock);
+		__bind(tz, tzp->trip_mask[i], pos);
+		mutex_unlock(&thermal_list_lock);
+	}
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -975,7 +1076,6 @@  thermal_cooling_device_register(char *type, void *devdata,
 				const struct thermal_cooling_device_ops *ops)
 {
 	struct thermal_cooling_device *cdev;
-	struct thermal_zone_device *pos;
 	int result;
 
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
@@ -1025,20 +1125,15 @@  thermal_cooling_device_register(char *type, void *devdata,
 	if (result)
 		goto unregister;
 
+	/* 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)
-		return cdev;
+	/* Update binding information for 'this' new cdev */
+	update_bind_info(cdev);
+
+	return cdev;
 
 unregister:
 	release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
@@ -1054,10 +1149,10 @@  EXPORT_SYMBOL(thermal_cooling_device_register);
  * thermal_cooling_device_unregister() must be called when the device is no
  * longer needed.
  */
-void thermal_cooling_device_unregister(struct
-				       thermal_cooling_device
-				       *cdev)
+void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
 {
+	int i;
+	struct thermal_zone_params *tzp;
 	struct thermal_zone_device *tz;
 	struct thermal_cooling_device *pos = NULL;
 
@@ -1074,12 +1169,23 @@  void thermal_cooling_device_unregister(struct
 		return;
 	}
 	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)
+		tzp = tz->tzp;
+		if (!tzp && !tz->ops->unbind)
 			continue;
-		tz->ops->unbind(tz, cdev);
+
+		if (!tzp && tz->ops->unbind)
+			tz->ops->unbind(tz, cdev);
+
+		for (i = 0; i < tzp->num_cdevs; i++)
+			if (!strcmp(cdev->type, tzp->cdevs_name[i]))
+				__unbind(tz, tzp->trip_mask[i], cdev);
 	}
+
 	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);
@@ -1424,7 +1530,6 @@  struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	int passive_delay, int polling_delay)
 {
 	struct thermal_zone_device *tz;
-	struct thermal_cooling_device *pos;
 	enum thermal_trip_type trip_type;
 	int result;
 	int count;
@@ -1519,14 +1624,12 @@  struct thermal_zone_device *thermal_zone_device_register(const char *type,
 
 	mutex_lock(&thermal_list_lock);
 	list_add_tail(&tz->node, &thermal_tz_list);
-	if (ops->bind)
-		list_for_each_entry(pos, &thermal_cdev_list, node) {
-		result = ops->bind(tz, pos);
-		if (result)
-			break;
-		}
 	mutex_unlock(&thermal_list_lock);
 
+	/* Bind cooling devices for this zone */
+	do_binding(tz);
+
+
 	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
 
 	thermal_zone_device_update(tz);
@@ -1547,12 +1650,16 @@  EXPORT_SYMBOL(thermal_zone_device_register);
  */
 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 {
+	int i;
+	struct thermal_zone_params *tzp;
 	struct thermal_cooling_device *cdev;
 	struct thermal_zone_device *pos = NULL;
 
 	if (!tz)
 		return;
 
+	tzp = tz->tzp;
+
 	mutex_lock(&thermal_list_lock);
 	list_for_each_entry(pos, &thermal_tz_list, node)
 	    if (pos == tz)
@@ -1563,9 +1670,20 @@  void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 		return;
 	}
 	list_del(&tz->node);
-	if (tz->ops->unbind)
-		list_for_each_entry(cdev, &thermal_cdev_list, node)
-		    tz->ops->unbind(tz, cdev);
+
+	/* Unbind all cdevs associated with 'this' thermal zone */
+	list_for_each_entry(cdev, &thermal_cdev_list, node) {
+		if (!tzp && !tz->ops->unbind)
+			break;
+
+		if (!tzp && tz->ops->unbind)
+			tz->ops->unbind(tz, cdev);
+
+		for (i = 0; i < tzp->num_cdevs; i++)
+			if (!strcmp(cdev->type, tzp->cdevs_name[i]))
+				__unbind(tz, tzp->trip_mask[i], cdev);
+	}
+
 	mutex_unlock(&thermal_list_lock);
 
 	thermal_zone_device_set_polling(tz, 0);