2016-04-23 23:34:47

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 00/11] thermal: sysfs rework

Hello Linux PM, Rui,

This is a series of patches for review. In this series I am proposing
to rework how we do sysfs, mainly for thermal zone attributes.

Currently, as many features have been added recently, there are more
than one way of attribute handling. This series is an attempt to
standardize the sysfs handling. Essentially, this will move all
attributes to the dev.groups field, so sysfs core code handles the
attributes properly. Apart from the obvious code organization benefit,
this change should also take care properly of attribute destruction,
when thermal zones are removed.

The cooling device attributes are more or less handled in this manner.
But they still require some piece of rework. In this series, I am not
touching them yet.

I don't expect any impact on userspace.

The only change in behavior is that now, thermal zones with empty
.type will not be allowed to be registered.

Please give your inputs.

BR,

Eduardo Valentin
------
Eduardo Valentin (11):
thermal: prevent zones with no types to be registered
thermal: group thermal_zone DEVICE_ATTR's declarations
thermal: group device_create_file() calls that are always created
thermal: use dev.groups to manage always present tz attributes
thermal: move emul_temp creation to tz->device.groups
thermal: move mode attribute to tz->device.groups
thermal: move passive attr to tz->device.groups
thermal: move power actor code out of sysfs I/F section
thermal: move the trip attrs to the tz sysfs I/F section
thermal: create tz->device.groups dynamically
thermal: move trips attributes to tz->device.groups

drivers/thermal/thermal_core.c | 549 ++++++++++++++++++++++-------------------
include/linux/thermal.h | 2 +
2 files changed, 295 insertions(+), 256 deletions(-)

--
2.1.4


2016-04-23 23:34:50

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 02/11] thermal: group thermal_zone DEVICE_ATTR's declarations

Simply reorganize the code to have all DEVICE_ATTR's
in one point in the file.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 650e5fa..e28d547 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -917,7 +917,6 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,

return ret ? ret : count;
}
-static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);

static ssize_t
sustainable_power_show(struct device *dev, struct device_attribute *devattr,
@@ -948,8 +947,6 @@ sustainable_power_store(struct device *dev, struct device_attribute *devattr,

return count;
}
-static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
- sustainable_power_store);

#define create_s32_tzp_attr(name) \
static ssize_t \
@@ -992,6 +989,16 @@ create_s32_tzp_attr(slope);
create_s32_tzp_attr(offset);
#undef create_s32_tzp_attr

+static DEVICE_ATTR(type, 0444, type_show, NULL);
+static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
+static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
+static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
+static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
+static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
+ sustainable_power_store);
+
static struct device_attribute *dev_tzp_attrs[] = {
&dev_attr_sustainable_power,
&dev_attr_k_po,
@@ -1099,13 +1106,6 @@ int power_actor_set_power(struct thermal_cooling_device *cdev,
return 0;
}

-static DEVICE_ATTR(type, 0444, type_show, NULL);
-static DEVICE_ATTR(temp, 0444, temp_show, NULL);
-static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
-static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
-static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
-static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
-
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
container_of(_dev, struct thermal_cooling_device, device)
--
2.1.4

2016-04-23 23:34:54

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 04/11] thermal: use dev.groups to manage always present tz attributes

Thermal zones attributes are all being created using
device_create_file(). This has the disadvantage of making the code
complicated and sometimes we may miss the cleanup of them.

This patch starts to move the thermal zone sysfs attributes to the
dev.groups, so Linux device core manage them for us. For now, this patch
only moves those attributes are always present regardless of thermal
zone condition.

This change has also the advantage of cleaning up the thermal zone
parameters sysfs entries that are left unclean after device
registration.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 86 ++++++++++++++++--------------------------
1 file changed, 33 insertions(+), 53 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 2227264..0a7d918 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -989,42 +989,46 @@ create_s32_tzp_attr(slope);
create_s32_tzp_attr(offset);
#undef create_s32_tzp_attr

+/*
+ * These are thermal zone device attributes that will always be present.
+ * All the attributes created for tzp (create_s32_tzp_attr) also are always
+ * present on the sysfs interface.
+ */
static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(temp, 0444, temp_show, NULL);
-static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
-static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
-static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
sustainable_power_store);

-static struct device_attribute *dev_tzp_attrs[] = {
- &dev_attr_sustainable_power,
- &dev_attr_k_po,
- &dev_attr_k_pu,
- &dev_attr_k_i,
- &dev_attr_k_d,
- &dev_attr_integral_cutoff,
- &dev_attr_slope,
- &dev_attr_offset,
-};
-
-static int create_tzp_attrs(struct device *dev)
-{
- int i;
+/* These thermal zone device attributes are created based on conditions */
+static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
+static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);

- for (i = 0; i < ARRAY_SIZE(dev_tzp_attrs); i++) {
- int ret;
- struct device_attribute *dev_attr = dev_tzp_attrs[i];
+static struct attribute *thermal_zone_dev_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_temp.attr,
+ &dev_attr_policy.attr,
+ &dev_attr_available_policies.attr,
+ &dev_attr_sustainable_power.attr,
+ &dev_attr_k_po.attr,
+ &dev_attr_k_pu.attr,
+ &dev_attr_k_i.attr,
+ &dev_attr_k_d.attr,
+ &dev_attr_integral_cutoff.attr,
+ &dev_attr_slope.attr,
+ &dev_attr_offset.attr,
+};

- ret = device_create_file(dev, dev_attr);
- if (ret)
- return ret;
- }
+static struct attribute_group thermal_zone_attribute_group = {
+ .attrs = thermal_zone_dev_attrs,
+};

- return 0;
-}
+static const struct attribute_group *thermal_zone_attribute_groups[] = {
+ &thermal_zone_attribute_group,
+ NULL
+};

/**
* power_actor_get_max_power() - get the maximum power that a cdev can consume
@@ -1846,6 +1850,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
tz->trips = trips;
tz->passive_delay = passive_delay;
tz->polling_delay = polling_delay;
+
+ /* Add nodes that are always present via .groups */
+ tz->device.groups = thermal_zone_attribute_groups;
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);

@@ -1892,29 +1899,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
goto unregister;
}

- result = device_create_file(&tz->device, &dev_attr_type);
- if (result)
- goto unregister;
-
- result = device_create_file(&tz->device, &dev_attr_temp);
- if (result)
- goto unregister;
-
- /* Create policy attribute */
- result = device_create_file(&tz->device, &dev_attr_policy);
- if (result)
- goto unregister;
-
- /* Create available_policies attribute */
- result = device_create_file(&tz->device, &dev_attr_available_policies);
- if (result)
- goto unregister;
-
- /* Add thermal zone params */
- result = create_tzp_attrs(&tz->device);
- if (result)
- goto unregister;
-
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);

@@ -2009,12 +1993,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)

thermal_zone_device_set_polling(tz, 0);

- device_remove_file(&tz->device, &dev_attr_type);
- device_remove_file(&tz->device, &dev_attr_temp);
if (tz->ops->get_mode)
device_remove_file(&tz->device, &dev_attr_mode);
- device_remove_file(&tz->device, &dev_attr_policy);
- device_remove_file(&tz->device, &dev_attr_available_policies);
remove_trip_attrs(tz);
thermal_set_governor(tz, NULL);

--
2.1.4

2016-04-23 23:35:01

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 09/11] thermal: move the trip attrs to the tz sysfs I/F section

Code reorganization to keep all the sysfs I/F of a thermal zone in the
same section.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 218 ++++++++++++++++++++---------------------
1 file changed, 109 insertions(+), 109 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 7c95978..b1b2945 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1172,6 +1172,115 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
NULL
};

+/**
+ * create_trip_attrs() - create attributes for trip points
+ * @tz: the thermal zone device
+ * @mask: Writeable trip point bitmap.
+ *
+ * helper function to instantiate sysfs entries for every trip
+ * point and its properties of a struct thermal_zone_device.
+ *
+ * Return: 0 on success, the proper error value otherwise.
+ */
+static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
+{
+ int indx;
+ int size = sizeof(struct thermal_attr) * tz->trips;
+
+ tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
+ if (!tz->trip_type_attrs)
+ return -ENOMEM;
+
+ tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
+ if (!tz->trip_temp_attrs) {
+ kfree(tz->trip_type_attrs);
+ return -ENOMEM;
+ }
+
+ if (tz->ops->get_trip_hyst) {
+ tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
+ if (!tz->trip_hyst_attrs) {
+ kfree(tz->trip_type_attrs);
+ kfree(tz->trip_temp_attrs);
+ return -ENOMEM;
+ }
+ }
+
+
+ for (indx = 0; indx < tz->trips; indx++) {
+ /* create trip type attribute */
+ snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_type", indx);
+
+ sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
+ tz->trip_type_attrs[indx].attr.attr.name =
+ 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);
+
+ /* create trip temp attribute */
+ snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_temp", indx);
+
+ sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
+ tz->trip_temp_attrs[indx].attr.attr.name =
+ tz->trip_temp_attrs[indx].name;
+ tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
+ tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
+ if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
+ mask & (1 << indx)) {
+ tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
+ tz->trip_temp_attrs[indx].attr.store =
+ trip_point_temp_store;
+ }
+
+ device_create_file(&tz->device,
+ &tz->trip_temp_attrs[indx].attr);
+
+ /* create Optional trip hyst attribute */
+ if (!tz->ops->get_trip_hyst)
+ continue;
+ snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
+ "trip_point_%d_hyst", indx);
+
+ sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
+ tz->trip_hyst_attrs[indx].attr.attr.name =
+ tz->trip_hyst_attrs[indx].name;
+ tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
+ tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
+ if (tz->ops->set_trip_hyst) {
+ tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
+ tz->trip_hyst_attrs[indx].attr.store =
+ trip_point_hyst_store;
+ }
+
+ device_create_file(&tz->device,
+ &tz->trip_hyst_attrs[indx].attr);
+ }
+ return 0;
+}
+
+static void remove_trip_attrs(struct thermal_zone_device *tz)
+{
+ int indx;
+
+ 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);
+}
+
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
container_of(_dev, struct thermal_cooling_device, device)
@@ -1730,115 +1839,6 @@ void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
EXPORT_SYMBOL_GPL(thermal_notify_framework);

/**
- * create_trip_attrs() - create attributes for trip points
- * @tz: the thermal zone device
- * @mask: Writeable trip point bitmap.
- *
- * helper function to instantiate sysfs entries for every trip
- * point and its properties of a struct thermal_zone_device.
- *
- * Return: 0 on success, the proper error value otherwise.
- */
-static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
-{
- int indx;
- int size = sizeof(struct thermal_attr) * tz->trips;
-
- tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_type_attrs)
- return -ENOMEM;
-
- tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_temp_attrs) {
- kfree(tz->trip_type_attrs);
- return -ENOMEM;
- }
-
- if (tz->ops->get_trip_hyst) {
- tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
- if (!tz->trip_hyst_attrs) {
- kfree(tz->trip_type_attrs);
- kfree(tz->trip_temp_attrs);
- return -ENOMEM;
- }
- }
-
-
- for (indx = 0; indx < tz->trips; indx++) {
- /* create trip type attribute */
- snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_type", indx);
-
- sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
- tz->trip_type_attrs[indx].attr.attr.name =
- 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);
-
- /* create trip temp attribute */
- snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_temp", indx);
-
- sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
- tz->trip_temp_attrs[indx].attr.attr.name =
- tz->trip_temp_attrs[indx].name;
- tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
- if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
- mask & (1 << indx)) {
- tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_temp_attrs[indx].attr.store =
- trip_point_temp_store;
- }
-
- device_create_file(&tz->device,
- &tz->trip_temp_attrs[indx].attr);
-
- /* create Optional trip hyst attribute */
- if (!tz->ops->get_trip_hyst)
- continue;
- snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
- "trip_point_%d_hyst", indx);
-
- sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
- tz->trip_hyst_attrs[indx].attr.attr.name =
- tz->trip_hyst_attrs[indx].name;
- tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
- tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
- if (tz->ops->set_trip_hyst) {
- tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
- tz->trip_hyst_attrs[indx].attr.store =
- trip_point_hyst_store;
- }
-
- device_create_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
- }
- return 0;
-}
-
-static void remove_trip_attrs(struct thermal_zone_device *tz)
-{
- int indx;
-
- 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);
-}
-
-/**
* thermal_zone_device_register() - register a new thermal zone device
* @type: the thermal zone device type
* @trips: the number of trip points the thermal zone support
--
2.1.4

2016-04-23 23:35:06

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 11/11] thermal: 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 <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 75 +++++++++++++++++++++---------------------
include/linux/thermal.h | 2 ++
2 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 13a85d7..e844a04 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1184,8 +1184,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)
@@ -1206,6 +1207,14 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
}
}

+ attrs = kzalloc(sizeof(*attrs) * tz->trips * 3, 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 */
@@ -1217,9 +1226,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,
@@ -1236,9 +1243,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_type_attrs[indx].attr.attr;

/* create Optional trip hyst attribute */
if (!tz->ops->get_trip_hyst)
@@ -1256,45 +1261,37 @@ 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_type_attrs[indx].attr.attr;
}
- return 0;
-}

-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 = kzalloc(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;
+
tz->device.groups = groups;

return 0;
@@ -1931,8 +1928,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);

@@ -1944,11 +1945,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);
@@ -2053,7 +2049,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 97b86c5..17c4431 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.1.4

2016-04-23 23:35:25

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 10/11] thermal: create tz->device.groups dynamically

This is a patch to allow adding groups created dynamically. For now we
create only the existing group. However, this is a preparation to allow
creating trip groups, which are determined only when the number of trips
are known at runtime.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b1b2945..13a85d7 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1169,7 +1169,7 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
&thermal_zone_attribute_group,
&thermal_zone_mode_attribute_group,
&thermal_zone_passive_attribute_group,
- NULL
+ /* This is not NULL terminated as we create the group dynamically */
};

/**
@@ -1281,6 +1281,25 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
kfree(tz->trip_hyst_attrs);
}

+static int thermal_zone_create_device_groups(struct thermal_zone_device *tz)
+{
+ const struct attribute_group **groups;
+ int i, size;
+
+ size = ARRAY_SIZE(thermal_zone_attribute_groups) + 1;
+ /* This also takes care of API requirement to be NULL terminated */
+ groups = kzalloc(size * sizeof(*groups), GFP_KERNEL);
+ if (!groups)
+ return -ENOMEM;
+
+ for (i = 0; i < size - 1; i++)
+ groups[i] = thermal_zone_attribute_groups[i];
+
+ tz->device.groups = groups;
+
+ return 0;
+}
+
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
container_of(_dev, struct thermal_cooling_device, device)
@@ -1913,7 +1932,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
tz->polling_delay = polling_delay;

/* Add nodes that are always present via .groups */
- tz->device.groups = thermal_zone_attribute_groups;
+ thermal_zone_create_device_groups(tz);
/* A new thermal zone needs to be updated anyway. */
atomic_set(&tz->need_update, 1);

@@ -2042,7 +2061,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
idr_destroy(&tz->idr);
mutex_destroy(&tz->lock);
device_unregister(&tz->device);
- return;
+ kfree(tz->device.groups);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);

--
2.1.4

2016-04-23 23:34:58

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 06/11] thermal: move mode attribute to tz->device.groups

Moving mode attribute to tz->device.groups requires the implementation
of a .is_visible() callback. The condition returned by .is_visible() of
the mode attribute group is kept the same, we allow the attribute to be
visible only if ops->get_mode() is set by the thermal driver.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e32f851..6e44038 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1006,6 +1006,7 @@ static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);

+/* These attributes are unconditionally added to a thermal zone */
static struct attribute *thermal_zone_dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_temp.attr,
@@ -1028,8 +1029,34 @@ static struct attribute_group thermal_zone_attribute_group = {
.attrs = thermal_zone_dev_attrs,
};

+/* We expose mode only if .get_mode is present */
+static struct attribute *thermal_zone_mode_attrs[] = {
+ &dev_attr_mode.attr,
+};
+
+static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int attrno)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct thermal_zone_device *tz;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ if (tz->ops->get_mode)
+ return attr->mode;
+
+ return 0;
+}
+
+static struct attribute_group thermal_zone_mode_attribute_group = {
+ .attrs = thermal_zone_mode_attrs,
+ .is_visible = thermal_zone_mode_is_visible,
+};
+
static const struct attribute_group *thermal_zone_attribute_groups[] = {
&thermal_zone_attribute_group,
+ &thermal_zone_mode_attribute_group,
NULL
};

@@ -1868,12 +1895,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
}

/* sys I/F */
- if (ops->get_mode) {
- result = device_create_file(&tz->device, &dev_attr_mode);
- if (result)
- goto unregister;
- }
-
result = create_trip_attrs(tz, mask);
if (result)
goto unregister;
@@ -1990,8 +2011,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)

thermal_zone_device_set_polling(tz, 0);

- if (tz->ops->get_mode)
- device_remove_file(&tz->device, &dev_attr_mode);
remove_trip_attrs(tz);
thermal_set_governor(tz, NULL);

--
2.1.4

2016-04-23 23:36:01

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 08/11] thermal: move power actor code out of sysfs I/F section

Simply reorganize code to keep only functions of sysfs interface
of thermal zone device together. Therefore, move the power actor code
out of the sysfs I/F section.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 160 ++++++++++++++++++++---------------------
1 file changed, 80 insertions(+), 80 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e48c720..7c95978 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -582,6 +582,86 @@ static void thermal_zone_device_check(struct work_struct *work)
thermal_zone_device_update(tz);
}

+/**
+ * power_actor_get_max_power() - get the maximum power that a cdev can consume
+ * @cdev: pointer to &thermal_cooling_device
+ * @tz: a valid thermal zone device pointer
+ * @max_power: pointer in which to store the maximum power
+ *
+ * Calculate the maximum power consumption in milliwats that the
+ * cooling device can currently consume and store it in @max_power.
+ *
+ * Return: 0 on success, -EINVAL if @cdev doesn't support the
+ * power_actor API or -E* on other error.
+ */
+int power_actor_get_max_power(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz, u32 *max_power)
+{
+ if (!cdev_is_power_actor(cdev))
+ return -EINVAL;
+
+ return cdev->ops->state2power(cdev, tz, 0, max_power);
+}
+
+/**
+ * power_actor_get_min_power() - get the mainimum power that a cdev can consume
+ * @cdev: pointer to &thermal_cooling_device
+ * @tz: a valid thermal zone device pointer
+ * @min_power: pointer in which to store the minimum power
+ *
+ * Calculate the minimum power consumption in milliwatts that the
+ * cooling device can currently consume and store it in @min_power.
+ *
+ * Return: 0 on success, -EINVAL if @cdev doesn't support the
+ * power_actor API or -E* on other error.
+ */
+int power_actor_get_min_power(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz, u32 *min_power)
+{
+ unsigned long max_state;
+ int ret;
+
+ if (!cdev_is_power_actor(cdev))
+ return -EINVAL;
+
+ ret = cdev->ops->get_max_state(cdev, &max_state);
+ if (ret)
+ return ret;
+
+ return cdev->ops->state2power(cdev, tz, max_state, min_power);
+}
+
+/**
+ * power_actor_set_power() - limit the maximum power that a cooling device can consume
+ * @cdev: pointer to &thermal_cooling_device
+ * @instance: thermal instance to update
+ * @power: the power in milliwatts
+ *
+ * Set the cooling device to consume at most @power milliwatts.
+ *
+ * Return: 0 on success, -EINVAL if the cooling device does not
+ * implement the power actor API or -E* for other failures.
+ */
+int power_actor_set_power(struct thermal_cooling_device *cdev,
+ struct thermal_instance *instance, u32 power)
+{
+ unsigned long state;
+ int ret;
+
+ if (!cdev_is_power_actor(cdev))
+ return -EINVAL;
+
+ ret = cdev->ops->power2state(cdev, instance->tz, power, &state);
+ if (ret)
+ return ret;
+
+ instance->target = state;
+ cdev->updated = false;
+ thermal_cdev_update(cdev);
+
+ return 0;
+}
+
/* sys I/F for thermal zone */

#define to_thermal_zone(_dev) \
@@ -1092,86 +1172,6 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
NULL
};

-/**
- * power_actor_get_max_power() - get the maximum power that a cdev can consume
- * @cdev: pointer to &thermal_cooling_device
- * @tz: a valid thermal zone device pointer
- * @max_power: pointer in which to store the maximum power
- *
- * Calculate the maximum power consumption in milliwats that the
- * cooling device can currently consume and store it in @max_power.
- *
- * Return: 0 on success, -EINVAL if @cdev doesn't support the
- * power_actor API or -E* on other error.
- */
-int power_actor_get_max_power(struct thermal_cooling_device *cdev,
- struct thermal_zone_device *tz, u32 *max_power)
-{
- if (!cdev_is_power_actor(cdev))
- return -EINVAL;
-
- return cdev->ops->state2power(cdev, tz, 0, max_power);
-}
-
-/**
- * power_actor_get_min_power() - get the mainimum power that a cdev can consume
- * @cdev: pointer to &thermal_cooling_device
- * @tz: a valid thermal zone device pointer
- * @min_power: pointer in which to store the minimum power
- *
- * Calculate the minimum power consumption in milliwatts that the
- * cooling device can currently consume and store it in @min_power.
- *
- * Return: 0 on success, -EINVAL if @cdev doesn't support the
- * power_actor API or -E* on other error.
- */
-int power_actor_get_min_power(struct thermal_cooling_device *cdev,
- struct thermal_zone_device *tz, u32 *min_power)
-{
- unsigned long max_state;
- int ret;
-
- if (!cdev_is_power_actor(cdev))
- return -EINVAL;
-
- ret = cdev->ops->get_max_state(cdev, &max_state);
- if (ret)
- return ret;
-
- return cdev->ops->state2power(cdev, tz, max_state, min_power);
-}
-
-/**
- * power_actor_set_power() - limit the maximum power that a cooling device can consume
- * @cdev: pointer to &thermal_cooling_device
- * @instance: thermal instance to update
- * @power: the power in milliwatts
- *
- * Set the cooling device to consume at most @power milliwatts.
- *
- * Return: 0 on success, -EINVAL if the cooling device does not
- * implement the power actor API or -E* for other failures.
- */
-int power_actor_set_power(struct thermal_cooling_device *cdev,
- struct thermal_instance *instance, u32 power)
-{
- unsigned long state;
- int ret;
-
- if (!cdev_is_power_actor(cdev))
- return -EINVAL;
-
- ret = cdev->ops->power2state(cdev, instance->tz, power, &state);
- if (ret)
- return ret;
-
- instance->target = state;
- cdev->updated = false;
- thermal_cdev_update(cdev);
-
- return 0;
-}
-
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
container_of(_dev, struct thermal_cooling_device, device)
--
2.1.4

2016-04-23 23:36:00

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 05/11] thermal: move emul_temp creation to tz->device.groups

emul_temp creation is dependent on a compile time
condition. Moving to tz->device.groups.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 0a7d918..e32f851 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -996,6 +996,7 @@ create_s32_tzp_attr(offset);
*/
static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
@@ -1004,11 +1005,13 @@ static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
/* These thermal zone device attributes are created based on conditions */
static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
-static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);

static struct attribute *thermal_zone_dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_temp.attr,
+#if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
+ &dev_attr_emul_temp.attr,
+#endif
&dev_attr_policy.attr,
&dev_attr_available_policies.attr,
&dev_attr_sustainable_power.attr,
@@ -1893,12 +1896,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
goto unregister;
}

- if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
- result = device_create_file(&tz->device, &dev_attr_emul_temp);
- if (result)
- goto unregister;
- }
-
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);

--
2.1.4

2016-04-23 23:36:38

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 07/11] thermal: move passive attr to tz->device.groups

This patch moves the passive attribute to tz->device.groups. Moving the
passive attribute also requires a .is_visible() callback implementation
for its attribute group.

The logic behind the visibility of passive attribute is kept the same.
We only expose the passive attribute if the thermal driver has exposed
at least one passive trip point.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 41 ++++++++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 6e44038..e48c720 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1054,9 +1054,41 @@ static struct attribute_group thermal_zone_mode_attribute_group = {
.is_visible = thermal_zone_mode_is_visible,
};

+/* We expose passive only if passive trips are present */
+static struct attribute *thermal_zone_passive_attrs[] = {
+ &dev_attr_passive.attr,
+};
+
+static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int attrno)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct thermal_zone_device *tz;
+ enum thermal_trip_type trip_type;
+ int count;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ for (count = 0; count < tz->trips; count++) {
+ tz->ops->get_trip_type(tz, count, &trip_type);
+
+ if (trip_type == THERMAL_TRIP_PASSIVE)
+ return attr->mode;
+ }
+
+ return 0;
+}
+
+static struct attribute_group thermal_zone_passive_attribute_group = {
+ .attrs = thermal_zone_passive_attrs,
+ .is_visible = thermal_zone_passive_is_visible,
+};
+
static const struct attribute_group *thermal_zone_attribute_groups[] = {
&thermal_zone_attribute_group,
&thermal_zone_mode_attribute_group,
+ &thermal_zone_passive_attribute_group,
NULL
};

@@ -1841,7 +1873,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
int trip_temp;
int result;
int count;
- int passive = 0;
struct thermal_governor *governor;

if (!type || strlen(type) == 0)
@@ -1902,8 +1933,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
for (count = 0; count < trips; count++) {
if (tz->ops->get_trip_type(tz, count, &trip_type))
set_bit(count, &tz->trips_disabled);
- if (trip_type == THERMAL_TRIP_PASSIVE)
- passive = 1;
if (tz->ops->get_trip_temp(tz, count, &trip_temp))
set_bit(count, &tz->trips_disabled);
/* Check for bogus trip points */
@@ -1911,12 +1940,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
set_bit(count, &tz->trips_disabled);
}

- if (!passive) {
- result = device_create_file(&tz->device, &dev_attr_passive);
- if (result)
- goto unregister;
- }
-
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);

--
2.1.4

2016-04-23 23:37:05

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 03/11] thermal: group device_create_file() calls that are always created

Simple code reorganization to group files that are always created
when registering a thermal zone.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e28d547..2227264 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1858,14 +1858,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
}

/* sys I/F */
- result = device_create_file(&tz->device, &dev_attr_type);
- if (result)
- goto unregister;
-
- result = device_create_file(&tz->device, &dev_attr_temp);
- if (result)
- goto unregister;
-
if (ops->get_mode) {
result = device_create_file(&tz->device, &dev_attr_mode);
if (result)
@@ -1900,13 +1892,16 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
goto unregister;
}

- /* Create policy attribute */
- result = device_create_file(&tz->device, &dev_attr_policy);
+ result = device_create_file(&tz->device, &dev_attr_type);
if (result)
goto unregister;

- /* Add thermal zone params */
- result = create_tzp_attrs(&tz->device);
+ result = device_create_file(&tz->device, &dev_attr_temp);
+ if (result)
+ goto unregister;
+
+ /* Create policy attribute */
+ result = device_create_file(&tz->device, &dev_attr_policy);
if (result)
goto unregister;

@@ -1915,6 +1910,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
if (result)
goto unregister;

+ /* Add thermal zone params */
+ result = create_tzp_attrs(&tz->device);
+ if (result)
+ goto unregister;
+
/* Update 'this' zone's governor information */
mutex_lock(&thermal_governor_lock);

--
2.1.4

2016-04-23 23:37:39

by Eduardo Valentin

[permalink] [raw]
Subject: [RFC PATCH 01/11] thermal: prevent zones with no types to be registered

There are APIs that rely on tz->type. This patch
prevent thermal zones without it to be registered.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d4b5465..650e5fa 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1810,6 +1810,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
int passive = 0;
struct thermal_governor *governor;

+ if (!type || strlen(type) == 0)
+ return ERR_PTR(-EINVAL);
+
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
return ERR_PTR(-EINVAL);

@@ -1835,7 +1838,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
return ERR_PTR(result);
}

- strlcpy(tz->type, type ? : "", sizeof(tz->type));
+ strlcpy(tz->type, type, sizeof(tz->type));
tz->ops = ops;
tz->tzp = tzp;
tz->device.class = &thermal_class;
@@ -1855,11 +1858,9 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
}

/* sys I/F */
- if (type) {
- result = device_create_file(&tz->device, &dev_attr_type);
- if (result)
- goto unregister;
- }
+ result = device_create_file(&tz->device, &dev_attr_type);
+ if (result)
+ goto unregister;

result = device_create_file(&tz->device, &dev_attr_temp);
if (result)
@@ -2008,8 +2009,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)

thermal_zone_device_set_polling(tz, 0);

- if (tz->type[0])
- device_remove_file(&tz->device, &dev_attr_type);
+ device_remove_file(&tz->device, &dev_attr_type);
device_remove_file(&tz->device, &dev_attr_temp);
if (tz->ops->get_mode)
device_remove_file(&tz->device, &dev_attr_mode);
--
2.1.4