From 1f7d8542fcc721eb3231e11829523e3e2456be9d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 2 Jun 2009 18:57:14 +0000 Subject: [PATCH] Made sysfs attribute code compatible with earlier kernels. --- comedi/comedi_fops.c | 166 +++++++++++++++++++------------------- include/linux/comedidev.h | 4 +- include/linux/device.h | 94 +++++++++++++-------- 3 files changed, 145 insertions(+), 119 deletions(-) diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index bc0549a4..19295728 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -95,11 +95,55 @@ static int is_device_busy(comedi_device * dev); static int resize_async_buffer(comedi_device *dev, comedi_subdevice *s, comedi_async *async, unsigned new_size); -//declarations for sysfs attribute files -struct device_attribute dev_attr_max_read_buffer_kb; -struct device_attribute dev_attr_read_buffer_kb; -struct device_attribute dev_attr_max_write_buffer_kb; -struct device_attribute dev_attr_write_buffer_kb; +// sysfs attribute files + +static COMEDI_DECLARE_ATTR_SHOW(show_max_read_buffer_kb, dev, buf); +static COMEDI_DECLARE_ATTR_STORE(store_max_read_buffer_kb, dev, buf, count); +static comedi_device_attribute_t dev_attr_max_read_buffer_kb = +{ + .attr = { + .name = "max_read_buffer_kb", + .mode = S_IRUGO | S_IWUSR + }, + .show = &show_max_read_buffer_kb, + .store = &store_max_read_buffer_kb +}; + +static COMEDI_DECLARE_ATTR_SHOW(show_read_buffer_kb, dev, buf); +static COMEDI_DECLARE_ATTR_STORE(store_read_buffer_kb, dev, buf, count); +static comedi_device_attribute_t dev_attr_read_buffer_kb = +{ + .attr = { + .name = "read_buffer_kb", + .mode = S_IRUGO | S_IWUSR | S_IWGRP + }, + .show = &show_read_buffer_kb, + .store = &store_read_buffer_kb +}; + +static COMEDI_DECLARE_ATTR_SHOW(show_max_write_buffer_kb, dev, buf); +static COMEDI_DECLARE_ATTR_STORE(store_max_write_buffer_kb, dev, buf, count); +static comedi_device_attribute_t dev_attr_max_write_buffer_kb = +{ + .attr = { + .name = "max_write_buffer_kb", + .mode = S_IRUGO | S_IWUSR + }, + .show = &show_max_write_buffer_kb, + .store = &store_max_write_buffer_kb +}; + +static COMEDI_DECLARE_ATTR_SHOW(show_write_buffer_kb, dev, buf); +static COMEDI_DECLARE_ATTR_STORE(store_write_buffer_kb, dev, buf, count); +static comedi_device_attribute_t dev_attr_write_buffer_kb = +{ + .attr = { + .name = "write_buffer_kb", + .mode = S_IRUGO | S_IWUSR | S_IWGRP + }, + .show = &show_write_buffer_kb, + .store = &store_write_buffer_kb +}; #ifdef HAVE_UNLOCKED_IOCTL static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, @@ -2105,7 +2149,7 @@ int comedi_alloc_board_minor(struct device *hardware_device) { unsigned long flags; struct comedi_device_file_info *info; - device_create_result_type *csdev; + comedi_device_create_t *csdev; unsigned i; int retval; @@ -2142,29 +2186,29 @@ int comedi_alloc_board_minor(struct device *hardware_device) if(!IS_ERR(csdev)) { info->device->class_dev = csdev; } - dev_set_drvdata(csdev, info); - retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); + COMEDI_DEV_SET_DRVDATA(csdev, info); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_max_read_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_max_read_buffer_kb.attr.name); comedi_free_board_minor(i); return retval; } - retval = device_create_file(csdev, &dev_attr_read_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_read_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_read_buffer_kb.attr.name); comedi_free_board_minor(i); return retval; } - retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_max_write_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_max_write_buffer_kb.attr.name); comedi_free_board_minor(i); return retval; } - retval = device_create_file(csdev, &dev_attr_write_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_write_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_write_buffer_kb.attr.name); @@ -2192,7 +2236,8 @@ void comedi_free_board_minor(unsigned minor) { if(dev->class_dev) { - device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, dev->minor)); + COMEDI_DEVICE_DESTROY(comedi_class, + MKDEV(COMEDI_MAJOR, dev->minor)); } comedi_device_cleanup(dev); kfree(dev); @@ -2205,7 +2250,7 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s) { unsigned long flags; struct comedi_device_file_info *info; - device_create_result_type *csdev; + comedi_device_create_t *csdev; unsigned i; int retval; @@ -2237,29 +2282,29 @@ int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s) { s->class_dev = csdev; } - dev_set_drvdata(csdev, info); - retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); + COMEDI_DEV_SET_DRVDATA(csdev, info); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_max_read_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_max_read_buffer_kb.attr.name); comedi_free_subdevice_minor(s); return retval; } - retval = device_create_file(csdev, &dev_attr_read_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_read_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_read_buffer_kb.attr.name); comedi_free_subdevice_minor(s); return retval; } - retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_max_write_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_max_write_buffer_kb.attr.name); comedi_free_subdevice_minor(s); return retval; } - retval = device_create_file(csdev, &dev_attr_write_buffer_kb); + retval = COMEDI_DEVICE_CREATE_FILE(csdev, &dev_attr_write_buffer_kb); if(retval) { printk(KERN_ERR "comedi: failed to create sysfs attribute file \"%s\".\n", dev_attr_write_buffer_kb.attr.name); @@ -2287,7 +2332,8 @@ void comedi_free_subdevice_minor(comedi_subdevice *s) if(s->class_dev) { - device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); + COMEDI_DEVICE_DESTROY(comedi_class, + MKDEV(COMEDI_MAJOR, s->minor)); s->class_dev = NULL; } kfree(info); @@ -2344,15 +2390,14 @@ static int resize_async_buffer(comedi_device *dev, return 0; } -// sysfs attribute files +// sysfs attribute file functions static const unsigned bytes_per_kibi = 1024; -ssize_t show_max_read_buffer_kb(struct device *dev, - struct device_attribute *attr, char *buf) +static COMEDI_DECLARE_ATTR_SHOW(show_max_read_buffer_kb, dev, buf) { ssize_t retval; - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned max_buffer_size_kb = 0; comedi_subdevice * const read_subdevice = comedi_get_read_subdevice(info); @@ -2369,10 +2414,9 @@ ssize_t show_max_read_buffer_kb(struct device *dev, return retval; } -ssize_t store_max_read_buffer_kb(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static COMEDI_DECLARE_ATTR_STORE(store_max_read_buffer_kb, dev, buf, count) { - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned long new_max_size_kb; uint64_t new_max_size; comedi_subdevice * const read_subdevice = comedi_get_read_subdevice(info); @@ -2399,21 +2443,10 @@ ssize_t store_max_read_buffer_kb(struct device *dev, struct device_attribute *at return count; } -struct device_attribute dev_attr_max_read_buffer_kb = -{ - .attr = { - .name = "max_read_buffer_kb", - .mode = S_IRUGO | S_IWUSR - }, - .show = &show_max_read_buffer_kb, - .store = &store_max_read_buffer_kb -}; - -ssize_t show_read_buffer_kb(struct device *dev, - struct device_attribute *attr, char *buf) +static COMEDI_DECLARE_ATTR_SHOW(show_read_buffer_kb, dev, buf) { ssize_t retval; - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned buffer_size_kb = 0; comedi_subdevice * const read_subdevice = comedi_get_read_subdevice(info); @@ -2430,10 +2463,9 @@ ssize_t show_read_buffer_kb(struct device *dev, return retval; } -ssize_t store_read_buffer_kb(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static COMEDI_DECLARE_ATTR_STORE(store_read_buffer_kb, dev, buf, count) { - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned long new_size_kb; uint64_t new_size; int retval; @@ -2463,21 +2495,10 @@ ssize_t store_read_buffer_kb(struct device *dev, struct device_attribute *attr, return count; } -struct device_attribute dev_attr_read_buffer_kb = -{ - .attr = { - .name = "read_buffer_kb", - .mode = S_IRUGO | S_IWUSR | S_IWGRP - }, - .show = &show_read_buffer_kb, - .store = &store_read_buffer_kb -}; - -ssize_t show_max_write_buffer_kb(struct device *dev, - struct device_attribute *attr, char *buf) +static COMEDI_DECLARE_ATTR_SHOW(show_max_write_buffer_kb, dev, buf) { ssize_t retval; - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned max_buffer_size_kb = 0; comedi_subdevice * const write_subdevice = comedi_get_write_subdevice(info); @@ -2494,10 +2515,9 @@ ssize_t show_max_write_buffer_kb(struct device *dev, return retval; } -ssize_t store_max_write_buffer_kb(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static COMEDI_DECLARE_ATTR_STORE(store_max_write_buffer_kb, dev, buf, count) { - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned long new_max_size_kb; uint64_t new_max_size; comedi_subdevice * const write_subdevice = comedi_get_write_subdevice(info); @@ -2524,21 +2544,10 @@ ssize_t store_max_write_buffer_kb(struct device *dev, struct device_attribute *a return count; } -struct device_attribute dev_attr_max_write_buffer_kb = -{ - .attr = { - .name = "max_write_buffer_kb", - .mode = S_IRUGO | S_IWUSR - }, - .show = &show_max_write_buffer_kb, - .store = &store_max_write_buffer_kb -}; - -ssize_t show_write_buffer_kb(struct device *dev, - struct device_attribute *attr, char *buf) +static COMEDI_DECLARE_ATTR_SHOW(show_write_buffer_kb, dev, buf) { ssize_t retval; - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned buffer_size_kb = 0; comedi_subdevice * const write_subdevice = comedi_get_write_subdevice(info); @@ -2555,10 +2564,9 @@ ssize_t show_write_buffer_kb(struct device *dev, return retval; } -ssize_t store_write_buffer_kb(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static COMEDI_DECLARE_ATTR_STORE(store_write_buffer_kb, dev, buf, count) { - struct comedi_device_file_info *info = dev_get_drvdata(dev); + struct comedi_device_file_info *info = COMEDI_DEV_GET_DRVDATA(dev); unsigned long new_size_kb; uint64_t new_size; int retval; @@ -2587,13 +2595,3 @@ ssize_t store_write_buffer_kb(struct device *dev, struct device_attribute *attr, if(retval < 0) return retval; return count; } - -struct device_attribute dev_attr_write_buffer_kb = -{ - .attr = { - .name = "write_buffer_kb", - .mode = S_IRUGO | S_IWUSR | S_IWGRP - }, - .show = &show_write_buffer_kb, - .store = &store_write_buffer_kb -}; diff --git a/include/linux/comedidev.h b/include/linux/comedidev.h index 74d6cb4e..b8db1380 100644 --- a/include/linux/comedidev.h +++ b/include/linux/comedidev.h @@ -187,7 +187,7 @@ struct comedi_subdevice_struct { unsigned int state; - device_create_result_type *class_dev; + comedi_device_create_t *class_dev; int minor; }; @@ -260,7 +260,7 @@ struct comedi_device_struct { comedi_driver *driver; void *private; - device_create_result_type *class_dev; + comedi_device_create_t *class_dev; int minor; /* hw_dev is passed to dma_alloc_coherent when allocating async buffers for subdevices that have async_dma_dir set to something other than DMA_NONE */ diff --git a/include/linux/device.h b/include/linux/device.h index cf71c80f..327dc633 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -28,24 +28,26 @@ /* * Notes: * - * The 'struct device *' returned by the device_create() compatibility - * functions (assuming the return value is not an error pointer for which - * 'IS_ERR(ptr)' is true) is not really a 'struct device *' and should not - * be treated as such. For kernel versions 2.5.0 to 2.6.17, the return - * value is actually a 'struct class_device *' in disguise and we assume - * the 'parent' parameter of device_create() is also a 'struct class_device *' - * in disguise from a previous call to device_create(). + * Call COMEDI_DEVICE_CREATE() instead of device_create() for compatibility + * with kernel versions prior to 2.6.27. This returns a PTR_ERR() value or a + * 'comedi_device_create_t *' which will be a 'struct class_device *' for + * kernel versions prior to 2.6.19, and a 'struct device *' for kernel version + * 2.6.19 onwards. Call COMEDI_DEVICE_DESTROY() to destroy it. * - * The main limitation is that we cannot use a *real* 'struct device *' as - * the parent parameter of device_create(), only a pointer from a previous - * call to device_create(). + * The result of COMEDI_DEVICE_CREATE() can be used to set or get a private + * data pointer, using COMEDI_DEV_SET_DRVDATA() and COMEDI_DEV_GET_DRVDATA(). * - * Call COMEDI_DEVICE_CREATE() instead of device_create() for compatibility - * with kernel versions prior to 2.6.27. + * The result of COMEDI_DEVICE_CREATE() can be used to create or remove + * sysfs attributes, using COMEDI_DECLARE_ATTR_SHOW() to declare the "show + * attribute" function, COMEDI_DECLARE_ATTR_STORE() macro to declare the + * "store attribute" function, COMEDI_DEVICE_CREATE_FILE() to create the + * attribute, and COMEDI_DEVICE_REMOVE_FILE() to remove it. + * + * The 'drvdata' parameter of COMEDI_DEVICE_CREATE() doesn't work for kernel + * versions prior to 2.6.26, so please don't use it! * - * We do not currently support 'dev_get_drvdata()' and 'dev_set_drvdata()' - * for kernel versions prior to 2.6.26, so the 'drvdata' parameter of - * COMEDI_DEVICE_CREATE() is pretty useless. + * + * None of the above is currently supported for 2.4 kernels! */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -81,6 +83,21 @@ static inline void device_destroy(struct class *cs, dev_t devt) #include_next +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) + +/* Use 'struct class_device' before kernel 2.6.19. */ + +typedef struct class_device comedi_device_create_t; +typedef struct class_device_attribute comedi_device_attribute_t; +#define COMEDI_DEV_SET_DRVDATA(csdev, data) class_set_devdata(csdev, data) +#define COMEDI_DEV_GET_DRVDATA(csdev) class_get_devdata(csdev) +#define COMEDI_DEVICE_CREATE_FILE(csdev, attr) class_device_create_file(csdev, attr) +#define COMEDI_DEVICE_REMOVE_FILE(csdev, attr) class_device_remove_file(csdev, attr) +#define COMEDI_DECLARE_ATTR_SHOW(func, dev, buf) \ +ssize_t func(struct class_device *dev, char *buf) +#define COMEDI_DECLARE_ATTR_STORE(func, dev, buf, count) \ +ssize_t func(struct class_device *dev, const char *buf, size_t count) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) #define class_create(owner, name) \ @@ -88,65 +105,76 @@ static inline void device_destroy(struct class *cs, dev_t devt) #define class_destroy(cs) \ class_simple_destroy((struct class_simple *)(cs)) -typedef struct class_device device_create_result_type; #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ class_simple_device_add((struct class_simple *)(cs), \ devt, device, fmt) -#define device_destroy(cs, devt) \ +#define COMEDI_DEVICE_DESTROY(cs, devt) \ class_simple_device_remove(devt) #else #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -typedef struct class_device device_create_result_type; #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ class_device_create(cs, devt, device, fmt) -#define device_destroy(cs, devt) \ +#define COMEDI_DEVICE_DESTROY(cs, devt) \ class_device_destroy(cs, devt) #else -/* device_create does not work for NULL parent with 2.6.18, not sure -exactly which kernel version it was fixed in. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -typedef struct class_device device_create_result_type; #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ - class_device_create( \ - cs, parent, devt, device, fmt) -#define device_destroy(cs, devt) \ + class_device_create(cs, parent, devt, device, fmt) +#define COMEDI_DEVICE_DESTROY(cs, devt) \ class_device_destroy(cs, devt) +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + #else +/* Use 'struct device' from kernel 2.6.19 onwards. */ + +typedef struct device comedi_device_create_t; +typedef struct device_attribute comedi_device_attribute_t; +#define COMEDI_DEV_SET_DRVDATA(csdev, data) dev_set_drvdata(csdev, data) +#define COMEDI_DEV_GET_DRVDATA(csdev) dev_get_drvdata(csdev) +#define COMEDI_DEVICE_CREATE_FILE(csdev, attr) device_create_file(csdev, attr) +#define COMEDI_DEVICE_REMOVE_FILE(csdev, attr) device_remove_file(csdev, attr) +#define COMEDI_DECLARE_ATTR_SHOW(func, dev, buf) \ +ssize_t func(struct device *dev, struct device_attribute *_attr, char *buf) +#define COMEDI_DECLARE_ATTR_STORE(func, dev, buf, count) \ +ssize_t func(struct device *dev, struct device_attribute *_attr, \ + const char *buf, size_t count) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -typedef struct device device_create_result_type; #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ device_create(cs, ((parent) ? (parent) : (device)), devt, fmt) +#define COMEDI_DEVICE_DESTROY(cs, devt) \ + device_destroy(cs, devt) #else -typedef struct device device_create_result_type; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ device_create_drvdata(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt) +#define COMEDI_DEVICE_DESTROY(cs, devt) \ + device_destroy(cs, devt) #else #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt) +#define COMEDI_DEVICE_DESTROY(cs, devt) \ + device_destroy(cs, devt) #endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) #endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - -#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) +#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) #endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -- 2.26.2