lkml.org 
[lkml]   [2016]   [May]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCHv3 22/48] thermal: core: move thermal_zone sysfs to thermal_sysfs.c
    Date
    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 <rui.zhang@intel.com>
    Cc: linux-pm@vger.kernel.org
    Cc: linux-kernel@vger.kernel.org
    Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
    ---
    drivers/thermal/Makefile | 2 +-
    drivers/thermal/thermal_core.c | 590 --------------------------------------
    drivers/thermal/thermal_core.h | 3 +
    drivers/thermal/thermal_sysfs.c | 614 ++++++++++++++++++++++++++++++++++++++++
    4 files changed, 618 insertions(+), 591 deletions(-)
    create mode 100644 drivers/thermal/thermal_sysfs.c

    diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
    index 10b07c1..95ccb75 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 f22fd7e..9778ce5 100644
    --- a/drivers/thermal/thermal_core.c
    +++ b/drivers/thermal/thermal_core.c
    @@ -741,596 +741,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);
    -
    - 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);
    -
    - 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);
    -
    - 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);
    -
    - 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,
    -};
    -
    -static struct attribute_group thermal_zone_attribute_group = {
    - .attrs = thermal_zone_dev_attrs,
    -};
    -
    -/* We expose mode only if .get_mode is present */
    -static struct attribute *thermal_zone_mode_attrs[] = {
    - &dev_attr_mode.attr,
    -};
    -
    -static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
    - struct attribute *attr,
    - int attrno)
    -{
    - struct device *dev = container_of(kobj, struct device, kobj);
    - struct thermal_zone_device *tz;
    -
    - tz = container_of(dev, struct thermal_zone_device, device);
    -
    - if (tz->ops->get_mode)
    - return attr->mode;
    -
    - return 0;
    -}
    -
    -static struct attribute_group thermal_zone_mode_attribute_group = {
    - .attrs = thermal_zone_mode_attrs,
    - .is_visible = thermal_zone_mode_is_visible,
    -};
    -
    -/* We expose passive only if passive trips are present */
    -static struct attribute *thermal_zone_passive_attrs[] = {
    - &dev_attr_passive.attr,
    -};
    -
    -static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
    - struct attribute *attr,
    - int attrno)
    -{
    - struct device *dev = container_of(kobj, struct device, kobj);
    - struct thermal_zone_device *tz;
    - enum thermal_trip_type trip_type;
    - int count;
    -
    - tz = container_of(dev, struct thermal_zone_device, device);
    -
    - for (count = 0; count < tz->trips; count++) {
    - tz->ops->get_trip_type(tz, count, &trip_type);
    -
    - if (trip_type == THERMAL_TRIP_PASSIVE)
    - return attr->mode;
    - }
    -
    - return 0;
    -}
    -
    -static struct attribute_group thermal_zone_passive_attribute_group = {
    - .attrs = thermal_zone_passive_attrs,
    - .is_visible = thermal_zone_passive_is_visible,
    -};
    -
    -static const struct attribute_group *thermal_zone_attribute_groups[] = {
    - &thermal_zone_attribute_group,
    - &thermal_zone_mode_attribute_group,
    - &thermal_zone_passive_attribute_group,
    - /* 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;
    -
    - 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, 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_type_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_type_attrs[indx].attr.attr;
    - }
    -
    - 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;
    -
    - result = create_trip_attrs(tz, mask);
    - if (result)
    - return 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];
    -
    - groups[size - 2] = &tz->trips_attribute_group;
    -
    - tz->device.groups = groups;
    -
    - return 0;
    -}
    -
    /* sys I/F for cooling device */
    #define to_cooling_device(_dev) \
    container_of(_dev, struct thermal_cooling_device, device)
    diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
    index 097abee..bd88693 100644
    --- a/drivers/thermal/thermal_core.h
    +++ b/drivers/thermal/thermal_core.h
    @@ -66,6 +66,9 @@ void thermal_zone_device_unbind_exception(struct thermal_zone_device *,
    int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
    int thermal_build_list_of_policies(char *buf);

    +/* sysfs I/F */
    +int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
    +
    #ifdef CONFIG_THERMAL_GOV_STEP_WISE
    int thermal_gov_step_wise_register(void);
    void thermal_gov_step_wise_unregister(void);
    diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
    new file mode 100644
    index 0000000..60122a2
    --- /dev/null
    +++ b/drivers/thermal/thermal_sysfs.c
    @@ -0,0 +1,614 @@
    +/*
    + * thermal.c - sysfs interface of thermal devices
    + *
    + * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
    + *
    + * Highly based on original thermal_core.c
    + * Copyright (C) 2008 Intel Corp
    + * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
    + * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation; version 2 of the License.
    + */
    +
    +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
    +
    +#include <linux/sysfs.h>
    +#include <linux/device.h>
    +#include <linux/err.h>
    +#include <linux/slab.h>
    +#include <linux/string.h>
    +
    +#include "thermal_core.h"
    +
    +/* sys I/F for thermal zone */
    +
    +static ssize_t
    +type_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    +
    + return sprintf(buf, "%s\n", tz->type);
    +}
    +
    +static ssize_t
    +temp_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    + int temperature, ret;
    +
    + ret = thermal_zone_get_temp(tz, &temperature);
    +
    + if (ret)
    + return ret;
    +
    + return sprintf(buf, "%d\n", temperature);
    +}
    +
    +static ssize_t
    +mode_show(struct device *dev, struct device_attribute *attr, char *buf)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    + enum thermal_device_mode mode;
    + int result;
    +
    + if (!tz->ops->get_mode)
    + return -EPERM;
    +
    + result = tz->ops->get_mode(tz, &mode);
    + if (result)
    + return result;
    +
    + return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
    + : "disabled");
    +}
    +
    +static ssize_t
    +mode_store(struct device *dev, struct device_attribute *attr,
    + const char *buf, size_t count)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    + int result;
    +
    + if (!tz->ops->set_mode)
    + return -EPERM;
    +
    + if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
    + result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
    + else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
    + result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
    + else
    + result = -EINVAL;
    +
    + if (result)
    + return result;
    +
    + return count;
    +}
    +
    +static ssize_t
    +trip_point_type_show(struct device *dev, struct device_attribute *attr,
    + char *buf)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    + enum thermal_trip_type type;
    + int trip, result;
    +
    + if (!tz->ops->get_trip_type)
    + return -EPERM;
    +
    + if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
    + return -EINVAL;
    +
    + result = tz->ops->get_trip_type(tz, trip, &type);
    + if (result)
    + return result;
    +
    + switch (type) {
    + case THERMAL_TRIP_CRITICAL:
    + return sprintf(buf, "critical\n");
    + case THERMAL_TRIP_HOT:
    + return sprintf(buf, "hot\n");
    + case THERMAL_TRIP_PASSIVE:
    + return sprintf(buf, "passive\n");
    + case THERMAL_TRIP_ACTIVE:
    + return sprintf(buf, "active\n");
    + default:
    + return sprintf(buf, "unknown\n");
    + }
    +}
    +
    +static ssize_t
    +trip_point_temp_store(struct device *dev, struct device_attribute *attr,
    + const char *buf, size_t count)
    +{
    + struct thermal_zone_device *tz = to_thermal_zone(dev);
    + int trip, ret;
    + int temperature;
    +
    + if (!tz->ops->set_trip_temp)
    + return -EPERM;
    +
    + if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
    + return -EINVAL;
    +
    + if (kstrtoint(buf, 10, &temperature))
    + return -EINVAL;
    +
    + ret = tz->ops->set_trip_temp(tz, trip, temperature);
    + if (ret)
    + return ret;
    +
    + thermal_zone_device_update(tz);
    +
    + 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);
    +
    + 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);
    +
    + 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);
    +
    + 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,
    +};
    +
    +static struct attribute_group thermal_zone_attribute_group = {
    + .attrs = thermal_zone_dev_attrs,
    +};
    +
    +/* We expose mode only if .get_mode is present */
    +static struct attribute *thermal_zone_mode_attrs[] = {
    + &dev_attr_mode.attr,
    +};
    +
    +static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
    + struct attribute *attr,
    + int attrno)
    +{
    + struct device *dev = container_of(kobj, struct device, kobj);
    + struct thermal_zone_device *tz;
    +
    + tz = container_of(dev, struct thermal_zone_device, device);
    +
    + if (tz->ops->get_mode)
    + return attr->mode;
    +
    + return 0;
    +}
    +
    +static struct attribute_group thermal_zone_mode_attribute_group = {
    + .attrs = thermal_zone_mode_attrs,
    + .is_visible = thermal_zone_mode_is_visible,
    +};
    +
    +/* We expose passive only if passive trips are present */
    +static struct attribute *thermal_zone_passive_attrs[] = {
    + &dev_attr_passive.attr,
    +};
    +
    +static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
    + struct attribute *attr,
    + int attrno)
    +{
    + struct device *dev = container_of(kobj, struct device, kobj);
    + struct thermal_zone_device *tz;
    + enum thermal_trip_type trip_type;
    + int count;
    +
    + tz = container_of(dev, struct thermal_zone_device, device);
    +
    + for (count = 0; count < tz->trips; count++) {
    + tz->ops->get_trip_type(tz, count, &trip_type);
    +
    + if (trip_type == THERMAL_TRIP_PASSIVE)
    + return attr->mode;
    + }
    +
    + return 0;
    +}
    +
    +static struct attribute_group thermal_zone_passive_attribute_group = {
    + .attrs = thermal_zone_passive_attrs,
    + .is_visible = thermal_zone_passive_is_visible,
    +};
    +
    +static const struct attribute_group *thermal_zone_attribute_groups[] = {
    + &thermal_zone_attribute_group,
    + &thermal_zone_mode_attribute_group,
    + &thermal_zone_passive_attribute_group,
    + /* 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;
    +
    + 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, 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_type_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_type_attrs[indx].attr.attr;
    + }
    +
    + 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;
    +
    + result = create_trip_attrs(tz, mask);
    + if (result)
    + return 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];
    +
    + groups[size - 2] = &tz->trips_attribute_group;
    +
    + tz->device.groups = groups;
    +
    + return 0;
    +}
    --
    2.1.4
    \
     
     \ /
      Last update: 2016-05-31 00:41    [W:3.962 / U:0.296 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site