public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* RFC-patch - make sysfs_create_group skip members with attr.mode == 0
@ 2006-08-17 22:50 Jim Cromie
  2006-08-18  1:49 ` Alexey Dobriyan
  0 siblings, 1 reply; 4+ messages in thread
From: Jim Cromie @ 2006-08-17 22:50 UTC (permalink / raw)
  To: Linux kernel


Currently, code in hwmon/*.c uses sysfs_create_group less than it could.
A contributing reason is that many individual attr-files are created 
conditionally,
depending upon both underlying hardware, driver configuration, etc.

With proposed patch, the members of a group are conditionally created,
based upon the mode of the underlying attribute.  mode == 0 suppresses 
attr-file
creation, allowing run-time tweaks of compile-time defined groups.

The driver defining the group need only disable the unwanted members
before calling sysfs_create_group()  (theyre 'enabled' by initialization 
macros,
since thats the most useful default)

Specifically
- only group members are created conditionally,
    theres no effect on calls to device_create_file.
- only mode == 0 disables member creation,
    common values like  S_IWUSR | S_IRUGO have un-altered behavior.


Signed-off-by:  Jim Cromie  <jim.cromie@gmail.com>

$ diffstat diff.sys-grp-conditional-members
 group.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletion(-)

diff -ruNp -X dontdiff -X exclude-diffs try1/fs/sysfs/group.c try2/fs/sysfs/group.c
--- try1/fs/sysfs/group.c	2006-06-17 19:49:35.000000000 -0600
+++ try2/fs/sysfs/group.c	2006-08-17 10:06:26.000000000 -0600
@@ -32,7 +33,8 @@ static int create_files(struct dentry * 
 	int error = 0;
 
 	for (attr = grp->attrs; *attr && !error; attr++) {
-		error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
+		if ((*attr)->mode)
+			error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
 	}
 	if (error)
 		remove_files(dir,grp);



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC-patch - make sysfs_create_group skip members with attr.mode == 0
  2006-08-17 22:50 RFC-patch - make sysfs_create_group skip members with attr.mode == 0 Jim Cromie
@ 2006-08-18  1:49 ` Alexey Dobriyan
  2006-08-18  4:25   ` Jim Cromie
  0 siblings, 1 reply; 4+ messages in thread
From: Alexey Dobriyan @ 2006-08-18  1:49 UTC (permalink / raw)
  To: Jim Cromie; +Cc: linux-kernel

On Thu, Aug 17, 2006 at 04:50:25PM -0600, Jim Cromie wrote:
> Currently, code in hwmon/*.c uses sysfs_create_group less than it could.

Please, provide sample patch which will use this feature. And I personally
don't understand the reasoning: can i2c code use sysfs_create_group()
with elements of struct attribute_group::attrs array ifdeffed?

> A contributing reason is that many individual attr-files are created
> conditionally,
> depending upon both underlying hardware, driver configuration, etc.

> --- try1/fs/sysfs/group.c	2006-06-17 19:49:35.000000000 -0600
> +++ try2/fs/sysfs/group.c	2006-08-17 10:06:26.000000000 -0600
> @@ -32,7 +33,8 @@ static int create_files(struct dentry *
> 	int error = 0;
>
> 	for (attr = grp->attrs; *attr && !error; attr++) {
> -		error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
> +		if ((*attr)->mode)
> +			error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
> 	}


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC-patch - make sysfs_create_group skip members with attr.mode == 0
  2006-08-18  1:49 ` Alexey Dobriyan
@ 2006-08-18  4:25   ` Jim Cromie
       [not found]     ` <200608190019.01389.dtor@insightbb.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Jim Cromie @ 2006-08-18  4:25 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: linux-kernel

Alexey Dobriyan wrote:
> On Thu, Aug 17, 2006 at 04:50:25PM -0600, Jim Cromie wrote:
>   
>> Currently, code in hwmon/*.c uses sysfs_create_group less than it could.
>>     
>
> Please, provide sample patch which will use this feature. And I personally
> don't understand the reasoning: can i2c code use sysfs_create_group()
> with elements of struct attribute_group::attrs array ifdeffed?
>
>   
>> A contributing reason is that many individual attr-files are created
>> conditionally,
>> depending upon both underlying hardware, driver configuration, etc.
>>     
>
>   
>> --- try1/fs/sysfs/group.c	2006-06-17 19:49:35.000000000 -0600
>> +++ try2/fs/sysfs/group.c	2006-08-17 10:06:26.000000000 -0600
>> @@ -32,7 +33,8 @@ static int create_files(struct dentry *
>> 	int error = 0;
>>
>> 	for (attr = grp->attrs; *attr && !error; attr++) {
>> -		error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
>> +		if ((*attr)->mode)
>> +			error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
>> 	}
>>     
>
>
>   
Hi Alexy,

Heres my motivation for the above patch, in 2 parts.

hwmon/pc87360 supports 5 kinds of sensors -
voltages, temps, thermistors, fans, pwm-fan-controllers.
Formerly, all attr-files were created by individual calls
to device_create_file().

patch 1 declares 4 separate groups (fans & pwm are together),
and creates the attr-files by calling sysfs_create_group()
for each.  

This patch doesnt require the proposed patch, but sets it up..



diff -ruNp -X dontdiff -X exclude-diffs ../linux-2.6.18-rc4-mm1-sk/drivers/hwmon/pc87360.c sys-grp/drivers/hwmon/pc87360.c
--- ../linux-2.6.18-rc4-mm1-sk/drivers/hwmon/pc87360.c	2006-08-14 21:19:24.000000000 -0600
+++ sys-grp/drivers/hwmon/pc87360.c	2006-08-15 22:46:16.000000000 -0600
@@ -327,6 +327,12 @@ static struct sensor_device_attribute fa
 	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
 };
 
+#define FAN_UNIT_ATTRS(X)	\
+	&fan_input[X].dev_attr.attr,	\
+	&fan_status[X].dev_attr.attr,	\
+	&fan_div[X].dev_attr.attr,	\
+	&fan_min[X].dev_attr.attr
+
 static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -359,6 +365,19 @@ static struct sensor_device_attribute pw
 	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
 };
 
+static struct attribute * pc8736x_fan_attr_array[] = {
+	FAN_UNIT_ATTRS(0),
+	FAN_UNIT_ATTRS(1),
+	FAN_UNIT_ATTRS(2),
+	&pwm[0].dev_attr.attr,
+	&pwm[1].dev_attr.attr,
+	&pwm[2].dev_attr.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_fan_group = {
+	.attrs = pc8736x_fan_attr_array,
+};
+
 static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -471,6 +490,61 @@ static struct sensor_device_attribute in
 	SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
 };
 
+#define VIN_UNIT_ATTRS(X) \
+	&in_input[X].dev_attr.attr,	\
+	&in_status[X].dev_attr.attr,	\
+	&in_min[X].dev_attr.attr,	\
+	&in_max[X].dev_attr.attr
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->vrm);
+}
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	data->vrm = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+
+static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->in_alarms);
+}
+static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+
+static struct attribute *pc8736x_vin_attr_array[] = {
+	VIN_UNIT_ATTRS(0),
+	VIN_UNIT_ATTRS(1),
+	VIN_UNIT_ATTRS(2),
+	VIN_UNIT_ATTRS(3),
+	VIN_UNIT_ATTRS(4),
+	VIN_UNIT_ATTRS(5),
+	VIN_UNIT_ATTRS(6),
+	VIN_UNIT_ATTRS(7),
+	VIN_UNIT_ATTRS(8),
+	VIN_UNIT_ATTRS(9),
+	VIN_UNIT_ATTRS(10),
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	&dev_attr_alarms_in.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_vin_group = {
+	.attrs = pc8736x_vin_attr_array,
+};
+
 static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -589,33 +663,22 @@ static struct sensor_device_attribute th
 		    show_therm_crit, set_therm_crit, 2+11),
 };
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
-}
-static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", data->vrm);
-}
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
-	data->vrm = simple_strtoul(buf, NULL, 10);
-	return count;
-}
-static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-
-static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%u\n", data->in_alarms);
-}
-static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
+#define THERM_UNIT_ATTRS(X) \
+	&therm_input[X].dev_attr.attr,	\
+	&therm_status[X].dev_attr.attr,	\
+	&therm_min[X].dev_attr.attr,	\
+	&therm_max[X].dev_attr.attr,	\
+	&therm_crit[X].dev_attr.attr
+
+static struct attribute * pc8736x_therm_attr_array[] = {
+	THERM_UNIT_ATTRS(0),
+	THERM_UNIT_ATTRS(1),
+	THERM_UNIT_ATTRS(2),
+	NULL
+};
+static const struct attribute_group pc8736x_therm_group = {
+	.attrs = pc8736x_therm_attr_array,
+};
 
 static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
@@ -735,6 +798,25 @@ static ssize_t show_temp_alarms(struct d
 }
 static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
 
+#define TEMP_UNIT_ATTRS(X) \
+	&temp_input[X].dev_attr.attr,	\
+	&temp_status[X].dev_attr.attr,	\
+	&temp_min[X].dev_attr.attr,	\
+	&temp_max[X].dev_attr.attr,	\
+	&temp_crit[X].dev_attr.attr
+
+static struct attribute * pc8736x_temp_attr_array[] = {
+	TEMP_UNIT_ATTRS(0),
+	TEMP_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(2),
+	/* include the few miscellaneous atts here */
+	&dev_attr_alarms_temp.attr,
+	NULL
+};
+static const struct attribute_group pc8736x_temp_group = {
+	.attrs = pc8736x_temp_attr_array,
+};
+
 /*
  * Device detection, registration and update
  */
@@ -935,67 +1017,46 @@ static int pc87360_detect(struct i2c_ada
 		pc87360_init_client(client, use_thermistors);
 	}
 
-	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
+	/* Register sysfs groups */
+
+	if (data->innr && 
+	    sysfs_create_group(&client->dev.kobj,
+			       &pc8736x_vin_group))
 		goto ERROR3;
-	}
 
-	if (data->innr) {
-		for (i = 0; i < 11; i++) {
-			device_create_file(dev, &in_input[i].dev_attr);
-			device_create_file(dev, &in_min[i].dev_attr);
-			device_create_file(dev, &in_max[i].dev_attr);
-			device_create_file(dev, &in_status[i].dev_attr);
-		}
-		device_create_file(dev, &dev_attr_cpu0_vid);
-		device_create_file(dev, &dev_attr_vrm);
-		device_create_file(dev, &dev_attr_alarms_in);
-	}
+	if (data->tempnr &&
+	    sysfs_create_group(&client->dev.kobj, 
+			       &pc8736x_temp_group))
+		goto ERROR3;
 
-	if (data->tempnr) {
-		for (i = 0; i < data->tempnr; i++) {
-			device_create_file(dev, &temp_input[i].dev_attr);
-			device_create_file(dev, &temp_min[i].dev_attr);
-			device_create_file(dev, &temp_max[i].dev_attr);
-			device_create_file(dev, &temp_crit[i].dev_attr);
-			device_create_file(dev, &temp_status[i].dev_attr);
-		}
-		device_create_file(dev, &dev_attr_alarms_temp);
-	}
+	if (data->innr == 14 &&
+	    sysfs_create_group(&client->dev.kobj, 
+			       &pc8736x_therm_group))
+		goto ERROR3;
 
-	if (data->innr == 14) {
-		for (i = 0; i < 3; i++) {
-			device_create_file(dev, &therm_input[i].dev_attr);
-			device_create_file(dev, &therm_min[i].dev_attr);
-			device_create_file(dev, &therm_max[i].dev_attr);
-			device_create_file(dev, &therm_crit[i].dev_attr);
-			device_create_file(dev, &therm_status[i].dev_attr);
-		}
-	}
+	if (data->fannr &&
+	    sysfs_create_group(&client->dev.kobj,
+			       &pc8736x_fan_group))
+		goto ERROR3;
 
-	for (i = 0; i < data->fannr; i++) {
-		if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
-			device_create_file(dev, &fan_input[i].dev_attr);
-			device_create_file(dev, &fan_min[i].dev_attr);
-			device_create_file(dev, &fan_div[i].dev_attr);
-			device_create_file(dev, &fan_status[i].dev_attr);
-		}
-		if (FAN_CONFIG_CONTROL(data->fan_conf, i))
-			device_create_file(dev, &pwm[i].dev_attr);
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
 	}
-
 	return 0;
 
 ERROR3:
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
 	i2c_detach_client(client);
 ERROR2:
-	for (i = 0; i < 3; i++) {
-		if (data->address[i]) {
+	for (i = 0; i < 3; i++)
+		if (data->address[i])
 			release_region(data->address[i], PC87360_EXTENT);
-		}
-	}
 ERROR1:
 	kfree(data);
 	return err;
@@ -1008,16 +1069,19 @@ static int pc87360_detach_client(struct 
 
 	hwmon_device_unregister(data->class_dev);
 
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
+
 	if ((i = i2c_detach_client(client)))
 		return i;
 
-	for (i = 0; i < 3; i++) {
-		if (data->address[i]) {
+	for (i = 0; i < 3; i++)
+		if (data->address[i])
 			release_region(data->address[i], PC87360_EXTENT);
-		}
-	}
-	kfree(data);
 
+	kfree(data);
 	return 0;
 }
 

So, now we have 4 working groups (with a few problems)

However, the driver supports several different chips,
which have varying numbers of voltage & temp measurement circuits.

Prior to this patch, the way to get 3 sets of voltage-device-attrs
was to call device_create_file for the 1st 3, but not for 4..N.
If you'd declared (at compile time) a group of voltage-attrs, 
the corresponding attr-files would be created en-masse.

With this patch, atts 4..N can be disabled at runtime,
by setting mode = 0.  Afterwards, when sysfs_group_create
is called, it creates attr-files *only* for those whose
mode != 0.  IOW - no attr-files for non-existent hardware.
Normally, mode is set usefully, and attr-files
are created as normal.


IE, like this:


diff -ruNp -X dontdiff -X exclude-diffs sys-grp/drivers/hwmon/pc87360.c grp2/drivers/hwmon/pc87360.c
--- sys-grp/drivers/hwmon/pc87360.c	2006-08-16 07:53:00.000000000 -0600
+++ grp2/drivers/hwmon/pc87360.c	2006-08-17 11:54:59.000000000 -0600
@@ -1020,7 +1020,32 @@ static int pc87360_detect(struct i2c_ada
 		pc87360_init_client(client, use_thermistors);
 	}
 
-	/* Register sysfs groups */
+	/* disable group members which arent supported by the
+	   available hardware.  For efficiency, we handle all-or-none
+	   groups separately below, and more variant groups here
+	 */
+
+#	define disable_attr(X) 	(X).dev_attr.attr.mode = 0
+
+	for (i = 0; i < ARRAY_SIZE(fan_input); i++) {
+		if (!FAN_CONFIG_MONITOR(data->fan_conf, i)) {
+			disable_attr(fan_input[i]);
+			disable_attr(fan_min[i]);
+			disable_attr(fan_div[i]);
+			disable_attr(fan_status[i]);
+		}
+		if (FAN_CONFIG_CONTROL(data->fan_conf, i))
+			disable_attr(pwm[i]);
+	}
+	for (i = data->tempnr; i &&  i < ARRAY_SIZE(temp_input); i++) {
+		disable_attr(temp_input[i]);
+		disable_attr(temp_min[i]);
+		disable_attr(temp_max[i]);
+		disable_attr(temp_crit[i]);
+		disable_attr(temp_status[i]);
+	}
+
+	/* Register sysfs groups for available hardware */
 
 	if (data->innr && 
 	    sysfs_create_group(&client->dev.kobj,



I hope that clarifies (and sufficiently justifies) ..

thanks






^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC-patch - make sysfs_create_group skip members with attr.mode == 0
       [not found]     ` <200608190019.01389.dtor@insightbb.com>
@ 2006-08-19  5:21       ` Jim Cromie
  0 siblings, 0 replies; 4+ messages in thread
From: Jim Cromie @ 2006-08-19  5:21 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Alexey Dobriyan, linux-kernel

Dmitry Torokhov wrote:
> On Friday 18 August 2006 00:25, Jim Cromie wrote:
>   
>> With this patch, atts 4..N can be disabled at runtime,
>> by setting mode = 0.  Afterwards, when sysfs_group_create
>> is called, it creates attr-files *only* for those whose
>> mode != 0.  IOW - no attr-files for non-existent hardware.
>> Normally, mode is set usefully, and attr-files
>> are created as normal.
>>
>>     
patch trimmed
>
> Unfortunately this does not work too well if your box happen to have
> 2 or more different chips served by the same driver as you fiddle with
> the static array of attributes shared by all device instances.
>
>   

Ack, yes.  Thats become clear over on lm-sensors.
Kinda spoils the supposed generality..

thanks

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-08-19  5:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-17 22:50 RFC-patch - make sysfs_create_group skip members with attr.mode == 0 Jim Cromie
2006-08-18  1:49 ` Alexey Dobriyan
2006-08-18  4:25   ` Jim Cromie
     [not found]     ` <200608190019.01389.dtor@insightbb.com>
2006-08-19  5:21       ` Jim Cromie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox