aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2007-04-24 10:48:14 -0400
committerLen Brown <len.brown@intel.com>2007-04-25 02:00:27 -0400
commit7252374a39d794879f5e47bcfa0a16e7599b27b5 (patch)
treef6a0801099b74b9d78ea1240d725b7aa2f6c6a0b
parent176750d68801bfa4a88d1cf54174aa0347d7e5d8 (diff)
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: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/misc/thinkpad_acpi.c86
-rw-r--r--drivers/misc/thinkpad_acpi.h21
2 files changed, 102 insertions, 5 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index a31d00d570cb..ca6d15cdc5f0 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -520,12 +520,8 @@ static ssize_t tpacpi_driver_debug_store(struct device_driver *drv,
520 const char *buf, size_t count) 520 const char *buf, size_t count)
521{ 521{
522 unsigned long t; 522 unsigned long t;
523 char *endp;
524 523
525 t = simple_strtoul(buf, &endp, 0); 524 if (parse_strtoul(buf, 0xffff, &t))
526 while (*endp && isspace(*endp))
527 endp++;
528 if (*endp)
529 return -EINVAL; 525 return -EINVAL;
530 526
531 dbg_level = t; 527 dbg_level = t;
@@ -575,6 +571,86 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
575 driver_remove_file(drv, tpacpi_driver_attributes[i]); 571 driver_remove_file(drv, tpacpi_driver_attributes[i]);
576} 572}
577 573
574/*************************************************************************
575 * sysfs support helpers
576 */
577
578struct attribute_set_obj {
579 struct attribute_set s;
580 struct attribute *a;
581} __attribute__((packed));
582
583static struct attribute_set *create_attr_set(unsigned int max_members,
584 const char* name)
585{
586 struct attribute_set_obj *sobj;
587
588 if (max_members == 0)
589 return NULL;
590
591 /* Allocates space for implicit NULL at the end too */
592 sobj = kzalloc(sizeof(struct attribute_set_obj) +
593 max_members * sizeof(struct attribute *),
594 GFP_KERNEL);
595 if (!sobj)
596 return NULL;
597 sobj->s.max_members = max_members;
598 sobj->s.group.attrs = &sobj->a;
599 sobj->s.group.name = name;
600
601 return &sobj->s;
602}
603
604/* not multi-threaded safe, use it in a single thread per set */
605static int add_to_attr_set(struct attribute_set* s, struct attribute *attr)
606{
607 if (!s || !attr)
608 return -EINVAL;
609
610 if (s->members >= s->max_members)
611 return -ENOMEM;
612
613 s->group.attrs[s->members] = attr;
614 s->members++;
615
616 return 0;
617}
618
619static int add_many_to_attr_set(struct attribute_set* s,
620 struct attribute **attr,
621 unsigned int count)
622{
623 int i, res;
624
625 for (i = 0; i < count; i++) {
626 res = add_to_attr_set(s, attr[i]);
627 if (res)
628 return res;
629 }
630
631 return 0;
632}
633
634static void delete_attr_set(struct attribute_set* s, struct kobject *kobj)
635{
636 sysfs_remove_group(kobj, &s->group);
637 destroy_attr_set(s);
638}
639
640static int parse_strtoul(const char *buf,
641 unsigned long max, unsigned long *value)
642{
643 char *endp;
644
645 *value = simple_strtoul(buf, &endp, 0);
646 while (*endp && isspace(*endp))
647 endp++;
648 if (*endp || *value > max)
649 return -EINVAL;
650
651 return 0;
652}
653
578/**************************************************************************** 654/****************************************************************************
579 **************************************************************************** 655 ****************************************************************************
580 * 656 *
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 37860582956f..84fdefe0d200 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -134,6 +134,27 @@ static int dispatch_procfs_write(struct file *file,
134 unsigned long count, void *data); 134 unsigned long count, void *data);
135static char *next_cmd(char **cmds); 135static char *next_cmd(char **cmds);
136 136
137/* sysfs support */
138struct attribute_set {
139 unsigned int members, max_members;
140 struct attribute_group group;
141};
142
143static struct attribute_set *create_attr_set(unsigned int max_members,
144 const char* name);
145#define destroy_attr_set(_set) \
146 kfree(_set);
147static int add_to_attr_set(struct attribute_set* s, struct attribute *attr);
148static int add_many_to_attr_set(struct attribute_set* s,
149 struct attribute **attr,
150 unsigned int count);
151#define register_attr_set_with_sysfs(_attr_set, _kobj) \
152 sysfs_create_group(_kobj, &_attr_set->group)
153static void delete_attr_set(struct attribute_set* s, struct kobject *kobj);
154
155static int parse_strtoul(const char *buf, unsigned long max,
156 unsigned long *value);
157
137/* Device model */ 158/* Device model */
138static struct platform_device *tpacpi_pdev; 159static struct platform_device *tpacpi_pdev;
139static struct class_device *tpacpi_hwmon; 160static struct class_device *tpacpi_hwmon;