From 54fa38cc2eda43599b51695f9918208e7250ac46 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:39 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 226b0b4aced6..ec0d15805df2 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); -- cgit v1.2.3 From ef1d8bff72e15854fd7db9b56d807fcad36e16d9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:40 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec0d15805df2..97f314e39b3d 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) -- cgit v1.2.3 From 308f726ac872bee72ab0fccb0ef6a75364e47496 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:41 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 97f314e39b3d..3d43c297948a 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); -- cgit v1.2.3 From 1c600861fa6fd8891c3c6936e93288f912630f53 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:42 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 87 +++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 53 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3d43c297948a..3da4cd3f7fb8 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); -- cgit v1.2.3 From 66e554bde9f879ea09379848acc4446effad9dfb Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:43 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3da4cd3f7fb8..ec15a600fbbb 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); -- cgit v1.2.3 From 8baa5dae60adf95c44d52be3dae2367e3d5e9530 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:44 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec15a600fbbb..ec8551a83a87 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); -- cgit v1.2.3 From 3a836bfe9ff6342303bd2a146bcc42eebc3a259a Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:45 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 45 +++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ec8551a83a87..f3d9fe9d5c48 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); -- cgit v1.2.3 From 059386f43ef96bd61af40715aff757b727c3105b Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:46 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f3d9fe9d5c48..3d2adfac9578 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. -- cgit v1.2.3 From 1a7e7cc03f172622792dafbbc6c93d8891fba569 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:47 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 166 ++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 83 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3d2adfac9578..e8098f695c84 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) -- cgit v1.2.3 From 9d934fc8838b061cc02b8b7416e5defb6299dec1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:48 -0800 Subject: thermal: core: remove useless empty line Fix style problem on create_trip_attrs(); Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e8098f695c84..122eba77360c 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, -- cgit v1.2.3 From 3bafb5e2a683626387337eda28bbef927bce1a0d Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:49 -0800 Subject: thermal: core: fix style on remove_trip_attrs() Align to parentheses, removing checkpatch warning. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 122eba77360c..592c72bd5835 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); -- cgit v1.2.3 From 0a9de81907e6dc2adaddedca91ee26a7479b3750 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:50 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 216 ++++++++++++++++++++--------------------- 1 file changed, 108 insertions(+), 108 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 592c72bd5835..e399ae67b18b 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) @@ -1799,114 +1907,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 -- cgit v1.2.3 From e161aefb9a5fff038054231ffb80abbc2aa42238 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:51 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e399ae67b18b..971f033368b2 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); -- cgit v1.2.3 From 4d0fe7490d7f4d61b582acbae718328284f151b9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:52 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 86 +++++++++++++++++++++++------------------- include/linux/thermal.h | 2 + 2 files changed, 50 insertions(+), 38 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 971f033368b2..b1d6de9185f4 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 511182a88e76..e275e98bdceb 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -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; -- cgit v1.2.3 From 2a4806bf7afd37c719b10099415318a9936a3293 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:53 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b1d6de9185f4..6100ae70ccfb 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; -- cgit v1.2.3 From 3d0055d2b252d9bbae8c064b37dd444b77f4c4c1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:54 -0800 Subject: thermal: core: split passive_store Split passive_store between sysfs handling and thermal core internal data handling. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 62 ++++++++++++++++++++++++++++-------------- drivers/thermal/thermal_core.h | 4 +++ 2 files changed, 45 insertions(+), 21 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 6100ae70ccfb..4e315c979f89 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 749d41abfbab..a765c753c62c 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); -- cgit v1.2.3 From 6b885202d7c17157a44d5cb42793f795d6d7a58e Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:55 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 37 ++++++++++++++++++++++++------------- drivers/thermal/thermal_core.h | 1 + 2 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 4e315c979f89..23f138f7eb68 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 a765c753c62c..db65d3b08cf7 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); -- cgit v1.2.3 From 97d2423bd9738bb75cd716d01c4c4e1d6fae8441 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:56 -0800 Subject: thermal: core: split available_policies_show() This patch creates a helper to build a list of available governors. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 35 ++++++++++++++++++++--------------- drivers/thermal/thermal_core.h | 1 + 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 23f138f7eb68..3d5118473eb0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -779,6 +779,25 @@ exit: 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 db65d3b08cf7..8994d2a379c3 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); -- cgit v1.2.3 From ba78da443bd5cae5079d2b1e8174d3a3cb040adb Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:57 -0800 Subject: thermal: core: move to_thermal_zone() macro to header file Simply making this macro available to other thermal core files. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 3 --- drivers/thermal/thermal_core.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 3d5118473eb0..f5b519a9f567 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 8994d2a379c3..097abee34633 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 *, -- cgit v1.2.3 From 09544da9e8255ef0f3aafd1e7da067dd2b521b40 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:58 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f5b519a9f567..e2c4fc4904d6 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) -- cgit v1.2.3 From 72afe8e54974823454e4c10d4b29e486ea79f6b7 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:08:59 -0800 Subject: thermal: core: match parenthesis on code alignment Cosmetic change in the sysfs handling functions, as recommended by checkpatch.pl. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e2c4fc4904d6..f66c19c7f201 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; -- cgit v1.2.3 From a369ee88f7f6059a582087dc8bd9fc42b2731f5b Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:00 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- 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 (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index c92eb22a41ff..767c3c9aeeea 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 f66c19c7f201..b14913ea5544 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 097abee34633..bd8869333739 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 000000000000..8a7323f63b78 --- /dev/null +++ b/drivers/thermal/thermal_sysfs.c @@ -0,0 +1,633 @@ +/* + * thermal.c - sysfs interface of thermal devices + * + * Copyright (C) 2016 Eduardo Valentin + * + * Highly based on original thermal_core.c + * Copyright (C) 2008 Intel Corp + * Copyright (C) 2008 Zhang Rui + * Copyright (C) 2008 Sujith Thomas + * + * 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 +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3 From 99ea2eff91080740d91df6ce5bfdfba666a4a035 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:01 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 3 --- drivers/thermal/thermal_core.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b14913ea5544..d55a41a317b5 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 bd8869333739..56192434ea81 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 *, -- cgit v1.2.3 From 45cf2ec99c160e5c33402521bcff1a585629230a Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:02 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- 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(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d55a41a317b5..fb1902135740 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 56192434ea81..2412b3759e16 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 8a7323f63b78..87d9f4d3afaf 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; +} -- cgit v1.2.3 From 77dc4f9032008f097145e6cff7a7532bb9de4ea0 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:03 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index fb1902135740..3a189fd729b9 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) -- cgit v1.2.3 From cd221c7b638f83193ffcacf9c2e3f087033fd4cf Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:04 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- 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 (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 767c3c9aeeea..6a3d7b573036 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 3a189fd729b9..519aa94d0837 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 000000000000..dfdba5a720cd --- /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 + * + * Highly based on original thermal_core.c + * Copyright (C) 2008 Intel Corp + * Copyright (C) 2008 Zhang Rui + * Copyright (C) 2008 Sujith Thomas + * + * 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 +#include +#include +#include +#include + +#include + +#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); -- cgit v1.2.3 From 1b4f48494eb2886d42b034b57f0c4005add296b0 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:05 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 153 +++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 73 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 519aa94d0837..e36a6a6e58db 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 @@ exit: 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) { -- cgit v1.2.3 From c30176fc6f483163affeb0f629c0e27b23c084a1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:06 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e36a6a6e58db..f6e24ef1d904 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 -- cgit v1.2.3 From 4f5163fac28efc4f4d7fefdaa6a7ed41b4febde9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:07 -0800 Subject: thermal: core: small style fix on __unbind() helper Simply aligning to parenthesis. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f6e24ef1d904..c31d0bbdfb2c 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; -- cgit v1.2.3 From f11997fa24220c91f8e951ebd047d69f47ab6759 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:08 -0800 Subject: thermal: core: move __unbind() helper to where it is used Simply moving the helper to closer where it is actually used. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index c31d0bbdfb2c..c12193315a15 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. -- cgit v1.2.3 From 949aad839c33fc6aaace5b063a331a711876d499 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:09 -0800 Subject: thermal: core: move bind_cdev() to where it is used Moving the helper to closer where it is used. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 76 +++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index c12193315a15..e397d88ce267 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. -- cgit v1.2.3 From 90f5b5bb7f4d8455a7965be4b13d50bea39ab6dc Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:10 -0800 Subject: thermal: core: move bind_tz() to where it is used Moving the helper to closer where it is used. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 80 +++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e397d88ce267..bff2905ddbed 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 -- cgit v1.2.3 From 9b68ef89c957c4089cfc3f8aa985b0a7bc0dfc37 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:11 -0800 Subject: thermal: core: fix couple of style issues on __bind() helper Removing style issues on __bind() and its helpers. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index bff2905ddbed..ebec7ce63abf 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; -- cgit v1.2.3 From f502ab84401341be2726ffd747ad6131d5371507 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:12 -0800 Subject: thermal: core: move __bind() to where it is used Moving the helper to closer where it is used. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 66 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ebec7ce63abf..258962bc2813 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; -- cgit v1.2.3 From 4b0d3c2d3b60cf8f517684ab230e8fbeaec5c541 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:13 -0800 Subject: thermal: core: add inline to print_bind_err_msg() Given that this is simple wrapper, adding the inline flag. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 258962bc2813..bc9a4220e8b5 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); -- cgit v1.2.3 From 106339ab7e98da3e51c109926af6f394dcc06812 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:14 -0800 Subject: thermal: core: move notify to the zone update section moving the helper function to closer to similar functions. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index bc9a4220e8b5..884235f216bd 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; -- cgit v1.2.3 From 8772e185f191bf1280445dfe6b4f9c59e725c473 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:15 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 884235f216bd..bf108db6ae5d 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) { -- cgit v1.2.3 From 712afbdfdf0d4137f7b14877d01309b76577d90a Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:16 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index bf108db6ae5d..e9e6bb9085a1 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 -- cgit v1.2.3 From 81193e2e6b473734bcb531a25206780d4f2dbea9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:17 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e9e6bb9085a1..01b1a4e064c0 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; -- cgit v1.2.3 From 7eb4bd723e113d709d04121869964fcd3eb8cb4d Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:19 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 01b1a4e064c0..09d521a56c6f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -5,22 +5,9 @@ * Copyright (C) 2008 Zhang Rui * Copyright (C) 2008 Sujith Thomas * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * * 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 -- cgit v1.2.3 From 5027ba36cda6924488b5752820503cdf7a79dbe9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:20 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 09d521a56c6f..f19fe03e919f 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); -- cgit v1.2.3 From eb7be329bd93b7ab09f442ffe3862b014ab84477 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:21 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f19fe03e919f..d33b29a1553f 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 @@ exit: * 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; -- cgit v1.2.3 From 2a0b4c44ce345f5ea8c240d7d3317974301032cd Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:22 -0800 Subject: thermal: core: remove void function return statements Simply removing useless returns of void functions. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d33b29a1553f..8365d0b81f77 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); -- cgit v1.2.3 From b659a30d7bdd5d9aa0d36b0215bfe3f9961ddf78 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:23 -0800 Subject: thermal: core: remove style warnings and checks Removing several style issues in thermal code code. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 8365d0b81f77..e3cdba530418 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); -- cgit v1.2.3 From 38e7b549af829ad2abd94b60e555227a15f9ecff Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:24 -0800 Subject: thermal: core: improve kerneldoc entry of thermal_cooling_device_unregister Improve description and keep 80 columns limit. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e3cdba530418..2db21e53d0d0 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) { -- cgit v1.2.3 From 95e3ed1513494aa2d0aaba7a99fb7aa8b51dcfc8 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:25 -0800 Subject: 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 Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 2db21e53d0d0..4f9384482818 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); -- cgit v1.2.3 From 373f91d1256db7d8f494fd473c05dbc961a37f23 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 7 Nov 2016 21:09:27 -0800 Subject: thermal: core: move slop and offset helpers to thermal_helpers.c Reorganize code to reflect better placement. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 30 ------------------------------ drivers/thermal/thermal_helpers.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers/thermal/thermal_core.c') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 4f9384482818..7daffc14949a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1358,36 +1358,6 @@ exit: } 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 dfdba5a720cd..8cdf75adcce1 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); -- cgit v1.2.3