Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sysdev: Add utility functions for simple int/ulong variable sysdev attributes

This adds a new sysdev_ext_attribute that stores a pointer to the variable
it manages and some utility functions/macro to easily use them.

Previously all users wrote custom macros to generate show/store
functions for each variable, with this it is possible to avoid
that in many cases.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Andi Kleen and committed by
Greg Kroah-Hartman
9800794a 4a0b2b4d

+83
+49
drivers/base/sys.c
··· 479 479 480 480 EXPORT_SYMBOL_GPL(sysdev_register); 481 481 EXPORT_SYMBOL_GPL(sysdev_unregister); 482 + 483 + #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) 484 + 485 + ssize_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 + } 497 + EXPORT_SYMBOL_GPL(sysdev_store_ulong); 498 + 499 + ssize_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 + } 506 + EXPORT_SYMBOL_GPL(sysdev_show_ulong); 507 + 508 + ssize_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 + } 520 + EXPORT_SYMBOL_GPL(sysdev_store_int); 521 + 522 + ssize_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 + } 529 + EXPORT_SYMBOL_GPL(sysdev_show_int); 530 +
+34
include/linux/sysdev.h
··· 119 119 extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); 120 120 extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); 121 121 122 + struct 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 + 134 + extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *, 135 + char *); 136 + extern ssize_t sysdev_store_ulong(struct sys_device *, 137 + struct sysdev_attribute *, const char *, size_t); 138 + extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *, 139 + char *); 140 + extern 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 156 #endif /* _SYSDEV_H_ */