All of lore.kernel.org
 help / color / mirror / Atom feed
From: "R, Durgadoss" <durgadoss.r@intel.com>
To: Eduardo Valentin <eduardo.valentin@ti.com>
Cc: "Zhang, Rui" <rui.zhang@intel.com>,
	"linux-pm@vger.kernel.org" <linux-pm@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"hongbo.zhang@linaro.org" <hongbo.zhang@linaro.org>,
	"wni@nvidia.com" <wni@nvidia.com>
Subject: RE: [PATCH 2/8] Thermal: Create zone level APIs
Date: Fri, 1 Mar 2013 15:31:43 +0000	[thread overview]
Message-ID: <4D68720C2E767A4AA6A8796D42C8EB59293FAF@BGSMSX101.gar.corp.intel.com> (raw)
In-Reply-To: <512FB02C.3090802@ti.com>

> -----Original Message-----
> From: linux-pm-owner@vger.kernel.org [mailto:linux-pm-
> owner@vger.kernel.org] On Behalf Of Eduardo Valentin
> Sent: Friday, March 01, 2013 1:00 AM
> To: R, Durgadoss
> Cc: Zhang, Rui; linux-pm@vger.kernel.org; linux-kernel@vger.kernel.org;
> hongbo.zhang@linaro.org; wni@nvidia.com
> Subject: Re: [PATCH 2/8] Thermal: Create zone level APIs
> 
> On 05-02-2013 06:46, Durgadoss R wrote:
> > This patch adds a new thermal_zone structure to
> > thermal.h. Also, adds zone level APIs to the thermal
> > framework.
> >
> > A thermal zone is a hot spot on the platform, which
> > can have one or more sensors and cooling devices attached
> > to it. These sensors can be mapped to a set of cooling
> > devices, which when throttled, can help to bring down
> > the temperature of the hot spot.
> >
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
> > ---
> >   drivers/thermal/thermal_sys.c |  196
> +++++++++++++++++++++++++++++++++++++++++
> >   include/linux/thermal.h       |   22 +++++
> >   2 files changed, 218 insertions(+)
> >
> > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
> > index cb94497..838d4fb 100644
> > --- a/drivers/thermal/thermal_sys.c
> > +++ b/drivers/thermal/thermal_sys.c
> > @@ -43,19 +43,46 @@ MODULE_DESCRIPTION("Generic thermal
> management sysfs support");
> >   MODULE_LICENSE("GPL");
> >
> >   static DEFINE_IDR(thermal_tz_idr);
> > +static DEFINE_IDR(thermal_zone_idr);
> >   static DEFINE_IDR(thermal_cdev_idr);
> >   static DEFINE_IDR(thermal_sensor_idr);
> >   static DEFINE_MUTEX(thermal_idr_lock);
> >
> >   static LIST_HEAD(thermal_tz_list);
> >   static LIST_HEAD(thermal_sensor_list);
> > +static LIST_HEAD(thermal_zone_list);
> >   static LIST_HEAD(thermal_cdev_list);
> >   static LIST_HEAD(thermal_governor_list);
> >
> >   static DEFINE_MUTEX(thermal_list_lock);
> >   static DEFINE_MUTEX(sensor_list_lock);
> > +static DEFINE_MUTEX(zone_list_lock);
> >   static DEFINE_MUTEX(thermal_governor_lock);
> >
> > +#define for_each_thermal_sensor(pos) \
> > +	list_for_each_entry(pos, &thermal_sensor_list, node)
> > +
> > +#define for_each_thermal_zone(pos) \
> > +	list_for_each_entry(pos, &thermal_zone_list, node)
> > +
> > +#define GET_INDEX(tz, ptr, type)			\
> 
> Why do you need type? You seam to be using it only for sensors. It
> becomes a bit cryptic :-)

In the next patch, we use it for cooling devices also.

> 
> > +({							\
> > +	int i, ret = -EINVAL;				\
> > +	do {						\
> > +		if (!tz || !ptr)			\
> > +			break;				\
> > +		mutex_lock(&type##_list_lock);		\
> > +		for (i = 0; i < tz->type##_indx; i++) {	\
> > +			if (tz->type##s[i] == ptr) {	\
> > +				ret = i;		\
> > +				break;			\
> > +			}				\
> > +		}					\
> > +		mutex_unlock(&type##_list_lock);	\
> > +	} while (0);					\
> > +	ret;						\
> > +})
> > +
> >   static struct thermal_governor *__find_governor(const char *name)
> >   {
> >   	struct thermal_governor *pos;
> > @@ -421,15 +448,44 @@ static void thermal_zone_device_check(struct
> work_struct *work)
> >   	thermal_zone_device_update(tz);
> >   }
> >
> > +static void remove_sensor_from_zone(struct thermal_zone *tz,
> > +				struct thermal_sensor *ts)
> > +{
> > +	int j, indx;
> > +
> > +	indx = GET_INDEX(tz, ts, sensor);
> > +	if (indx < 0)
> > +		return;
> > +
> > +	sysfs_remove_link(&tz->device.kobj, kobject_name(&ts-
> >device.kobj));
> > +
> > +	/* Shift the entries in the tz->sensors array */
> > +	for (j = indx; j < MAX_SENSORS_PER_ZONE - 1; j++)
> > +		tz->sensors[j] = tz->sensors[j + 1];
> > +
> > +	tz->sensor_indx--;
> > +}
> > +
> >   /* sys I/F for thermal zone */
> >
> >   #define to_thermal_zone(_dev) \
> >   	container_of(_dev, struct thermal_zone_device, device)
> >
> > +#define to_zone(_dev) \
> > +	container_of(_dev, struct thermal_zone, device)
> > +
> >   #define to_thermal_sensor(_dev) \
> >   	container_of(_dev, struct thermal_sensor, device)
> >
> >   static ssize_t
> > +zone_name_show(struct device *dev, struct device_attribute *attr, char
> *buf)
> > +{
> > +	struct thermal_zone *tz = to_zone(dev);
> > +
> > +	return sprintf(buf, "%s\n", tz->name);
> snprintf
> 
> > +}
> > +
> > +static ssize_t
> >   sensor_name_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> >   {
> >   	struct thermal_sensor *ts = to_thermal_sensor(dev);
> > @@ -811,6 +867,8 @@ static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR,
> policy_show, policy_store);
> >   static DEVICE_ATTR(sensor_name, 0444, sensor_name_show, NULL);
> >   static DEVICE_ATTR(temp_input, 0444, sensor_temp_show, NULL);
> >
> > +static DEVICE_ATTR(zone_name, 0444, zone_name_show, NULL);
> > +
> >   /* sys I/F for cooling device */
> >   #define to_cooling_device(_dev)	\
> >   	container_of(_dev, struct thermal_cooling_device, device)
> > @@ -1656,6 +1714,136 @@ static int enable_sensor_thresholds(struct
> thermal_sensor *ts, int count)
> >   	return 0;
> >   }
> >
> > +struct thermal_zone *create_thermal_zone(const char *name, void
> *devdata)
> > +{
> > +	struct thermal_zone *tz;
> > +	int ret;
> > +
> > +	if (!name || (name && strlen(name) >= THERMAL_NAME_LENGTH))
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	tz = kzalloc(sizeof(*tz), GFP_KERNEL);
> 
> devm_ helpers
> 
> > +	if (!tz)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	idr_init(&tz->idr);
> > +	ret = get_idr(&thermal_zone_idr, &thermal_idr_lock, &tz->id);
> > +	if (ret)
> > +		goto exit_free;
> > +
> > +	strcpy(tz->name, name);
> 
> strlcpy
> 
> > +	tz->devdata = devdata;
> > +	tz->device.class = &thermal_class;
> > +
> > +	dev_set_name(&tz->device, "zone%d", tz->id);
> > +	ret = device_register(&tz->device);
> > +	if (ret)
> > +		goto exit_idr;
> > +
> > +	ret = device_create_file(&tz->device, &dev_attr_zone_name);
> > +	if (ret)
> > +		goto exit_unregister;
> > +
> > +	/* Add this zone to the global list of thermal zones */
> > +	mutex_lock(&zone_list_lock);
> > +	list_add_tail(&tz->node, &thermal_zone_list);
> > +	mutex_unlock(&zone_list_lock);
> > +	return tz;
> > +
> > +exit_unregister:
> > +	device_unregister(&tz->device);
> > +exit_idr:
> > +	release_idr(&thermal_zone_idr, &thermal_idr_lock, tz->id);
> > +exit_free:
> > +	kfree(tz);
> > +	return ERR_PTR(ret);
> > +}
> > +EXPORT_SYMBOL(create_thermal_zone);
> > +
> > +void remove_thermal_zone(struct thermal_zone *tz)
> > +{
> > +	struct thermal_zone *pos, *next;
> > +	bool found = false;
> > +
> > +	if (!tz)
> > +		return;
> > +
> > +	mutex_lock(&zone_list_lock);
> > +
> > +	list_for_each_entry_safe(pos, next, &thermal_zone_list, node) {
> > +		if (pos == tz) {
> > +			list_del(&tz->node);
> > +			found = true;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (!found)
> > +		goto exit;
> > +
> > +	device_remove_file(&tz->device, &dev_attr_zone_name);
> > +
> > +	release_idr(&thermal_zone_idr, &thermal_idr_lock, tz->id);
> > +	idr_destroy(&tz->idr);
> > +
> > +	device_unregister(&tz->device);
> > +	kfree(tz);
> > +exit:
> > +	mutex_unlock(&zone_list_lock);
> > +	return;
> > +}
> > +EXPORT_SYMBOL(remove_thermal_zone);
> 
> Do we need to impose removal ordering here? Meaning, what happens if
> the
> above is called with sensors registered?

A zone only contains a symbolic link to a sensor. So, when this is called with
sensors registered, all the symbolic links will go away i.e /sys/../zone/sensorX
will go but /sys/../sensorX will remain as such.

> 
> > +
> > +struct thermal_sensor *get_sensor_by_name(const char *name)
> Why do you need this function? does not seam to be used anywhere in this
> patch. Besides it is unrelated to what this patch proposes itself to do.
> 
> > +{
> > +	struct thermal_sensor *pos;
> > +	struct thermal_sensor *ts = NULL;
> > +
> > +	mutex_lock(&sensor_list_lock);
> > +	for_each_thermal_sensor(pos) {
> > +		if (!strnicmp(pos->name, name, THERMAL_NAME_LENGTH))
> {
> > +			ts = pos;
> > +			break;
> > +		}
> > +	}
> > +	mutex_unlock(&sensor_list_lock);
> > +	return ts;
> > +}
> > +EXPORT_SYMBOL(get_sensor_by_name);
> > +
> > +int add_sensor_to_zone(struct thermal_zone *tz, struct thermal_sensor
> *ts)
> > +{
> > +	int ret;
> > +
> > +	if (!tz || !ts)
> > +		return -EINVAL;
> > +
> > +	mutex_lock(&zone_list_lock);
> > +
> > +	/* Ensure we are not adding the same sensor again!! */
> > +	ret = GET_INDEX(tz, ts, sensor);
> > +	if (ret >= 0) {
> > +		ret = -EEXIST;
> > +		goto exit_zone;
> > +	}
> > +
> > +	mutex_lock(&sensor_list_lock);
> > +
> > +	ret = sysfs_create_link(&tz->device.kobj, &ts->device.kobj,
> > +				kobject_name(&ts->device.kobj));
> > +	if (ret)
> > +		goto exit_sensor;
> > +
> > +	tz->sensors[tz->sensor_indx++] = ts;
> 
> you may overflow your sensors buffer with the above implementation.

Will add a check before the increment.

> 
> you may have a contention on sensors/sensor_indx.
> 
> Consider using linked lists.
> 
> > +
> > +exit_sensor:
> > +	mutex_unlock(&sensor_list_lock);
> > +exit_zone:
> > +	mutex_unlock(&zone_list_lock);
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(add_sensor_to_zone);
> > +
> >   /**
> >    * thermal_sensor_register - register a new thermal sensor
> >    * @name:	name of the thermal sensor
> > @@ -1732,6 +1920,7 @@ EXPORT_SYMBOL(thermal_sensor_register);
> >   void thermal_sensor_unregister(struct thermal_sensor *ts)
> >   {
> >   	int i;
> > +	struct thermal_zone *tz;
> >   	struct thermal_sensor *pos, *next;
> >   	bool found = false;
> >
> > @@ -1751,6 +1940,13 @@ void thermal_sensor_unregister(struct
> thermal_sensor *ts)
> >   	if (!found)
> >   		return;
> >
> > +	mutex_lock(&zone_list_lock);
> > +
> > +	for_each_thermal_zone(tz)
> > +		remove_sensor_from_zone(tz, ts);
> > +
> > +	mutex_unlock(&zone_list_lock);
> > +
> >   	for (i = 0; i < ts->thresholds; i++) {
> >   		device_remove_file(&ts->device, &ts->thresh_attrs[i].attr);
> >   		if (ts->ops->get_hyst) {
> > diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> > index 5470dae..2194519 100644
> > --- a/include/linux/thermal.h
> > +++ b/include/linux/thermal.h
> > @@ -55,6 +55,8 @@
> >   #define DEFAULT_THERMAL_GOVERNOR       "user_space"
> >   #endif
> >
> > +#define MAX_SENSORS_PER_ZONE		5
> 
> 
> Why not making it a linked list? Why does it need to be static? Just
> trying to avoid to maintain this number sane, as we cannot predict what
> happens in future :-)

As I said earlier, making it a list makes things even more complex.
But I wanted this to be configurable through Kconfig, for which I
submitted a patch in my v2. But we had some comments against it.
So, we removed it, and need to revisit this later.

Thanks,
Durga

> 
> > +
> >   struct thermal_sensor;
> >   struct thermal_zone_device;
> >   struct thermal_cooling_device;
> > @@ -202,6 +204,21 @@ struct thermal_zone_device {
> >   	struct delayed_work poll_queue;
> >   };
> >
> > +struct thermal_zone {
> > +	char name[THERMAL_NAME_LENGTH];
> > +	int id;
> > +	void *devdata;
> > +	struct thermal_zone *ops;
> > +	struct thermal_governor *governor;
> > +	struct idr idr;
> > +	struct device device;
> > +	struct list_head node;
> > +
> > +	/* Sensor level information */
> > +	int sensor_indx; /* index into 'sensors' array */
> > +	struct thermal_sensor *sensors[MAX_SENSORS_PER_ZONE];
> > +};
> 
> 
> Could you please add documentation for the above structure? Why it does
> not need locking? what is *ops?
> > +
> >   /* Structure that holds thermal governor information */
> >   struct thermal_governor {
> >   	char name[THERMAL_NAME_LENGTH];
> > @@ -274,6 +291,11 @@ struct thermal_sensor
> *thermal_sensor_register(const char *, int,
> >   				struct thermal_sensor_ops *, void *);
> >   void thermal_sensor_unregister(struct thermal_sensor *);
> >
> > +struct thermal_zone *create_thermal_zone(const char *, void *);
> > +void remove_thermal_zone(struct thermal_zone *);
> > +int add_sensor_to_zone(struct thermal_zone *, struct thermal_sensor
> *);
> > +struct thermal_sensor *get_sensor_by_name(const char *);
> > +
> 
> I believe we need a better naming for this API. First suggestion is to
> use same prefix on all of them. Probably this comment applies not only
> to this specific patch.
> 
> Besides, for all functions above, you may want to add comments
> documenting them and their parameters?
> 
> >   #ifdef CONFIG_NET
> >   extern int thermal_generate_netlink_event(struct thermal_zone_device
> *tz,
> >   						enum events event);
> >
> 
> --
> 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

  reply	other threads:[~2013-03-01 15:31 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-05 10:46 [PATCHv3 0/8] Thermal Framework Enhancements Durgadoss R
2013-02-05 10:46 ` [PATCH 1/8] Thermal: Create sensor level APIs Durgadoss R
2013-02-08  7:53   ` Zhang Rui
2013-02-08  8:26     ` R, Durgadoss
2013-02-08  8:26       ` R, Durgadoss
2013-02-08  9:54       ` Zhang Rui
2013-02-28 18:58   ` Eduardo Valentin
2013-02-28 18:58     ` Eduardo Valentin
2013-03-01  5:08     ` R, Durgadoss
2013-02-05 10:46 ` [PATCH 2/8] Thermal: Create zone " Durgadoss R
2013-02-08  8:11   ` Zhang Rui
2013-02-08  8:54     ` R, Durgadoss
2013-02-08  8:54       ` R, Durgadoss
2013-02-08  9:54       ` Zhang Rui
2013-02-08 10:27         ` R, Durgadoss
2013-02-08 10:27           ` R, Durgadoss
2013-02-28 19:29   ` Eduardo Valentin
2013-02-28 19:29     ` Eduardo Valentin
2013-03-01 15:31     ` R, Durgadoss [this message]
2013-02-05 10:46 ` [PATCH 3/8] Thermal: Add APIs to bind cdev to new zone structure Durgadoss R
2013-02-08  8:28   ` Zhang Rui
2013-02-28 19:35   ` Eduardo Valentin
2013-02-28 19:35     ` Eduardo Valentin
2013-03-01 15:33     ` R, Durgadoss
2013-02-05 10:46 ` [PATCH 4/8] Thermal: Add trip point sysfs nodes for sensor Durgadoss R
2013-02-08  8:50   ` Zhang Rui
2013-02-28 19:51   ` Eduardo Valentin
2013-02-28 19:51     ` Eduardo Valentin
2013-03-01 15:34     ` R, Durgadoss
2013-02-05 10:46 ` [PATCH 5/8] Thermal: Create Thermal map sysfs attributes for a zone Durgadoss R
2013-02-08  9:04   ` Zhang Rui
2013-02-08  9:08     ` R, Durgadoss
2013-02-08  9:08       ` R, Durgadoss
2013-02-08  9:55       ` Zhang Rui
2013-02-28 21:30   ` Eduardo Valentin
2013-02-28 21:30     ` Eduardo Valentin
2013-02-05 10:46 ` [PATCH 6/8] Thermal: Add Documentation to new APIs Durgadoss R
2013-02-08  9:21   ` Zhang Rui
2013-02-05 10:46 ` [PATCH 7/8] Thermal: Add ABI Documentation for sysfs interfaces Durgadoss R
2013-02-05 10:46 ` [PATCH 8/8] Thermal: Dummy driver used for testing Durgadoss R
2013-02-08  7:53 ` [PATCHv3 0/8] Thermal Framework Enhancements Zhang Rui
2013-02-08  9:35 ` Zhang Rui
2013-02-28 21:33 ` Eduardo Valentin
2013-02-28 21:33   ` Eduardo Valentin
2013-03-01  5:12   ` R, Durgadoss
2013-08-29 19:38 ` Eduardo Valentin
2013-08-29 19:38   ` Eduardo Valentin
2013-08-30  9:20   ` R, Durgadoss
2013-08-30 12:34     ` Eduardo Valentin
2013-08-30 13:21       ` R, Durgadoss
  -- strict thread matches above, loose matches on Subject: below --
2012-12-18  9:29 [PATCH " Durgadoss R
2012-12-18  9:29 ` [PATCH 2/8] Thermal: Create zone level APIs Durgadoss R
2012-12-18 11:30   ` Joe Perches
2012-12-20  6:02     ` R, Durgadoss

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D68720C2E767A4AA6A8796D42C8EB59293FAF@BGSMSX101.gar.corp.intel.com \
    --to=durgadoss.r@intel.com \
    --cc=eduardo.valentin@ti.com \
    --cc=hongbo.zhang@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rui.zhang@intel.com \
    --cc=wni@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.