Module: xenomai-3
Branch: next
Commit: d5303299657a16d94f971f73f1191202dd2eeb7e
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d5303299657a16d94f971f73f1191202dd2eeb7e

Author: Philippe Gerum <r...@xenomai.org>
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(&register_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
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to