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); |