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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Oct  3 19:04:30 2015 +0200

cobalt/rtdm: fix default minor assignation

Devices may come and go, so using the device reference count
maintained in the driver descriptor is not a particularly bright
idea from /me.

Replace this by a bitmap, allowing for proper dynamic minor
registration/deregistration.

---

 include/cobalt/kernel/rtdm/driver.h |    4 ++++
 kernel/cobalt/rtdm/device.c         |   33 +++++++++++++++++++++------------
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h 
b/include/cobalt/kernel/rtdm/driver.h
index 541fb04..b0a37c4 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -93,6 +93,9 @@ enum rtdm_selecttype;
 #define RTDM_SECURE_DEVICE             0x80000000
 /** @} Device Flags */
 
+/** Maximum number of named devices per driver. */
+#define RTDM_MAX_MINOR 256
+
 /** @} rtdm_device_register */
 
 /*!
@@ -279,6 +282,7 @@ struct rtdm_driver {
                };
                atomic_t refcount;
                struct notifier_block nb_statechange;
+               DECLARE_BITMAP(minor_map, RTDM_MAX_MINOR);
        };
 };
 
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 9af2221..4943be4 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -303,6 +303,7 @@ static int register_driver(struct rtdm_driver *drv)
 
        drv->named.major = MAJOR(rdev);
        atomic_set(&drv->refcount, 1);
+       bitmap_zero(drv->minor_map, RTDM_MAX_MINOR);
 
 done:
        drv->nb_statechange.notifier_call = state_change_notifier;
@@ -354,9 +355,9 @@ static void unregister_driver(struct rtdm_driver *drv)
  */
 int rtdm_dev_register(struct rtdm_device *dev)
 {
-       int ret, pos, major, minor;
        struct device *kdev = NULL;
        struct rtdm_driver *drv;
+       int ret, major, minor;
        xnkey_t id;
        dev_t rdev;
 
@@ -369,7 +370,6 @@ int rtdm_dev_register(struct rtdm_device *dev)
 
        dev->name = NULL;
        drv = dev->driver;
-       pos = atomic_read(&drv->refcount);
        ret = register_driver(drv);
        if (ret) {
                mutex_unlock(&register_lock);
@@ -386,16 +386,22 @@ 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->device_flags & RTDM_FIXED_MINOR) {
-               minor = dev->minor;
-               if (minor < 0 || minor >= drv->device_count) {
-                       ret = -EINVAL;
-                       goto fail;
+       if (drv->device_flags & RTDM_NAMED_DEVICE) {
+               if (drv->device_flags & RTDM_FIXED_MINOR) {
+                       minor = dev->minor;
+                       if (minor < 0 || minor >= drv->device_count) {
+                               ret = -ENXIO;
+                               goto fail;
+                       }
+               } else {
+                       minor = find_first_zero_bit(drv->minor_map, 
RTDM_MAX_MINOR);
+                       if (minor >= RTDM_MAX_MINOR) {
+                               ret = -ENXIO;
+                               goto fail;
+                       }
+                       dev->minor = minor;
                }
-       } else
-               dev->minor = minor = pos;
 
-       if (drv->device_flags & RTDM_NAMED_DEVICE) {
                major = drv->named.major;
                dev->name = kasformat(dev->label, minor);
                if (dev->name == NULL) {
@@ -416,7 +422,9 @@ int rtdm_dev_register(struct rtdm_device *dev)
                        ret = PTR_ERR(kdev);
                        goto fail;
                }
+               __set_bit(minor, drv->minor_map);
        } else {
+               dev->minor = -1;
                dev->name = kstrdup(dev->label, GFP_KERNEL);
                if (dev->name == NULL) {
                        ret = -ENOMEM;
@@ -489,9 +497,10 @@ void rtdm_dev_unregister(struct rtdm_device *dev)
 
        mutex_lock(&register_lock);
 
-       if (drv->device_flags & RTDM_NAMED_DEVICE)
+       if (drv->device_flags & RTDM_NAMED_DEVICE) {
                xnregistry_remove(dev->named.handle);
-       else
+               __clear_bit(dev->minor, drv->minor_map);
+       } else
                xnid_remove(&protocol_devices, &dev->proto.id);
 
        device_destroy(rtdm_class, dev->rdev);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to