From: Jim Cromie <jim.cromie@gmail.com>
To: Alexey Dobriyan <adobriyan@gmail.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: RFC-patch - make sysfs_create_group skip members with attr.mode == 0
Date: Thu, 17 Aug 2006 22:25:27 -0600 [thread overview]
Message-ID: <44E54137.8030805@gmail.com> (raw)
In-Reply-To: <20060818014922.GA2622@martell.zuzino.mipt.ru>
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
next prev parent reply other threads:[~2006-08-18 4:25 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
[not found] ` <200608190019.01389.dtor@insightbb.com>
2006-08-19 5:21 ` Jim Cromie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44E54137.8030805@gmail.com \
--to=jim.cromie@gmail.com \
--cc=adobriyan@gmail.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.