Commit 7252374a authored by Henrique de Moraes Holschuh's avatar Henrique de Moraes Holschuh Committed by Len Brown

ACPI: thinkpad-acpi: add infrastructure for the sysfs device attributes

Add infrastructure to deal with sysfs attributes and grouping, and helpers
for common sysfs parsing.  Switch driver attributes to use them.
Signed-off-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 176750d6
......@@ -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;
}
/****************************************************************************
****************************************************************************
*
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment