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;
                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;
+}
+
 /****************************************************************************
  ****************************************************************************
  *
 
                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;