Module: xenomai-3 Branch: wip/dovetail Commit: d5303299657a16d94f971f73f1191202dd2eeb7e URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d5303299657a16d94f971f73f1191202dd2eeb7e
Author: Philippe Gerum <[email protected]> Date: Sat Apr 23 15:05:43 2016 +0200 cobalt/rtdm: allow setting the kernel device class of a driver It may be convenient to set the Linux device class for a particular RTDM driver, either to provide a specific set of sysfs attributes for the attached devices, or using a different hierarchy for the device nodes (instead of /dev/rtdm). The new rtdm_drv_set_sysclass() call allows this, provided the non-default class is set before the first device referring to the driver is registered by a call rtdm_dev_register(). --- include/cobalt/kernel/rtdm/driver.h | 5 +++ kernel/cobalt/rtdm/device.c | 57 ++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 01601c3..7d62f13 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -225,6 +225,7 @@ struct rtdm_profile_info { /** Reserved */ unsigned int magic; struct module *owner; + struct class *kdev_class; }; struct rtdm_driver; @@ -314,8 +315,11 @@ struct rtdm_driver { .version = (__version), \ .magic = ~RTDM_CLASS_MAGIC, \ .owner = THIS_MODULE, \ + .kdev_class = NULL, \ } +int rtdm_drv_set_sysclass(struct rtdm_driver *drv, struct class *cls); + /** * @brief RTDM device * @@ -368,6 +372,7 @@ struct rtdm_device { }; dev_t rdev; struct device *kdev; + struct class *kdev_class; atomic_t refcount; struct rtdm_fd_ops ops; wait_queue_head_t putwq; diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c index 660f61c..c760f31 100644 --- a/kernel/cobalt/rtdm/device.c +++ b/kernel/cobalt/rtdm/device.c @@ -359,6 +359,7 @@ static void unregister_driver(struct rtdm_driver *drv) */ int rtdm_dev_register(struct rtdm_device *dev) { + struct class *kdev_class = rtdm_class; struct device *kdev = NULL; struct rtdm_driver *drv; int ret, major, minor; @@ -390,6 +391,9 @@ int rtdm_dev_register(struct rtdm_device *dev) dev->ops.close = __rtdm_dev_close; /* Interpose on driver's handler. */ atomic_set(&dev->refcount, 0); + if (drv->profile_info.kdev_class) + kdev_class = drv->profile_info.kdev_class; + if (drv->device_flags & RTDM_NAMED_DEVICE) { if (drv->device_flags & RTDM_FIXED_MINOR) { minor = dev->minor; @@ -419,7 +423,7 @@ int rtdm_dev_register(struct rtdm_device *dev) goto fail; rdev = MKDEV(major, minor); - kdev = device_create(rtdm_class, NULL, rdev, + kdev = device_create(kdev_class, NULL, rdev, dev, dev->label, minor); if (IS_ERR(kdev)) { xnregistry_remove(dev->named.handle); @@ -443,7 +447,7 @@ int rtdm_dev_register(struct rtdm_device *dev) } rdev = MKDEV(0, minor); - kdev = device_create(rtdm_class, NULL, rdev, + kdev = device_create(kdev_class, NULL, rdev, dev, dev->name); if (IS_ERR(kdev)) { ret = PTR_ERR(kdev); @@ -460,6 +464,7 @@ int rtdm_dev_register(struct rtdm_device *dev) dev->rdev = rdev; dev->kdev = kdev; dev->magic = RTDM_DEVICE_MAGIC; + dev->kdev_class = kdev_class; mutex_unlock(®ister_lock); @@ -468,7 +473,7 @@ int rtdm_dev_register(struct rtdm_device *dev) return 0; fail: if (kdev) - device_destroy(rtdm_class, rdev); + device_destroy(kdev_class, rdev); if (atomic_dec_and_test(&drv->refcount)) unregister_driver(drv); @@ -517,7 +522,7 @@ void rtdm_dev_unregister(struct rtdm_device *dev) __clear_bit(dev->minor, protocol_devices_minor_map); } - device_destroy(rtdm_class, dev->rdev); + device_destroy(dev->kdev_class, dev->rdev); unregister_driver(drv); @@ -527,6 +532,50 @@ void rtdm_dev_unregister(struct rtdm_device *dev) } EXPORT_SYMBOL_GPL(rtdm_dev_unregister); +/** + * @brief Set the kernel device class of a RTDM driver. + * + * Set the kernel device class assigned to the RTDM driver. By + * default, RTDM drivers belong to Linux's "rtdm" device class, + * creating a device node hierarchy rooted at /dev/rtdm, and sysfs + * nodes under /sys/class/rtdm. + * + * This call assigns a user-defined kernel device class to the RTDM + * driver, so that its devices are created into a different system + * hierarchy. + * + * rtdm_drv_set_sysclass() is meaningful only before the first device + * which is attached to @a drv is registered by a call to + * rtdm_dev_register(). + * + * @param[in] drv Address of the RTDM driver descriptor. + * + * @param[in] cls Pointer to the kernel device class. + * + * @return 0 on success, otherwise: + * + * - -EBUSY is returned if the kernel device class has already been + * set for @a drv, or some device(s) attached to @a drv are currently + * registered. + * + * @coretags{task-unrestricted} + * + * @attention The kernel device class set by this call is not related to + * the RTDM class identification as defined by the @ref rtdm_profiles + * "RTDM profiles" in any way. This is strictly related to the Linux + * kernel device hierarchy. + */ +int rtdm_drv_set_sysclass(struct rtdm_driver *drv, struct class *cls) +{ + if (drv->profile_info.kdev_class || atomic_read(&drv->refcount)) + return -EBUSY; + + drv->profile_info.kdev_class = cls; + + return 0; +} +EXPORT_SYMBOL_GPL(rtdm_drv_set_sysclass); + /** @} */ int __init rtdm_init(void) _______________________________________________ Xenomai-git mailing list [email protected] https://xenomai.org/mailman/listinfo/xenomai-git
