diff options
Diffstat (limited to 'drivers/hwmon/hwmon.c')
-rw-r--r-- | drivers/hwmon/hwmon.c | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index a74c075a30ec..3932f9276c07 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -38,12 +38,15 @@ struct hwmon_device { #define to_hwmon_device(d) container_of(d, struct hwmon_device, dev) +#define MAX_SYSFS_ATTR_NAME_LENGTH 32 + struct hwmon_device_attribute { struct device_attribute dev_attr; const struct hwmon_ops *ops; enum hwmon_sensor_types type; u32 attr; int index; + char name[MAX_SYSFS_ATTR_NAME_LENGTH]; }; #define to_hwmon_attr(d) \ @@ -178,6 +181,22 @@ static ssize_t hwmon_attr_show(struct device *dev, return sprintf(buf, "%ld\n", val); } +static ssize_t hwmon_attr_show_string(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); + char *s; + int ret; + + ret = hattr->ops->read_string(dev, hattr->type, hattr->attr, + hattr->index, &s); + if (ret < 0) + return ret; + + return sprintf(buf, "%s\n", s); +} + static ssize_t hwmon_attr_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) @@ -205,6 +224,17 @@ static int hwmon_attr_base(enum hwmon_sensor_types type) return 1; } +static bool is_string_attr(enum hwmon_sensor_types type, u32 attr) +{ + return (type == hwmon_temp && attr == hwmon_temp_label) || + (type == hwmon_in && attr == hwmon_in_label) || + (type == hwmon_curr && attr == hwmon_curr_label) || + (type == hwmon_power && attr == hwmon_power_label) || + (type == hwmon_energy && attr == hwmon_energy_label) || + (type == hwmon_humidity && attr == hwmon_humidity_label) || + (type == hwmon_fan && attr == hwmon_fan_label); +} + static struct attribute *hwmon_genattr(struct device *dev, const void *drvdata, enum hwmon_sensor_types type, @@ -218,6 +248,7 @@ static struct attribute *hwmon_genattr(struct device *dev, struct attribute *a; umode_t mode; char *name; + bool is_string = is_string_attr(type, attr); /* The attribute is invisible if there is no template string */ if (!template) @@ -227,32 +258,31 @@ static struct attribute *hwmon_genattr(struct device *dev, if (!mode) return ERR_PTR(-ENOENT); - if ((mode & S_IRUGO) && !ops->read) + if ((mode & S_IRUGO) && ((is_string && !ops->read_string) || + (!is_string && !ops->read))) return ERR_PTR(-EINVAL); if ((mode & S_IWUGO) && !ops->write) return ERR_PTR(-EINVAL); + hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL); + if (!hattr) + return ERR_PTR(-ENOMEM); + if (type == hwmon_chip) { name = (char *)template; } else { - name = devm_kzalloc(dev, strlen(template) + 16, GFP_KERNEL); - if (!name) - return ERR_PTR(-ENOMEM); - scnprintf(name, strlen(template) + 16, template, + scnprintf(hattr->name, sizeof(hattr->name), template, index + hwmon_attr_base(type)); + name = hattr->name; } - hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL); - if (!hattr) - return ERR_PTR(-ENOMEM); - hattr->type = type; hattr->attr = attr; hattr->index = index; hattr->ops = ops; dattr = &hattr->dev_attr; - dattr->show = hwmon_attr_show; + dattr->show = is_string ? hwmon_attr_show_string : hwmon_attr_show; dattr->store = hwmon_attr_store; a = &dattr->attr; @@ -263,7 +293,11 @@ static struct attribute *hwmon_genattr(struct device *dev, return a; } -static const char * const hwmon_chip_attr_templates[] = { +/* + * Chip attributes are not attribute templates but actual sysfs attributes. + * See hwmon_genattr() for special handling. + */ +static const char * const hwmon_chip_attrs[] = { [hwmon_chip_temp_reset_history] = "temp_reset_history", [hwmon_chip_in_reset_history] = "in_reset_history", [hwmon_chip_curr_reset_history] = "curr_reset_history", @@ -400,7 +434,7 @@ static const char * const hwmon_pwm_attr_templates[] = { }; static const char * const *__templates[] = { - [hwmon_chip] = hwmon_chip_attr_templates, + [hwmon_chip] = hwmon_chip_attrs, [hwmon_temp] = hwmon_temp_attr_templates, [hwmon_in] = hwmon_in_attr_templates, [hwmon_curr] = hwmon_curr_attr_templates, @@ -412,7 +446,7 @@ static const char * const *__templates[] = { }; static const int __templates_size[] = { - [hwmon_chip] = ARRAY_SIZE(hwmon_chip_attr_templates), + [hwmon_chip] = ARRAY_SIZE(hwmon_chip_attrs), [hwmon_temp] = ARRAY_SIZE(hwmon_temp_attr_templates), [hwmon_in] = ARRAY_SIZE(hwmon_in_attr_templates), [hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates), @@ -526,9 +560,9 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, hdev = &hwdev->dev; - if (chip && chip->ops->is_visible) { + if (chip) { struct attribute **attrs; - int ngroups = 2; + int ngroups = 2; /* terminating NULL plus &hwdev->groups */ if (groups) for (i = 0; groups[i]; i++) @@ -572,7 +606,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, if (err) goto free_hwmon; - if (chip && chip->ops->is_visible && chip->ops->read && + if (chip && chip->ops->read && chip->info[0]->type == hwmon_chip && (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) { const struct hwmon_channel_info **info = chip->info; @@ -626,8 +660,8 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups); * @dev: the parent device * @name: hwmon name attribute * @drvdata: driver data to attach to created device - * @info: Pointer to hwmon chip information - * @groups - pointer to list of driver specific attribute groups + * @info: pointer to hwmon chip information + * @extra_groups: pointer to list of additional non-standard attribute groups * * hwmon_device_unregister() must be called when the device is no * longer needed. @@ -638,12 +672,12 @@ struct device * hwmon_device_register_with_info(struct device *dev, const char *name, void *drvdata, const struct hwmon_chip_info *chip, - const struct attribute_group **groups) + const struct attribute_group **extra_groups) { - if (chip && (!chip->ops || !chip->info)) + if (chip && (!chip->ops || !chip->ops->is_visible || !chip->info)) return ERR_PTR(-EINVAL); - return __hwmon_device_register(dev, name, drvdata, chip, groups); + return __hwmon_device_register(dev, name, drvdata, chip, extra_groups); } EXPORT_SYMBOL_GPL(hwmon_device_register_with_info); @@ -658,6 +692,9 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_with_info); */ struct device *hwmon_device_register(struct device *dev) { + dev_warn(dev, + "hwmon_device_register() is deprecated. Please convert the driver to use hwmon_device_register_with_info().\n"); + return hwmon_device_register_with_groups(dev, NULL, NULL, NULL); } EXPORT_SYMBOL_GPL(hwmon_device_register); |