Module: xenomai-3 Branch: next Commit: b41a23aebb37a50ef6c734f2813277d29007c67e URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b41a23aebb37a50ef6c734f2813277d29007c67e
Author: Philippe Gerum <r...@xenomai.org> Date: Sat Apr 18 11:12:51 2015 +0200 drivers/udd: fix mapper device supporting multiple regions --- include/cobalt/kernel/rtdm/udd.h | 5 +++- kernel/drivers/udd/udd.c | 61 +++++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/include/cobalt/kernel/rtdm/udd.h b/include/cobalt/kernel/rtdm/udd.h index 8190d98..028e602 100644 --- a/include/cobalt/kernel/rtdm/udd.h +++ b/include/cobalt/kernel/rtdm/udd.h @@ -287,7 +287,10 @@ struct udd_device { struct rtdm_driver driver; struct rtdm_device device; struct rtdm_driver mapper_driver; - struct rtdm_device mapper; + struct udd_mapper { + struct udd_device *udd; + struct rtdm_device dev; + } mapdev[UDD_NR_MAPS]; char *mapper_name; int nr_maps; } __reserved; diff --git a/kernel/drivers/udd/udd.c b/kernel/drivers/udd/udd.c index e5a12a1..4a47e59 100644 --- a/kernel/drivers/udd/udd.c +++ b/kernel/drivers/udd/udd.c @@ -208,7 +208,7 @@ static int mapper_open(struct rtdm_fd *fd, int oflags) if (minor < 0 || minor >= UDD_NR_MAPS) return -EIO; - udd = container_of(rtdm_fd_device(fd), struct udd_device, __reserved.mapper); + udd = udd_get_device(fd); if (udd->mem_regions[minor].type == UDD_MEM_NONE) return -EIO; @@ -227,7 +227,7 @@ static int mapper_mmap(struct rtdm_fd *fd, struct vm_area_struct *vma) size_t len; int ret; - udd = container_of(rtdm_fd_device(fd), struct udd_device, __reserved.mapper); + udd = udd_get_device(fd); if (udd->ops.mmap) /* Offload to client driver if handler is present. */ return udd->ops.mmap(fd, vma); @@ -260,10 +260,6 @@ static int mapper_mmap(struct rtdm_fd *fd, struct vm_area_struct *vma) static inline int check_memregion(struct udd_device *udd, struct udd_memregion *rn) { - /* We allow sparse region arrays. */ - if (rn->type == UDD_MEM_NONE) - return 0; - if (rn->name == NULL) return -EINVAL; @@ -273,16 +269,16 @@ static inline int check_memregion(struct udd_device *udd, if (rn->len == 0) return -EINVAL; - udd->__reserved.nr_maps++; - return 0; } static inline int register_mapper(struct udd_device *udd) { struct udd_reserved *ur = &udd->__reserved; - struct rtdm_device *dev = &ur->mapper; struct rtdm_driver *drv = &ur->mapper_driver; + struct udd_mapper *mapper; + struct udd_memregion *rn; + int n, ret; ur->mapper_name = kasformat("%s,mapper%%d", udd->device_name); if (ur->mapper_name == NULL) @@ -291,17 +287,32 @@ static inline int register_mapper(struct udd_device *udd) drv->profile_info = (struct rtdm_profile_info) RTDM_PROFILE_INFO("mapper", RTDM_CLASS_MEMORY, RTDM_SUBCLASS_GENERIC, 0); - drv->device_flags = RTDM_NAMED_DEVICE; + drv->device_flags = RTDM_NAMED_DEVICE|RTDM_FIXED_MINOR; drv->device_count = UDD_NR_MAPS; drv->ops = (struct rtdm_fd_ops){ .open = mapper_open, .close = mapper_close, .mmap = mapper_mmap, }; - dev->driver = drv; - dev->label = ur->mapper_name; - return rtdm_dev_register(dev); + for (n = 0, mapper = ur->mapdev; n < UDD_NR_MAPS; n++, mapper++) { + rn = udd->mem_regions + n; + if (rn->type == UDD_MEM_NONE) + continue; + mapper->dev.driver = drv; + mapper->dev.label = ur->mapper_name; + mapper->dev.minor = n; + ret = rtdm_dev_register(&mapper->dev); + if (ret) + goto undo; + } + + return 0; +undo: + while (--n >= 0) + rtdm_dev_unregister(&ur->mapdev[n].dev); + + return ret; } /** @@ -337,6 +348,7 @@ int udd_register_device(struct udd_device *udd) struct rtdm_device *dev = &udd->__reserved.device; struct udd_reserved *ur = &udd->__reserved; struct rtdm_driver *drv = &ur->driver; + struct udd_memregion *rn; int ret, n; if (!realtime_core_enabled()) @@ -349,9 +361,14 @@ int udd_register_device(struct udd_device *udd) return -EINVAL; for (n = 0, ur->nr_maps = 0; n < UDD_NR_MAPS; n++) { - ret = check_memregion(udd, udd->mem_regions + n); + /* We allow sparse region arrays. */ + rn = udd->mem_regions + n; + if (rn->type == UDD_MEM_NONE) + continue; + ret = check_memregion(udd, rn); if (ret) return ret; + udd->__reserved.nr_maps++; } drv->profile_info = (struct rtdm_profile_info) @@ -398,7 +415,11 @@ int udd_register_device(struct udd_device *udd) return 0; fail_irq_request: - rtdm_dev_unregister(&ur->mapper); + for (n = 0; n < UDD_NR_MAPS; n++) { + rn = udd->mem_regions + n; + if (rn->type != UDD_MEM_NONE) + rtdm_dev_unregister(&ur->mapdev[n].dev); + } fail_mapper: rtdm_dev_unregister(dev); if (ur->mapper_name) @@ -425,6 +446,8 @@ EXPORT_SYMBOL_GPL(udd_register_device); int udd_unregister_device(struct udd_device *udd) { struct udd_reserved *ur = &udd->__reserved; + struct udd_memregion *rn; + int n; if (!realtime_core_enabled()) return -ENXIO; @@ -434,7 +457,11 @@ int udd_unregister_device(struct udd_device *udd) if (udd->irq != UDD_IRQ_NONE && udd->irq != UDD_IRQ_CUSTOM) rtdm_irq_free(&ur->irqh); - rtdm_dev_unregister(&ur->mapper); + for (n = 0; n < UDD_NR_MAPS; n++) { + rn = udd->mem_regions + n; + if (rn->type != UDD_MEM_NONE) + rtdm_dev_unregister(&ur->mapdev[n].dev); + } if (ur->mapper_name) kfree(ur->mapper_name); @@ -587,7 +614,7 @@ struct udd_device *udd_get_device(struct rtdm_fd *fd) struct rtdm_device *dev = rtdm_fd_device(fd); if (dev->driver->profile_info.class_id == RTDM_CLASS_MEMORY) - return container_of(dev, struct udd_device, __reserved.mapper); + return container_of(dev, struct udd_mapper, dev)->udd; 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