All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhang Rui <rui.zhang@intel.com>
To: Eduardo Valentin <edubezval@gmail.com>
Cc: Linux PM <linux-pm@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>, Keerthy <a0393675@ti.com>
Subject: Re: [PATCHv4 14/48] thermal: core: move trips attributes to tz->device.groups
Date: Fri, 17 Jun 2016 16:44:56 +0800	[thread overview]
Message-ID: <1466153096.9422.34.camel@intel.com> (raw)
In-Reply-To: <1464675535-2433-15-git-send-email-edubezval@gmail.com>

On 一, 2016-05-30 at 23:18 -0700, Eduardo Valentin wrote:
> Finally, move the last thermal zone sysfs attributes to
> tz->device.groups: trips attributes. This requires adding a
> attribute_group to thermal_zone_device, creating it dynamically, and
> then setting all trips attributes in it. The trips attribute is then
> added to the tz->device.groups.
> 
> As the removal of all attributes are handled by device core, the
> device
> remove calls are not needed anymore.
> 
> Cc: Zhang Rui <rui.zhang@intel.com>
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
> ---
>  drivers/thermal/thermal_core.c | 77 +++++++++++++++++++++-----------
> ----------
>  include/linux/thermal.h        |  2 ++
>  2 files changed, 41 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c
> b/drivers/thermal/thermal_core.c
> index ba4f7a9..0b60b04 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -1188,8 +1188,9 @@ static const struct attribute_group
> *thermal_zone_attribute_groups[] = {
>   */
>  static int create_trip_attrs(struct thermal_zone_device *tz, int
> mask)
>  {
> -	int indx;
>  	int size = sizeof(struct thermal_attr) * tz->trips;
> +	struct attribute **attrs;
> +	int indx;
>  
>  	tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
>  	if (!tz->trip_type_attrs)
> @@ -1210,6 +1211,15 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  		}
>  	}
>  
> +	attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1,
> GFP_KERNEL);
> +	if (!attrs) {
> +		kfree(tz->trip_type_attrs);
> +		kfree(tz->trip_temp_attrs);
> +		if (tz->ops->get_trip_hyst)
> +			kfree(tz->trip_hyst_attrs);
> +		return -ENOMEM;
> +	}
> +
>  	for (indx = 0; indx < tz->trips; indx++) {
>  		/* create trip type attribute */
>  		snprintf(tz->trip_type_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> @@ -1220,9 +1230,7 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  						tz-
> >trip_type_attrs[indx].name;
>  		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
>  		tz->trip_type_attrs[indx].attr.show =
> trip_point_type_show;
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_type_attrs[indx].attr);
> +		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
>  
>  		/* create trip temp attribute */
>  		snprintf(tz->trip_temp_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> @@ -1239,9 +1247,7 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  			tz->trip_temp_attrs[indx].attr.store =
>  							trip_point_t
> emp_store;
>  		}
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_temp_attrs[indx].attr);
> +		attrs[indx + tz->trips] = &tz-
> >trip_temp_attrs[indx].attr.attr;
>  
>  		/* create Optional trip hyst attribute */
>  		if (!tz->ops->get_trip_hyst)
> @@ -1259,45 +1265,38 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  			tz->trip_hyst_attrs[indx].attr.store =
>  					trip_point_hyst_store;
>  		}
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_hyst_attrs[indx].attr);
> +		attrs[indx + tz->trips * 2] =
> +					&tz-
> >trip_hyst_attrs[indx].attr.attr;
>  	}
> -	return 0;
> -}
> +	attrs[tz->trips * 3] = NULL;

why bother clearing it explicitly? kzalloc already handles this, right?

> -static void remove_trip_attrs(struct thermal_zone_device *tz)
> -{
> -	int indx;
> +	tz->trips_attribute_group.attrs = attrs;
>  
> -	for (indx = 0; indx < tz->trips; indx++) {
> -		device_remove_file(&tz->device,
> -				   &tz->trip_type_attrs[indx].attr);
> -		device_remove_file(&tz->device,
> -				   &tz->trip_temp_attrs[indx].attr);
> -		if (tz->ops->get_trip_hyst)
> -			device_remove_file(&tz->device,
> -					   &tz-
> >trip_hyst_attrs[indx].attr);
> -	}
> -	kfree(tz->trip_type_attrs);
> -	kfree(tz->trip_temp_attrs);
> -	kfree(tz->trip_hyst_attrs);
> +	return 0;
>  }
>  
> -static int thermal_zone_create_device_groups(struct
> thermal_zone_device *tz)
> +static int thermal_zone_create_device_groups(struct
> thermal_zone_device *tz,
> +					     int mask)
>  {
>  	const struct attribute_group **groups;
> -	int i, size;
> +	int i, size, result;
> +
> +	result = create_trip_attrs(tz, mask);
> +	if (result)
> +		return result;
>  
> -	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1;
> +	/* we need one extra for trips and the NULL to terminate the
> array */
> +	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
>  	/* This also takes care of API requirement to be NULL
> terminated */
>  	groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
>  	if (!groups)
>  		return -ENOMEM;
>  
> -	for (i = 0; i < size - 1; i++)
> +	for (i = 0; i < size - 2; i++)
>  		groups[i] = thermal_zone_attribute_groups[i];
>  
> +	groups[size - 2] = &tz->trips_attribute_group;
> +

Problem is that, previously, create_trip_attrs() does not handle the
case that tz->trips == 0 good enough, it happens to not bring big
problem.
tz->trip_type_attrs/tz->trip_temp_attrs/tz->trip_hyst_attrs is set
to ZERO_SIZE_PTR when tz->trips equals 0, kfree() handles this.
But registering a sysfs group with one invalid attribute item is wrong.
And this causes oops in my machine when test_power driver, which has no
trip point, is unloaded. And maybe this is also the root cause of this
report http://www.spinics.net/lists/kernel/msg2280260.html

Attached is an updated version, which creates trip attributes only if
tz->trips > 0, which solves the problem for me.

From e1e917e790b70b88bd418545a29b1eefa01a5566 Mon Sep 17 00:00:00 2001
From: Eduardo Valentin <edubezval@gmail.com>
Date: Mon, 30 May 2016 23:18:21 -0700
Subject: [PATCH] thermal: core: move trips attributes to tz->device.groups

Finally, move the last thermal zone sysfs attributes to
tz->device.groups: trips attributes. This requires adding a
attribute_group to thermal_zone_device, creating it dynamically, and
then setting all trips attributes in it. The trips attribute is then
added to the tz->device.groups.

As the removal of all attributes are handled by device core, the device
remove calls are not needed anymore.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_core.c | 78 ++++++++++++++++++++++--------------------
 include/linux/thermal.h        |  2 ++
 2 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 657ba02..9926c89 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1188,8 +1188,9 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
  */
 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 {
-	int indx;
 	int size = sizeof(struct thermal_attr) * tz->trips;
+	struct attribute **attrs;
+	int indx;
 
 	tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
 	if (!tz->trip_type_attrs)
@@ -1210,6 +1211,15 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 		}
 	}
 
+	attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1, GFP_KERNEL);
+	if (!attrs) {
+		kfree(tz->trip_type_attrs);
+		kfree(tz->trip_temp_attrs);
+		if (tz->ops->get_trip_hyst)
+			kfree(tz->trip_hyst_attrs);
+		return -ENOMEM;
+	}
+
 	for (indx = 0; indx < tz->trips; indx++) {
 		/* create trip type attribute */
 		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
@@ -1220,9 +1230,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 						tz->trip_type_attrs[indx].name;
 		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
 		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
-
-		device_create_file(&tz->device,
-				   &tz->trip_type_attrs[indx].attr);
+		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
 
 		/* create trip temp attribute */
 		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
@@ -1239,9 +1247,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 			tz->trip_temp_attrs[indx].attr.store =
 							trip_point_temp_store;
 		}
-
-		device_create_file(&tz->device,
-				   &tz->trip_temp_attrs[indx].attr);
+		attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
 
 		/* create Optional trip hyst attribute */
 		if (!tz->ops->get_trip_hyst)
@@ -1259,45 +1265,39 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 			tz->trip_hyst_attrs[indx].attr.store =
 					trip_point_hyst_store;
 		}
-
-		device_create_file(&tz->device,
-				   &tz->trip_hyst_attrs[indx].attr);
+		attrs[indx + tz->trips * 2] =
+					&tz->trip_hyst_attrs[indx].attr.attr;
 	}
-	return 0;
-}
+	attrs[tz->trips * 3] = NULL;
 
-static void remove_trip_attrs(struct thermal_zone_device *tz)
-{
-	int indx;
+	tz->trips_attribute_group.attrs = attrs;
 
-	for (indx = 0; indx < tz->trips; indx++) {
-		device_remove_file(&tz->device,
-				   &tz->trip_type_attrs[indx].attr);
-		device_remove_file(&tz->device,
-				   &tz->trip_temp_attrs[indx].attr);
-		if (tz->ops->get_trip_hyst)
-			device_remove_file(&tz->device,
-					   &tz->trip_hyst_attrs[indx].attr);
-	}
-	kfree(tz->trip_type_attrs);
-	kfree(tz->trip_temp_attrs);
-	kfree(tz->trip_hyst_attrs);
+	return 0;
 }
 
-static int thermal_zone_create_device_groups(struct thermal_zone_device *tz)
+static int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
+					     int mask)
 {
 	const struct attribute_group **groups;
-	int i, size;
+	int i, size, result;
 
-	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1;
+	/* we need one extra for trips and the NULL to terminate the array */
+	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
 	/* This also takes care of API requirement to be NULL terminated */
 	groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
 	if (!groups)
 		return -ENOMEM;
 
-	for (i = 0; i < size - 1; i++)
+	for (i = 0; i < size - 2; i++)
 		groups[i] = thermal_zone_attribute_groups[i];
 
+	if (tz->trips) {
+		result = create_trip_attrs(tz, mask);
+		if (result)
+			return result;
+		groups[size - 2] = &tz->trips_attribute_group;
+	}
+
 	tz->device.groups = groups;
 
 	return 0;
@@ -1934,8 +1934,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	tz->passive_delay = passive_delay;
 	tz->polling_delay = polling_delay;
 
+	/* sys I/F */
 	/* Add nodes that are always present via .groups */
-	thermal_zone_create_device_groups(tz);
+	result = thermal_zone_create_device_groups(tz, mask);
+	if (result)
+		goto unregister;
+
 	/* A new thermal zone needs to be updated anyway. */
 	atomic_set(&tz->need_update, 1);
 
@@ -1947,11 +1951,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 		return ERR_PTR(result);
 	}
 
-	/* sys I/F */
-	result = create_trip_attrs(tz, mask);
-	if (result)
-		goto unregister;
-
 	for (count = 0; count < trips; count++) {
 		if (tz->ops->get_trip_type(tz, count, &trip_type))
 			set_bit(count, &tz->trips_disabled);
@@ -2056,7 +2055,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
 	thermal_zone_device_set_polling(tz, 0);
 
-	remove_trip_attrs(tz);
+	kfree(tz->trip_type_attrs);
+	kfree(tz->trip_temp_attrs);
+	kfree(tz->trip_hyst_attrs);
+	kfree(tz->trips_attribute_group.attrs);
 	thermal_set_governor(tz, NULL);
 
 	thermal_remove_hwmon_sysfs(tz);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ee517be..580809c 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/idr.h>
 #include <linux/device.h>
+#include <linux/sysfs.h>
 #include <linux/workqueue.h>
 #include <uapi/linux/thermal.h>
 
@@ -187,6 +188,7 @@ struct thermal_zone_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
 	struct device device;
+	struct attribute_group trips_attribute_group;
 	struct thermal_attr *trip_temp_attrs;
 	struct thermal_attr *trip_type_attrs;
 	struct thermal_attr *trip_hyst_attrs;
-- 
2.7.4

WARNING: multiple messages have this Message-ID (diff)
From: Zhang Rui <rui.zhang@intel.com>
To: Eduardo Valentin <edubezval@gmail.com>
Cc: Linux PM <linux-pm@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>, Keerthy <a0393675@ti.com>
Subject: Re: [PATCHv4 14/48] thermal: core: move trips attributes to tz->device.groups
Date: Fri, 17 Jun 2016 16:44:56 +0800	[thread overview]
Message-ID: <1466153096.9422.34.camel@intel.com> (raw)
In-Reply-To: <1464675535-2433-15-git-send-email-edubezval@gmail.com>

On 一, 2016-05-30 at 23:18 -0700, Eduardo Valentin wrote:
> Finally, move the last thermal zone sysfs attributes to
> tz->device.groups: trips attributes. This requires adding a
> attribute_group to thermal_zone_device, creating it dynamically, and
> then setting all trips attributes in it. The trips attribute is then
> added to the tz->device.groups.
> 
> As the removal of all attributes are handled by device core, the
> device
> remove calls are not needed anymore.
> 
> Cc: Zhang Rui <rui.zhang@intel.com>
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
> ---
>  drivers/thermal/thermal_core.c | 77 +++++++++++++++++++++-----------
> ----------
>  include/linux/thermal.h        |  2 ++
>  2 files changed, 41 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c
> b/drivers/thermal/thermal_core.c
> index ba4f7a9..0b60b04 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -1188,8 +1188,9 @@ static const struct attribute_group
> *thermal_zone_attribute_groups[] = {
>   */
>  static int create_trip_attrs(struct thermal_zone_device *tz, int
> mask)
>  {
> -	int indx;
>  	int size = sizeof(struct thermal_attr) * tz->trips;
> +	struct attribute **attrs;
> +	int indx;
>  
>  	tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
>  	if (!tz->trip_type_attrs)
> @@ -1210,6 +1211,15 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  		}
>  	}
>  
> +	attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1,
> GFP_KERNEL);
> +	if (!attrs) {
> +		kfree(tz->trip_type_attrs);
> +		kfree(tz->trip_temp_attrs);
> +		if (tz->ops->get_trip_hyst)
> +			kfree(tz->trip_hyst_attrs);
> +		return -ENOMEM;
> +	}
> +
>  	for (indx = 0; indx < tz->trips; indx++) {
>  		/* create trip type attribute */
>  		snprintf(tz->trip_type_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> @@ -1220,9 +1230,7 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  						tz-
> >trip_type_attrs[indx].name;
>  		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
>  		tz->trip_type_attrs[indx].attr.show =
> trip_point_type_show;
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_type_attrs[indx].attr);
> +		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
>  
>  		/* create trip temp attribute */
>  		snprintf(tz->trip_temp_attrs[indx].name,
> THERMAL_NAME_LENGTH,
> @@ -1239,9 +1247,7 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  			tz->trip_temp_attrs[indx].attr.store =
>  							trip_point_t
> emp_store;
>  		}
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_temp_attrs[indx].attr);
> +		attrs[indx + tz->trips] = &tz-
> >trip_temp_attrs[indx].attr.attr;
>  
>  		/* create Optional trip hyst attribute */
>  		if (!tz->ops->get_trip_hyst)
> @@ -1259,45 +1265,38 @@ static int create_trip_attrs(struct
> thermal_zone_device *tz, int mask)
>  			tz->trip_hyst_attrs[indx].attr.store =
>  					trip_point_hyst_store;
>  		}
> -
> -		device_create_file(&tz->device,
> -				   &tz->trip_hyst_attrs[indx].attr);
> +		attrs[indx + tz->trips * 2] =
> +					&tz-
> >trip_hyst_attrs[indx].attr.attr;
>  	}
> -	return 0;
> -}
> +	attrs[tz->trips * 3] = NULL;

why bother clearing it explicitly? kzalloc already handles this, right?

> -static void remove_trip_attrs(struct thermal_zone_device *tz)
> -{
> -	int indx;
> +	tz->trips_attribute_group.attrs = attrs;
>  
> -	for (indx = 0; indx < tz->trips; indx++) {
> -		device_remove_file(&tz->device,
> -				   &tz->trip_type_attrs[indx].attr);
> -		device_remove_file(&tz->device,
> -				   &tz->trip_temp_attrs[indx].attr);
> -		if (tz->ops->get_trip_hyst)
> -			device_remove_file(&tz->device,
> -					   &tz-
> >trip_hyst_attrs[indx].attr);
> -	}
> -	kfree(tz->trip_type_attrs);
> -	kfree(tz->trip_temp_attrs);
> -	kfree(tz->trip_hyst_attrs);
> +	return 0;
>  }
>  
> -static int thermal_zone_create_device_groups(struct
> thermal_zone_device *tz)
> +static int thermal_zone_create_device_groups(struct
> thermal_zone_device *tz,
> +					     int mask)
>  {
>  	const struct attribute_group **groups;
> -	int i, size;
> +	int i, size, result;
> +
> +	result = create_trip_attrs(tz, mask);
> +	if (result)
> +		return result;
>  
> -	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1;
> +	/* we need one extra for trips and the NULL to terminate the
> array */
> +	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
>  	/* This also takes care of API requirement to be NULL
> terminated */
>  	groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
>  	if (!groups)
>  		return -ENOMEM;
>  
> -	for (i = 0; i < size - 1; i++)
> +	for (i = 0; i < size - 2; i++)
>  		groups[i] = thermal_zone_attribute_groups[i];
>  
> +	groups[size - 2] = &tz->trips_attribute_group;
> +

Problem is that, previously, create_trip_attrs() does not handle the
case that tz->trips == 0 good enough, it happens to not bring big
problem.
tz->trip_type_attrs/tz->trip_temp_attrs/tz->trip_hyst_attrs is set
to ZERO_SIZE_PTR when tz->trips equals 0, kfree() handles this.
But registering a sysfs group with one invalid attribute item is wrong.
And this causes oops in my machine when test_power driver, which has no
trip point, is unloaded. And maybe this is also the root cause of this
report http://www.spinics.net/lists/kernel/msg2280260.html

Attached is an updated version, which creates trip attributes only if
tz->trips > 0, which solves the problem for me.

>From e1e917e790b70b88bd418545a29b1eefa01a5566 Mon Sep 17 00:00:00 2001
From: Eduardo Valentin <edubezval@gmail.com>
Date: Mon, 30 May 2016 23:18:21 -0700
Subject: [PATCH] thermal: core: move trips attributes to tz->device.groups

Finally, move the last thermal zone sysfs attributes to
tz->device.groups: trips attributes. This requires adding a
attribute_group to thermal_zone_device, creating it dynamically, and
then setting all trips attributes in it. The trips attribute is then
added to the tz->device.groups.

As the removal of all attributes are handled by device core, the device
remove calls are not needed anymore.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
 drivers/thermal/thermal_core.c | 78 ++++++++++++++++++++++--------------------
 include/linux/thermal.h        |  2 ++
 2 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 657ba02..9926c89 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1188,8 +1188,9 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
  */
 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 {
-	int indx;
 	int size = sizeof(struct thermal_attr) * tz->trips;
+	struct attribute **attrs;
+	int indx;
 
 	tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
 	if (!tz->trip_type_attrs)
@@ -1210,6 +1211,15 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 		}
 	}
 
+	attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1, GFP_KERNEL);
+	if (!attrs) {
+		kfree(tz->trip_type_attrs);
+		kfree(tz->trip_temp_attrs);
+		if (tz->ops->get_trip_hyst)
+			kfree(tz->trip_hyst_attrs);
+		return -ENOMEM;
+	}
+
 	for (indx = 0; indx < tz->trips; indx++) {
 		/* create trip type attribute */
 		snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
@@ -1220,9 +1230,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 						tz->trip_type_attrs[indx].name;
 		tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
 		tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
-
-		device_create_file(&tz->device,
-				   &tz->trip_type_attrs[indx].attr);
+		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
 
 		/* create trip temp attribute */
 		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
@@ -1239,9 +1247,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 			tz->trip_temp_attrs[indx].attr.store =
 							trip_point_temp_store;
 		}
-
-		device_create_file(&tz->device,
-				   &tz->trip_temp_attrs[indx].attr);
+		attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
 
 		/* create Optional trip hyst attribute */
 		if (!tz->ops->get_trip_hyst)
@@ -1259,45 +1265,39 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
 			tz->trip_hyst_attrs[indx].attr.store =
 					trip_point_hyst_store;
 		}
-
-		device_create_file(&tz->device,
-				   &tz->trip_hyst_attrs[indx].attr);
+		attrs[indx + tz->trips * 2] =
+					&tz->trip_hyst_attrs[indx].attr.attr;
 	}
-	return 0;
-}
+	attrs[tz->trips * 3] = NULL;
 
-static void remove_trip_attrs(struct thermal_zone_device *tz)
-{
-	int indx;
+	tz->trips_attribute_group.attrs = attrs;
 
-	for (indx = 0; indx < tz->trips; indx++) {
-		device_remove_file(&tz->device,
-				   &tz->trip_type_attrs[indx].attr);
-		device_remove_file(&tz->device,
-				   &tz->trip_temp_attrs[indx].attr);
-		if (tz->ops->get_trip_hyst)
-			device_remove_file(&tz->device,
-					   &tz->trip_hyst_attrs[indx].attr);
-	}
-	kfree(tz->trip_type_attrs);
-	kfree(tz->trip_temp_attrs);
-	kfree(tz->trip_hyst_attrs);
+	return 0;
 }
 
-static int thermal_zone_create_device_groups(struct thermal_zone_device *tz)
+static int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
+					     int mask)
 {
 	const struct attribute_group **groups;
-	int i, size;
+	int i, size, result;
 
-	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1;
+	/* we need one extra for trips and the NULL to terminate the array */
+	size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
 	/* This also takes care of API requirement to be NULL terminated */
 	groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
 	if (!groups)
 		return -ENOMEM;
 
-	for (i = 0; i < size - 1; i++)
+	for (i = 0; i < size - 2; i++)
 		groups[i] = thermal_zone_attribute_groups[i];
 
+	if (tz->trips) {
+		result = create_trip_attrs(tz, mask);
+		if (result)
+			return result;
+		groups[size - 2] = &tz->trips_attribute_group;
+	}
+
 	tz->device.groups = groups;
 
 	return 0;
@@ -1934,8 +1934,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	tz->passive_delay = passive_delay;
 	tz->polling_delay = polling_delay;
 
+	/* sys I/F */
 	/* Add nodes that are always present via .groups */
-	thermal_zone_create_device_groups(tz);
+	result = thermal_zone_create_device_groups(tz, mask);
+	if (result)
+		goto unregister;
+
 	/* A new thermal zone needs to be updated anyway. */
 	atomic_set(&tz->need_update, 1);
 
@@ -1947,11 +1951,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 		return ERR_PTR(result);
 	}
 
-	/* sys I/F */
-	result = create_trip_attrs(tz, mask);
-	if (result)
-		goto unregister;
-
 	for (count = 0; count < trips; count++) {
 		if (tz->ops->get_trip_type(tz, count, &trip_type))
 			set_bit(count, &tz->trips_disabled);
@@ -2056,7 +2055,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
 	thermal_zone_device_set_polling(tz, 0);
 
-	remove_trip_attrs(tz);
+	kfree(tz->trip_type_attrs);
+	kfree(tz->trip_temp_attrs);
+	kfree(tz->trip_hyst_attrs);
+	kfree(tz->trips_attribute_group.attrs);
 	thermal_set_governor(tz, NULL);
 
 	thermal_remove_hwmon_sysfs(tz);
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ee517be..580809c 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/idr.h>
 #include <linux/device.h>
+#include <linux/sysfs.h>
 #include <linux/workqueue.h>
 #include <uapi/linux/thermal.h>
 
@@ -187,6 +188,7 @@ struct thermal_zone_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
 	struct device device;
+	struct attribute_group trips_attribute_group;
 	struct thermal_attr *trip_temp_attrs;
 	struct thermal_attr *trip_type_attrs;
 	struct thermal_attr *trip_hyst_attrs;
-- 
2.7.4

  reply	other threads:[~2016-06-17  8:44 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-31  6:18 [PATCHv4 00/48] thermal: reorganizing thermal core Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 01/48] thermal: core: prevent zones with no types to be registered Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 02/48] thermal: core: group thermal_zone DEVICE_ATTR's declarations Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 03/48] thermal: core: group device_create_file() calls that are always created Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 04/48] thermal: core: use dev.groups to manage always present tz attributes Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 05/48] thermal: core: move emul_temp creation to tz->device.groups Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 06/48] thermal: core: move mode attribute " Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 07/48] thermal: core: move passive attr " Eduardo Valentin
2016-06-16  3:27   ` Zhang Rui
2016-06-16  4:15     ` Zhang Rui
2016-06-16  4:15       ` Zhang Rui
2016-05-31  6:18 ` [PATCHv4 08/48] thermal: core: improve power actor documentation Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 09/48] thermal: core: move power actor code out of sysfs I/F section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 10/48] thermal: core: remove useless empty line Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 11/48] thermal: core: fix style on remove_trip_attrs() Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 12/48] thermal: core: move the trip attrs to the tz sysfs I/F section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 13/48] thermal: core: create tz->device.groups dynamically Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 14/48] thermal: core: move trips attributes to tz->device.groups Eduardo Valentin
2016-06-17  8:44   ` Zhang Rui [this message]
2016-06-17  8:44     ` Zhang Rui
2016-05-31  6:18 ` [PATCHv4 15/48] thermal: core: remove unnecessary device_remove() calls Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 16/48] thermal: core: split passive_store Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 17/48] thermal: core: split policy_store Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 18/48] thermal: core: split available_policies_show() Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 19/48] thermal: core: move to_thermal_zone() macro to header file Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 20/48] thermal: core: treat correctly the return value of *scanf calls Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 21/48] thermal: core: match parenthesis on code alignment Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 22/48] thermal: core: move thermal_zone sysfs to thermal_sysfs.c Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 23/48] thermal: core: move to_cooling_device macro to header file Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 24/48] thermal: core: move cooling device sysfs to thermal_sysfs.c Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 25/48] thermal: core: remove a couple of style issues on helpers Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 26/48] thermal: core: introduce thermal_helpers.c Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 27/48] thermal: core: group functions related to governor handling Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 28/48] thermal: core: move idr handling to device management section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 29/48] thermal: core: small style fix on __unbind() helper Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 30/48] thermal: core: move __unbind() helper to where it is used Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 31/48] thermal: core: move bind_cdev() " Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 32/48] thermal: core: move bind_tz() " Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 33/48] thermal: core: fix couple of style issues on __bind() helper Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 34/48] thermal: core: move __bind() to where it is used Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 35/48] thermal: core: add inline to print_bind_err_msg() Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 36/48] thermal: core: move notify to the zone update section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 37/48] thermal: core: add a comment describing the main update loop Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 38/48] thermal: core: add a comment describing the power actor section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 39/48] thermal: core: add a comment describing the device management section Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 40/48] thermal: sysfs: remove symbols of emul_temp when config is disabled Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 41/48] thermal: core: remove FSF address in the GPL notice Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 42/48] thermal: core: small style fix when checking for __find_governor() Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 43/48] thermal: core: standardize line breaking alignment Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 44/48] thermal: core: remove void function return statements Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 45/48] thermal: core: remove style warnings and checks Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 46/48] thermal: core: improve kerneldoc entry of thermal_cooling_device_unregister Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 47/48] thermal: core: use kzalloc(sizeof(*ptr),...) Eduardo Valentin
2016-05-31  6:18 ` [PATCHv4 48/48] thermal: sysfs: use kcalloc() instead of kzalloc() Eduardo Valentin
2016-05-31  9:42 ` [PATCHv4 00/48] thermal: reorganizing thermal core Keerthy

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=1466153096.9422.34.camel@intel.com \
    --to=rui.zhang@intel.com \
    --cc=a0393675@ti.com \
    --cc=edubezval@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    /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.