[PATCH 2.6.12-rc4 3/3] (dynamic sysfs callbacks) device_attribute

Yani Ioannou
2005-05-11T08:01:07Z

[-- Attachment #1: Type: text/plain, Size: 973 bytes --]

Hi,

This patch presents as an example one possible way to use the dynamic
callbacks to clean up one of the i2c chip drivers, adm1026 (for more
information please see
http://archives.andrew.net.au/lm-sensors/msg31310.html).

The first patch defines a new macros like DEVICE_ATTR that also sets
the attribute private data (Greg whats your opinion on defining a
separate set of macros for this v.s. rolling it into one macro?).

The second patch changes adm1026 to pass the sensor index/number via
the private data pointer. I can't test this patch (so you won't want
to apply this) but I'm CCing it to the adm1026 maintainer.

The size difference:

-----------------2.6.11.7--------------------
Module Size Used by
adm1026 44692 0
------2.6.12-rc4-sysdyncallback-----
Module Size Used by
adm1026 32656 0

Signed-off-by: Yani Ioannou <yani.ioannou@gmail.com>

Thanks,
Yani

---

[-- Attachment #2: patch-linux-2.6.12-rc4-sysfsdyncallback-deviceattr-macro.diff --]
[-- Type: text/x-patch, Size: 1252 bytes --]

diff -uprN -X dontdiff linux-2.6.12-rc4-sysfsdyncallback-deviceattr-nowarn/include/linux/device.h linux-2.6.12-rc4-sysfsdyncallback-deviceattr-macro/include/linux/device.h
--- linux-2.6.12-rc4-sysfsdyncallback-deviceattr-nowarn/include/linux/device.h 2005-05-10 23:38:13.000000000 -0400
+++ linux-2.6.12-rc4-sysfsdyncallback-deviceattr-macro/include/linux/device.h 2005-05-11 03:15:40.000000000 -0400
@@ -343,6 +343,13 @@ struct device_attribute {
#define DEVICE_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)

+#define DEVICE_ATTR_PRIVATE(_name,_mode,_show,_store,_private) \
+struct device_attribute dev_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE, \
+ .private = _private, }, \
+ .show = _show, \
+ .store = _store, \
+}

extern int device_create_file(struct device *device, struct device_attribute * entry);
extern void device_remove_file(struct device * dev, struct device_attribute * attr);

[-- Attachment #3: adm1026-sysdyncallback.diff --]
[-- Type: text/x-patch, Size: 21594 bytes --]

--- linux-2.6.12-rc4-sysfsdyncallback-deviceattr-nowarn/drivers/i2c/chips/adm1026.c 2005-05-11 00:32:26.000000000 -0400
+++ /usr/src/linux/drivers/i2c/chips/adm1026.c 2005-05-11 03:40:25.000000000 -0400
@@ -711,19 +711,22 @@ static struct adm1026_data *adm1026_upda
return data;
}

-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private);
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]));
}
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private);
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]));
}
static ssize_t set_in_min(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private);
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -734,14 +737,16 @@ static ssize_t set_in_min(struct device
up(&data->update_lock);
return count;
}
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private);
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]));
}
static ssize_t set_in_max(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private);
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -753,35 +758,13 @@ static ssize_t set_in_max(struct device
return count;
}

-#define in_reg(offset) \
-static ssize_t show_in##offset (struct device *dev, char *buf, void *private) \
-{ \
- return show_in(dev, buf, offset); \
-} \
-static ssize_t show_in##offset##_min (struct device *dev, char *buf, void *private) \
-{ \
- return show_in_min(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_min (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t show_in##offset##_max (struct device *dev, char *buf, void *private) \
-{ \
- return show_in_max(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_max (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in##offset##_max, set_in##offset##_max);
-
+#define in_reg(offset) \
+static DEVICE_ATTR_PRIVATE(in##offset##_input, S_IRUGO, show_in, NULL,\
+ (void *)offset); \
+static DEVICE_ATTR_PRIVATE(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, (void *) offset); \
+static DEVICE_ATTR_PRIVATE(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, (void *) offset);

in_reg(0);
in_reg(1);
@@ -852,21 +835,24 @@ static DEVICE_ATTR(in16_max, S_IRUGO | S

/* Now add fan read/write functions */

-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
data->fan_div[nr]));
}
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
data->fan_div[nr]));
}
static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -879,23 +865,11 @@ static ssize_t set_fan_min(struct device
return count;
}

-#define fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf, void *private) \
-{ \
- return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf, void *private) \
-{ \
- return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_min, set_fan_##offset##_min);
+#define fan_offset(offset) \
+static DEVICE_ATTR_PRIVATE(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+ (void *)offset); \
+static DEVICE_ATTR_PRIVATE(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, (void *)offset);

fan_offset(1);
fan_offset(2);
@@ -926,14 +900,16 @@ static void fixup_fan_min(struct device
}

/* Now add fan_div read/write functions */
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", data->fan_div[nr]);
}
static ssize_t set_fan_div(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val,orig_div,new_div,shift;
@@ -967,17 +943,8 @@ static ssize_t set_fan_div(struct device
}

#define fan_offset_div(offset) \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf, void *private) \
-{ \
- return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_div (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_fan_div(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_div, set_fan_##offset##_div);
+static DEVICE_ATTR_PRIVATE(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, set_fan_div, (void *)offset);

fan_offset_div(1);
fan_offset_div(2);
@@ -989,19 +956,22 @@ fan_offset_div(7);
fan_offset_div(8);

/* Temps */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]));
}
-static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_min(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]));
}
static ssize_t set_temp_min(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1013,14 +983,16 @@ static ssize_t set_temp_min(struct devic
up(&data->update_lock);
return count;
}
-static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_max(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]));
}
static ssize_t set_temp_max(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1032,48 +1004,30 @@ static ssize_t set_temp_max(struct devic
up(&data->update_lock);
return count;
}
+
#define temp_reg(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf, void *private) \
-{ \
- return show_temp(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf, void *private) \
-{ \
- return show_temp_min(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf, void *private) \
-{ \
- return show_temp_max(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_min (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_temp_min(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_max (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_temp_max(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_min, set_temp_##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_max, set_temp_##offset##_max);
+static DEVICE_ATTR_PRIVATE(temp##offset##_input, S_IRUGO, show_temp, NULL, \
+ (void *)offset); \
+static DEVICE_ATTR_PRIVATE(temp##offset##_min, S_IRUGO | S_IWUSR, \
+ show_temp_min, set_temp_min, (void *)offset); \
+static DEVICE_ATTR_PRIVATE(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, (void *)offset);

temp_reg(1);
temp_reg(2);
temp_reg(3);

-static ssize_t show_temp_offset(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_offset(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
}
static ssize_t set_temp_offset(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1087,45 +1041,40 @@ static ssize_t set_temp_offset(struct de
}

#define temp_offset_reg(offset) \
-static ssize_t show_temp_##offset##_offset (struct device *dev, char *buf, void *private) \
-{ \
- return show_temp_offset(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_offset (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_temp_offset(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_offset, set_temp_##offset##_offset);
+static DEVICE_ATTR_PRIVATE(temp##offset##_offset, S_IRUGO | S_IWUSR, \
+ show_temp_offset, set_temp_offset, (void *)offset);

temp_offset_reg(1);
temp_offset_reg(2);
temp_offset_reg(3);

static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, char *buf,
- int nr)
+ void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(
ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
}
static ssize_t show_temp_auto_point2_temp(struct device *dev, char *buf,
- int nr)
+ void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
ADM1026_FAN_CONTROL_TEMP_RANGE));
}
static ssize_t show_temp_auto_point1_temp(struct device *dev, char *buf,
- int nr)
+ void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
}
static ssize_t set_temp_auto_point1_temp(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1138,34 +1087,13 @@ static ssize_t set_temp_auto_point1_temp
return count;
}

-#define temp_auto_point(offset) \
-static ssize_t show_temp##offset##_auto_point1_temp (struct device *dev, \
- char *buf, void *private) \
-{ \
- return show_temp_auto_point1_temp(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp##offset##_auto_point1_temp (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_temp_auto_point1_temp(dev, buf, count, offset - 1); \
-} \
-static ssize_t show_temp##offset##_auto_point1_temp_hyst (struct device \
- *dev, char *buf, void *private) \
-{ \
- return show_temp_auto_point1_temp_hyst(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp##offset##_auto_point2_temp (struct device *dev, \
- char *buf, void *private) \
-{ \
- return show_temp_auto_point2_temp(dev, buf, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \
- show_temp##offset##_auto_point1_temp, \
- set_temp##offset##_auto_point1_temp); \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \
- show_temp##offset##_auto_point1_temp_hyst, NULL); \
-static DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \
- show_temp##offset##_auto_point2_temp, NULL);
+#define temp_auto_point(offset) \
+static DEVICE_ATTR_PRIVATE(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \
+ show_temp_auto_point1_temp, set_temp_auto_point1_temp, (void *)offset); \
+static DEVICE_ATTR_PRIVATE(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \
+ show_temp_auto_point1_temp_hyst, NULL, (void *)offset); \
+static DEVICE_ATTR_PRIVATE(temp##offset##_auto_point2_temp, S_IRUGO, \
+ show_temp_auto_point2_temp, NULL, (void *)offset);

temp_auto_point(1);
temp_auto_point(2);
@@ -1203,14 +1131,16 @@ static DEVICE_ATTR(temp3_crit_enable, S_
show_temp_crit_enable, set_temp_crit_enable);

-static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_crit(struct device *dev, char *buf, void *private)
{
+ int nr = *((int*)private)-1;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
}
static ssize_t set_temp_crit(struct device *dev, const char *buf,
- size_t count, int nr)
+ size_t count, void *private)
{
+ int nr = *((int*)private)-1;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1224,17 +1154,8 @@ static ssize_t set_temp_crit(struct devi
}

#define temp_crit_reg(offset) \
-static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf, void *private) \
-{ \
- return show_temp_crit(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_crit (struct device *dev, \
- const char *buf, size_t count, void *private) \
-{ \
- return set_temp_crit(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_crit, set_temp_##offset##_crit);
+static DEVICE_ATTR_PRIVATE(temp##offset##_crit, S_IRUGO | S_IWUSR, \
+ show_temp_crit, set_temp_crit, (void *)offset);

temp_crit_reg(1);
temp_crit_reg(2);