2016-11-08 05:09:36

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 00/49] thermal: reorganizing thermal core

Folks, Rui,

After some radio silence time, here is a refreshed series of patches
of the thermal sysfs code refactoring.

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

After this series, thermal core is split into the following files:
- thermal_sysfs.c: contains the functions handling the sysfs nodes
- thermal_helpers.c: groups functions that do not need to touch thermal
core internal data structures, such as internal lists, and list locks.
- thermal_core.c: functions to handle the lifecycle of the subsystem,
its governors, cooling devices, thermal zone devices, and their
interactions.

Most of these changes are moving code. Because of that some patches
may have checkpatch.pl warns, but I believe they are existing warns.

I don't expect any impact on userspace.

I intentionally avoided sending the locking rework. I noticed that
it will require further analysis, as many drivers have stronger
dependency with the tz->lock, and therefore, would need to be
carefully reworked.

As for the testing aspect of this series, I have compile tested and
boot tested using a x86 laptop, an OMAP4 panda device, and with help
from Keerthy, a DRA7 device. The testing was done to check if the sysfs
nodes were still working. On top of that I have also boot tested
different devices using kernel CI infrastructure and the 0-day testing.

BR,

Eduardo Valentin (49):
thermal: core: prevent zones with no types to be registered
thermal: core: group thermal_zone DEVICE_ATTR's declarations
thermal: core: group device_create_file() calls that are always
created
thermal: core: use dev.groups to manage always present tz attributes
thermal: core: move emul_temp creation to tz->device.groups
thermal: core: move mode attribute to tz->device.groups
thermal: core: move passive attr to tz->device.groups
thermal: core: improve power actor documentation
thermal: core: move power actor code out of sysfs I/F section
thermal: core: remove useless empty line
thermal: core: fix style on remove_trip_attrs()
thermal: core: move the trip attrs to the tz sysfs I/F section
thermal: core: create tz->device.groups dynamically
thermal: core: move trips attributes to tz->device.groups
thermal: core: remove unnecessary device_remove() calls
thermal: core: split passive_store
thermal: core: split policy_store
thermal: core: split available_policies_show()
thermal: core: move to_thermal_zone() macro to header file
thermal: core: treat correctly the return value of *scanf calls
thermal: core: match parenthesis on code alignment
thermal: core: move thermal_zone sysfs to thermal_sysfs.c
thermal: core: move to_cooling_device macro to header file
thermal: core: move cooling device sysfs to thermal_sysfs.c
thermal: core: remove a couple of style issues on helpers
thermal: core: introduce thermal_helpers.c
thermal: core: group functions related to governor handling
thermal: core: move idr handling to device management section
thermal: core: small style fix on __unbind() helper
thermal: core: move __unbind() helper to where it is used
thermal: core: move bind_cdev() to where it is used
thermal: core: move bind_tz() to where it is used
thermal: core: fix couple of style issues on __bind() helper
thermal: core: move __bind() to where it is used
thermal: core: add inline to print_bind_err_msg()
thermal: core: move notify to the zone update section
thermal: core: add a comment describing the main update loop
thermal: core: add a comment describing the power actor section
thermal: core: add a comment describing the device management section
thermal: sysfs: remove symbols of emul_temp when config is disabled
thermal: core: remove FSF address in the GPL notice
thermal: core: small style fix when checking for __find_governor()
thermal: core: standardize line breaking alignment
thermal: core: remove void function return statements
thermal: core: remove style warnings and checks
thermal: core: improve kerneldoc entry of
thermal_cooling_device_unregister
thermal: core: use kzalloc(sizeof(*ptr),...)
thermal: sysfs: use kcalloc() instead of kzalloc()
thermal: core: move slop and offset helpers to thermal_helpers.c

drivers/thermal/Makefile | 3 +-
drivers/thermal/thermal_core.c | 1446 ++++++++-----------------------------
drivers/thermal/thermal_core.h | 26 +
drivers/thermal/thermal_helpers.c | 226 ++++++
drivers/thermal/thermal_sysfs.c | 771 ++++++++++++++++++++
include/linux/thermal.h | 2 +
6 files changed, 1334 insertions(+), 1140 deletions(-)
create mode 100644 drivers/thermal/thermal_helpers.c
create mode 100644 drivers/thermal/thermal_sysfs.c

--
2.1.4


2016-11-08 05:09:41

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 03/49] thermal: core: 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 97f314e..3d43c29 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1921,14 +1921,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)
@@ -1963,13 +1955,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;

@@ -1978,6 +1973,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-11-08 05:09:48

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 05/49] thermal: core: 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 3da4cd3..ec15a60 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1054,6 +1054,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,
@@ -1062,11 +1063,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,
@@ -1957,12 +1960,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-11-08 05:09:54

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 07/49] thermal: core: 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 | 45 +++++++++++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index ec8551a..f3d9fe9 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1114,9 +1114,45 @@ 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,
+ NULL,
+};
+
+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, passive = 0;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ for (count = 0; count < tz->trips && !passive; count++) {
+ tz->ops->get_trip_type(tz, count, &trip_type);
+
+ if (trip_type == THERMAL_TRIP_PASSIVE)
+ passive = 1;
+ }
+
+ if (!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
};

@@ -1906,7 +1942,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)
@@ -1967,8 +2002,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 */
@@ -1976,12 +2009,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-11-08 05:10:02

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 09/49] thermal: core: 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 | 166 ++++++++++++++++++++---------------------
1 file changed, 83 insertions(+), 83 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3d2adfa..e8098f6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -637,6 +637,89 @@ static void thermal_zone_device_check(struct work_struct *work)
thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
}

+/**
+ * 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 a cooling device consumes
+ * @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. The limit is
+ * expected to be a cap at the maximum power consumption.
+ *
+ * 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;
+ mutex_lock(&cdev->lock);
+ cdev->updated = false;
+ mutex_unlock(&cdev->lock);
+ thermal_cdev_update(cdev);
+
+ return 0;
+}
+
/* sys I/F for thermal zone */

#define to_thermal_zone(_dev) \
@@ -1156,89 +1239,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 a cooling device consumes
- * @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. The limit is
- * expected to be a cap at the maximum power consumption.
- *
- * 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;
- mutex_lock(&cdev->lock);
- cdev->updated = false;
- mutex_unlock(&cdev->lock);
- 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-11-08 05:10:09

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 11/49] thermal: core: fix style on remove_trip_attrs()

Align to parentheses, removing checkpatch warning.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 122eba7..592c72b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1900,7 +1900,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
&tz->trip_temp_attrs[indx].attr);
if (tz->ops->get_trip_hyst)
device_remove_file(&tz->device,
- &tz->trip_hyst_attrs[indx].attr);
+ &tz->trip_hyst_attrs[indx].attr);
}
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
--
2.1.4

2016-11-08 05:10:16

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 12/49] thermal: core: 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 | 216 ++++++++++++++++++++---------------------
1 file changed, 108 insertions(+), 108 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 592c72b..e399ae6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1239,6 +1239,114 @@ 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)
@@ -1800,114 +1908,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-11-08 05:10:24

by Eduardo Valentin

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 971f033..b1d6de9 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1251,8 +1251,13 @@ 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;
+
+ /* This function works only for zones with at least one trip */
+ if (tz->trips <= 0)
+ return -EINVAL;

tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
if (!tz->trip_type_attrs)
@@ -1273,6 +1278,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,
@@ -1283,9 +1297,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,
@@ -1302,9 +1314,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)
@@ -1322,45 +1332,43 @@ 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) {
+ kfree(groups);
+
+ return result;
+ }
+
+ groups[size - 2] = &tz->trips_attribute_group;
+ }
+
tz->device.groups = groups;

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

@@ -2013,11 +2025,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);
@@ -2122,7 +2129,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 511182a..e275e98 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>

@@ -204,6 +205,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-11-08 05:10:27

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 17/49] thermal: core: split policy_store

Similarly to passive_store, policy_store now is split
between thermal core data structure handling and sysfs handling.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4e315c9..23f138f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -757,6 +757,28 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
mutex_unlock(&thermal_list_lock);
}

+int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
+ char *policy)
+{
+ struct thermal_governor *gov;
+ int ret = -EINVAL;
+
+ mutex_lock(&thermal_governor_lock);
+ mutex_lock(&tz->lock);
+
+ gov = __find_governor(strim(policy));
+ if (!gov)
+ goto exit;
+
+ ret = thermal_set_governor(tz, gov);
+
+exit:
+ mutex_unlock(&tz->lock);
+ mutex_unlock(&thermal_governor_lock);
+
+ return ret;
+}
+
/* sys I/F for thermal zone */

#define to_thermal_zone(_dev) \
@@ -1001,27 +1023,16 @@ static ssize_t
policy_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- int ret = -EINVAL;
struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_governor *gov;
char name[THERMAL_NAME_LENGTH];
+ int ret;

snprintf(name, sizeof(name), "%s", buf);

- mutex_lock(&thermal_governor_lock);
- mutex_lock(&tz->lock);
-
- gov = __find_governor(strim(name));
- if (!gov)
- goto exit;
-
- ret = thermal_set_governor(tz, gov);
+ ret = thermal_zone_device_set_policy(tz, name);
if (!ret)
ret = count;

-exit:
- mutex_unlock(&tz->lock);
- mutex_unlock(&thermal_governor_lock);
return ret;
}

diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index a765c75..db65d3b 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -60,6 +60,7 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
const char *, size_t);
void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
const char *, size_t);
+int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);

#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
--
2.1.4

2016-11-08 05:10:34

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 20/49] thermal: core: treat correctly the return value of *scanf calls

This patch checks the return value of all calls to *scanf.
The check is to simply match the number of expect inputs.

The current code does not do any recovery in case the
number of treated inputs are different than the expected.
Therefore, keeping the same behavior.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f5b519a..e2c4fc4 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -874,7 +874,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if (!tz->ops->get_trip_type)
return -EPERM;

- if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
+ if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
return -EINVAL;

result = tz->ops->get_trip_type(tz, trip, &type);
@@ -906,7 +906,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
if (!tz->ops->set_trip_temp)
return -EPERM;

- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
return -EINVAL;

if (kstrtoint(buf, 10, &temperature))
@@ -932,7 +932,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (!tz->ops->get_trip_temp)
return -EPERM;

- if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
return -EINVAL;

ret = tz->ops->get_trip_temp(tz, trip, &temperature);
@@ -954,7 +954,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
if (!tz->ops->set_trip_hyst)
return -EPERM;

- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
return -EINVAL;

if (kstrtoint(buf, 10, &temperature))
@@ -984,7 +984,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
if (!tz->ops->get_trip_hyst)
return -EPERM;

- if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
return -EINVAL;

ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
@@ -999,7 +999,7 @@ passive_store(struct device *dev, struct device_attribute *attr,
struct thermal_zone_device *tz = to_thermal_zone(dev);
int state;

- if (!sscanf(buf, "%d\n", &state))
+ if (sscanf(buf, "%d\n", &state) != 1)
return -EINVAL;

/* sanity check: values below 1000 millicelcius don't make sense
@@ -1457,7 +1457,7 @@ thermal_cooling_device_cur_state_store(struct device *dev,
unsigned long state;
int result;

- if (!sscanf(buf, "%ld\n", &state))
+ if (sscanf(buf, "%ld\n", &state) != 1)
return -EINVAL;

if ((long)state < 0)
--
2.1.4

2016-11-08 05:10:43

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 19/49] thermal: core: move to_thermal_zone() macro to header file

Simply making this macro available to other thermal core
files.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3d51184..f5b519a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -800,9 +800,6 @@ int thermal_build_list_of_policies(char *buf)

/* sys I/F for thermal zone */

-#define to_thermal_zone(_dev) \
- container_of(_dev, struct thermal_zone_device, device)
-
static ssize_t
type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 8994d2a..097abee 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -54,6 +54,9 @@ struct thermal_instance {
unsigned int weight; /* The weight of the cooling device */
};

+#define to_thermal_zone(_dev) \
+ container_of(_dev, struct thermal_zone_device, device)
+
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
--
2.1.4

2016-11-08 05:10:47

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 22/49] thermal: core: move thermal_zone sysfs to thermal_sysfs.c

This is a code reorganization, simply to concentrate
the code handling sysfs in a specific file: thermal_sysfs.c.

Right now, moving only the sysfs entries of thermal_zone_device.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/Makefile | 2 +-
drivers/thermal/thermal_core.c | 609 --------------------------------------
drivers/thermal/thermal_core.h | 3 +
drivers/thermal/thermal_sysfs.c | 633 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 637 insertions(+), 610 deletions(-)
create mode 100644 drivers/thermal/thermal_sysfs.c

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c92eb22..767c3c9 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,7 +3,7 @@
#

obj-$(CONFIG_THERMAL) += thermal_sys.o
-thermal_sys-y += thermal_core.o
+thermal_sys-y += thermal_core.o thermal_sysfs.o

# interface to/from other layers providing sensors
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f66c19c..b14913e 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -798,615 +798,6 @@ int thermal_build_list_of_policies(char *buf)
return count;
}

-/* sys I/F for thermal zone */
-
-static ssize_t
-type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->type);
-}
-
-static ssize_t
-temp_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int temperature, ret;
-
- ret = thermal_zone_get_temp(tz, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-mode_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_device_mode mode;
- int result;
-
- if (!tz->ops->get_mode)
- return -EPERM;
-
- result = tz->ops->get_mode(tz, &mode);
- if (result)
- return result;
-
- return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
- : "disabled");
-}
-
-static ssize_t
-mode_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int result;
-
- if (!tz->ops->set_mode)
- return -EPERM;
-
- if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
- else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
- result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
- else
- result = -EINVAL;
-
- if (result)
- return result;
-
- return count;
-}
-
-static ssize_t
-trip_point_type_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- enum thermal_trip_type type;
- int trip, result;
-
- if (!tz->ops->get_trip_type)
- return -EPERM;
-
- if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
- return -EINVAL;
-
- result = tz->ops->get_trip_type(tz, trip, &type);
- if (result)
- return result;
-
- switch (type) {
- case THERMAL_TRIP_CRITICAL:
- return sprintf(buf, "critical\n");
- case THERMAL_TRIP_HOT:
- return sprintf(buf, "hot\n");
- case THERMAL_TRIP_PASSIVE:
- return sprintf(buf, "passive\n");
- case THERMAL_TRIP_ACTIVE:
- return sprintf(buf, "active\n");
- default:
- return sprintf(buf, "unknown\n");
- }
-}
-
-static ssize_t
-trip_point_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_temp)
- return -EPERM;
-
- if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- ret = tz->ops->set_trip_temp(tz, trip, temperature);
- if (ret)
- return ret;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-trip_point_temp_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_temp)
- return -EPERM;
-
- if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
- return -EINVAL;
-
- ret = tz->ops->get_trip_temp(tz, trip, &temperature);
-
- if (ret)
- return ret;
-
- return sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->set_trip_hyst)
- return -EPERM;
-
- if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
- return -EINVAL;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- /*
- * We are not doing any check on the 'temperature' value
- * here. The driver implementing 'set_trip_hyst' has to
- * take care of this.
- */
- ret = tz->ops->set_trip_hyst(tz, trip, temperature);
-
- if (!ret)
- thermal_zone_set_trips(tz);
-
- return ret ? ret : count;
-}
-
-static ssize_t
-trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int trip, ret;
- int temperature;
-
- if (!tz->ops->get_trip_hyst)
- return -EPERM;
-
- if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
- return -EINVAL;
-
- ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
-
- return ret ? ret : sprintf(buf, "%d\n", temperature);
-}
-
-static ssize_t
-passive_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int state;
-
- if (sscanf(buf, "%d\n", &state) != 1)
- return -EINVAL;
-
- /* sanity check: values below 1000 millicelcius don't make sense
- * and can cause the system to go into a thermal heart attack
- */
- if (state && state < 1000)
- return -EINVAL;
-
- if (state && !tz->forced_passive) {
- if (!tz->passive_delay)
- tz->passive_delay = 1000;
- thermal_zone_device_rebind_exception(tz, "Processor",
- sizeof("Processor"));
- } else if (!state && tz->forced_passive) {
- tz->passive_delay = 0;
- thermal_zone_device_unbind_exception(tz, "Processor",
- sizeof("Processor"));
- }
-
- tz->forced_passive = state;
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return count;
-}
-
-static ssize_t
-passive_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%d\n", tz->forced_passive);
-}
-
-static ssize_t
-policy_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- char name[THERMAL_NAME_LENGTH];
- int ret;
-
- snprintf(name, sizeof(name), "%s", buf);
-
- ret = thermal_zone_device_set_policy(tz, name);
- if (!ret)
- ret = count;
-
- return ret;
-}
-
-static ssize_t
-policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- return sprintf(buf, "%s\n", tz->governor->name);
-}
-
-static ssize_t
-available_policies_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- return thermal_build_list_of_policies(buf);
-}
-
-static ssize_t
-emul_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- int ret = 0;
- int temperature;
-
- if (kstrtoint(buf, 10, &temperature))
- return -EINVAL;
-
- if (!tz->ops->set_emul_temp) {
- mutex_lock(&tz->lock);
- tz->emul_temperature = temperature;
- mutex_unlock(&tz->lock);
- } else {
- ret = tz->ops->set_emul_temp(tz, temperature);
- }
-
- if (!ret)
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- return ret ? ret : count;
-}
-
-static ssize_t
-sustainable_power_show(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
-
- if (tz->tzp)
- return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
- else
- return -EIO;
-}
-
-static ssize_t
-sustainable_power_store(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct thermal_zone_device *tz = to_thermal_zone(dev);
- u32 sustainable_power;
-
- if (!tz->tzp)
- return -EIO;
-
- if (kstrtou32(buf, 10, &sustainable_power))
- return -EINVAL;
-
- tz->tzp->sustainable_power = sustainable_power;
-
- return count;
-}
-
-#define create_s32_tzp_attr(name) \
- static ssize_t \
- name##_show(struct device *dev, struct device_attribute *devattr, \
- char *buf) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- \
- if (tz->tzp) \
- return sprintf(buf, "%d\n", tz->tzp->name); \
- else \
- return -EIO; \
- } \
- \
- static ssize_t \
- name##_store(struct device *dev, struct device_attribute *devattr, \
- const char *buf, size_t count) \
- { \
- struct thermal_zone_device *tz = to_thermal_zone(dev); \
- s32 value; \
- \
- if (!tz->tzp) \
- return -EIO; \
- \
- if (kstrtos32(buf, 10, &value)) \
- return -EINVAL; \
- \
- tz->tzp->name = value; \
- \
- return count; \
- } \
- static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
-
-create_s32_tzp_attr(k_po);
-create_s32_tzp_attr(k_pu);
-create_s32_tzp_attr(k_i);
-create_s32_tzp_attr(k_d);
-create_s32_tzp_attr(integral_cutoff);
-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(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,
- sustainable_power_store);
-
-/* 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);
-
-/* These attributes are unconditionally added to a thermal zone */
-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,
- &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,
- NULL,
-};
-
-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,
- NULL,
-};
-
-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,
-};
-
-/* We expose passive only if passive trips are present */
-static struct attribute *thermal_zone_passive_attrs[] = {
- &dev_attr_passive.attr,
- NULL,
-};
-
-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, passive = 0;
-
- tz = container_of(dev, struct thermal_zone_device, device);
-
- for (count = 0; count < tz->trips && !passive; count++) {
- tz->ops->get_trip_type(tz, count, &trip_type);
-
- if (trip_type == THERMAL_TRIP_PASSIVE)
- passive = 1;
- }
-
- if (!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,
- /* This is not NULL terminated as we create the group dynamically */
-};
-
-/**
- * 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 size = sizeof(struct thermal_attr) * tz->trips;
- struct attribute **attrs;
- int indx;
-
- /* This function works only for zones with at least one trip */
- if (tz->trips <= 0)
- return -EINVAL;
-
- 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;
- }
- }
-
- 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,
- "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;
- attrs[indx] = &tz->trip_type_attrs[indx].attr.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;
- }
- attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.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;
- }
- attrs[indx + tz->trips * 2] =
- &tz->trip_hyst_attrs[indx].attr.attr;
- }
- attrs[tz->trips * 3] = NULL;
-
- tz->trips_attribute_group.attrs = attrs;
-
- return 0;
-}
-
-static int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
- int mask)
-{
- const struct attribute_group **groups;
- int i, size, result;
-
- /* 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 - 2; i++)
- groups[i] = thermal_zone_attribute_groups[i];
-
- if (tz->trips) {
- result = create_trip_attrs(tz, mask);
- if (result) {
- kfree(groups);
-
- return result;
- }
-
- groups[size - 2] = &tz->trips_attribute_group;
- }
-
- 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)
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 097abee..bd88693 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -66,6 +66,9 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
int thermal_build_list_of_policies(char *buf);

+/* sysfs I/F */
+int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
+
#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
void thermal_gov_step_wise_unregister(void);
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
new file mode 100644
index 0000000..8a7323f
--- /dev/null
+++ b/drivers/thermal/thermal_sysfs.c
@@ -0,0 +1,633 @@
+/*
+ * thermal.c - sysfs interface of thermal devices
+ *
+ * Copyright (C) 2016 Eduardo Valentin <[email protected]>
+ *
+ * Highly based on original thermal_core.c
+ * Copyright (C) 2008 Intel Corp
+ * Copyright (C) 2008 Zhang Rui <[email protected]>
+ * Copyright (C) 2008 Sujith Thomas <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "thermal_core.h"
+
+/* sys I/F for thermal zone */
+
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%s\n", tz->type);
+}
+
+static ssize_t
+temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int temperature, ret;
+
+ ret = thermal_zone_get_temp(tz, &temperature);
+
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ enum thermal_device_mode mode;
+ int result;
+
+ if (!tz->ops->get_mode)
+ return -EPERM;
+
+ result = tz->ops->get_mode(tz, &mode);
+ if (result)
+ return result;
+
+ return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
+ : "disabled");
+}
+
+static ssize_t
+mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int result;
+
+ if (!tz->ops->set_mode)
+ return -EPERM;
+
+ if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
+ result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
+ else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
+ result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
+ else
+ result = -EINVAL;
+
+ if (result)
+ return result;
+
+ return count;
+}
+
+static ssize_t
+trip_point_type_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ enum thermal_trip_type type;
+ int trip, result;
+
+ if (!tz->ops->get_trip_type)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
+ return -EINVAL;
+
+ result = tz->ops->get_trip_type(tz, trip, &type);
+ if (result)
+ return result;
+
+ switch (type) {
+ case THERMAL_TRIP_CRITICAL:
+ return sprintf(buf, "critical\n");
+ case THERMAL_TRIP_HOT:
+ return sprintf(buf, "hot\n");
+ case THERMAL_TRIP_PASSIVE:
+ return sprintf(buf, "passive\n");
+ case THERMAL_TRIP_ACTIVE:
+ return sprintf(buf, "active\n");
+ default:
+ return sprintf(buf, "unknown\n");
+ }
+}
+
+static ssize_t
+trip_point_temp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->set_trip_temp)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ ret = tz->ops->set_trip_temp(tz, trip, temperature);
+ if (ret)
+ return ret;
+
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->get_trip_temp)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
+ return -EINVAL;
+
+ ret = tz->ops->get_trip_temp(tz, trip, &temperature);
+
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->set_trip_hyst)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ /*
+ * We are not doing any check on the 'temperature' value
+ * here. The driver implementing 'set_trip_hyst' has to
+ * take care of this.
+ */
+ ret = tz->ops->set_trip_hyst(tz, trip, temperature);
+
+ if (!ret)
+ thermal_zone_set_trips(tz);
+
+ return ret ? ret : count;
+}
+
+static ssize_t
+trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int trip, ret;
+ int temperature;
+
+ if (!tz->ops->get_trip_hyst)
+ return -EPERM;
+
+ if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
+ return -EINVAL;
+
+ ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+
+ return ret ? ret : sprintf(buf, "%d\n", temperature);
+}
+
+static ssize_t
+passive_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int state;
+
+ if (sscanf(buf, "%d\n", &state) != 1)
+ return -EINVAL;
+
+ /* sanity check: values below 1000 millicelcius don't make sense
+ * and can cause the system to go into a thermal heart attack
+ */
+ if (state && state < 1000)
+ return -EINVAL;
+
+ if (state && !tz->forced_passive) {
+ if (!tz->passive_delay)
+ tz->passive_delay = 1000;
+ thermal_zone_device_rebind_exception(tz, "Processor",
+ sizeof("Processor"));
+ } else if (!state && tz->forced_passive) {
+ tz->passive_delay = 0;
+ thermal_zone_device_unbind_exception(tz, "Processor",
+ sizeof("Processor"));
+ }
+
+ tz->forced_passive = state;
+
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+passive_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%d\n", tz->forced_passive);
+}
+
+static ssize_t
+policy_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ char name[THERMAL_NAME_LENGTH];
+ int ret;
+
+ snprintf(name, sizeof(name), "%s", buf);
+
+ ret = thermal_zone_device_set_policy(tz, name);
+ if (!ret)
+ ret = count;
+
+ return ret;
+}
+
+static ssize_t
+policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return sprintf(buf, "%s\n", tz->governor->name);
+}
+
+static ssize_t
+available_policies_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return thermal_build_list_of_policies(buf);
+}
+
+static ssize_t
+emul_temp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int ret = 0;
+ int temperature;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+
+ if (!tz->ops->set_emul_temp) {
+ mutex_lock(&tz->lock);
+ tz->emul_temperature = temperature;
+ mutex_unlock(&tz->lock);
+ } else {
+ ret = tz->ops->set_emul_temp(tz, temperature);
+ }
+
+ if (!ret)
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return ret ? ret : count;
+}
+
+static ssize_t
+sustainable_power_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ if (tz->tzp)
+ return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
+ else
+ return -EIO;
+}
+
+static ssize_t
+sustainable_power_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ u32 sustainable_power;
+
+ if (!tz->tzp)
+ return -EIO;
+
+ if (kstrtou32(buf, 10, &sustainable_power))
+ return -EINVAL;
+
+ tz->tzp->sustainable_power = sustainable_power;
+
+ return count;
+}
+
+#define create_s32_tzp_attr(name) \
+ static ssize_t \
+ name##_show(struct device *dev, struct device_attribute *devattr, \
+ char *buf) \
+ { \
+ struct thermal_zone_device *tz = to_thermal_zone(dev); \
+ \
+ if (tz->tzp) \
+ return sprintf(buf, "%d\n", tz->tzp->name); \
+ else \
+ return -EIO; \
+ } \
+ \
+ static ssize_t \
+ name##_store(struct device *dev, struct device_attribute *devattr, \
+ const char *buf, size_t count) \
+ { \
+ struct thermal_zone_device *tz = to_thermal_zone(dev); \
+ s32 value; \
+ \
+ if (!tz->tzp) \
+ return -EIO; \
+ \
+ if (kstrtos32(buf, 10, &value)) \
+ return -EINVAL; \
+ \
+ tz->tzp->name = value; \
+ \
+ return count; \
+ } \
+ static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
+
+create_s32_tzp_attr(k_po);
+create_s32_tzp_attr(k_pu);
+create_s32_tzp_attr(k_i);
+create_s32_tzp_attr(k_d);
+create_s32_tzp_attr(integral_cutoff);
+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(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,
+ sustainable_power_store);
+
+/* 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);
+
+/* These attributes are unconditionally added to a thermal zone */
+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,
+ &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,
+ NULL,
+};
+
+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,
+ NULL,
+};
+
+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,
+};
+
+/* We expose passive only if passive trips are present */
+static struct attribute *thermal_zone_passive_attrs[] = {
+ &dev_attr_passive.attr,
+ NULL,
+};
+
+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, passive = 0;
+
+ tz = container_of(dev, struct thermal_zone_device, device);
+
+ for (count = 0; count < tz->trips && !passive; count++) {
+ tz->ops->get_trip_type(tz, count, &trip_type);
+
+ if (trip_type == THERMAL_TRIP_PASSIVE)
+ passive = 1;
+ }
+
+ if (!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,
+ /* This is not NULL terminated as we create the group dynamically */
+};
+
+/**
+ * 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 size = sizeof(struct thermal_attr) * tz->trips;
+ struct attribute **attrs;
+ int indx;
+
+ /* This function works only for zones with at least one trip */
+ if (tz->trips <= 0)
+ return -EINVAL;
+
+ 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;
+ }
+ }
+
+ 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,
+ "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;
+ attrs[indx] = &tz->trip_type_attrs[indx].attr.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;
+ }
+ attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.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;
+ }
+ attrs[indx + tz->trips * 2] =
+ &tz->trip_hyst_attrs[indx].attr.attr;
+ }
+ attrs[tz->trips * 3] = NULL;
+
+ tz->trips_attribute_group.attrs = attrs;
+
+ return 0;
+}
+
+int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
+ int mask)
+{
+ const struct attribute_group **groups;
+ int i, size, result;
+
+ /* 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 - 2; i++)
+ groups[i] = thermal_zone_attribute_groups[i];
+
+ if (tz->trips) {
+ result = create_trip_attrs(tz, mask);
+ if (result) {
+ kfree(groups);
+
+ return result;
+ }
+
+ groups[size - 2] = &tz->trips_attribute_group;
+ }
+
+ tz->device.groups = groups;
+
+ return 0;
+}
--
2.1.4

2016-11-08 05:10:55

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 32/49] thermal: core: move bind_tz() to where it is used

Moving the helper to closer where it is used.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e397d88..bff2905 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -319,46 +319,6 @@ static void __bind(struct thermal_zone_device *tz, int mask,
}
}

-static void bind_tz(struct thermal_zone_device *tz)
-{
- int i, ret;
- struct thermal_cooling_device *pos = NULL;
- const struct thermal_zone_params *tzp = tz->tzp;
-
- if (!tzp && !tz->ops->bind)
- return;
-
- mutex_lock(&thermal_list_lock);
-
- /* If there is ops->bind, try to use ops->bind */
- if (tz->ops->bind) {
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- ret = tz->ops->bind(tz, pos);
- if (ret)
- print_bind_err_msg(tz, pos, ret);
- }
- goto exit;
- }
-
- if (!tzp || !tzp->tbp)
- goto exit;
-
- list_for_each_entry(pos, &thermal_cdev_list, node) {
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(tz, pos))
- continue;
- tzp->tbp[i].cdev = pos;
- __bind(tz, tzp->tbp[i].trip_mask, pos,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
-exit:
- mutex_unlock(&thermal_list_lock);
-}
-
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
int delay)
{
@@ -1094,6 +1054,46 @@ void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
}
EXPORT_SYMBOL_GPL(thermal_notify_framework);

+static void bind_tz(struct thermal_zone_device *tz)
+{
+ int i, ret;
+ struct thermal_cooling_device *pos = NULL;
+ const struct thermal_zone_params *tzp = tz->tzp;
+
+ if (!tzp && !tz->ops->bind)
+ return;
+
+ mutex_lock(&thermal_list_lock);
+
+ /* If there is ops->bind, try to use ops->bind */
+ if (tz->ops->bind) {
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ ret = tz->ops->bind(tz, pos);
+ if (ret)
+ print_bind_err_msg(tz, pos, ret);
+ }
+ goto exit;
+ }
+
+ if (!tzp || !tzp->tbp)
+ goto exit;
+
+ list_for_each_entry(pos, &thermal_cdev_list, node) {
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(tz, pos))
+ continue;
+ tzp->tbp[i].cdev = pos;
+ __bind(tz, tzp->tbp[i].trip_mask, pos,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
+ }
+ }
+exit:
+ mutex_unlock(&thermal_list_lock);
+}
+
/**
* thermal_zone_device_register() - register a new thermal zone device
* @type: the thermal zone device type
--
2.1.4

2016-11-08 05:10:51

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 24/49] thermal: core: move cooling device sysfs to thermal_sysfs.c

This is a code reorganization, simply to concentrate
the sysfs handling functions in thermal_sysfs.c.

This patch moves the cooling device handling functions.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 128 +-------------------------------------
drivers/thermal/thermal_core.h | 11 ++++
drivers/thermal/thermal_sysfs.c | 133 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 145 insertions(+), 127 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d55a41a..fb19021 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -798,132 +798,6 @@ int thermal_build_list_of_policies(char *buf)
return count;
}

-/* sys I/F for cooling device */
-static ssize_t
-thermal_cooling_device_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
-
- return sprintf(buf, "%s\n", cdev->type);
-}
-
-static ssize_t
-thermal_cooling_device_max_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int ret;
-
- ret = cdev->ops->get_max_state(cdev, &state);
- if (ret)
- return ret;
- return sprintf(buf, "%ld\n", state);
-}
-
-static ssize_t
-thermal_cooling_device_cur_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int ret;
-
- ret = cdev->ops->get_cur_state(cdev, &state);
- if (ret)
- return ret;
- return sprintf(buf, "%ld\n", state);
-}
-
-static ssize_t
-thermal_cooling_device_cur_state_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_cooling_device *cdev = to_cooling_device(dev);
- unsigned long state;
- int result;
-
- if (sscanf(buf, "%ld\n", &state) != 1)
- return -EINVAL;
-
- if ((long)state < 0)
- return -EINVAL;
-
- result = cdev->ops->set_cur_state(cdev, state);
- if (result)
- return result;
- return count;
-}
-
-static struct device_attribute dev_attr_cdev_type =
-__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
-static DEVICE_ATTR(max_state, 0444,
- thermal_cooling_device_max_state_show, NULL);
-static DEVICE_ATTR(cur_state, 0644,
- thermal_cooling_device_cur_state_show,
- thermal_cooling_device_cur_state_store);
-
-static ssize_t
-thermal_cooling_device_trip_point_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance =
- container_of(attr, struct thermal_instance, attr);
-
- if (instance->trip == THERMAL_TRIPS_NONE)
- return sprintf(buf, "-1\n");
- else
- return sprintf(buf, "%d\n", instance->trip);
-}
-
-static struct attribute *cooling_device_attrs[] = {
- &dev_attr_cdev_type.attr,
- &dev_attr_max_state.attr,
- &dev_attr_cur_state.attr,
- NULL,
-};
-
-static const struct attribute_group cooling_device_attr_group = {
- .attrs = cooling_device_attrs,
-};
-
-static const struct attribute_group *cooling_device_attr_groups[] = {
- &cooling_device_attr_group,
- NULL,
-};
-
-static ssize_t
-thermal_cooling_device_weight_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct thermal_instance *instance;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
-
- return sprintf(buf, "%d\n", instance->weight);
-}
-
-static ssize_t
-thermal_cooling_device_weight_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct thermal_instance *instance;
- int ret, weight;
-
- ret = kstrtoint(buf, 0, &weight);
- if (ret)
- return ret;
-
- instance = container_of(attr, struct thermal_instance, weight_attr);
- instance->weight = weight;
-
- return count;
-}
/* Device management */

/**
@@ -1175,7 +1049,7 @@ __thermal_cooling_device_register(struct device_node *np,
cdev->ops = ops;
cdev->updated = false;
cdev->device.class = &thermal_class;
- cdev->device.groups = cooling_device_attr_groups;
+ thermal_cooling_device_setup_sysfs(cdev);
cdev->devdata = devdata;
dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
result = device_register(&cdev->device);
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 5619243..2412b37 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -71,6 +71,17 @@ int thermal_build_list_of_policies(char *buf);

/* sysfs I/F */
int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
+void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
+/* used only at binding time */
+ssize_t
+thermal_cooling_device_trip_point_show(struct device *,
+ struct device_attribute *, char *);
+ssize_t thermal_cooling_device_weight_show(struct device *,
+ struct device_attribute *, char *);
+
+ssize_t thermal_cooling_device_weight_store(struct device *,
+ struct device_attribute *,
+ const char *, size_t);

#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 8a7323f..87d9f4d 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -631,3 +631,136 @@ int thermal_zone_create_device_groups(struct thermal_zone_device *tz,

return 0;
}
+
+/* sys I/F for cooling device */
+static ssize_t
+thermal_cooling_device_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+ return sprintf(buf, "%s\n", cdev->type);
+}
+
+static ssize_t
+thermal_cooling_device_max_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int ret;
+
+ ret = cdev->ops->get_max_state(cdev, &state);
+ if (ret)
+ return ret;
+ return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+thermal_cooling_device_cur_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int ret;
+
+ ret = cdev->ops->get_cur_state(cdev, &state);
+ if (ret)
+ return ret;
+ return sprintf(buf, "%ld\n", state);
+}
+
+static ssize_t
+thermal_cooling_device_cur_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+ unsigned long state;
+ int result;
+
+ if (sscanf(buf, "%ld\n", &state) != 1)
+ return -EINVAL;
+
+ if ((long)state < 0)
+ return -EINVAL;
+
+ result = cdev->ops->set_cur_state(cdev, state);
+ if (result)
+ return result;
+ return count;
+}
+
+static struct device_attribute dev_attr_cdev_type =
+__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
+static DEVICE_ATTR(max_state, 0444,
+ thermal_cooling_device_max_state_show, NULL);
+static DEVICE_ATTR(cur_state, 0644,
+ thermal_cooling_device_cur_state_show,
+ thermal_cooling_device_cur_state_store);
+
+static struct attribute *cooling_device_attrs[] = {
+ &dev_attr_cdev_type.attr,
+ &dev_attr_max_state.attr,
+ &dev_attr_cur_state.attr,
+ NULL,
+};
+
+static const struct attribute_group cooling_device_attr_group = {
+ .attrs = cooling_device_attrs,
+};
+
+static const struct attribute_group *cooling_device_attr_groups[] = {
+ &cooling_device_attr_group,
+ NULL,
+};
+
+void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
+{
+ cdev->device.groups = cooling_device_attr_groups;
+}
+
+/* these helper will be used only at the time of bindig */
+ssize_t
+thermal_cooling_device_trip_point_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_instance *instance;
+
+ instance =
+ container_of(attr, struct thermal_instance, attr);
+
+ if (instance->trip == THERMAL_TRIPS_NONE)
+ return sprintf(buf, "-1\n");
+ else
+ return sprintf(buf, "%d\n", instance->trip);
+}
+
+ssize_t
+thermal_cooling_device_weight_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct thermal_instance *instance;
+
+ instance = container_of(attr, struct thermal_instance, weight_attr);
+
+ return sprintf(buf, "%d\n", instance->weight);
+}
+
+ssize_t
+thermal_cooling_device_weight_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_instance *instance;
+ int ret, weight;
+
+ ret = kstrtoint(buf, 0, &weight);
+ if (ret)
+ return ret;
+
+ instance = container_of(attr, struct thermal_instance, weight_attr);
+ instance->weight = weight;
+
+ return count;
+}
--
2.1.4

2016-11-08 05:11:02

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 33/49] thermal: core: fix couple of style issues on __bind() helper

Removing style issues on __bind() and its helpers.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index bff2905..ebec7ce 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -287,16 +287,16 @@ static void thermal_unregister_governors(void)
}

static void print_bind_err_msg(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int ret)
+ struct thermal_cooling_device *cdev, int ret)
{
dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
- tz->type, cdev->type, ret);
+ tz->type, cdev->type, ret);
}

static void __bind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev,
- unsigned long *limits,
- unsigned int weight)
+ struct thermal_cooling_device *cdev,
+ unsigned long *limits,
+ unsigned int weight)
{
int i, ret;

--
2.1.4

2016-11-08 05:11:11

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 38/49] thermal: core: add a comment describing the power actor section

Simply marking the power actor section and adding a
comment describing it.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index bf108db..e9e6bb9 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -461,6 +461,13 @@ static void thermal_zone_device_check(struct work_struct *work)
thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
}

+/*
+ * Power actor section: interface to power actors to estimate power
+ *
+ * Set of functions used to interact to cooling devices that know
+ * how to estimate their devices power consumption.
+ */
+
/**
* power_actor_get_max_power() - get the maximum power that a cdev can consume
* @cdev: pointer to &thermal_cooling_device
--
2.1.4

2016-11-08 05:11:16

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 43/49] thermal: core: standardize line breaking alignment

Pass through the code to remove check suggested by
checkpatch.pl (alignment to parenthesis):
CHECK: Alignment should match open parenthesis

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f19fe03..d33b29a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -137,10 +137,15 @@ int thermal_register_governor(struct thermal_governor *governor)

err = -EBUSY;
if (!__find_governor(governor->name)) {
+ bool match_default;
+
err = 0;
list_add(&governor->governor_list, &thermal_governor_list);
- if (!def_governor && !strncmp(governor->name,
- DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH))
+ match_default = !strncmp(governor->name,
+ DEFAULT_THERMAL_GOVERNOR,
+ THERMAL_NAME_LENGTH);
+
+ if (!def_governor && match_default)
def_governor = governor;
}

@@ -189,7 +194,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)

list_for_each_entry(pos, &thermal_tz_list, node) {
if (!strncasecmp(pos->governor->name, governor->name,
- THERMAL_NAME_LENGTH))
+ THERMAL_NAME_LENGTH))
thermal_set_governor(pos, NULL);
}

@@ -312,14 +317,15 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
}

static void handle_non_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip,
+ enum thermal_trip_type trip_type)
{
tz->governor ? tz->governor->throttle(tz, trip) :
def_governor->throttle(tz, trip);
}

static void handle_critical_trips(struct thermal_zone_device *tz,
- int trip, enum thermal_trip_type trip_type)
+ int trip, enum thermal_trip_type trip_type)
{
int trip_temp;

@@ -797,7 +803,7 @@ static void thermal_release(struct device *dev)
tz = to_thermal_zone(dev);
kfree(tz);
} else if(!strncmp(dev_name(dev), "cooling_device",
- sizeof("cooling_device") - 1)){
+ sizeof("cooling_device") - 1)) {
cdev = to_cooling_device(dev);
kfree(cdev);
}
@@ -1131,11 +1137,11 @@ static void bind_tz(struct thermal_zone_device *tz)
* in case of error, an ERR_PTR. Caller must check return value with
* IS_ERR*() helpers.
*/
-struct thermal_zone_device *thermal_zone_device_register(const char *type,
- int trips, int mask, void *devdata,
- struct thermal_zone_device_ops *ops,
- struct thermal_zone_params *tzp,
- int passive_delay, int polling_delay)
+struct thermal_zone_device *
+thermal_zone_device_register(const char *type, int trips, int mask,
+ void *devdata, struct thermal_zone_device_ops *ops,
+ struct thermal_zone_params *tzp, int passive_delay,
+ int polling_delay)
{
struct thermal_zone_device *tz;
enum thermal_trip_type trip_type;
@@ -1400,7 +1406,7 @@ static struct genl_family thermal_event_genl_family = {
};

int thermal_generate_netlink_event(struct thermal_zone_device *tz,
- enum events event)
+ enum events event)
{
struct sk_buff *skb;
struct nlattr *attr;
@@ -1477,7 +1483,7 @@ static inline void genetlink_exit(void) {}
#endif /* !CONFIG_NET */

static int thermal_pm_notify(struct notifier_block *nb,
- unsigned long mode, void *_unused)
+ unsigned long mode, void *_unused)
{
struct thermal_zone_device *tz;

--
2.1.4

2016-11-08 05:11:21

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 46/49] thermal: core: improve kerneldoc entry of thermal_cooling_device_unregister

Improve description and keep 80 columns limit.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e3cdba5..2db21e5 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1018,11 +1018,11 @@ static void __unbind(struct thermal_zone_device *tz, int mask,
}

/**
- * thermal_cooling_device_unregister - removes the registered thermal cooling device
+ * thermal_cooling_device_unregister - removes a thermal cooling device
* @cdev: the thermal cooling device to remove.
*
- * thermal_cooling_device_unregister() must be called when the device is no
- * longer needed.
+ * thermal_cooling_device_unregister() must be called when a registered
+ * thermal cooling device is no longer needed.
*/
void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
{
--
2.1.4

2016-11-08 05:11:28

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 48/49] thermal: sysfs: use kcalloc() instead of kzalloc()

Simplify size computation by using kcalloc() for
allocating memory for arrays.

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

diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 4807015..a694de9 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -511,7 +511,6 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
*/
static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
{
- int size = sizeof(struct thermal_attr) * tz->trips;
struct attribute **attrs;
int indx;

@@ -519,18 +518,22 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
if (tz->trips <= 0)
return -EINVAL;

- tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
+ tz->trip_type_attrs = kcalloc(tz->trips, sizeof(*tz->trip_type_attrs),
+ GFP_KERNEL);
if (!tz->trip_type_attrs)
return -ENOMEM;

- tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
+ tz->trip_temp_attrs = kcalloc(tz->trips, sizeof(*tz->trip_temp_attrs),
+ 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);
+ tz->trip_hyst_attrs = kcalloc(tz->trips,
+ sizeof(*tz->trip_hyst_attrs),
+ GFP_KERNEL);
if (!tz->trip_hyst_attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
@@ -538,7 +541,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
}
}

- attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1, GFP_KERNEL);
+ attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL);
if (!attrs) {
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
--
2.1.4

2016-11-08 05:12:01

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 40/49] thermal: sysfs: remove symbols of emul_temp when config is disabled

Remove the following warning:
In file included from drivers/thermal/thermal_sysfs.c:19:0:
include/linux/device.h:575:26: warning: ‘dev_attr_emul_temp’ defined but not used [-Wunused-variable]
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
^
drivers/thermal/thermal_sysfs.c:395:8: note: in expansion of macro ‘DEVICE_ATTR’

when emul temp is disabled at Kconfig.

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

diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 87d9f4d..4807015 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -292,6 +292,7 @@ available_policies_show(struct device *dev, struct device_attribute *devattr,
return thermal_build_list_of_policies(buf);
}

+#if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
static ssize_t
emul_temp_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -316,6 +317,8 @@ 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);
+#endif

static ssize_t
sustainable_power_show(struct device *dev, struct device_attribute *devattr,
@@ -395,7 +398,6 @@ 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,
--
2.1.4

2016-11-08 05:11:59

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 41/49] thermal: core: remove FSF address in the GPL notice

Simplify the GPL notice by removing the FSF address.
No need to track FSF location in this file.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 01b1a4e..09d521a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -5,22 +5,9 @@
* Copyright (C) 2008 Zhang Rui <[email protected]>
* Copyright (C) 2008 Sujith Thomas <[email protected]>
*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
--
2.1.4

2016-11-08 05:12:28

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 39/49] thermal: core: add a comment describing the device management section

comment describing the section with function to handle
registration, unregistration, binding, and unbinding of
thermal devices.

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, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e9e6bb9..01b1a4e 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -588,8 +588,15 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
mutex_unlock(&thermal_list_lock);
}

-/* Device management */
-
+/*
+ * Device management section: cooling devices, zones devices, and binding
+ *
+ * Set of functions provided by the thermal core for:
+ * - cooling devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ * - thermal zone devices lifecycle: registration, unregistration,
+ * binding, and unbinding.
+ */
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
int ret;
--
2.1.4

2016-11-08 05:12:31

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 37/49] thermal: core: add a comment describing the main update loop

Simply marking the main update loop section and adding a
comment describing it.

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, 11 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 884235f..bf108db 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -286,6 +286,17 @@ static void thermal_unregister_governors(void)
thermal_gov_power_allocator_unregister();
}

+/*
+ * Zone update section: main control loop applied to each zone while monitoring
+ *
+ * in polling mode. The monitoring is done using a workqueue.
+ * Same update may be done on a zone by calling thermal_zone_device_update().
+ *
+ * An update means:
+ * - Non-critical trips will invoke the governor responsible for that zone;
+ * - Hot trips will produce a notification to userspace;
+ * - Critical trip point will cause a system shutdown.
+ */
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
int delay)
{
--
2.1.4

2016-11-08 05:12:56

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 36/49] thermal: core: move notify to the zone update section

moving the helper function to closer to similar functions.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index bc9a422..884235f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -424,6 +424,24 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);

+/**
+ * thermal_notify_framework - Sensor drivers use this API to notify framework
+ * @tz: thermal zone device
+ * @trip: indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
+ */
+void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
+{
+ handle_thermal_trip(tz, trip);
+}
+EXPORT_SYMBOL_GPL(thermal_notify_framework);
+
static void thermal_zone_device_check(struct work_struct *work)
{
struct thermal_zone_device *tz = container_of(work, struct
@@ -1037,24 +1055,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);

-/**
- * thermal_notify_framework - Sensor drivers use this API to notify framework
- * @tz: thermal zone device
- * @trip: indicates which trip point has been crossed
- *
- * This function handles the trip events from sensor drivers. It starts
- * throttling the cooling devices according to the policy configured.
- * For CRITICAL and HOT trip points, this notifies the respective drivers,
- * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
- * The throttling policy is based on the configured platform data; if no
- * platform data is provided, this uses the step_wise throttling policy.
- */
-void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
-{
- handle_thermal_trip(tz, trip);
-}
-EXPORT_SYMBOL_GPL(thermal_notify_framework);
-
static void bind_tz(struct thermal_zone_device *tz)
{
int i, ret;
--
2.1.4

2016-11-08 05:13:27

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 30/49] thermal: core: move __unbind() helper to where it is used

Simply moving the helper to closer where it is actually used.

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 c31d0bb..c121933 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -319,16 +319,6 @@ static void __bind(struct thermal_zone_device *tz, int mask,
}
}

-static void __unbind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev)
-{
- int i;
-
- for (i = 0; i < tz->trips; i++)
- if (mask & (1 << i))
- thermal_zone_unbind_cooling_device(tz, i, cdev);
-}
-
static void bind_cdev(struct thermal_cooling_device *cdev)
{
int i, ret;
@@ -1021,6 +1011,16 @@ thermal_of_cooling_device_register(struct device_node *np,
}
EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);

+static void __unbind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev)
+{
+ int i;
+
+ for (i = 0; i < tz->trips; i++)
+ if (mask & (1 << i))
+ thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
/**
* thermal_cooling_device_unregister - removes the registered thermal cooling device
* @cdev: the thermal cooling device to remove.
--
2.1.4

2016-11-08 05:10:40

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 23/49] thermal: core: move to_cooling_device macro to header file

Make the to_cooling_device() macro available across
files in thermal core.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b14913e..d55a41a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -799,9 +799,6 @@ int thermal_build_list_of_policies(char *buf)
}

/* sys I/F for cooling device */
-#define to_cooling_device(_dev) \
- container_of(_dev, struct thermal_cooling_device, device)
-
static ssize_t
thermal_cooling_device_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index bd88693..5619243 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -57,6 +57,9 @@ struct thermal_instance {
#define to_thermal_zone(_dev) \
container_of(_dev, struct thermal_zone_device, device)

+#define to_cooling_device(_dev) \
+ container_of(_dev, struct thermal_cooling_device, device)
+
int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
--
2.1.4

2016-11-08 05:14:17

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 21/49] thermal: core: match parenthesis on code alignment

Cosmetic change in the sysfs handling functions, as
recommended by checkpatch.pl.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e2c4fc4..f66c19c 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -897,7 +897,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,

static ssize_t
trip_point_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
@@ -945,7 +945,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,

static ssize_t
trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
@@ -975,7 +975,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,

static ssize_t
trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+ char *buf)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int trip, ret;
@@ -994,7 +994,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,

static ssize_t
passive_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int state;
@@ -1028,7 +1028,7 @@ passive_store(struct device *dev, struct device_attribute *attr,

static ssize_t
passive_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+ char *buf)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);

@@ -1037,7 +1037,7 @@ passive_show(struct device *dev, struct device_attribute *attr,

static ssize_t
policy_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
char name[THERMAL_NAME_LENGTH];
@@ -1069,7 +1069,7 @@ available_policies_show(struct device *dev, struct device_attribute *devattr,

static ssize_t
emul_temp_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
int ret = 0;
--
2.1.4

2016-11-08 05:14:36

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 18/49] thermal: core: split available_policies_show()

This patch creates a helper to build a list of available governors.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 23f138f..3d51184 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -779,6 +779,25 @@ int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
return ret;
}

+int thermal_build_list_of_policies(char *buf)
+{
+ struct thermal_governor *pos;
+ ssize_t count = 0;
+ ssize_t size = PAGE_SIZE;
+
+ mutex_lock(&thermal_governor_lock);
+
+ list_for_each_entry(pos, &thermal_governor_list, governor_list) {
+ size = PAGE_SIZE - count;
+ count += scnprintf(buf + count, size, "%s ", pos->name);
+ }
+ count += scnprintf(buf + count, size, "\n");
+
+ mutex_unlock(&thermal_governor_lock);
+
+ return count;
+}
+
/* sys I/F for thermal zone */

#define to_thermal_zone(_dev) \
@@ -1048,21 +1067,7 @@ static ssize_t
available_policies_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
- struct thermal_governor *pos;
- ssize_t count = 0;
- ssize_t size = PAGE_SIZE;
-
- mutex_lock(&thermal_governor_lock);
-
- list_for_each_entry(pos, &thermal_governor_list, governor_list) {
- size = PAGE_SIZE - count;
- count += scnprintf(buf + count, size, "%s ", pos->name);
- }
- count += scnprintf(buf + count, size, "\n");
-
- mutex_unlock(&thermal_governor_lock);
-
- return count;
+ return thermal_build_list_of_policies(buf);
}

static ssize_t
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index db65d3b..8994d2a 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -61,6 +61,7 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
const char *, size_t);
int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
+int thermal_build_list_of_policies(char *buf);

#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
--
2.1.4

2016-11-08 05:14:58

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 16/49] thermal: core: split passive_store

Split passive_store between sysfs handling and thermal
core internal data handling.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 62 ++++++++++++++++++++++++++++--------------
drivers/thermal/thermal_core.h | 4 +++
2 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 6100ae7..4e315c9 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -720,6 +720,43 @@ int power_actor_set_power(struct thermal_cooling_device *cdev,
return 0;
}

+void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
+{
+ struct thermal_cooling_device *cdev = NULL;
+
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
+
+ /* re binding the exception matching the type pattern */
+ thermal_zone_bind_cooling_device(tz, THERMAL_TRIPS_NONE, cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ }
+ mutex_unlock(&thermal_list_lock);
+}
+
+void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
+ const char *cdev_type, size_t size)
+{
+ struct thermal_cooling_device *cdev = NULL;
+
+ mutex_lock(&thermal_list_lock);
+ list_for_each_entry(cdev, &thermal_cdev_list, node) {
+ /* skip non matching cdevs */
+ if (strncmp(cdev_type, cdev->type, size))
+ continue;
+ /* unbinding the exception matching the type pattern */
+ thermal_zone_unbind_cooling_device(tz, THERMAL_TRIPS_NONE,
+ cdev);
+ }
+ mutex_unlock(&thermal_list_lock);
+}
+
/* sys I/F for thermal zone */

#define to_thermal_zone(_dev) \
@@ -922,7 +959,6 @@ passive_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct thermal_zone_device *tz = to_thermal_zone(dev);
- struct thermal_cooling_device *cdev = NULL;
int state;

if (!sscanf(buf, "%d\n", &state))
@@ -935,30 +971,14 @@ passive_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;

if (state && !tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_bind_cooling_device(tz,
- THERMAL_TRIPS_NONE, cdev,
- THERMAL_NO_LIMIT,
- THERMAL_NO_LIMIT,
- THERMAL_WEIGHT_DEFAULT);
- }
- mutex_unlock(&thermal_list_lock);
if (!tz->passive_delay)
tz->passive_delay = 1000;
+ thermal_zone_device_rebind_exception(tz, "Processor",
+ sizeof("Processor"));
} else if (!state && tz->forced_passive) {
- mutex_lock(&thermal_list_lock);
- list_for_each_entry(cdev, &thermal_cdev_list, node) {
- if (!strncmp("Processor", cdev->type,
- sizeof("Processor")))
- thermal_zone_unbind_cooling_device(tz,
- THERMAL_TRIPS_NONE,
- cdev);
- }
- mutex_unlock(&thermal_list_lock);
tz->passive_delay = 0;
+ thermal_zone_device_unbind_exception(tz, "Processor",
+ sizeof("Processor"));
}

tz->forced_passive = state;
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 749d41a..a765c75 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -56,6 +56,10 @@ struct thermal_instance {

int thermal_register_governor(struct thermal_governor *);
void thermal_unregister_governor(struct thermal_governor *);
+void thermal_zone_device_rebind_exception(struct thermal_zone_device *,
+ const char *, size_t);
+void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
+ const char *, size_t);

#ifdef CONFIG_THERMAL_GOV_STEP_WISE
int thermal_gov_step_wise_register(void);
--
2.1.4

2016-11-08 05:09:39

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 02/49] thermal: core: 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 ec0d158..97f314e 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -975,7 +975,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,
@@ -1006,8 +1005,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 \
@@ -1050,6 +1047,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,
@@ -1159,13 +1166,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-11-08 05:22:17

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 10/49] thermal: core: remove useless empty line

Fix style problem on create_trip_attrs();

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e8098f6..122eba7 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1833,7 +1833,6 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
}
}

-
for (indx = 0; indx < tz->trips; indx++) {
/* create trip type attribute */
snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
--
2.1.4

2016-11-08 05:22:45

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 01/49] thermal: core: 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 226b0b4ac..ec0d158 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1873,6 +1873,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);

@@ -1898,7 +1901,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;
@@ -1918,11 +1921,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)
@@ -2071,8 +2072,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

2016-11-08 05:22:52

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 06/49] thermal: core: 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 | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index ec15a60..ec8551a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1064,6 +1064,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,
@@ -1087,8 +1088,35 @@ 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,
+ NULL,
+};
+
+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
};

@@ -1932,12 +1960,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;
@@ -2054,8 +2076,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-11-08 05:23:07

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 25/49] thermal: core: remove a couple of style issues on helpers

Reorganizing the code of helper functions to improve
readability and style, as recommended by checkpatch.pl.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index fb19021..3a189fd 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -248,8 +248,9 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip)
}
EXPORT_SYMBOL(get_tz_trend);

-struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int trip)
+struct thermal_instance *
+get_thermal_instance(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int trip)
{
struct thermal_instance *pos = NULL;
struct thermal_instance *target_instance = NULL;
@@ -513,7 +514,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
if (!ret && *temp < crit_temp)
*temp = tz->emul_temperature;
}
-
+
mutex_unlock(&tz->lock);
exit:
return ret;
@@ -1192,7 +1193,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
/* Make sure cdev enters the deepest cooling state */
list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
dev_dbg(&cdev->device, "zone%d->target=%lu\n",
- instance->tz->id, instance->target);
+ instance->tz->id, instance->target);
if (instance->target == THERMAL_NO_TARGET)
continue;
if (instance->target > target)
--
2.1.4

2016-11-08 05:24:30

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 28/49] thermal: core: move idr handling to device management section

Given that idr is only used to get id for thermal devices
(zones and cooling), makes sense to move the code closer.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e36a6a6..f6e24ef 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -286,30 +286,6 @@ static void thermal_unregister_governors(void)
thermal_gov_power_allocator_unregister();
}

-static int get_idr(struct idr *idr, struct mutex *lock, int *id)
-{
- int ret;
-
- if (lock)
- mutex_lock(lock);
- ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
- if (lock)
- mutex_unlock(lock);
- if (unlikely(ret < 0))
- return ret;
- *id = ret;
- return 0;
-}
-
-static void release_idr(struct idr *idr, struct mutex *lock, int id)
-{
- if (lock)
- mutex_lock(lock);
- idr_remove(idr, id);
- if (lock)
- mutex_unlock(lock);
-}
-
static void print_bind_err_msg(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, int ret)
{
@@ -699,6 +675,30 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,

/* Device management */

+static int get_idr(struct idr *idr, struct mutex *lock, int *id)
+{
+ int ret;
+
+ if (lock)
+ mutex_lock(lock);
+ ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL);
+ if (lock)
+ mutex_unlock(lock);
+ if (unlikely(ret < 0))
+ return ret;
+ *id = ret;
+ return 0;
+}
+
+static void release_idr(struct idr *idr, struct mutex *lock, int id)
+{
+ if (lock)
+ mutex_lock(lock);
+ idr_remove(idr, id);
+ if (lock)
+ mutex_unlock(lock);
+}
+
/**
* thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone
* @tz: pointer to struct thermal_zone_device
--
2.1.4

2016-11-08 05:24:42

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 49/49] thermal: core: move slop and offset helpers to thermal_helpers.c

Reorganize code to reflect better placement.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/thermal_core.c | 30 ------------------------------
drivers/thermal/thermal_helpers.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4f93844..7daffc1 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1358,36 +1358,6 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
}
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);

-/**
- * thermal_zone_get_slope - return the slope attribute of the thermal zone
- * @tz: thermal zone device with the slope attribute
- *
- * Return: If the thermal zone device has a slope attribute, return it, else
- * return 1.
- */
-int thermal_zone_get_slope(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->slope;
- return 1;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
-
-/**
- * thermal_zone_get_offset - return the offset attribute of the thermal zone
- * @tz: thermal zone device with the offset attribute
- *
- * Return: If the thermal zone device has a offset attribute, return it, else
- * return 0.
- */
-int thermal_zone_get_offset(struct thermal_zone_device *tz)
-{
- if (tz && tz->tzp)
- return tz->tzp->offset;
- return 0;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
-
#ifdef CONFIG_NET
static const struct genl_multicast_group thermal_event_mcgrps[] = {
{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c
index dfdba5a..8cdf75a 100644
--- a/drivers/thermal/thermal_helpers.c
+++ b/drivers/thermal/thermal_helpers.c
@@ -194,3 +194,33 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
dev_dbg(&cdev->device, "set to state %lu\n", target);
}
EXPORT_SYMBOL(thermal_cdev_update);
+
+/**
+ * thermal_zone_get_slope - return the slope attribute of the thermal zone
+ * @tz: thermal zone device with the slope attribute
+ *
+ * Return: If the thermal zone device has a slope attribute, return it, else
+ * return 1.
+ */
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+ if (tz && tz->tzp)
+ return tz->tzp->slope;
+ return 1;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+/**
+ * thermal_zone_get_offset - return the offset attribute of the thermal zone
+ * @tz: thermal zone device with the offset attribute
+ *
+ * Return: If the thermal zone device has a offset attribute, return it, else
+ * return 0.
+ */
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+ if (tz && tz->tzp)
+ return tz->tzp->offset;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
--
2.1.4

2016-11-08 05:24:49

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 35/49] thermal: core: add inline to print_bind_err_msg()

Given that this is simple wrapper, adding the inline flag.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 258962b..bc9a422 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -778,8 +778,9 @@ static struct class thermal_class = {
.dev_release = thermal_release,
};

-static void print_bind_err_msg(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int ret)
+static inline
+void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret)
{
dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
tz->type, cdev->type, ret);
--
2.1.4

2016-11-08 05:26:06

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 42/49] thermal: core: small style fix when checking for __find_governor()

Remove style issue:
CHECK: Comparison to NULL could be written "!__find_governor"
+ if (__find_governor(governor->name) == NULL) {

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 09d521a..f19fe03 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -136,7 +136,7 @@ int thermal_register_governor(struct thermal_governor *governor)
mutex_lock(&thermal_governor_lock);

err = -EBUSY;
- if (__find_governor(governor->name) == NULL) {
+ if (!__find_governor(governor->name)) {
err = 0;
list_add(&governor->governor_list, &thermal_governor_list);
if (!def_governor && !strncmp(governor->name,
@@ -182,7 +182,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)

mutex_lock(&thermal_governor_lock);

- if (__find_governor(governor->name) == NULL)
+ if (!__find_governor(governor->name))
goto exit;

mutex_lock(&thermal_list_lock);
--
2.1.4

2016-11-08 05:26:17

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 04/49] thermal: core: 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 | 87 +++++++++++++++++-------------------------
1 file changed, 34 insertions(+), 53 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3d43c29..3da4cd3 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1047,42 +1047,47 @@ 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,
+ NULL,
+};

- 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
@@ -1909,6 +1914,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);

@@ -1955,29 +1963,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);

@@ -2072,12 +2057,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-11-08 05:26:43

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 44/49] thermal: core: remove void function return statements

Simply removing useless returns of void functions.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d33b29a..8365d0b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -202,7 +202,6 @@ void thermal_unregister_governor(struct thermal_governor *governor)
list_del(&governor->governor_list);
exit:
mutex_unlock(&thermal_governor_lock);
- return;
}

int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
@@ -1069,7 +1068,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
device_unregister(&cdev->device);
- return;
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);

--
2.1.4

2016-11-08 05:27:27

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 27/49] thermal: core: group functions related to governor handling

Organize thermal core code to group the functions
handling with governor manipulation in one single section.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 519aa94..e36a6a6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -64,6 +64,13 @@ static atomic_t in_suspend;

static struct thermal_governor *def_governor;

+/*
+ * Governor section: set of functions to handle thermal governors
+ *
+ * Functions to help in the life cycle of thermal governors within
+ * the thermal core and by the thermal governor code.
+ */
+
static struct thermal_governor *__find_governor(const char *name)
{
struct thermal_governor *pos;
@@ -206,6 +213,79 @@ void thermal_unregister_governor(struct thermal_governor *governor)
return;
}

+int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
+ char *policy)
+{
+ struct thermal_governor *gov;
+ int ret = -EINVAL;
+
+ mutex_lock(&thermal_governor_lock);
+ mutex_lock(&tz->lock);
+
+ gov = __find_governor(strim(policy));
+ if (!gov)
+ goto exit;
+
+ ret = thermal_set_governor(tz, gov);
+
+exit:
+ mutex_unlock(&tz->lock);
+ mutex_unlock(&thermal_governor_lock);
+
+ return ret;
+}
+
+int thermal_build_list_of_policies(char *buf)
+{
+ struct thermal_governor *pos;
+ ssize_t count = 0;
+ ssize_t size = PAGE_SIZE;
+
+ mutex_lock(&thermal_governor_lock);
+
+ list_for_each_entry(pos, &thermal_governor_list, governor_list) {
+ size = PAGE_SIZE - count;
+ count += scnprintf(buf + count, size, "%s ", pos->name);
+ }
+ count += scnprintf(buf + count, size, "\n");
+
+ mutex_unlock(&thermal_governor_lock);
+
+ return count;
+}
+
+static int __init thermal_register_governors(void)
+{
+ int result;
+
+ result = thermal_gov_step_wise_register();
+ if (result)
+ return result;
+
+ result = thermal_gov_fair_share_register();
+ if (result)
+ return result;
+
+ result = thermal_gov_bang_bang_register();
+ if (result)
+ return result;
+
+ result = thermal_gov_user_space_register();
+ if (result)
+ return result;
+
+ return thermal_gov_power_allocator_register();
+}
+
+static void thermal_unregister_governors(void)
+{
+ thermal_gov_step_wise_unregister();
+ thermal_gov_fair_share_unregister();
+ thermal_gov_bang_bang_unregister();
+ thermal_gov_user_space_unregister();
+ thermal_gov_power_allocator_unregister();
+}
+
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
int ret;
@@ -617,47 +697,6 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz,
mutex_unlock(&thermal_list_lock);
}

-int thermal_zone_device_set_policy(struct thermal_zone_device *tz,
- char *policy)
-{
- struct thermal_governor *gov;
- int ret = -EINVAL;
-
- mutex_lock(&thermal_governor_lock);
- mutex_lock(&tz->lock);
-
- gov = __find_governor(strim(policy));
- if (!gov)
- goto exit;
-
- ret = thermal_set_governor(tz, gov);
-
-exit:
- mutex_unlock(&tz->lock);
- mutex_unlock(&thermal_governor_lock);
-
- return ret;
-}
-
-int thermal_build_list_of_policies(char *buf)
-{
- struct thermal_governor *pos;
- ssize_t count = 0;
- ssize_t size = PAGE_SIZE;
-
- mutex_lock(&thermal_governor_lock);
-
- list_for_each_entry(pos, &thermal_governor_list, governor_list) {
- size = PAGE_SIZE - count;
- count += scnprintf(buf + count, size, "%s ", pos->name);
- }
- count += scnprintf(buf + count, size, "\n");
-
- mutex_unlock(&thermal_governor_lock);
-
- return count;
-}
-
/* Device management */

/**
@@ -1424,38 +1463,6 @@ static inline int genetlink_init(void) { return 0; }
static inline void genetlink_exit(void) {}
#endif /* !CONFIG_NET */

-static int __init thermal_register_governors(void)
-{
- int result;
-
- result = thermal_gov_step_wise_register();
- if (result)
- return result;
-
- result = thermal_gov_fair_share_register();
- if (result)
- return result;
-
- result = thermal_gov_bang_bang_register();
- if (result)
- return result;
-
- result = thermal_gov_user_space_register();
- if (result)
- return result;
-
- return thermal_gov_power_allocator_register();
-}
-
-static void thermal_unregister_governors(void)
-{
- thermal_gov_step_wise_unregister();
- thermal_gov_fair_share_unregister();
- thermal_gov_bang_bang_unregister();
- thermal_gov_user_space_unregister();
- thermal_gov_power_allocator_unregister();
-}
-
static int thermal_pm_notify(struct notifier_block *nb,
unsigned long mode, void *_unused)
{
--
2.1.4

2016-11-08 05:27:30

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 29/49] thermal: core: small style fix on __unbind() helper

Simply aligning to parenthesis.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f6e24ef..c31d0bb 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -320,7 +320,7 @@ static void __bind(struct thermal_zone_device *tz, int mask,
}

static void __unbind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev)
+ struct thermal_cooling_device *cdev)
{
int i;

--
2.1.4

2016-11-08 05:27:42

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 31/49] thermal: core: move bind_cdev() to where it is used

Moving the helper to closer where it is used.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index c121933..e397d88 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -319,44 +319,6 @@ static void __bind(struct thermal_zone_device *tz, int mask,
}
}

-static void bind_cdev(struct thermal_cooling_device *cdev)
-{
- int i, ret;
- const struct thermal_zone_params *tzp;
- struct thermal_zone_device *pos = NULL;
-
- mutex_lock(&thermal_list_lock);
-
- list_for_each_entry(pos, &thermal_tz_list, node) {
- if (!pos->tzp && !pos->ops->bind)
- continue;
-
- if (pos->ops->bind) {
- ret = pos->ops->bind(pos, cdev);
- if (ret)
- print_bind_err_msg(pos, cdev, ret);
- continue;
- }
-
- tzp = pos->tzp;
- if (!tzp || !tzp->tbp)
- continue;
-
- for (i = 0; i < tzp->num_tbps; i++) {
- if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
- continue;
- if (tzp->tbp[i].match(pos, cdev))
- continue;
- tzp->tbp[i].cdev = cdev;
- __bind(pos, tzp->tbp[i].trip_mask, cdev,
- tzp->tbp[i].binding_limits,
- tzp->tbp[i].weight);
- }
- }
-
- mutex_unlock(&thermal_list_lock);
-}
-
static void bind_tz(struct thermal_zone_device *tz)
{
int i, ret;
@@ -889,6 +851,44 @@ static struct class thermal_class = {
.dev_release = thermal_release,
};

+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+ int i, ret;
+ const struct thermal_zone_params *tzp;
+ struct thermal_zone_device *pos = NULL;
+
+ mutex_lock(&thermal_list_lock);
+
+ list_for_each_entry(pos, &thermal_tz_list, node) {
+ if (!pos->tzp && !pos->ops->bind)
+ continue;
+
+ if (pos->ops->bind) {
+ ret = pos->ops->bind(pos, cdev);
+ if (ret)
+ print_bind_err_msg(pos, cdev, ret);
+ continue;
+ }
+
+ tzp = pos->tzp;
+ if (!tzp || !tzp->tbp)
+ continue;
+
+ for (i = 0; i < tzp->num_tbps; i++) {
+ if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+ continue;
+ if (tzp->tbp[i].match(pos, cdev))
+ continue;
+ tzp->tbp[i].cdev = cdev;
+ __bind(pos, tzp->tbp[i].trip_mask, cdev,
+ tzp->tbp[i].binding_limits,
+ tzp->tbp[i].weight);
+ }
+ }
+
+ mutex_unlock(&thermal_list_lock);
+}
+
/**
* __thermal_cooling_device_register() - register a new thermal cooling device
* @np: a pointer to a device tree node.
--
2.1.4

2016-11-08 05:27:52

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 13/49] thermal: core: 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 e399ae6..971f033 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1236,7 +1236,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 */
};

/**
@@ -1347,6 +1347,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 = kcalloc(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)
@@ -1982,7 +2001,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);

@@ -2111,7 +2130,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-11-08 05:29:59

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 45/49] thermal: core: remove style warnings and checks

Removing several style issues in thermal code code.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 8365d0b..e3cdba5 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -718,10 +718,10 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
mutex_lock(&tz->lock);
mutex_lock(&cdev->lock);
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
- result = -EEXIST;
- break;
- }
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+ result = -EEXIST;
+ break;
+ }
if (!result) {
list_add_tail(&dev->tz_node, &tz->thermal_instances);
list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
@@ -801,8 +801,8 @@ static void thermal_release(struct device *dev)
sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev);
kfree(tz);
- } else if(!strncmp(dev_name(dev), "cooling_device",
- sizeof("cooling_device") - 1)) {
+ } else if (!strncmp(dev_name(dev), "cooling_device",
+ sizeof("cooling_device") - 1)) {
cdev = to_cooling_device(dev);
kfree(cdev);
}
@@ -1036,8 +1036,8 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_cdev_list, node)
- if (pos == cdev)
- break;
+ if (pos == cdev)
+ break;
if (pos != cdev) {
/* thermal cooling device not found */
mutex_unlock(&thermal_list_lock);
@@ -1241,7 +1241,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
/* Bind cooling devices for this zone */
bind_tz(tz);

- INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+ INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);

thermal_zone_device_reset(tz);
/* Update the new thermal zone and mark it as already updated. */
@@ -1275,8 +1275,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)

mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
- if (pos == tz)
- break;
+ if (pos == tz)
+ break;
if (pos != tz) {
/* thermal zone device not found */
mutex_unlock(&thermal_list_lock);
--
2.1.4

2016-11-08 05:30:16

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 26/49] thermal: core: introduce thermal_helpers.c

Here we have a simple code organization. This patch moves
functions that do not need to handle thermal core internal
data structure to thermal_helpers.c file.

Cc: Zhang Rui <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Eduardo Valentin <[email protected]>
---
drivers/thermal/Makefile | 3 +-
drivers/thermal/thermal_core.c | 170 ---------------------------------
drivers/thermal/thermal_helpers.c | 196 ++++++++++++++++++++++++++++++++++++++
3 files changed, 198 insertions(+), 171 deletions(-)
create mode 100644 drivers/thermal/thermal_helpers.c

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 767c3c9..6a3d7b5 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,7 +3,8 @@
#

obj-$(CONFIG_THERMAL) += thermal_sys.o
-thermal_sys-y += thermal_core.o thermal_sysfs.o
+thermal_sys-y += thermal_core.o thermal_sysfs.o \
+ thermal_helpers.o

# interface to/from other layers providing sensors
thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3a189fd..519aa94 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -230,48 +230,6 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
mutex_unlock(lock);
}

-int get_tz_trend(struct thermal_zone_device *tz, int trip)
-{
- enum thermal_trend trend;
-
- if (tz->emul_temperature || !tz->ops->get_trend ||
- tz->ops->get_trend(tz, trip, &trend)) {
- if (tz->temperature > tz->last_temperature)
- trend = THERMAL_TREND_RAISING;
- else if (tz->temperature < tz->last_temperature)
- trend = THERMAL_TREND_DROPPING;
- else
- trend = THERMAL_TREND_STABLE;
- }
-
- return trend;
-}
-EXPORT_SYMBOL(get_tz_trend);
-
-struct thermal_instance *
-get_thermal_instance(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int trip)
-{
- struct thermal_instance *pos = NULL;
- struct thermal_instance *target_instance = NULL;
-
- mutex_lock(&tz->lock);
- mutex_lock(&cdev->lock);
-
- list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
- if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
- target_instance = pos;
- break;
- }
- }
-
- mutex_unlock(&cdev->lock);
- mutex_unlock(&tz->lock);
-
- return target_instance;
-}
-EXPORT_SYMBOL(get_thermal_instance);
-
static void print_bind_err_msg(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev, int ret)
{
@@ -472,105 +430,6 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
monitor_thermal_zone(tz);
}

-/**
- * thermal_zone_get_temp() - returns the temperature of a thermal zone
- * @tz: a valid pointer to a struct thermal_zone_device
- * @temp: a valid pointer to where to store the resulting temperature.
- *
- * When a valid thermal zone reference is passed, it will fetch its
- * temperature and fill @temp.
- *
- * Return: On success returns 0, an error code otherwise
- */
-int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
-{
- int ret = -EINVAL;
- int count;
- int crit_temp = INT_MAX;
- enum thermal_trip_type type;
-
- if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
- goto exit;
-
- mutex_lock(&tz->lock);
-
- ret = tz->ops->get_temp(tz, temp);
-
- if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
- for (count = 0; count < tz->trips; count++) {
- ret = tz->ops->get_trip_type(tz, count, &type);
- if (!ret && type == THERMAL_TRIP_CRITICAL) {
- ret = tz->ops->get_trip_temp(tz, count,
- &crit_temp);
- break;
- }
- }
-
- /*
- * Only allow emulating a temperature when the real temperature
- * is below the critical temperature so that the emulation code
- * cannot hide critical conditions.
- */
- if (!ret && *temp < crit_temp)
- *temp = tz->emul_temperature;
- }
-
- mutex_unlock(&tz->lock);
-exit:
- return ret;
-}
-EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
-
-void thermal_zone_set_trips(struct thermal_zone_device *tz)
-{
- int low = -INT_MAX;
- int high = INT_MAX;
- int trip_temp, hysteresis;
- int i, ret;
-
- mutex_lock(&tz->lock);
-
- if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
- goto exit;
-
- for (i = 0; i < tz->trips; i++) {
- int trip_low;
-
- tz->ops->get_trip_temp(tz, i, &trip_temp);
- tz->ops->get_trip_hyst(tz, i, &hysteresis);
-
- trip_low = trip_temp - hysteresis;
-
- if (trip_low < tz->temperature && trip_low > low)
- low = trip_low;
-
- if (trip_temp > tz->temperature && trip_temp < high)
- high = trip_temp;
- }
-
- /* No need to change trip points */
- if (tz->prev_low_trip == low && tz->prev_high_trip == high)
- goto exit;
-
- tz->prev_low_trip = low;
- tz->prev_high_trip = high;
-
- dev_dbg(&tz->device,
- "new temperature boundaries: %d < x < %d\n", low, high);
-
- /*
- * Set a temperature window. When this window is left the driver
- * must inform the thermal core via thermal_zone_device_update.
- */
- ret = tz->ops->set_trips(tz, low, high);
- if (ret)
- dev_err(&tz->device, "Failed to set trips: %d\n", ret);
-
-exit:
- mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
-
static void update_temperature(struct thermal_zone_device *tz)
{
int temp, ret;
@@ -1178,35 +1037,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);

-void thermal_cdev_update(struct thermal_cooling_device *cdev)
-{
- struct thermal_instance *instance;
- unsigned long target = 0;
-
- mutex_lock(&cdev->lock);
- /* cooling device is updated*/
- if (cdev->updated) {
- mutex_unlock(&cdev->lock);
- return;
- }
-
- /* Make sure cdev enters the deepest cooling state */
- list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
- dev_dbg(&cdev->device, "zone%d->target=%lu\n",
- instance->tz->id, instance->target);
- if (instance->target == THERMAL_NO_TARGET)
- continue;
- if (instance->target > target)
- target = instance->target;
- }
- cdev->ops->set_cur_state(cdev, target);
- cdev->updated = true;
- mutex_unlock(&cdev->lock);
- trace_cdev_update(cdev, target);
- dev_dbg(&cdev->device, "set to state %lu\n", target);
-}
-EXPORT_SYMBOL(thermal_cdev_update);
-
/**
* thermal_notify_framework - Sensor drivers use this API to notify framework
* @tz: thermal zone device
diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c
new file mode 100644
index 0000000..dfdba5a
--- /dev/null
+++ b/drivers/thermal/thermal_helpers.c
@@ -0,0 +1,196 @@
+/*
+ * thermal_helpers.c - helper functions to handle thermal devices
+ *
+ * Copyright (C) 2016 Eduardo Valentin <[email protected]>
+ *
+ * Highly based on original thermal_core.c
+ * Copyright (C) 2008 Intel Corp
+ * Copyright (C) 2008 Zhang Rui <[email protected]>
+ * Copyright (C) 2008 Sujith Thomas <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <trace/events/thermal.h>
+
+#include "thermal_core.h"
+
+int get_tz_trend(struct thermal_zone_device *tz, int trip)
+{
+ enum thermal_trend trend;
+
+ if (tz->emul_temperature || !tz->ops->get_trend ||
+ tz->ops->get_trend(tz, trip, &trend)) {
+ if (tz->temperature > tz->last_temperature)
+ trend = THERMAL_TREND_RAISING;
+ else if (tz->temperature < tz->last_temperature)
+ trend = THERMAL_TREND_DROPPING;
+ else
+ trend = THERMAL_TREND_STABLE;
+ }
+
+ return trend;
+}
+EXPORT_SYMBOL(get_tz_trend);
+
+struct thermal_instance *
+get_thermal_instance(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int trip)
+{
+ struct thermal_instance *pos = NULL;
+ struct thermal_instance *target_instance = NULL;
+
+ mutex_lock(&tz->lock);
+ mutex_lock(&cdev->lock);
+
+ list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
+ if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+ target_instance = pos;
+ break;
+ }
+ }
+
+ mutex_unlock(&cdev->lock);
+ mutex_unlock(&tz->lock);
+
+ return target_instance;
+}
+EXPORT_SYMBOL(get_thermal_instance);
+
+/**
+ * thermal_zone_get_temp() - returns the temperature of a thermal zone
+ * @tz: a valid pointer to a struct thermal_zone_device
+ * @temp: a valid pointer to where to store the resulting temperature.
+ *
+ * When a valid thermal zone reference is passed, it will fetch its
+ * temperature and fill @temp.
+ *
+ * Return: On success returns 0, an error code otherwise
+ */
+int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ int ret = -EINVAL;
+ int count;
+ int crit_temp = INT_MAX;
+ enum thermal_trip_type type;
+
+ if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+ goto exit;
+
+ mutex_lock(&tz->lock);
+
+ ret = tz->ops->get_temp(tz, temp);
+
+ if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
+ for (count = 0; count < tz->trips; count++) {
+ ret = tz->ops->get_trip_type(tz, count, &type);
+ if (!ret && type == THERMAL_TRIP_CRITICAL) {
+ ret = tz->ops->get_trip_temp(tz, count,
+ &crit_temp);
+ break;
+ }
+ }
+
+ /*
+ * Only allow emulating a temperature when the real temperature
+ * is below the critical temperature so that the emulation code
+ * cannot hide critical conditions.
+ */
+ if (!ret && *temp < crit_temp)
+ *temp = tz->emul_temperature;
+ }
+
+ mutex_unlock(&tz->lock);
+exit:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+
+void thermal_zone_set_trips(struct thermal_zone_device *tz)
+{
+ int low = -INT_MAX;
+ int high = INT_MAX;
+ int trip_temp, hysteresis;
+ int i, ret;
+
+ mutex_lock(&tz->lock);
+
+ if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
+ goto exit;
+
+ for (i = 0; i < tz->trips; i++) {
+ int trip_low;
+
+ tz->ops->get_trip_temp(tz, i, &trip_temp);
+ tz->ops->get_trip_hyst(tz, i, &hysteresis);
+
+ trip_low = trip_temp - hysteresis;
+
+ if (trip_low < tz->temperature && trip_low > low)
+ low = trip_low;
+
+ if (trip_temp > tz->temperature && trip_temp < high)
+ high = trip_temp;
+ }
+
+ /* No need to change trip points */
+ if (tz->prev_low_trip == low && tz->prev_high_trip == high)
+ goto exit;
+
+ tz->prev_low_trip = low;
+ tz->prev_high_trip = high;
+
+ dev_dbg(&tz->device,
+ "new temperature boundaries: %d < x < %d\n", low, high);
+
+ /*
+ * Set a temperature window. When this window is left the driver
+ * must inform the thermal core via thermal_zone_device_update.
+ */
+ ret = tz->ops->set_trips(tz, low, high);
+ if (ret)
+ dev_err(&tz->device, "Failed to set trips: %d\n", ret);
+
+exit:
+ mutex_unlock(&tz->lock);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_set_trips);
+
+void thermal_cdev_update(struct thermal_cooling_device *cdev)
+{
+ struct thermal_instance *instance;
+ unsigned long target = 0;
+
+ mutex_lock(&cdev->lock);
+ /* cooling device is updated*/
+ if (cdev->updated) {
+ mutex_unlock(&cdev->lock);
+ return;
+ }
+
+ /* Make sure cdev enters the deepest cooling state */
+ list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
+ dev_dbg(&cdev->device, "zone%d->target=%lu\n",
+ instance->tz->id, instance->target);
+ if (instance->target == THERMAL_NO_TARGET)
+ continue;
+ if (instance->target > target)
+ target = instance->target;
+ }
+ cdev->ops->set_cur_state(cdev, target);
+ cdev->updated = true;
+ mutex_unlock(&cdev->lock);
+ trace_cdev_update(cdev, target);
+ dev_dbg(&cdev->device, "set to state %lu\n", target);
+}
+EXPORT_SYMBOL(thermal_cdev_update);
--
2.1.4

2016-11-08 06:06:05

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 47/49] thermal: core: use kzalloc(sizeof(*ptr),...)

As a safety check, this patch changes thermal
core to check for pointer content size, instead of type size,
while allocating memory.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 2db21e5..4f93844 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -674,8 +674,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
if (lower > upper || upper > max_state)
return -EINVAL;

- dev =
- kzalloc(sizeof(struct thermal_instance), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->tz = tz;
@@ -917,7 +916,7 @@ __thermal_cooling_device_register(struct device_node *np,
!ops->set_cur_state)
return ERR_PTR(-EINVAL);

- cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL);
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return ERR_PTR(-ENOMEM);

@@ -1163,7 +1162,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
return ERR_PTR(-EINVAL);

- tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
+ tz = kzalloc(sizeof(*tz), GFP_KERNEL);
if (!tz)
return ERR_PTR(-ENOMEM);

--
2.1.4

2016-11-08 06:18:39

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 15/49] thermal: core: remove unnecessary device_remove() calls

Given that cdevs sysfs properties are already registered using
the dev.groups, there is no need to explicitly call device_remove()
for each property.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b1d6de9..6100ae7 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1876,11 +1876,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

mutex_unlock(&thermal_list_lock);

- if (cdev->type[0])
- device_remove_file(&cdev->device, &dev_attr_cdev_type);
- device_remove_file(&cdev->device, &dev_attr_max_state);
- device_remove_file(&cdev->device, &dev_attr_cur_state);
-
release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
device_unregister(&cdev->device);
return;
--
2.1.4

2016-11-08 08:51:24

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 08/49] thermal: core: improve power actor documentation

Simple improvement on clarity and removal of checkpatch warning
in the documentation of power actor kernel doc.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f3d9fe9..3d2adfa 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1206,12 +1206,13 @@ int power_actor_get_min_power(struct thermal_cooling_device *cdev,
}

/**
- * power_actor_set_power() - limit the maximum power that a cooling device can consume
+ * power_actor_set_power() - limit the maximum power a cooling device consumes
* @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.
+ * Set the cooling device to consume at most @power milliwatts. The limit is
+ * expected to be a cap at the maximum power consumption.
*
* Return: 0 on success, -EINVAL if the cooling device does not
* implement the power actor API or -E* for other failures.
--
2.1.4

2016-11-08 09:04:59

by Eduardo Valentin

[permalink] [raw]
Subject: [PATCHv2 34/49] thermal: core: move __bind() to where it is used

Moving the helper to closer where it is used.

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

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index ebec7ce..258962b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -286,39 +286,6 @@ static void thermal_unregister_governors(void)
thermal_gov_power_allocator_unregister();
}

-static void print_bind_err_msg(struct thermal_zone_device *tz,
- struct thermal_cooling_device *cdev, int ret)
-{
- dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
- tz->type, cdev->type, ret);
-}
-
-static void __bind(struct thermal_zone_device *tz, int mask,
- struct thermal_cooling_device *cdev,
- unsigned long *limits,
- unsigned int weight)
-{
- int i, ret;
-
- for (i = 0; i < tz->trips; i++) {
- if (mask & (1 << i)) {
- unsigned long upper, lower;
-
- upper = THERMAL_NO_LIMIT;
- lower = THERMAL_NO_LIMIT;
- if (limits) {
- lower = limits[i * 2];
- upper = limits[i * 2 + 1];
- }
- ret = thermal_zone_bind_cooling_device(tz, i, cdev,
- upper, lower,
- weight);
- if (ret)
- print_bind_err_msg(tz, cdev, ret);
- }
- }
-}
-
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
int delay)
{
@@ -811,6 +778,39 @@ static struct class thermal_class = {
.dev_release = thermal_release,
};

+static void print_bind_err_msg(struct thermal_zone_device *tz,
+ struct thermal_cooling_device *cdev, int ret)
+{
+ dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+ tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+ struct thermal_cooling_device *cdev,
+ unsigned long *limits,
+ unsigned int weight)
+{
+ int i, ret;
+
+ for (i = 0; i < tz->trips; i++) {
+ if (mask & (1 << i)) {
+ unsigned long upper, lower;
+
+ upper = THERMAL_NO_LIMIT;
+ lower = THERMAL_NO_LIMIT;
+ if (limits) {
+ lower = limits[i * 2];
+ upper = limits[i * 2 + 1];
+ }
+ ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+ upper, lower,
+ weight);
+ if (ret)
+ print_bind_err_msg(tz, cdev, ret);
+ }
+ }
+}
+
static void bind_cdev(struct thermal_cooling_device *cdev)
{
int i, ret;
--
2.1.4