Module: xenomai-gch Branch: for-forge-rtdm-rework Commit: 4e5c9a8e081b6e369afd67bdda1bd3acc9755627 URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=4e5c9a8e081b6e369afd67bdda1bd3acc9755627
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Sun Jan 26 23:47:24 2014 +0100 cobalt/rtdm: base named devices on nucleus registry --- include/cobalt/kernel/rtdm/driver.h | 12 ++-- kernel/cobalt/rtdm/device.c | 124 ++++++++++------------------------- kernel/cobalt/rtdm/internal.h | 2 +- kernel/cobalt/rtdm/proc.c | 94 ++++++++------------------ 4 files changed, 70 insertions(+), 162 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index a872772..ee80886 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -447,8 +447,12 @@ rtdm_private_to_context(void *dev_private) } struct rtdm_dev_reserved { + unsigned magic; union { - struct list_head entry; + struct { + struct list_head entry; + xnhandle_t handle; + }; struct xnid id; }; atomic_t refcount; @@ -463,6 +467,9 @@ struct rtdm_dev_reserved { * not reside in write-protected 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; @@ -531,9 +538,6 @@ struct rtdm_device { int device_id; /** Driver definable device data */ void *device_data; - - /** Data stored by RTDM inside a registered device (internal use only) */ - struct rtdm_dev_reserved reserved; }; /** @} devregister */ diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c index e6d7bfe..2a9dd82 100644 --- a/kernel/cobalt/rtdm/device.c +++ b/kernel/cobalt/rtdm/device.c @@ -32,6 +32,8 @@ #include "rtdm/internal.h" #include <trace/events/cobalt-rtdm.h> +#define RTDM_DEVICE_MAGIC 0x82846877 + #define SET_DEFAULT_OP(device, operation) \ (device).operation##_rt = (void *)rtdm_no_support; \ (device).operation##_nrt = (void *)rtdm_no_support @@ -45,13 +47,7 @@ #define ANY_HANDLER(device, operation) \ ((device).operation##_rt || (device).operation##_nrt) -unsigned int devname_hashtab_size = DEF_DEVNAME_HASHTAB_SIZE; -module_param(devname_hashtab_size, uint, 0400); -MODULE_PARM_DESC(devname_hashtab_size, - "Size of hash table for named devices (must be power of 2)"); - -struct list_head *rtdm_named_devices; /* hash table */ -static int name_hashkey_mask; +struct list_head rtdm_named_devices; /* hash table */ struct rb_root rtdm_protocol_devices; int rtdm_apc; @@ -75,18 +71,6 @@ int rtdm_select_bind_no_support(struct rtdm_dev_context *context, return -EBADF; } -static inline int get_name_hash(const char *str, int limit, int hashkey_mask) -{ - int hash = 0; - - while (*str != 0) { - hash += *str++; - if (--limit == 0) - break; - } - return hash & hashkey_mask; -} - static inline unsigned long long get_proto_id(int pf, int type) { unsigned long long llpf = (unsigned)pf; @@ -100,30 +84,28 @@ static inline void rtdm_reference_device(struct rtdm_device *device) struct rtdm_device *get_named_device(const char *name) { - struct list_head *entry; struct rtdm_device *device; - int hashkey; + xnhandle_t handle; + int err; spl_t s; - hashkey = get_name_hash(name, RTDM_MAX_DEVNAME_LEN, name_hashkey_mask); + err = xnregistry_bind(name, XN_NONBLOCK, XN_RELATIVE, &handle); + if (err == -EWOULDBLOCK) + return NULL; xnlock_get_irqsave(&rt_dev_lock, s); - list_for_each(entry, &rtdm_named_devices[hashkey]) { - device = list_entry(entry, struct rtdm_device, reserved.entry); - - if (strcmp(name, device->device_name) == 0) { + device = xnregistry_lookup(handle, NULL); + if (device) { + if (device->reserved.magic != RTDM_DEVICE_MAGIC) + device = NULL; + else rtdm_reference_device(device); - - xnlock_put_irqrestore(&rt_dev_lock, s); - - return device; - } } xnlock_put_irqrestore(&rt_dev_lock, s); - return NULL; + return device; } struct rtdm_device *get_protocol_device(int protocol_family, int socket_type) @@ -185,10 +167,7 @@ struct rtdm_device *get_protocol_device(int protocol_family, int socket_type) int rtdm_dev_register(struct rtdm_device *device) { unsigned long long id; - int hashkey; spl_t s; - struct list_head *entry; - struct rtdm_device *existing_dev; int ret; /* Catch unsuccessful initialisation */ @@ -284,29 +263,23 @@ int rtdm_dev_register(struct rtdm_device *device) trace_cobalt_device_register(device); - if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE) { - hashkey = - get_name_hash(device->device_name, RTDM_MAX_DEVNAME_LEN, - name_hashkey_mask); - - list_for_each(entry, &rtdm_named_devices[hashkey]) { - existing_dev = - list_entry(entry, struct rtdm_device, - reserved.entry); - if (strcmp(device->device_name, - existing_dev->device_name) == 0) { - ret = -EEXIST; - goto err; - } - } + device->reserved.magic = RTDM_DEVICE_MAGIC; + if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == + RTDM_NAMED_DEVICE) { ret = rtdm_proc_register_device(device); if (ret) goto err; + ret = xnregistry_enter(device->device_name, device, + &device->reserved.handle, NULL); + if (ret) { + rtdm_proc_unregister_device(device); + goto err; + } + xnlock_get_irqsave(&rt_dev_lock, s); - list_add_tail(&device->reserved.entry, - &rtdm_named_devices[hashkey]); + list_add_tail(&device->reserved.entry, &rtdm_named_devices); xnlock_put_irqrestore(&rt_dev_lock, s); up(&nrt_dev_lock); @@ -314,15 +287,6 @@ int rtdm_dev_register(struct rtdm_device *device) id = get_proto_id(device->protocol_family, device->socket_type); - trace_mark(xn_rtdm, protocol_register, "device %p " - "protocol_family %d socket_type %d flags %d " - "class %d sub_class %d profile_version %d " - "driver_version %d", device, - device->protocol_family, device->socket_type, - device->device_flags, device->device_class, - device->device_sub_class, device->profile_version, - device->driver_version); - xnlock_get_irqsave(&rt_dev_lock, s); ret = xnid_enter(&rtdm_protocol_devices, &device->reserved.id, id); @@ -377,9 +341,10 @@ EXPORT_SYMBOL_GPL(rtdm_dev_register); */ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) { - spl_t s; struct rtdm_device *reg_dev; unsigned long warned = 0; + xnhandle_t handle = 0; + spl_t s; if (!rtdm_initialised) return -ENOSYS; @@ -414,15 +379,20 @@ int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay) xnlock_get_irqsave(&rt_dev_lock, s); } - if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE) + if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == + RTDM_NAMED_DEVICE) { + handle = reg_dev->reserved.handle; list_del(®_dev->reserved.entry); - else + } else xnid_remove(&rtdm_protocol_devices, ®_dev->reserved.id); xnlock_put_irqrestore(&rt_dev_lock, s); rtdm_proc_unregister_device(device); + if (handle) + xnregistry_remove(handle); + up(&nrt_dev_lock); if (reg_dev->reserved.exclusive_context) @@ -436,8 +406,6 @@ EXPORT_SYMBOL_GPL(rtdm_dev_unregister); int __init rtdm_dev_init(void) { - int err, i; - sema_init(&nrt_dev_lock, 1); rtdm_apc = xnapc_alloc("deferred RTDM close", rtdm_apc_handler, @@ -445,31 +413,10 @@ int __init rtdm_dev_init(void) if (rtdm_apc < 0) return rtdm_apc; - name_hashkey_mask = devname_hashtab_size - 1; - if (((devname_hashtab_size & name_hashkey_mask) != 0)) { - err = -EINVAL; - goto err_out1; - } - - rtdm_named_devices = (struct list_head *) - kmalloc(devname_hashtab_size * sizeof(struct list_head), - GFP_KERNEL); - if (!rtdm_named_devices) { - err = -ENOMEM; - goto err_out1; - } - - for (i = 0; i < devname_hashtab_size; i++) - INIT_LIST_HEAD(&rtdm_named_devices[i]); - + INIT_LIST_HEAD(&rtdm_named_devices); xntree_init(&rtdm_protocol_devices); return 0; - -err_out1: - xnapc_free(rtdm_apc); - - return err; } void rtdm_dev_cleanup(void) @@ -479,7 +426,6 @@ void rtdm_dev_cleanup(void) * to deregister as long as there are references. */ xnapc_free(rtdm_apc); - kfree(rtdm_named_devices); } /*@}*/ diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h index 0bebe8b..3288068 100644 --- a/kernel/cobalt/rtdm/internal.h +++ b/kernel/cobalt/rtdm/internal.h @@ -50,7 +50,7 @@ extern struct rtdm_fildes fildes_table[]; extern int open_fildes; extern struct semaphore nrt_dev_lock; extern unsigned int devname_hashtab_size; -extern struct list_head *rtdm_named_devices; +extern struct list_head rtdm_named_devices; extern struct rb_root rtdm_protocol_devices; extern struct xnpersonality rtdm_personality; diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c index 0d15385..1d6cbb0 100644 --- a/kernel/cobalt/rtdm/proc.c +++ b/kernel/cobalt/rtdm/proc.c @@ -23,10 +23,7 @@ struct xnvfile_directory rtdm_vfroot; /* /proc/xenomai/rtdm */ struct vfile_device_data { - int h; - int hmax; - struct list_head *devmap; - struct list_head *curr; + struct rtdm_device *curr; }; static int get_nrt_lock(struct xnvfile *vfile) @@ -44,95 +41,59 @@ static struct xnvfile_lock_ops lockops = { .put = put_nrt_lock, }; -static struct list_head *next_devlist(struct vfile_device_data *priv) -{ - struct list_head *head; - - while (priv->h < priv->hmax) { - head = priv->devmap + priv->h; - if (!list_empty(head)) - return head; - priv->h++; - } - - return NULL; -} - -static void *next_dev(struct xnvfile_regular_iterator *it) +static void *named_next(struct xnvfile_regular_iterator *it) { struct vfile_device_data *priv = xnvfile_iterator_priv(it); + struct rtdm_device *device = priv->curr; struct list_head *next; - next = priv->curr->next; -seek: - if (next == priv->devmap + priv->h) { - /* Done with the current hash slot, let's progress. */ - if (priv->h >= priv->hmax) { - next = NULL; /* all done. */ - goto out; - } - - priv->h++; - next = next_devlist(priv); - if (next) { - next = next->next; /* skip head. */ - goto seek; - } + next = device->reserved.entry.next; + if (next == &rtdm_named_devices) { + priv->curr = NULL; /* all done. */ + goto out; } -out: - priv->curr = next; - return next; + priv->curr = list_entry(next, struct rtdm_device, reserved.entry); + + out: + return priv->curr; } static void *named_begin(struct xnvfile_regular_iterator *it) { struct vfile_device_data *priv = xnvfile_iterator_priv(it); - struct list_head *devlist; + struct rtdm_device *device; loff_t pos = 0; - priv->devmap = rtdm_named_devices; - priv->hmax = devname_hashtab_size; - priv->h = 0; - - devlist = next_devlist(priv); - if (devlist == NULL) - return NULL; /* All devlists empty. */ + list_for_each_entry(device, &rtdm_named_devices, reserved.entry) + if (pos++ >= it->pos) + break; - priv->curr = devlist->next; /* Skip head. */ + if (&device->reserved.entry == &rtdm_named_devices) + return NULL; /* End of list. */ - /* - * priv->curr now points to the first device; advance to the requested - * position from there. - */ - while (priv->curr && pos++ < it->pos) - priv->curr = next_dev(it); + priv->curr = device; /* Skip head. */ if (pos == 1) /* Output the header once, only if some device follows. */ - xnvfile_puts(it, "Hash\tName\t\t\t\tDriver\t\t/proc\n"); + xnvfile_puts(it, "Name\t\t\t\tDriver\t\t/proc\n"); return priv->curr; } static int named_show(struct xnvfile_regular_iterator *it, void *data) { - struct vfile_device_data *priv = xnvfile_iterator_priv(it); - struct list_head *curr = data; - struct rtdm_device *device; + struct rtdm_device *device = data; - device = list_entry(curr, struct rtdm_device, reserved.entry); - xnvfile_printf(it, "%02X\t%-31s\t%-15s\t%s\n", - priv->h, device->device_name, - device->driver_name, - device->proc_name); + xnvfile_printf(it, "%-31s\t%-15s\t%s\n", device->device_name, + device->driver_name, device->proc_name); return 0; } static struct xnvfile_regular_ops named_vfile_ops = { .begin = named_begin, - .next = next_dev, + .next = named_next, .show = named_show, }; @@ -306,7 +267,6 @@ static struct xnvfile_regular allfd_vfile = { static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data) { struct rtdm_device *device; - int i; if (down_interruptible(&nrt_dev_lock)) return -ERESTARTSYS; @@ -315,11 +275,9 @@ 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. */ - for (i = 0; i < devname_hashtab_size; i++) - list_for_each_entry(device, &rtdm_named_devices[i], - reserved.entry) - if (device == xnvfile_priv(it->vfile)) - goto found; + list_for_each_entry(device, &rtdm_named_devices, reserved.entry) + if (device == xnvfile_priv(it->vfile)) + goto found; xntree_for_each_entry(device, &rtdm_protocol_devices, reserved.id) if (device == xnvfile_priv(it->vfile)) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git