Module: xenomai-forge Branch: next Commit: d817163953a063d5e7746f1273231d08629b1432 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=d817163953a063d5e7746f1273231d08629b1432
Author: Philippe Gerum <r...@xenomai.org> Date: Sun Sep 14 18:52:18 2014 +0200 cobalt/rtdm: split class / device --- include/cobalt/kernel/rtdm/analogy/context.h | 2 +- include/cobalt/kernel/rtdm/driver.h | 192 ++++++++++------ include/cobalt/kernel/rtdm/udd.h | 11 +- kernel/cobalt/posix/io.c | 43 ---- kernel/cobalt/posix/memory.c | 63 ++++-- kernel/cobalt/rtdm/core.c | 43 ++-- kernel/cobalt/rtdm/device.c | 312 +++++++++++++++++--------- kernel/cobalt/rtdm/fd.c | 43 ++++ kernel/cobalt/rtdm/internal.h | 2 +- kernel/cobalt/rtdm/proc.c | 68 +++--- kernel/cobalt/trace/cobalt-rtdm.h | 24 +- kernel/drivers/analogy/rtdm_interface.c | 76 ++++--- kernel/drivers/autotune/autotune.c | 17 +- kernel/drivers/can/rtcan_raw.c | 21 +- kernel/drivers/ipc/rtipc.c | 28 ++- kernel/drivers/serial/16550A.c | 40 ++-- kernel/drivers/serial/mpc52xx_uart.c | 1 - kernel/drivers/serial/rt_imx_uart.c | 1 - kernel/drivers/testing/rtdmtest.c | 63 +++--- kernel/drivers/testing/switchtest.c | 58 +++-- kernel/drivers/testing/timerbench.c | 60 ++--- kernel/drivers/udd/udd.c | 86 +++---- 22 files changed, 732 insertions(+), 522 deletions(-) diff --git a/include/cobalt/kernel/rtdm/analogy/context.h b/include/cobalt/kernel/rtdm/analogy/context.h index 35d356d..71a292c 100644 --- a/include/cobalt/kernel/rtdm/analogy/context.h +++ b/include/cobalt/kernel/rtdm/analogy/context.h @@ -43,7 +43,7 @@ static inline int a4l_get_minor(struct a4l_device_context *cxt) /* Get a pointer on the container structure */ struct rtdm_fd *fd = rtdm_private_to_fd(cxt); /* Get the minor index */ - return rtdm_fd_device(fd)->device_id; + return rtdm_fd_minor(fd); } #endif /* !_COBALT_RTDM_ANALOGY_CONTEXT_H */ diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 29045cc..f6b3c92 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -27,7 +27,7 @@ #include <asm/atomic.h> #include <linux/list.h> - +#include <linux/cdev.h> #include <xenomai/version.h> #include <cobalt/kernel/heap.h> #include <cobalt/kernel/sched.h> @@ -51,7 +51,7 @@ #endif /* CONFIG_PCI */ #include <asm/xenomai/syscall.h> -struct rtdm_dev_context; +struct class; typedef struct xnselector rtdm_selector_t; enum rtdm_selecttype; @@ -81,23 +81,17 @@ enum rtdm_selecttype; /** Mask selecting the device type. */ #define RTDM_DEVICE_TYPE_MASK 0x00F0 + +/** Flag indicating a secure variant of RTDM (not supported here) */ +#define RTDM_SECURE_DEVICE 0x80000000 /** @} Device Flags */ /*! * @anchor drv_versioning @name Driver Versioning - * Current revisions of RTDM structures, encoding of driver versions. See + * Encoding of driver versions. See * @ref rtdm_api_versioning "API Versioning" for the interface revision. * @{ */ -/** Version of struct rtdm_device */ -#define RTDM_DEVICE_STRUCT_VER 7 - -/** Version of struct rtdm_dev_context */ -#define RTDM_CONTEXT_STRUCT_VER 4 - -/** Flag indicating a secure variant of RTDM (not supported here) */ -#define RTDM_SECURE_DEVICE 0x80000000 - /** Version code constructor for driver revisions */ #define RTDM_DRIVER_VER(major, minor, patch) \ (((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF)) @@ -138,10 +132,6 @@ enum rtdm_selecttype { /** @} rtdm_sync */ -struct rtdm_devctx_reserved { - void (*close)(struct rtdm_fd *fd); -}; - /** * @brief Device context * @@ -149,9 +139,9 @@ struct rtdm_devctx_reserved { * RTDM takes care of its creation and destruction and passes it to the * operation handlers when being invoked. * - * Drivers can attach arbitrary data immediately after the official structure. - * The size of this data is provided via rtdm_device.context_size during - * device registration. + * Drivers can attach arbitrary data immediately after the official + * structure. The size of this data is provided via + * rtdm_device_class.context_size during device registration. */ struct rtdm_dev_context { struct rtdm_fd fd; @@ -160,9 +150,6 @@ struct rtdm_dev_context { /** Reference to owning device */ struct rtdm_device *device; - /** Data stored by RTDM inside a device context (internal use only) */ - struct rtdm_devctx_reserved reserved; - /** Begin of driver defined context data structure */ char dev_private[0]; }; @@ -183,7 +170,7 @@ static inline struct rtdm_dev_context *rtdm_fd_to_context(struct rtdm_fd *fd) */ static inline void *rtdm_fd_to_private(struct rtdm_fd *fd) { - return (void *)rtdm_fd_to_context(fd)->dev_private; + return &rtdm_fd_to_context(fd)->dev_private[0]; } /** @@ -227,79 +214,148 @@ static inline struct rtdm_device *rtdm_fd_device(struct rtdm_fd *fd) return rtdm_fd_to_context(fd)->device; } -struct rtdm_dev_reserved { - unsigned magic; - union { - struct { - struct list_head entry; - xnhandle_t handle; - }; - struct xnid id; - }; - atomic_t refcount; - struct rtdm_dev_context *exclusive_context; - void (*close)(struct rtdm_fd *); -}; +/** + * @brief RTDM profile information + * + * This descriptor details the profile information associated to a + * RTDM device class. + * + * @anchor rtdm_profile_info @name RTDM profile information descriptor + */ +struct rtdm_profile_info { + /** Device class name */ + const char *name; + /** Device class ID, see @ref RTDM_CLASS_xxx */ + int class_id; + /** Device sub-class, see RTDM_SUBCLASS_xxx definition in the + * @ref rtdm_profiles "Device Profiles" */ + int subclass_id; + /** Supported device profile version */ + int version; + /** Reserved */ + unsigned int magic; +}; /** - * @brief RTDM device + * @brief RTDM device class * - * This structure specifies a RTDM device. As some fields, especially - * the reserved area, will be modified by RTDM during runtime, the - * structure must not reside in write-protected memory. + * This descriptor describes a RTDM device class. The structure holds + * runtime data, therefore it must reside in writable memory. */ -struct rtdm_device { - /** Data stored by RTDM inside a registered device (internal use only) */ - struct rtdm_dev_reserved reserved; - /** Revision number of this structure, see - * @ref drv_versioning "Driver Versioning" defines */ - int struct_version; +struct rtdm_device_class { + /** + * Class profile information. The RTDM_PROFILE_INFO() macro @b + * must be used for filling up this field. + */ + struct rtdm_profile_info profile_info; /** Device flags, see @ref dev_flags "Device Flags" for details */ int device_flags; /** Size of driver defined appendix to struct rtdm_dev_context */ size_t context_size; - /** Named device identification (orthogonal to Linux device name space) */ - char device_name[RTDM_MAX_DEVNAME_LEN + 1]; /** Protocol device identification: protocol family (PF_xxx) */ int protocol_family; /** Protocol device identification: socket type (SOCK_xxx) */ int socket_type; - /** I/O operation handlers */ - struct rtdm_fd_ops ops; - /** Device class ID, see @ref RTDM_CLASS_xxx */ - int device_class; - /** Device sub-class, see RTDM_SUBCLASS_xxx definition in the - * @ref rtdm_profiles "Device Profiles" */ - int device_sub_class; - /** Supported device profile version */ - int profile_version; /** Informational driver name (reported via /proc) */ const char *driver_name; - /** Driver version, see @ref drv_versioning "Driver Versioning" defines */ + /** Driver version, see @ref drv_versioning "Driver Versioning" macros */ int driver_version; /** Informational peripheral name the device is attached to * (reported via /proc) */ const char *peripheral_name; /** Informational driver provider name (reported via /proc) */ const char *provider_name; - /** Name of /proc entry for the device, must not be NULL */ - const char *proc_name; -#ifdef CONFIG_XENO_OPT_VFILE - /** Set to device's vfile data after registration, do not modify */ - struct xnvfile_directory vfroot; - struct xnvfile_regular info_vfile; -#endif - /** Driver definable device ID */ - int device_id; + /** I/O operation handlers */ + struct rtdm_fd_ops ops; + /** Count of devices which belong to this class. */ + int device_count; + /** Reserved area */ + struct { + union { + struct { + struct cdev cdev; + struct class *kclass; + int major; + } named; + }; + atomic_t refcount; + }; +}; + +#define RTDM_CLASS_MAGIC 0x8284636c + +/** + * @brief Initializer for class profile information. + * + * This macro must be used to fill in the @ref rtdm_profile_info + * "class profile information" field from a RTDM device class. + * + * @param __name Class name (unquoted). + * + * @param __id Class major identification number + * (profile_version.class_id). + * + * @param __subid Class minor identification number + * (profile_version.subclass_id). + * + * @param __version Profile version number. + * + * @note See @ref rtdm_profiles "Device Profiles". + */ +#define RTDM_PROFILE_INFO(__name, __id, __subid, __version) \ +{ \ + .name = ( # __name ), \ + .class_id = (__id), \ + .subclass_id = (__subid), \ + .version = (__version), \ + .magic = ~RTDM_CLASS_MAGIC, \ +} + +/** + * @brief RTDM device + * + * This descriptor describes a RTDM device instance. The structure + * holds runtime data, therefore it must reside in writable memory. + */ +struct rtdm_device { + /** Device class. */ + struct rtdm_device_class *class; /** Driver definable device data */ void *device_data; + /** Device label template */ + const char *label; + /** Reserved area. */ + struct { + unsigned int magic; + char *name; + union { + struct { + struct list_head entry; + xnhandle_t handle; + int minor; + } named; + struct { + struct xnid id; + } proto; + }; + atomic_t refcount; + struct rtdm_dev_context *exclusive_context; + struct rtdm_fd_ops ops; +#ifdef CONFIG_XENO_OPT_VFILE + struct xnvfile_directory vfroot; + struct xnvfile_regular info_vfile; +#endif + }; }; + /** @} devregister */ /* --- device registration --- */ int rtdm_dev_register(struct rtdm_device *device); -int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay); + +int rtdm_dev_unregister(struct rtdm_device *device, + unsigned int poll_delay); /* --- inter-driver API --- */ diff --git a/include/cobalt/kernel/rtdm/udd.h b/include/cobalt/kernel/rtdm/udd.h index d21efc2..8fae461 100644 --- a/include/cobalt/kernel/rtdm/udd.h +++ b/include/cobalt/kernel/rtdm/udd.h @@ -129,10 +129,10 @@ * the memory region array as follows: * * @code + * static struct udd_device udd; + * * static int foocard_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) * { - * struct udd_device udd; - * * udd.device_name = "foocard"; * ... * udd.mem_regions[2].name = "ADC"; @@ -189,7 +189,10 @@ struct udd_memregion { * mini-driver when registering via a call to udd_register_device(). */ struct udd_device { - /** Name of the device managed by the mini-driver. */ + /** + * Name of the device managed by the mini-driver, appears + * automatically in the /dev namespace upon creation. + */ const char *device_name; /** * Additional device flags (e.g. RTDM_EXCLUSIVE, @@ -289,7 +292,9 @@ struct udd_device { atomic_t event; struct udd_signotify signfy; struct rtdm_event pulse; + struct rtdm_device_class class; struct rtdm_device device; + struct rtdm_device_class mapper_class; struct rtdm_device mapper; char *mapper_name; int nr_maps; diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c index 4d549bb..9810c32 100644 --- a/kernel/cobalt/posix/io.c +++ b/kernel/cobalt/posix/io.c @@ -20,7 +20,6 @@ #include <linux/err.h> #include <linux/file.h> #include <linux/fs.h> -#include <linux/poll.h> #include <linux/fdtable.h> #include <linux/anon_inodes.h> #include <cobalt/kernel/ppd.h> @@ -30,48 +29,6 @@ #include "clock.h" #include "io.h" -static inline void warn_user(const char *name) -{ -#ifdef CONFIG_XENO_OPT_DEBUG_USER - printk(XENO_WARN "%s[%d] called regular %s() with RTDM file/socket\n", - current->comm, current->pid, name + 5); -#endif -} - -static ssize_t dumb_read(struct file *file, char __user *buf, - size_t count, loff_t __user *ppos) -{ - warn_user(__func__); - return -EINVAL; -} - -static ssize_t dumb_write(struct file *file, const char __user *buf, - size_t count, loff_t __user *ppos) -{ - warn_user(__func__); - return -EINVAL; -} - -static unsigned int dumb_poll(struct file *file, poll_table *pt) -{ - warn_user(__func__); - return -EINVAL; -} - -static long dumb_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - warn_user(__func__); - return -EINVAL; -} - -const struct file_operations rtdm_dumb_fops = { - .read = dumb_read, - .write = dumb_write, - .poll = dumb_poll, - .unlocked_ioctl = dumb_ioctl, -}; - COBALT_SYSCALL(open, lostage, int, (const char __user *u_path, int oflag)) { diff --git a/kernel/cobalt/posix/memory.c b/kernel/cobalt/posix/memory.c index 78cae01..92ba6fd 100644 --- a/kernel/cobalt/posix/memory.c +++ b/kernel/cobalt/posix/memory.c @@ -209,65 +209,80 @@ static int sysmem_ioctl_nrt(struct rtdm_fd *fd, return do_sysmem_ioctls(fd, request, arg); } -static struct rtdm_device private_umm_device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, - .device_flags = RTDM_NAMED_DEVICE, - .context_size = 0, +static struct rtdm_device_class private_umm = { + .profile_info = RTDM_PROFILE_INFO(private_umm, + RTDM_CLASS_MEMORY, + UMM_PRIVATE, + 0), + .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, + .context_size = 0, .ops = { .ioctl_rt = umm_ioctl_rt, .ioctl_nrt = umm_ioctl_nrt, .mmap = umm_mmap, .get_unmapped_area = umm_get_unmapped_area, }, - .device_class = RTDM_CLASS_MEMORY, - .device_sub_class = UMM_PRIVATE, - .device_name = COBALT_MEMDEV_PRIVATE, .driver_name = "memdev", .driver_version = RTDM_DRIVER_VER(1, 0, 0), .peripheral_name = "Private user-mapped heap", - .proc_name = private_umm_device.device_name, .provider_name = "Philippe Gerum <r...@xenomai.org>", }; -static struct rtdm_device shared_umm_device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, - .device_flags = RTDM_NAMED_DEVICE, - .context_size = 0, +static struct rtdm_device private_umm_device = { + .class = &private_umm, + .label = COBALT_MEMDEV_PRIVATE, +}; + +static struct rtdm_device_class shared_umm = { + .profile_info = RTDM_PROFILE_INFO(shared_umm, + RTDM_CLASS_MEMORY, + UMM_SHARED, + 0), + .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, + .context_size = 0, .ops = { .ioctl_rt = umm_ioctl_rt, .ioctl_nrt = umm_ioctl_nrt, .mmap = umm_mmap, .get_unmapped_area = umm_get_unmapped_area, }, - .device_class = RTDM_CLASS_MEMORY, - .device_sub_class = UMM_SHARED, - .device_name = COBALT_MEMDEV_SHARED, .driver_name = "memdev", .driver_version = RTDM_DRIVER_VER(1, 0, 0), .peripheral_name = "Shared user-mapped heap", - .proc_name = shared_umm_device.device_name, .provider_name = "Philippe Gerum <r...@xenomai.org>", }; -static struct rtdm_device sysmem_device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, - .device_flags = RTDM_NAMED_DEVICE, - .context_size = 0, +static struct rtdm_device shared_umm_device = { + .class = &shared_umm, + .label = COBALT_MEMDEV_SHARED, +}; + +static struct rtdm_device_class sysmem = { + .profile_info = RTDM_PROFILE_INFO(sysmem, + RTDM_CLASS_MEMORY, + SYS_GLOBAL, + 0), + .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, + .context_size = 0, .ops = { .open = sysmem_open, .ioctl_rt = sysmem_ioctl_rt, .ioctl_nrt = sysmem_ioctl_nrt, }, - .device_class = RTDM_CLASS_MEMORY, - .device_sub_class = SYS_GLOBAL, - .device_name = COBALT_MEMDEV_SYS, .driver_name = "memdev", .driver_version = RTDM_DRIVER_VER(1, 0, 0), .peripheral_name = "System memory heap", - .proc_name = sysmem_device.device_name, .provider_name = "Philippe Gerum <r...@xenomai.org>", }; +static struct rtdm_device sysmem_device = { + .class = &sysmem, + .label = COBALT_MEMDEV_SYS, +}; + static inline void init_vdso(void) { nkvdso->features = XNVDSO_FEATURES; diff --git a/kernel/cobalt/rtdm/core.c b/kernel/cobalt/rtdm/core.c index f84d8b0..56ecbaa 100644 --- a/kernel/cobalt/rtdm/core.c +++ b/kernel/cobalt/rtdm/core.c @@ -44,7 +44,7 @@ static void cleanup_instance(struct rtdm_device *device, struct rtdm_dev_context *context) { if (context) { - if (device->reserved.exclusive_context) + if (device->exclusive_context) context->device = NULL; else kfree(context); @@ -56,9 +56,13 @@ static void cleanup_instance(struct rtdm_device *device, void __rt_dev_close(struct rtdm_fd *fd) { struct rtdm_dev_context *context = rtdm_fd_to_context(fd); - if (context->reserved.close) - context->reserved.close(fd); - cleanup_instance(context->device, context); + struct rtdm_device *device = context->device; + struct rtdm_device_class *class = device->class; + + if (class->ops.close) + class->ops.close(fd); + + cleanup_instance(device, context); } void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx) @@ -75,8 +79,8 @@ void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx) } static int create_instance(struct xnsys_ppd *p, int fd, - struct rtdm_device *device, - struct rtdm_dev_context **context_ptr) + struct rtdm_device *device, + struct rtdm_dev_context **context_ptr) { struct rtdm_dev_context *context; spl_t s; @@ -103,7 +107,7 @@ static int create_instance(struct xnsys_ppd *p, int fd, xnlock_put_irqrestore(&rt_fildes_lock, s); } - context = device->reserved.exclusive_context; + context = device->exclusive_context; if (context) { xnlock_get_irqsave(&rt_dev_lock, s); @@ -118,7 +122,7 @@ static int create_instance(struct xnsys_ppd *p, int fd, xnlock_put_irqrestore(&rt_dev_lock, s); } else { context = kmalloc(sizeof(struct rtdm_dev_context) + - device->context_size, GFP_KERNEL); + device->class->context_size, GFP_KERNEL); if (unlikely(context == NULL)) { err = -ENOMEM; goto fail; @@ -127,7 +131,6 @@ static int create_instance(struct xnsys_ppd *p, int fd, context->device = device; } - context->reserved.close = device->reserved.close; *context_ptr = context; err = rtdm_fd_enter(p, &context->fd, fd, RTDM_FD_MAGIC, &device->ops); @@ -165,7 +168,10 @@ int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag) goto cleanup_out; ufd = ret; - context->fd.minor = minor; + if (device->class->device_flags & RTDM_NAMED_DEVICE) + context->fd.minor = device->named.minor; + else + context->fd.minor = minor; trace_cobalt_fd_open(current, &context->fd, ufd, oflag); @@ -191,8 +197,8 @@ EXPORT_SYMBOL_GPL(__rt_dev_open); int __rt_dev_socket(struct xnsys_ppd *p, int ufd, int protocol_family, int socket_type, int protocol) { - struct rtdm_device *device; struct rtdm_dev_context *context; + struct rtdm_device *device; int ret; device = __rtdm_get_protocol_device(protocol_family, socket_type); @@ -225,19 +231,20 @@ cleanup_out: } EXPORT_SYMBOL_GPL(__rt_dev_socket); -int -__rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request, void __user *arg) +int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request, + void __user *arg) { - struct rtdm_device *dev = rtdm_fd_device(fd); + struct rtdm_device *device = rtdm_fd_device(fd); + struct rtdm_device_class *class = device->class; struct rtdm_device_info dev_info; if (fd->magic != RTDM_FD_MAGIC || request != RTIOC_DEVICE_INFO) return -ENOSYS; - dev_info.device_flags = dev->device_flags; - dev_info.device_class = dev->device_class; - dev_info.device_sub_class = dev->device_sub_class; - dev_info.profile_version = dev->profile_version; + dev_info.device_flags = class->device_flags; + dev_info.device_class = class->profile_info.class_id; + dev_info.device_sub_class = class->profile_info.subclass_id; + dev_info.profile_version = class->profile_info.version; return rtdm_safe_copy_to_user(fd, arg, &dev_info, sizeof(dev_info)); } diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c index d513685..39d42b0 100644 --- a/kernel/cobalt/rtdm/device.c +++ b/kernel/cobalt/rtdm/device.c @@ -23,7 +23,7 @@ #include <linux/semaphore.h> #include <linux/slab.h> #include <linux/ctype.h> -#include <cobalt/kernel/apc.h> +#include <linux/device.h> #include "rtdm/internal.h" #include <trace/events/cobalt-rtdm.h> @@ -45,15 +45,15 @@ static int enosys(void) return -ENOSYS; } -static inline unsigned long long get_proto_id(int pf, int type) +static inline xnkey_t get_proto_id(int pf, int type) { - unsigned long long llpf = (unsigned)pf; - return (llpf << 32) | (unsigned)type; + xnkey_t llpf = (unsigned int)pf; + return (llpf << 32) | (unsigned int)type; } static inline void rtdm_reference_device(struct rtdm_device *device) { - atomic_inc(&device->reserved.refcount); + atomic_inc(&device->refcount); } struct rtdm_device *__rtdm_get_named_device(const char *name, int *minor_r) @@ -105,8 +105,8 @@ struct rtdm_device *__rtdm_get_named_device(const char *name, int *minor_r) device = xnregistry_lookup(handle, NULL); if (device) { - if (device->reserved.magic == RTDM_DEVICE_MAGIC && - ((device->device_flags & RTDM_MINOR) != 0 || + if (device->magic == RTDM_DEVICE_MAGIC && + ((device->class->device_flags & RTDM_MINOR) != 0 || minor < 0)) { rtdm_reference_device(device); *minor_r = minor; @@ -122,9 +122,9 @@ struct rtdm_device *__rtdm_get_named_device(const char *name, int *minor_r) struct rtdm_device * __rtdm_get_protocol_device(int protocol_family, int socket_type) { - struct rtdm_device *device; - unsigned long long id; + struct rtdm_device *device = NULL; struct xnid *xnid; + xnkey_t id; spl_t s; id = get_proto_id(protocol_family, socket_type); @@ -133,11 +133,9 @@ __rtdm_get_protocol_device(int protocol_family, int socket_type) xnid = xnid_fetch(&rtdm_protocol_devices, id); if (xnid) { - device = container_of(xnid, struct rtdm_device, reserved.id); - + device = container_of(xnid, struct rtdm_device, proto.id); rtdm_reference_device(device); - } else - device = NULL; + } xnlock_put_irqrestore(&rt_dev_lock, s); @@ -150,143 +148,248 @@ __rtdm_get_protocol_device(int protocol_family, int socket_type) * @{ */ +static char *rtdm_devnode(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "rtdm/%s", dev_name(dev)); +} + +static int register_device_class(struct rtdm_device_class *class) +{ + struct class *kclass; + dev_t rdev; + int ret; + + if (class->profile_info.magic == RTDM_CLASS_MAGIC) { + atomic_inc(&class->refcount); + return 0; + } + + if (class->profile_info.magic != ~RTDM_CLASS_MAGIC) + return -EINVAL; + + switch (class->device_flags & RTDM_DEVICE_TYPE_MASK) { + case RTDM_NAMED_DEVICE: + case RTDM_PROTOCOL_DEVICE: + break; + default: + return -EINVAL; + } + + if (class->device_count <= 0) + return -EINVAL; + + if ((class->device_flags & RTDM_NAMED_DEVICE) == 0) + goto done; + + ret = alloc_chrdev_region(&rdev, 0, class->device_count, + class->profile_info.name); + if (ret) { + printk(XENO_WARN "cannot allocate chrdev region %s[0..%d]\n", + class->profile_info.name, class->device_count - 1); + return ret; + } + + cdev_init(&class->named.cdev, &rtdm_dumb_fops); + ret = cdev_add(&class->named.cdev, rdev, class->device_count); + if (ret) + goto fail_cdev; + + kclass = class_create(THIS_MODULE, class->profile_info.name); + if (IS_ERR(kclass)) { + printk(XENO_WARN "cannot create device class %s\n", + class->profile_info.name); + ret = PTR_ERR(kclass); + goto fail_class; + } + kclass->devnode = rtdm_devnode; + + class->named.kclass = kclass; + class->named.major = MAJOR(rdev); + atomic_set(&class->refcount, 1); +done: + class->profile_info.magic = RTDM_CLASS_MAGIC; + + return 0; + +fail_class: + cdev_del(&class->named.cdev); +fail_cdev: + unregister_chrdev_region(rdev, class->device_count); + + return ret; +} + +static void unregister_device_class(struct rtdm_device_class *class) +{ + XENO_BUGON(COBALT, class->profile_info.magic != RTDM_CLASS_MAGIC); + + if (!atomic_dec_and_test(&class->refcount)) + return; + + if (class->device_flags & RTDM_NAMED_DEVICE) { + class_destroy(class->named.kclass); + cdev_del(&class->named.cdev); + unregister_chrdev_region(MKDEV(class->named.major, 0), + class->device_count); + } +} + /** * @brief Register a RTDM device * - * @param[in] device Pointer to structure describing the new device. + * The device descriptor is initialized and registered in the RTDM + * namespace. * - * @return 0 is returned upon success. Otherwise: + * @param[in] device Pointer to the device descriptor register. + * @param[in] class RTDM class the new device belongs to. * - * - -EINVAL is returned if the device structure contains invalid entries. - * Check kernel log in this case. + * @return 0 is returned upon success. Otherwise: * - * - -ENOMEM is returned if a memory allocation failed in the process - * of registering the device. + * - -EINVAL is returned if the descriptor contains invalid + * entries. RTDM_PROFILE_INFO() must appear in the list of + * initializers setting up the class properties. * * - -EEXIST is returned if the specified device name of protocol ID is * already in use. * * - -EAGAIN is returned if some /proc entry cannot be created. * + * - -ENOMEM is returned if a memory allocation failed in the process + * of registering the device. + * + * - -EAGAIN is returned if some /proc entry cannot be created. + * * @coretags{secondary-only} */ int rtdm_dev_register(struct rtdm_device *device) { - unsigned long long id; + struct rtdm_device_class *class; + int ret, pos, major, minor; + struct device *kdev; + xnkey_t id; spl_t s; - int ret; if (!realtime_core_enabled()) return -ENOSYS; - /* Sanity check: structure version */ - if (!XENO_ASSERT(COBALT, device->struct_version == RTDM_DEVICE_STRUCT_VER)) { - printk(XENO_ERR "invalid rtdm_device version (%d, " - "required %d)\n", device->struct_version, - RTDM_DEVICE_STRUCT_VER); - return -EINVAL; - } + down(&nrt_dev_lock); - /* Sanity check: proc_name specified? */ - if (!XENO_ASSERT(COBALT, device->proc_name)) { - printk(XENO_ERR "no vfile (/proc) name specified for RTDM device\n"); - return -EINVAL; + device->name = NULL; + device->exclusive_context = NULL; + class = device->class; + pos = atomic_read(&class->refcount); + ret = register_device_class(class); + if (ret) { + up(&nrt_dev_lock); + return ret; } - switch (device->device_flags & RTDM_DEVICE_TYPE_MASK) { - case RTDM_NAMED_DEVICE: + device->ops = class->ops; + if (class->device_flags & RTDM_NAMED_DEVICE) device->ops.socket = (typeof(device->ops.socket))enosys; - break; - - case RTDM_PROTOCOL_DEVICE: + else device->ops.open = (typeof(device->ops.open))enosys; - break; - default: - return -EINVAL; - } + device->ops.close = __rt_dev_close; /* Interpose on driver's handler. */ + atomic_set(&device->refcount, 0); - device->reserved.close = device->ops.close; - device->ops.close = __rt_dev_close; - atomic_set(&device->reserved.refcount, 0); - device->reserved.exclusive_context = NULL; - - if (device->device_flags & RTDM_EXCLUSIVE) { - device->reserved.exclusive_context = - kmalloc(sizeof(struct rtdm_dev_context) + - device->context_size, GFP_KERNEL); - if (!device->reserved.exclusive_context) { - printk(XENO_ERR "no memory for exclusive context of RTDM device " - "(context size: %ld)\n", - (long)device->context_size); - return -ENOMEM; + if (class->device_flags & RTDM_EXCLUSIVE) { + device->exclusive_context = + kmalloc(sizeof(struct rtdm_dev_context) + + class->context_size, GFP_KERNEL); + if (device->exclusive_context == NULL) { + ret = -ENOMEM; + goto fail; } /* mark exclusive context as unused */ - device->reserved.exclusive_context->device = NULL; + device->exclusive_context->device = NULL; } - down(&nrt_dev_lock); + device->magic = RTDM_DEVICE_MAGIC; - trace_cobalt_device_register(device); + if (class->device_flags & RTDM_NAMED_DEVICE) { + major = class->named.major; + minor = pos; + device->named.minor = minor; + device->name = kasformat(device->label, minor); + if (device->name == NULL) { + ret = -ENOMEM; + goto fail; + } - device->reserved.magic = RTDM_DEVICE_MAGIC; + kdev = device_create(class->named.kclass, NULL, + MKDEV(major, minor), + device, device->label, minor); + if (IS_ERR(kdev)) { + ret = PTR_ERR(kdev); + goto fail; + } - if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == - RTDM_NAMED_DEVICE) { - ret = rtdm_proc_register_device(device); + ret = xnregistry_enter(device->name, device, + &device->named.handle, NULL); if (ret) - goto err; - - ret = xnregistry_enter(device->device_name, device, - &device->reserved.handle, NULL); - if (ret) { - rtdm_proc_unregister_device(device); - goto err; - } + goto fail_register; xnlock_get_irqsave(&rt_dev_lock, s); - list_add_tail(&device->reserved.entry, &rtdm_named_devices); + list_add_tail(&device->named.entry, &rtdm_named_devices); xnlock_put_irqrestore(&rt_dev_lock, s); - up(&nrt_dev_lock); - } else { - id = get_proto_id(device->protocol_family, - device->socket_type); + ret = rtdm_proc_register_device(device); + if (ret) + goto fail_proc; + } else { + device->name = kstrdup(device->label, GFP_KERNEL); + if (device->name == NULL) { + ret = -ENOMEM; + goto fail; + } + id = get_proto_id(class->protocol_family, class->socket_type); xnlock_get_irqsave(&rt_dev_lock, s); - ret = xnid_enter(&rtdm_protocol_devices, - &device->reserved.id, id); + ret = xnid_enter(&rtdm_protocol_devices, &device->proto.id, id); xnlock_put_irqrestore(&rt_dev_lock, s); if (ret < 0) - goto err; + goto fail; ret = rtdm_proc_register_device(device); if (ret) { xnlock_get_irqsave(&rt_dev_lock, s); - xnid_remove(&rtdm_protocol_devices, - &device->reserved.id); + xnid_remove(&rtdm_protocol_devices, &device->proto.id); xnlock_put_irqrestore(&rt_dev_lock, s); - goto err; + goto fail; } - - up(&nrt_dev_lock); } + + up(&nrt_dev_lock); + + trace_cobalt_device_register(device); + return 0; +fail_proc: + xnregistry_remove(device->named.handle); +fail_register: + device_destroy(class->named.kclass, MKDEV(major, minor)); +fail: + unregister_device_class(class); -err: up(&nrt_dev_lock); - if (device->reserved.exclusive_context) - kfree(device->reserved.exclusive_context); + + if (device->name) + kfree(device->name); + + if (device->exclusive_context) + kfree(device->exclusive_context); + return ret; } - EXPORT_SYMBOL_GPL(rtdm_dev_register); /** - * @brief Unregisters a RTDM device + * @brief Unregister a RTDM device + * + * The device descriptor removed from the RTDM namespace. * - * @param[in] device Pointer to structure describing the device to be - * unregistered. + * @param[in] device Pointer to the device descriptor. * @param[in] poll_delay Polling delay in milliseconds to check repeatedly for * open instances of @a device, or 0 for non-blocking mode. * @@ -299,13 +402,11 @@ EXPORT_SYMBOL_GPL(rtdm_dev_register); */ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) { + struct rtdm_device_class *class = device->class; + xnhandle_t handle = XN_NO_HANDLE; unsigned long warned = 0; - xnhandle_t handle = 0; spl_t s; - if (!realtime_core_enabled()) - return -ENOSYS; - rtdm_reference_device(device); trace_cobalt_device_unregister(device, poll_delay); @@ -313,7 +414,7 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) down(&nrt_dev_lock); xnlock_get_irqsave(&rt_dev_lock, s); - while (atomic_read(&device->reserved.refcount) > 1) { + while (atomic_read(&device->refcount) > 1) { xnlock_put_irqrestore(&rt_dev_lock, s); up(&nrt_dev_lock); @@ -324,18 +425,17 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) if (!__test_and_set_bit(0, &warned)) printk(XENO_WARN "RTDM device %s still in use - waiting for" - " release...\n", device->device_name); + " release...\n", device->name); msleep(poll_delay); down(&nrt_dev_lock); xnlock_get_irqsave(&rt_dev_lock, s); } - if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == - RTDM_NAMED_DEVICE) { - handle = device->reserved.handle; - list_del(&device->reserved.entry); + if (class->device_flags & RTDM_NAMED_DEVICE) { + handle = device->named.handle; + list_del(&device->named.entry); } else - xnid_remove(&rtdm_protocol_devices, &device->reserved.id); + xnid_remove(&rtdm_protocol_devices, &device->proto.id); xnlock_put_irqrestore(&rt_dev_lock, s); @@ -344,15 +444,19 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) if (handle) xnregistry_remove(handle); + unregister_device_class(class); + up(&nrt_dev_lock); - if (device->reserved.exclusive_context) - kfree(device->reserved.exclusive_context); + if (device->exclusive_context) + kfree(device->exclusive_context); + + kfree(device->name); return 0; } - EXPORT_SYMBOL_GPL(rtdm_dev_unregister); + /** @} */ int __init rtdm_dev_init(void) diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c index 9a7bb8c..8617e83 100644 --- a/kernel/cobalt/rtdm/fd.c +++ b/kernel/cobalt/rtdm/fd.c @@ -21,6 +21,7 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/poll.h> #include <linux/kthread.h> #include <linux/semaphore.h> #include <cobalt/kernel/registry.h> @@ -638,3 +639,45 @@ void rtdm_fd_init(void) sema_init(&rtdm_fd_cleanup_sem, 0); kthread_run(fd_cleanup_thread, NULL, "rtdm_fd"); } + +static inline void warn_user(const char *name) +{ +#ifdef CONFIG_XENO_OPT_DEBUG_USER + printk(XENO_WARN "%s[%d] called regular %s() with RTDM file/socket\n", + current->comm, current->pid, name + 5); +#endif +} + +static ssize_t dumb_read(struct file *file, char __user *buf, + size_t count, loff_t __user *ppos) +{ + warn_user(__func__); + return -EINVAL; +} + +static ssize_t dumb_write(struct file *file, const char __user *buf, + size_t count, loff_t __user *ppos) +{ + warn_user(__func__); + return -EINVAL; +} + +static unsigned int dumb_poll(struct file *file, poll_table *pt) +{ + warn_user(__func__); + return -EINVAL; +} + +static long dumb_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + warn_user(__func__); + return -EINVAL; +} + +const struct file_operations rtdm_dumb_fops = { + .read = dumb_read, + .write = dumb_write, + .poll = dumb_poll, + .unlocked_ioctl = dumb_ioctl, +}; diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h index 8012e22..985e01f 100644 --- a/kernel/cobalt/rtdm/internal.h +++ b/kernel/cobalt/rtdm/internal.h @@ -47,7 +47,7 @@ struct rtdm_device *__rtdm_get_protocol_device(int protocol_family, int socket_t static inline void rtdm_dereference_device(struct rtdm_device *device) { - atomic_dec(&device->reserved.refcount); + atomic_dec(&device->refcount); } int __init rtdm_dev_init(void); diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c index 10f6cb2..52f6d8d 100644 --- a/kernel/cobalt/rtdm/proc.c +++ b/kernel/cobalt/rtdm/proc.c @@ -46,15 +46,14 @@ static void *named_next(struct xnvfile_regular_iterator *it) struct rtdm_device *device = priv->curr; struct list_head *next; - next = device->reserved.entry.next; + next = device->named.entry.next; if (next == &rtdm_named_devices) { priv->curr = NULL; /* all done. */ goto out; } - priv->curr = list_entry(next, struct rtdm_device, reserved.entry); - - out: + priv->curr = list_entry(next, struct rtdm_device, named.entry); +out: return priv->curr; } @@ -64,18 +63,18 @@ static void *named_begin(struct xnvfile_regular_iterator *it) struct rtdm_device *device; loff_t pos = 0; - list_for_each_entry(device, &rtdm_named_devices, reserved.entry) + list_for_each_entry(device, &rtdm_named_devices, named.entry) if (pos++ >= it->pos) break; - if (&device->reserved.entry == &rtdm_named_devices) + if (&device->named.entry == &rtdm_named_devices) return NULL; /* End of list. */ priv->curr = device; /* Skip head. */ if (pos == 1) /* Output the header once, only if some device follows. */ - xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n"); + xnvfile_puts(it, "Name\t\t\t\tDriver\n"); return priv->curr; } @@ -84,8 +83,8 @@ static int named_show(struct xnvfile_regular_iterator *it, void *data) { struct rtdm_device *device = data; - xnvfile_printf(it, "%-31s\t%-15s\t%s\n", device->device_name, - device->driver_name, device->proc_name); + xnvfile_printf(it, "%-31s\t%-15s\n", device->name, + device->class->driver_name); return 0; } @@ -110,7 +109,7 @@ static void *proto_next(struct xnvfile_regular_iterator *it) { struct vfile_proto_data *priv = xnvfile_iterator_priv(it); - return priv->curr = xnid_next_entry(priv->curr, reserved.id); + return priv->curr = xnid_next_entry(priv->curr, proto.id); } static void *proto_begin(struct xnvfile_regular_iterator *it) @@ -120,7 +119,7 @@ static void *proto_begin(struct xnvfile_regular_iterator *it) struct rtdm_device *dev = NULL; loff_t pos = 0; - xntree_for_each_entry(dev, &rtdm_protocol_devices, reserved.id) + xntree_for_each_entry(dev, &rtdm_protocol_devices, proto.id) if (pos++ >= it->pos) break; @@ -131,7 +130,7 @@ static void *proto_begin(struct xnvfile_regular_iterator *it) if (pos == 1) /* Output the header once, only if some device follows. */ - xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n"); + xnvfile_puts(it, "Name\t\t\t\tDriver\n"); return priv->curr; } @@ -139,14 +138,15 @@ static void *proto_begin(struct xnvfile_regular_iterator *it) static int proto_show(struct xnvfile_regular_iterator *it, void *data) { struct rtdm_device *device = data; + struct rtdm_device_class *class = device->class; char pnum[32]; ksformat(pnum, sizeof(pnum), "%u:%u", - device->protocol_family, device->socket_type); + class->protocol_family, class->socket_type); xnvfile_printf(it, "%-31s\t%-15s\t%s\n", - pnum, device->driver_name, - device->proc_name); + pnum, class->driver_name, + device->name); return 0; } @@ -181,7 +181,6 @@ static void *openfd_next(struct xnvfile_regular_iterator *it) static int openfd_show(struct xnvfile_regular_iterator *it, void *data) { struct rtdm_dev_context *context; - struct rtdm_device *device; int close_lock_count, i; struct rtdm_fd *fd; @@ -198,13 +197,10 @@ static int openfd_show(struct xnvfile_regular_iterator *it, void *data) context = rtdm_fd_to_context(fd); close_lock_count = fd->refs; - device = context->device; xnvfile_printf(it, "%d\t%d\t%d\t%s\n", i, - close_lock_count, - rtdm_fd_minor(fd), - (device->device_flags & RTDM_NAMED_DEVICE) ? - device->device_name : device->proc_name); + close_lock_count, rtdm_fd_minor(fd), + context->device->name); rtdm_fd_put(fd); @@ -256,6 +252,7 @@ static struct xnvfile_regular allfd_vfile = { static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data) { + struct rtdm_device_class *class; struct rtdm_device *device; if (down_interruptible(&nrt_dev_lock)) @@ -265,11 +262,11 @@ static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data) * As the device may have disappeared while the handler was called, * first match the pointer against registered devices. */ - list_for_each_entry(device, &rtdm_named_devices, reserved.entry) + list_for_each_entry(device, &rtdm_named_devices, named.entry) if (device == xnvfile_priv(it->vfile)) goto found; - xntree_for_each_entry(device, &rtdm_protocol_devices, reserved.id) + xntree_for_each_entry(device, &rtdm_protocol_devices, proto.id) if (device == xnvfile_priv(it->vfile)) goto found; @@ -277,28 +274,31 @@ static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data) return -ENODEV; found: + class = device->class; + xnvfile_printf(it, "driver:\t\t%s\nversion:\t%d.%d.%d\n", - device->driver_name, - RTDM_DRIVER_MAJOR_VER(device->driver_version), - RTDM_DRIVER_MINOR_VER(device->driver_version), - RTDM_DRIVER_PATCH_VER(device->driver_version)); + class->driver_name, + RTDM_DRIVER_MAJOR_VER(class->driver_version), + RTDM_DRIVER_MINOR_VER(class->driver_version), + RTDM_DRIVER_PATCH_VER(class->driver_version)); xnvfile_printf(it, "peripheral:\t%s\nprovider:\t%s\n", - device->peripheral_name, device->provider_name); + class->peripheral_name, class->provider_name); xnvfile_printf(it, "class:\t\t%d\nsub-class:\t%d\n", - device->device_class, device->device_sub_class); + class->profile_info.class_id, + class->profile_info.subclass_id); xnvfile_printf(it, "flags:\t\t%s%s%s\n", - (device->device_flags & RTDM_EXCLUSIVE) ? + (class->device_flags & RTDM_EXCLUSIVE) ? "EXCLUSIVE " : "", - (device->device_flags & RTDM_NAMED_DEVICE) ? + (class->device_flags & RTDM_NAMED_DEVICE) ? "NAMED_DEVICE " : "", - (device->device_flags & RTDM_PROTOCOL_DEVICE) ? + (class->device_flags & RTDM_PROTOCOL_DEVICE) ? "PROTOCOL_DEVICE " : ""); xnvfile_printf(it, "lock count:\t%d\n", - atomic_read(&device->reserved.refcount)); + atomic_read(&device->refcount)); up(&nrt_dev_lock); return 0; @@ -312,7 +312,7 @@ int rtdm_proc_register_device(struct rtdm_device *device) { int ret; - ret = xnvfile_init_dir(device->proc_name, + ret = xnvfile_init_dir(device->name, &device->vfroot, &rtdm_vfroot); if (ret) goto err_out; diff --git a/kernel/cobalt/trace/cobalt-rtdm.h b/kernel/cobalt/trace/cobalt-rtdm.h index 2754a67..4ca71ef 100644 --- a/kernel/cobalt/trace/cobalt-rtdm.h +++ b/kernel/cobalt/trace/cobalt-rtdm.h @@ -151,29 +151,29 @@ TRACE_EVENT(cobalt_device_register, TP_STRUCT__entry( __field(struct rtdm_device *, device) - __string(device_name, device->device_name) + __string(device_name, device->name) __field(int, flags) - __field(int, device_class) - __field(int, device_subclass) + __field(int, class_id) + __field(int, subclass_id) __field(int, profile_version) __field(int, driver_version) ), TP_fast_assign( __entry->device = device; - __assign_str(device_name, device->device_name); - __entry->flags = device->device_flags; - __entry->device_class = device->device_class; - __entry->device_subclass = device->device_sub_class; - __entry->profile_version = device->profile_version; - __entry->driver_version = device->driver_version; + __assign_str(device_name, device->class->device_name); + __entry->flags = device->class->device_flags; + __entry->class_id = device->class->device_class; + __entry->subclass_id = device->class->device_sub_class; + __entry->profile_version = device->class->profile_version; + __entry->driver_version = device->class->driver_version; ), TP_printk("%s device %s=%p version=%d flags=0x%x, class=%d.%d profile=%d", (__entry->flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE ? "named" : "protocol", __get_str(device_name), __entry->device, __entry->driver_version, - __entry->flags, __entry->device_class, __entry->device_subclass, + __entry->flags, __entry->class_id, __entry->subclass_id, __entry->profile_version) ); @@ -183,13 +183,13 @@ TRACE_EVENT(cobalt_device_unregister, TP_STRUCT__entry( __field(struct rtdm_device *, device) - __string(device_name, device->device_name) + __string(device_name, device->class->device_name) __field(unsigned int, poll_delay) ), TP_fast_assign( __entry->device = device; - __assign_str(device_name, device->device_name); + __assign_str(device_name, device->class->device_name); __entry->poll_delay = poll_delay; ), diff --git a/kernel/drivers/analogy/rtdm_interface.c b/kernel/drivers/analogy/rtdm_interface.c index aae78ff..926ee52 100644 --- a/kernel/drivers/analogy/rtdm_interface.c +++ b/kernel/drivers/analogy/rtdm_interface.c @@ -213,51 +213,53 @@ int a4l_rt_select(struct rtdm_fd *fd, return a4l_select(cxt, selector, type, fd_index); } -static struct rtdm_device rtdm_devs[A4L_NB_DEVICES] = -{[0 ... A4L_NB_DEVICES - 1] = { - .struct_version = RTDM_DEVICE_STRUCT_VER, - .device_flags = RTDM_NAMED_DEVICE, - .context_size = sizeof(struct a4l_device_context), - .device_name = "", - .ops = { - .open = a4l_open, - .close = a4l_close, - .ioctl_rt = a4l_ioctl, - .read_rt = a4l_read, - .write_rt = a4l_write, - .ioctl_nrt = a4l_ioctl, - .read_nrt = a4l_read, - .write_nrt = a4l_write, - .select = a4l_rt_select, - }, - .device_class = RTDM_CLASS_EXPERIMENTAL, - .device_sub_class = RTDM_SUBCLASS_ANALOGY, - .driver_name = "rtdm_analogy", - .driver_version = RTDM_DRIVER_VER(1, 0, 0), - .peripheral_name = "Analogy", - .provider_name = "Alexis Berlemont", +static struct rtdm_device_class analogy = { + .profile_info = RTDM_PROFILE_INFO(analogy, + RTDM_CLASS_EXPERIMENTAL, + RTDM_SUBCLASS_ANALOGY, + 0), + .device_flags = RTDM_NAMED_DEVICE, + .device_count = A4L_NB_DEVICES, + .context_size = sizeof(struct a4l_device_context), + .ops = { + .open = a4l_open, + .close = a4l_close, + .ioctl_rt = a4l_ioctl, + .read_rt = a4l_read, + .write_rt = a4l_write, + .ioctl_nrt = a4l_ioctl, + .read_nrt = a4l_read, + .write_nrt = a4l_write, + .select = a4l_rt_select, + }, + .driver_name = "analogy", + .driver_version = RTDM_DRIVER_VER(1, 0, 0), + .peripheral_name = "Analogy", + .provider_name = "Alexis Berlemont", +}; + +static struct rtdm_device rtdm_devs[A4L_NB_DEVICES] = { + [0 ... A4L_NB_DEVICES - 1] = { + .class = &analogy, + .label = "analogy%d", } }; int a4l_register(void) { - int i, ret = 0; - - for (i = 0; i < A4L_NB_DEVICES && ret == 0; i++) { - - /* Sets the device name through which - user process can access the Analogy layer */ - ksformat(rtdm_devs[i].device_name, - RTDM_MAX_DEVNAME_LEN, "analogy%d", i); - rtdm_devs[i].proc_name = rtdm_devs[i].device_name; + int i, ret; - /* To keep things simple, the RTDM device ID - is the Analogy device index */ - rtdm_devs[i].device_id = i; - - ret = rtdm_dev_register(&(rtdm_devs[i])); + for (i = 0; i < A4L_NB_DEVICES; i++) { + ret = rtdm_dev_register(rtdm_devs + i); + if (ret) + goto fail; } + return 0; +fail: + while (i-- > 0) + rtdm_dev_unregister(rtdm_devs + i, 0); + return ret; } diff --git a/kernel/drivers/autotune/autotune.c b/kernel/drivers/autotune/autotune.c index 8e9b040..c407038 100644 --- a/kernel/drivers/autotune/autotune.c +++ b/kernel/drivers/autotune/autotune.c @@ -628,9 +628,13 @@ static void autotune_close(struct rtdm_fd *fd) tuner->destroy_tuner(tuner); } -static struct rtdm_device device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class autotune = { + .profile_info = RTDM_PROFILE_INFO(autotune, + RTDM_CLASS_AUTOTUNE, + RTDM_SUBCLASS_AUTOTUNE, + 0), .device_flags = RTDM_NAMED_DEVICE|RTDM_EXCLUSIVE, + .device_count = 1, .context_size = sizeof(struct autotune_context), .ops = { .open = autotune_open, @@ -638,16 +642,17 @@ static struct rtdm_device device = { .ioctl_nrt = autotune_ioctl_nrt, .close = autotune_close, }, - .device_class = RTDM_CLASS_AUTOTUNE, - .device_sub_class = RTDM_SUBCLASS_AUTOTUNE, - .device_name = "autotune", .driver_name = "autotune", .driver_version = RTDM_DRIVER_VER(1, 0, 0), .peripheral_name = "Auto-tuning services", - .proc_name = device.device_name, .provider_name = "Philippe Gerum <r...@xenomai.org>", }; +static struct rtdm_device device = { + .class = &autotune, + .label = "autotune", +}; + static int __init autotune_init(void) { int ret; diff --git a/kernel/drivers/can/rtcan_raw.c b/kernel/drivers/can/rtcan_raw.c index e658ea3..17e19f1 100644 --- a/kernel/drivers/can/rtcan_raw.c +++ b/kernel/drivers/can/rtcan_raw.c @@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); void rtcan_tx_push(struct rtcan_device *dev, struct rtcan_socket *sock, can_frame_t *frame); -static struct rtdm_device rtcan_proto_raw_dev; +static struct rtdm_device_class rtcan_proto_raw; static inline int rtcan_accept_msg(uint32_t can_id, can_filter_t *filter) @@ -128,7 +128,7 @@ static void rtcan_rcv_deliver(struct rtcan_recv *recv_listener, /* Overflow of socket's ring buffer! */ sock->rx_buf_full++; RTCAN_RTDM_DBG("%s: socket buffer overflow, message discarded\n", - rtcan_proto_raw_dev.driver_name); + rtcan_proto_raw.driver_name); } rtdm_fd_unlock(fd); @@ -976,9 +976,13 @@ ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd, } -static struct rtdm_device rtcan_proto_raw_dev = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class rtcan_proto_raw = { + .profile_info = RTDM_PROFILE_INFO(rtcan_proto_raw, + RTDM_CLASS_CAN, + RTDM_SUBCLASS_GENERIC, + RTCAN_PROFILE_VER), .device_flags = RTDM_PROTOCOL_DEVICE, + .device_count = 1, .context_size = sizeof(struct rtcan_socket), .protocol_family = PF_CAN, .socket_type = SOCK_RAW, @@ -990,25 +994,24 @@ static struct rtdm_device rtcan_proto_raw_dev = { .recvmsg_rt = rtcan_raw_recvmsg, .sendmsg_rt = rtcan_raw_sendmsg, }, - .device_class = RTDM_CLASS_CAN, - .device_sub_class = RTDM_SUBCLASS_GENERIC, - .profile_version = RTCAN_PROFILE_VER, .driver_name = "rtcan", .driver_version = RTDM_DRIVER_VER(RTCAN_MAJOR_VER, RTCAN_MINOR_VER, RTCAN_BUGFIX_VER), .peripheral_name = "Real-Time CAN Raw Socket Interface", .provider_name = "RT-Socket-CAN development team", - .proc_name = "rtcan" }; +static struct rtdm_device rtcan_proto_raw_dev = { + .class = &rtcan_proto_raw, + .label = "rtcan", +}; int __init rtcan_raw_proto_register(void) { return rtdm_dev_register(&rtcan_proto_raw_dev); } - void __exit rtcan_raw_proto_unregister(void) { rtdm_dev_unregister(&rtcan_proto_raw_dev, 1000); diff --git a/kernel/drivers/ipc/rtipc.c b/kernel/drivers/ipc/rtipc.c index 802b7f4..e64c22f 100644 --- a/kernel/drivers/ipc/rtipc.c +++ b/kernel/drivers/ipc/rtipc.c @@ -252,13 +252,16 @@ static int rtipc_select(struct rtdm_fd *fd, struct xnselector *selector, return ret; } -static struct rtdm_device device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, - .device_flags = RTDM_PROTOCOL_DEVICE, - .context_size = sizeof(struct rtipc_private), - .device_name = "rtipc", - .protocol_family= PF_RTIPC, - .socket_type = SOCK_DGRAM, +static struct rtdm_device_class rtipc = { + .profile_info = RTDM_PROFILE_INFO(rtipc, + RTDM_CLASS_RTIPC, + RTDM_SUBCLASS_GENERIC, + 1), + .device_flags = RTDM_PROTOCOL_DEVICE, + .device_count = 1, + .context_size = sizeof(struct rtipc_private), + .protocol_family = PF_RTIPC, + .socket_type = SOCK_DGRAM, .ops = { .socket = rtipc_socket, .close = rtipc_close, @@ -274,14 +277,15 @@ static struct rtdm_device device = { .write_nrt = NULL, .select = rtipc_select, }, - .device_class = RTDM_CLASS_RTIPC, - .device_sub_class = RTDM_SUBCLASS_GENERIC, - .profile_version = 1, .driver_name = "rtipc", .driver_version = RTDM_DRIVER_VER(1, 0, 0), .peripheral_name = "Real-time IPC interface", - .proc_name = device.device_name, - .provider_name = "Philippe Gerum (xenomai.org)", + .provider_name = "Philippe Gerum <r...@xenomai.org>", +}; + +static struct rtdm_device device = { + .class = &rtipc, + .label = "rtipc", }; int __init __rtipc_init(void) diff --git a/kernel/drivers/serial/16550A.c b/kernel/drivers/serial/16550A.c index 7b869f2..2d78c78 100644 --- a/kernel/drivers/serial/16550A.c +++ b/kernel/drivers/serial/16550A.c @@ -125,7 +125,6 @@ static unsigned long irqtype[MAX_DEVICES] = { }; static unsigned int baud_base[MAX_DEVICES]; static int tx_fifo[MAX_DEVICES]; -static unsigned int start_index; module_param_array(irq, uint, NULL, 0400); module_param_array(baud_base, uint, NULL, 0400); @@ -136,9 +135,6 @@ MODULE_PARM_DESC(baud_base, "Maximum baud rate of the serial device " "(internal clock rate / 16)"); MODULE_PARM_DESC(tx_fifo, "Transmitter FIFO size"); -module_param(start_index, uint, 0400); -MODULE_PARM_DESC(start_index, "First device instance number to be used"); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("jan.kis...@web.de"); @@ -313,7 +309,7 @@ static int rt_16550_set_config(struct rt_16550_context *ctx, rtdm_lock_get_irqsave(&ctx->lock, lock_ctx); if (config->config_mask & RTSER_SET_BAUD) { - int dev_id = rtdm_fd_device(rtdm_private_to_fd(ctx))->device_id; + int dev_id = rtdm_fd_minor(rtdm_private_to_fd(ctx)); int baud_div; ctx->config.baud_rate = config->baud_rate; @@ -441,7 +437,7 @@ void rt_16550_cleanup_ctx(struct rt_16550_context *ctx) int rt_16550_open(struct rtdm_fd *fd, int oflags) { struct rt_16550_context *ctx; - int dev_id = rtdm_fd_device(fd)->device_id; + int dev_id = rtdm_fd_minor(fd); int err; uint64_t *dummy; rtdm_lockctx_t lock_ctx; @@ -479,7 +475,7 @@ int rt_16550_open(struct rtdm_fd *fd, int oflags) err = rtdm_irq_request(&ctx->irq_handle, irq[dev_id], rt_16550_interrupt, irqtype[dev_id], - rtdm_fd_device(fd)->proc_name, ctx); + rtdm_fd_device(fd)->name, ctx); if (err) { /* reset DTR and RTS */ rt_16550_reg_out(rt_16550_io_mode_from_ctx(ctx), ctx->base_addr, @@ -584,7 +580,7 @@ int rt_16550_ioctl(struct rtdm_fd *fd, unsigned int request, void *arg) if ((config->config_mask & RTSER_SET_BAUD) && (config->baud_rate > - baud_base[rtdm_fd_device(fd)->device_id] || + baud_base[rtdm_fd_minor(fd)] || config->baud_rate <= 0)) /* invalid baudrate for this port */ return -EINVAL; @@ -1068,11 +1064,14 @@ ssize_t rt_16550_write(struct rtdm_fd *fd, const void *buf, size_t nbyte) return ret; } -static const struct rtdm_device __initdata device_tmpl = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class uart16550A = { + .profile_info = RTDM_PROFILE_INFO(uart16550A, + RTDM_CLASS_SERIAL, + RTDM_SUBCLASS_16550A, + RTSER_PROFILE_VER), .device_flags = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE, + .device_count = MAX_DEVICES, .context_size = sizeof(struct rt_16550_context), - .device_name = "", .ops = { .open = rt_16550_open, .close = rt_16550_close, @@ -1081,9 +1080,6 @@ static const struct rtdm_device __initdata device_tmpl = { .read_rt = rt_16550_read, .write_rt = rt_16550_write, }, - .device_class = RTDM_CLASS_SERIAL, - .device_sub_class = RTDM_SUBCLASS_16550A, - .profile_version = RTSER_PROFILE_VER, .driver_name = RT_16550_DRIVER_NAME, .driver_version = RTDM_DRIVER_VER(1, 5, 2), .peripheral_name = "UART 16550A", @@ -1096,6 +1092,7 @@ int __init rt_16550_init(void) { struct rtdm_device *dev; unsigned long base; + char *name; int mode; int err; int i; @@ -1114,19 +1111,18 @@ int __init rt_16550_init(void) if (!irq[i] || !rt_16550_addr_param_valid(i)) goto cleanup_out; - dev = kmalloc(sizeof(struct rtdm_device), GFP_KERNEL); + dev = kmalloc(sizeof(struct rtdm_device) + + RTDM_MAX_DEVNAME_LEN, GFP_KERNEL); err = -ENOMEM; if (!dev) goto cleanup_out; - memcpy(dev, &device_tmpl, sizeof(struct rtdm_device)); - ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtser%d", - start_index + i); - dev->device_id = i; - - dev->proc_name = dev->device_name; + dev->class = &uart16550A; + dev->label = "rtser%d"; + name = (char *)(dev + 1); + ksformat(name, RTDM_MAX_DEVNAME_LEN, dev->label, i); - err = rt_16550_init_io(i, dev->device_name); + err = rt_16550_init_io(i, name); if (err) goto kfree_out; diff --git a/kernel/drivers/serial/mpc52xx_uart.c b/kernel/drivers/serial/mpc52xx_uart.c index b960a7f..6e4f39b 100644 --- a/kernel/drivers/serial/mpc52xx_uart.c +++ b/kernel/drivers/serial/mpc52xx_uart.c @@ -1330,7 +1330,6 @@ static int rt_mpc52xx_uart_of_probe(struct platform_device *op) memcpy(dev, &device_tmpl, sizeof(struct rtdm_device)); ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtserPSC%d", idx); - dev->device_id = idx; dev->proc_name = dev->device_name; dev->device_data = port; diff --git a/kernel/drivers/serial/rt_imx_uart.c b/kernel/drivers/serial/rt_imx_uart.c index 1d547a9..8a04359 100644 --- a/kernel/drivers/serial/rt_imx_uart.c +++ b/kernel/drivers/serial/rt_imx_uart.c @@ -1426,7 +1426,6 @@ static int rt_imx_uart_probe(struct platform_device *pdev) memcpy(dev, &device_tmpl, sizeof(struct rtdm_device)); ksformat(dev->device_name, RTDM_MAX_DEVNAME_LEN, "rtser%d", start_index + pdev->id); - dev->device_id = pdev->id; dev->device_data = port; dev->proc_name = dev->device_name; diff --git a/kernel/drivers/testing/rtdmtest.c b/kernel/drivers/testing/rtdmtest.c index 849a0eb..2e671ba 100644 --- a/kernel/drivers/testing/rtdmtest.c +++ b/kernel/drivers/testing/rtdmtest.c @@ -21,11 +21,6 @@ #include <rtdm/driver.h> #include <rtdm/testing.h> -static unsigned int start_index; - -module_param(start_index, uint, 0400); -MODULE_PARM_DESC(start_index, "First device instance number to be used"); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("jan.kis...@web.de"); @@ -105,56 +100,52 @@ rtdm_test_ioctl(struct rtdm_fd *fd, unsigned int request, void __user *arg) return err; } -static struct rtdm_device device[2] = { [0 ... 1] = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class rtdmtest = { + .profile_info = RTDM_PROFILE_INFO(rtdmtest, + RTDM_CLASS_TESTING, + RTDM_SUBCLASS_RTDMTEST, + RTTST_PROFILE_VER), .device_flags = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE, + .device_count = 2, .context_size = sizeof(struct rtdm_test_context), - .device_name = "", .ops = { .open = rtdm_test_open, .close = rtdm_test_close, .ioctl_rt = rtdm_test_ioctl, .ioctl_nrt = rtdm_test_ioctl, }, - .device_class = RTDM_CLASS_TESTING, - .device_sub_class = RTDM_SUBCLASS_RTDMTEST, - .profile_version = RTTST_PROFILE_VER, - .driver_name = "xeno_rtdmtest", + .driver_name = "rtdmtest", .driver_version = RTDM_DRIVER_VER(0, 1, 0), .peripheral_name = "RTDM unit test", .provider_name = "Jan Kiszka", -} }; +}; + +static struct rtdm_device device[2] = { + [0 ... 1] = { + .class = &rtdmtest, + .label = "rttest-rtdm%d", + } +}; static int __init __rtdm_test_init(void) { - int dev = 0; - int err; + int i, ret; if (!realtime_core_enabled()) return -ENODEV; - while (1) { - device[dev].proc_name = device[dev].device_name; - - ksformat(device[dev].device_name, RTDM_MAX_DEVNAME_LEN, - "rttest-rtdm%d", - start_index); - err = rtdm_dev_register(&device[dev]); - - start_index++; - - if (!err) { - if (++dev >= ARRAY_SIZE(device)) - break; - } else if (err != -EEXIST) { - while (dev > 0) { - dev--; - rtdm_dev_unregister(&device[dev], 1000); - } - return err; - } + for (i = 0; i < ARRAY_SIZE(device); i++) { + ret = rtdm_dev_register(device + i); + if (ret) + goto fail; } + return 0; +fail: + while (i-- > 0) + rtdm_dev_unregister(device + i, 1000); + + return ret; } static void __exit __rtdm_test_exit(void) @@ -162,7 +153,7 @@ static void __exit __rtdm_test_exit(void) int i; for (i = 0; i < ARRAY_SIZE(device); i++) - rtdm_dev_unregister(&device[i], 1000); + rtdm_dev_unregister(device + i, 1000); } module_init(__rtdm_test_init); diff --git a/kernel/drivers/testing/switchtest.c b/kernel/drivers/testing/switchtest.c index c66dca5..f32782d 100644 --- a/kernel/drivers/testing/switchtest.c +++ b/kernel/drivers/testing/switchtest.c @@ -26,6 +26,8 @@ #include <rtdm/driver.h> #include <asm/xenomai/fptest.h> +#define NR_DEVICES 4 + #define RTSWITCH_RT 0x10000 #define RTSWITCH_NRT 0 #define RTSWITCH_KERNEL 0x20000 @@ -57,11 +59,6 @@ struct rtswitch_context { rtdm_nrtsig_t wake_utask; }; -static unsigned int start_index; - -module_param(start_index, uint, 0400); -MODULE_PARM_DESC(start_index, "First device instance number to be used"); - static int fp_features; MODULE_LICENSE("GPL"); @@ -720,52 +717,65 @@ static int rtswitch_ioctl_rt(struct rtdm_fd *fd, } } -static struct rtdm_device device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class switchtest = { + .profile_info = RTDM_PROFILE_INFO(switchtest, + RTDM_CLASS_TESTING, + RTDM_SUBCLASS_SWITCHTEST, + RTTST_PROFILE_VER), .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, .context_size = sizeof(struct rtswitch_context), - .device_name = "", .ops = { .open = rtswitch_open, .close = rtswitch_close, .ioctl_rt = rtswitch_ioctl_rt, .ioctl_nrt = rtswitch_ioctl_nrt, }, - .device_class = RTDM_CLASS_TESTING, - .device_sub_class = RTDM_SUBCLASS_SWITCHTEST, - .profile_version = RTTST_PROFILE_VER, - .driver_name = "xeno_switchtest", + .driver_name = "switchtest", .driver_version = RTDM_DRIVER_VER(0, 1, 1), .peripheral_name = "Context Switch Test", .provider_name = "Gilles Chanteperdrix", - .proc_name = device.device_name, +}; + +static struct rtdm_device devices[NR_DEVICES] = { + [ 0 ... NR_DEVICES - 1] = { + .class = &switchtest, + .label = "switchtest%d", + }, }; int __init __switchtest_init(void) { - int err; + int minor, ret; if (!realtime_core_enabled()) return 0; fp_features = fp_detect(); - do { - ksformat(device.device_name, RTDM_MAX_DEVNAME_LEN, - "rttest-switchtest%d", - start_index); - err = rtdm_dev_register(&device); + for (minor = 0; minor < NR_DEVICES; minor++) { + ret = rtdm_dev_register(devices + minor); + if (ret) + goto fail; + } - start_index++; - } while (err == -EEXIST); + return 0; +fail: + while (minor-- > 0) + rtdm_dev_unregister(devices + minor, 0); - return err; + return ret; } void __switchtest_exit(void) { - if (realtime_core_enabled()) - rtdm_dev_unregister(&device, 1000); + int minor; + + if (!realtime_core_enabled()) + return; + + for (minor = 0; minor < NR_DEVICES; minor++) + rtdm_dev_unregister(devices + minor, 1000); } module_init(__switchtest_init); diff --git a/kernel/drivers/testing/timerbench.c b/kernel/drivers/testing/timerbench.c index e244104..644177b 100644 --- a/kernel/drivers/testing/timerbench.c +++ b/kernel/drivers/testing/timerbench.c @@ -24,6 +24,8 @@ #include <rtdm/testing.h> #include <rtdm/driver.h> +#define NR_DEVICES 4 + struct rt_tmbench_context { int mode; unsigned long period; @@ -50,11 +52,6 @@ struct rt_tmbench_context { struct semaphore nrt_mutex; }; -static unsigned int start_index; - -module_param(start_index, uint, 0400); -MODULE_PARM_DESC(start_index, "First device instance number to be used"); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("jan.kis...@web.de"); @@ -296,7 +293,7 @@ static int rt_tmbench_start(struct rtdm_fd *fd, ctx->mode = RTTST_TMBENCH_TASK; } else { rtdm_timer_init(&ctx->timer, timer_proc, - rtdm_fd_device(fd)->device_name); + rtdm_fd_device(fd)->name); ctx->curr.test_loops = 0; @@ -453,50 +450,63 @@ static int rt_tmbench_ioctl_rt(struct rtdm_fd *fd, return err; } -static struct rtdm_device device = { - .struct_version = RTDM_DEVICE_STRUCT_VER, +static struct rtdm_device_class timerbench = { + .profile_info = RTDM_PROFILE_INFO(timerbench, + RTDM_CLASS_TESTING, + RTDM_SUBCLASS_TIMERBENCH, + RTTST_PROFILE_VER), .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, .context_size = sizeof(struct rt_tmbench_context), - .device_name = "", .ops = { .open = rt_tmbench_open, .close = rt_tmbench_close, .ioctl_rt = rt_tmbench_ioctl_rt, .ioctl_nrt = rt_tmbench_ioctl_nrt, }, - .device_class = RTDM_CLASS_TESTING, - .device_sub_class = RTDM_SUBCLASS_TIMERBENCH, - .profile_version = RTTST_PROFILE_VER, - .driver_name = "xeno_timerbench", + .driver_name = "timerbench", .driver_version = RTDM_DRIVER_VER(0, 2, 1), .peripheral_name = "Timer Latency Benchmark", .provider_name = "Jan Kiszka", - .proc_name = device.device_name, +}; + +static struct rtdm_device devices[NR_DEVICES] = { + [ 0 ... NR_DEVICES - 1] = { + .class = &timerbench, + .label = "timerbench%d", + }, }; static int __init __timerbench_init(void) { - int err; + int minor, ret; if (!realtime_core_enabled()) return 0; - do { - ksformat(device.device_name, RTDM_MAX_DEVNAME_LEN, - "rttest-timerbench%d", - start_index); - err = rtdm_dev_register(&device); + for (minor = 0; minor < NR_DEVICES; minor++) { + ret = rtdm_dev_register(devices + minor); + if (ret) + goto fail; + } - start_index++; - } while (err == -EEXIST); + return 0; +fail: + while (minor-- > 0) + rtdm_dev_unregister(devices + minor, 0); - return err; + return ret; } static void __timerbench_exit(void) { - if (realtime_core_enabled()) - rtdm_dev_unregister(&device, 1000); + int minor; + + if (!realtime_core_enabled()) + return; + + for (minor = 0; minor < NR_DEVICES; minor++) + rtdm_dev_unregister(devices + minor, 1000); } module_init(__timerbench_init); diff --git a/kernel/drivers/udd/udd.c b/kernel/drivers/udd/udd.c index 4bcec17..894e3f5 100644 --- a/kernel/drivers/udd/udd.c +++ b/kernel/drivers/udd/udd.c @@ -280,30 +280,31 @@ static inline int check_memregion(struct udd_device *udd, static inline int register_mapper(struct udd_device *udd) { - struct rtdm_device *dev = &udd->__reserved.mapper; struct udd_reserved *ur = &udd->__reserved; + struct rtdm_device *dev = &ur->mapper; + struct rtdm_device_class *class = &ur->mapper_class; - ur->mapper_name = kasformat("%s,mapper", udd->device_name); + ur->mapper_name = kasformat("%s,mapper%%d", udd->device_name); if (ur->mapper_name == NULL) return -ENOMEM; - memset(dev, 0, sizeof(*dev)); - dev->struct_version = RTDM_DEVICE_STRUCT_VER; - dev->device_flags = RTDM_NAMED_DEVICE|RTDM_MINOR; - dev->context_size = 0; - dev->ops = (struct rtdm_fd_ops){ - .open = mapper_open, - .close = mapper_close, - .mmap = mapper_mmap, + class->profile_info = (struct rtdm_profile_info) + RTDM_PROFILE_INFO("mapper", RTDM_CLASS_MEMORY, + RTDM_SUBCLASS_GENERIC, 0); + class->device_flags = RTDM_NAMED_DEVICE|RTDM_MINOR; + class->device_count = UDD_NR_MAPS; + class->ops = (struct rtdm_fd_ops){ + .open = mapper_open, + .close = mapper_close, + .mmap = mapper_mmap, }; - dev->device_class = RTDM_CLASS_MEMORY; - dev->device_sub_class = RTDM_SUBCLASS_GENERIC; - knamecpy(dev->device_name, ur->mapper_name); - dev->driver_name = "mapper"; - dev->driver_version = RTDM_DRIVER_VER(1, 0, 0); - dev->peripheral_name = "UDD mapper"; - dev->proc_name = ur->mapper_name; - dev->provider_name = "Philippe Gerum <r...@xenomai.org>"; + class->driver_name = "udd"; + class->driver_version = RTDM_DRIVER_VER(1, 0, 0); + class->peripheral_name = "UDD mapper"; + class->provider_name = "Philippe Gerum <r...@xenomai.org>"; + + dev->class = class; + dev->label = ur->mapper_name; return rtdm_dev_register(dev); } @@ -340,6 +341,7 @@ int udd_register_device(struct udd_device *udd) { struct rtdm_device *dev = &udd->__reserved.device; struct udd_reserved *ur = &udd->__reserved; + struct rtdm_device_class *class = &ur->class; int ret, n; if (!realtime_core_enabled()) @@ -357,11 +359,13 @@ int udd_register_device(struct udd_device *udd) return ret; } - memset(dev, 0, sizeof(*dev)); - dev->struct_version = RTDM_DEVICE_STRUCT_VER; - dev->device_flags = RTDM_NAMED_DEVICE|udd->device_flags; - dev->context_size = sizeof(struct udd_context); - dev->ops = (struct rtdm_fd_ops){ + class->profile_info = (struct rtdm_profile_info) + RTDM_PROFILE_INFO(udd->device_name, RTDM_CLASS_UDD, + udd->device_subclass, 0); + class->device_flags = RTDM_NAMED_DEVICE|udd->device_flags; + class->device_count = 1; + class->context_size = sizeof(struct udd_context); + class->ops = (struct rtdm_fd_ops){ .open = udd_open, .ioctl_rt = udd_ioctl_rt, .read_rt = udd_read_rt, @@ -369,19 +373,22 @@ int udd_register_device(struct udd_device *udd) .close = udd_close, .select = udd_select, }; - dev->device_class = RTDM_CLASS_UDD; - dev->device_sub_class = udd->device_subclass; - knamecpy(dev->device_name, udd->device_name); - dev->driver_name = "udd"; - dev->driver_version = udd->driver_version; - dev->peripheral_name = udd->device_description; - dev->proc_name = udd->device_name; - dev->provider_name = udd->driver_author; + class->driver_name = "udd"; + class->driver_version = udd->driver_version; + class->peripheral_name = udd->device_description; + class->provider_name = udd->driver_author; + + dev->class = class; + dev->label = udd->device_name; + + ret = rtdm_dev_register(dev); + if (ret) + return ret; if (ur->nr_maps > 0) { ret = register_mapper(udd); if (ret) - return ret; + goto fail_mapper; } else ur->mapper_name = NULL; @@ -392,22 +399,19 @@ int udd_register_device(struct udd_device *udd) if (udd->irq != UDD_IRQ_NONE && udd->irq != UDD_IRQ_CUSTOM) { ret = rtdm_irq_request(&ur->irqh, udd->irq, udd_irq_handler, 0, - dev->device_name, udd); + dev->name, udd); if (ret) goto fail_irq_request; } - ret = rtdm_dev_register(&ur->device); - if (ret) - goto fail_dev_register; - return 0; -fail_dev_register: - rtdm_irq_free(&ur->irqh); fail_irq_request: rtdm_dev_unregister(&ur->mapper, 0); - kfree(ur->mapper_name); +fail_mapper: + rtdm_dev_unregister(dev, 0); + if (ur->mapper_name) + kfree(ur->mapper_name); return ret; } @@ -591,7 +595,7 @@ struct udd_device *udd_get_device(struct rtdm_fd *fd) { struct rtdm_device *dev = rtdm_fd_device(fd); - if (dev->device_class == RTDM_CLASS_MEMORY) + if (dev->class->profile_info.class_id == RTDM_CLASS_MEMORY) return container_of(dev, struct udd_device, __reserved.mapper); return container_of(dev, struct udd_device, __reserved.device); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git