aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/sys.c49
-rw-r--r--include/linux/sysdev.h34
2 files changed, 83 insertions, 0 deletions
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index dc7dace14e1c..40fc14f03540 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -479,3 +479,52 @@ int __init system_bus_init(void)
479 479
480EXPORT_SYMBOL_GPL(sysdev_register); 480EXPORT_SYMBOL_GPL(sysdev_register);
481EXPORT_SYMBOL_GPL(sysdev_unregister); 481EXPORT_SYMBOL_GPL(sysdev_unregister);
482
483#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
484
485ssize_t sysdev_store_ulong(struct sys_device *sysdev,
486 struct sysdev_attribute *attr,
487 const char *buf, size_t size)
488{
489 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
490 char *end;
491 unsigned long new = simple_strtoul(buf, &end, 0);
492 if (end == buf)
493 return -EINVAL;
494 *(unsigned long *)(ea->var) = new;
495 return end - buf;
496}
497EXPORT_SYMBOL_GPL(sysdev_store_ulong);
498
499ssize_t sysdev_show_ulong(struct sys_device *sysdev,
500 struct sysdev_attribute *attr,
501 char *buf)
502{
503 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
504 return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
505}
506EXPORT_SYMBOL_GPL(sysdev_show_ulong);
507
508ssize_t sysdev_store_int(struct sys_device *sysdev,
509 struct sysdev_attribute *attr,
510 const char *buf, size_t size)
511{
512 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
513 char *end;
514 long new = simple_strtol(buf, &end, 0);
515 if (end == buf || new > INT_MAX || new < INT_MIN)
516 return -EINVAL;
517 *(int *)(ea->var) = new;
518 return end - buf;
519}
520EXPORT_SYMBOL_GPL(sysdev_store_int);
521
522ssize_t sysdev_show_int(struct sys_device *sysdev,
523 struct sysdev_attribute *attr,
524 char *buf)
525{
526 struct sysdev_ext_attribute *ea = to_ext_attr(attr);
527 return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
528}
529EXPORT_SYMBOL_GPL(sysdev_show_int);
530
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index 8dcf3162b21b..f395bb3fa2f2 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -119,4 +119,38 @@ struct sysdev_attribute {
119extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); 119extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
120extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); 120extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
121 121
122struct sysdev_ext_attribute {
123 struct sysdev_attribute attr;
124 void *var;
125};
126
127/*
128 * Support for simple variable sysdev attributes.
129 * The pointer to the variable is stored in a sysdev_ext_attribute
130 */
131
132/* Add more types as needed */
133
134extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
135 char *);
136extern ssize_t sysdev_store_ulong(struct sys_device *,
137 struct sysdev_attribute *, const char *, size_t);
138extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
139 char *);
140extern ssize_t sysdev_store_int(struct sys_device *,
141 struct sysdev_attribute *, const char *, size_t);
142
143#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \
144 { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
145 &(_var) }
146#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \
147 struct sysdev_ext_attribute attr_##_name = \
148 _SYSDEV_ULONG_ATTR(_name, _mode, _var);
149#define _SYSDEV_INT_ATTR(_name, _mode, _var) \
150 { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
151 &(_var) }
152#define SYSDEV_INT_ATTR(_name, _mode, _var) \
153 struct sysdev_ext_attribute attr_##_name = \
154 _SYSDEV_INT_ATTR(_name, _mode, _var);
155
122#endif /* _SYSDEV_H_ */ 156#endif /* _SYSDEV_H_ */