ACPI: thinkpad-acpi: add infrastructure for the sysfs device attributes
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Tue, 24 Apr 2007 14:48:14 +0000 (11:48 -0300)
committerLen Brown <len.brown@intel.com>
Wed, 25 Apr 2007 06:00:27 +0000 (02:00 -0400)
Add infrastructure to deal with sysfs attributes and grouping, and helpers
for common sysfs parsing.  Switch driver attributes to use them.

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/misc/thinkpad_acpi.c
drivers/misc/thinkpad_acpi.h

index a31d00d570cb3774cd320b40f5a0b03317291a7f..ca6d15cdc5f01b4ccd467378b76806b1db5f23be 100644 (file)
@@ -520,12 +520,8 @@ static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
                                                const char *buf, size_t count)
 {
        unsigned long t;
-       char *endp;
 
-       t = simple_strtoul(buf, &endp, 0);
-       while (*endp && isspace(*endp))
-               endp++;
-       if (*endp)
+       if (parse_strtoul(buf, 0xffff, &t))
                return -EINVAL;
 
        dbg_level = t;
@@ -575,6 +571,86 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
                driver_remove_file(drv, tpacpi_driver_attributes[i]);
 }
 
+/*************************************************************************
+ * sysfs support helpers
+ */
+
+struct attribute_set_obj {
+       struct attribute_set s;
+       struct attribute *a;
+} __attribute__((packed));
+
+static struct attribute_set *create_attr_set(unsigned int max_members,
+                                               const char* name)
+{
+       struct attribute_set_obj *sobj;
+
+       if (max_members == 0)
+               return NULL;
+
+       /* Allocates space for implicit NULL at the end too */
+       sobj = kzalloc(sizeof(struct attribute_set_obj) +
+                   max_members * sizeof(struct attribute *),
+                   GFP_KERNEL);
+       if (!sobj)
+               return NULL;
+       sobj->s.max_members = max_members;
+       sobj->s.group.attrs = &sobj->a;
+       sobj->s.group.name = name;
+
+       return &sobj->s;
+}
+
+/* not multi-threaded safe, use it in a single thread per set */
+static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
+{
+       if (!s || !attr)
+               return -EINVAL;
+
+       if (s->members >= s->max_members)
+               return -ENOMEM;
+
+       s->group.attrs[s->members] = attr;
+       s->members++;
+
+       return 0;
+}
+
+static int add_many_to_attr_set(struct attribute_set* s,
+                       struct attribute **attr,
+                       unsigned int count)
+{
+       int i, res;
+
+       for (i = 0; i < count; i++) {
+               res = add_to_attr_set(s, attr[i]);
+               if (res)
+                       return res;
+       }
+
+       return 0;
+}
+
+static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
+{
+       sysfs_remove_group(kobj, &s->group);
+       destroy_attr_set(s);
+}
+
+static int parse_strtoul(const char *buf,
+               unsigned long max, unsigned long *value)
+{
+       char *endp;
+
+       *value = simple_strtoul(buf, &endp, 0);
+       while (*endp && isspace(*endp))
+               endp++;
+       if (*endp || *value > max)
+               return -EINVAL;
+
+       return 0;
+}
+
 /****************************************************************************
  ****************************************************************************
  *
index 37860582956fbb107dd31af31601f317ac5540f5..84fdefe0d2001201be78a9a0a1e7d39ccecb4b27 100644 (file)
@@ -134,6 +134,27 @@ static int dispatch_procfs_write(struct file *file,
                unsigned long count, void *data);
 static char *next_cmd(char **cmds);
 
+/* sysfs support */
+struct attribute_set {
+       unsigned int members, max_members;
+       struct attribute_group group;
+};
+
+static struct attribute_set *create_attr_set(unsigned int max_members,
+                                               const char* name);
+#define destroy_attr_set(_set) \
+       kfree(_set);
+static int add_to_attr_set(struct attribute_set* s, struct attribute *attr);
+static int add_many_to_attr_set(struct attribute_set* s,
+                       struct attribute **attr,
+                       unsigned int count);
+#define register_attr_set_with_sysfs(_attr_set, _kobj) \
+       sysfs_create_group(_kobj, &_attr_set->group)
+static void delete_attr_set(struct attribute_set* s, struct kobject *kobj);
+
+static int parse_strtoul(const char *buf, unsigned long max,
+                       unsigned long *value);
+
 /* Device model */
 static struct platform_device *tpacpi_pdev;
 static struct class_device *tpacpi_hwmon;