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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Sep 18 17:09:31 2014 +0200

cobalt/rtdm: export device information through sysfs

/sys/class/<RTDM-device-class> enumerates the registered RTDM devices
which belong to this class. Device class and subclass ids, flags and
reference count are readable as sysfs attributes.

---

 include/cobalt/kernel/rtdm/driver.h |    4 +-
 kernel/cobalt/rtdm/device.c         |  125 ++++++++++++++++++++++++++++-------
 2 files changed, 103 insertions(+), 26 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h 
b/include/cobalt/kernel/rtdm/driver.h
index 0b4a70c..2896e3d 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -255,10 +255,10 @@ struct rtdm_device_class {
                union {
                        struct {
                                struct cdev cdev;
-                               struct class *kclass;
                                int major;
                        } named;
                };
+               struct class *kclass;
                atomic_t refcount;
        };
 };
@@ -344,6 +344,8 @@ struct rtdm_device {
                                struct xnid id;
                        } proto;
                };
+               dev_t rdev;
+               struct device *kdev;
                atomic_t refcount;
                struct rtdm_dev_context *exclusive_context;
                struct rtdm_fd_ops ops;
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 9825b93..131c9f1 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -121,6 +121,67 @@ static char *rtdm_devnode(struct device *dev, umode_t 
*mode)
        return kasprintf(GFP_KERNEL, "rtdm/%s", dev_name(dev));
 }
 
+static ssize_t class_id_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct rtdm_device *device = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d/%d\n",
+                      device->class->profile_info.class_id,
+                      device->class->profile_info.subclass_id);
+}
+static DEVICE_ATTR_RO(class_id);
+
+static ssize_t refcount_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct rtdm_device *device = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", atomic_read(&device->refcount));
+}
+static DEVICE_ATTR_RO(refcount);
+
+#define cat_count(__buf, __str)                        \
+       ({                                      \
+               int __ret = sizeof(__str) - 1;  \
+               strcat(__buf, __str);           \
+               __ret;                          \
+       })
+
+static ssize_t flags_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       struct rtdm_device *device = dev_get_drvdata(dev);
+       struct rtdm_device_class *class = device->class;
+       int ret;
+
+       ret = sprintf(buf, "%#x (", class->device_flags);
+       if (class->device_flags & RTDM_NAMED_DEVICE)
+               ret += cat_count(buf, "named");
+       else
+               ret += cat_count(buf, "protocol");
+
+       if (class->device_flags & RTDM_EXCLUSIVE)
+               ret += cat_count(buf, ", exclusive");
+               
+       if (class->device_flags & RTDM_SECURE_DEVICE)
+               ret += cat_count(buf, ", secure");
+               
+       ret += cat_count(buf, ")\n");
+
+       return ret;
+
+}
+static DEVICE_ATTR_RO(flags);
+
+static struct attribute *rtdm_attrs[] = {
+       &dev_attr_class_id.attr,
+       &dev_attr_refcount.attr,
+       &dev_attr_flags.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(rtdm);
+
 static int register_device_class(struct rtdm_device_class *class)
 {
        struct class *kclass;
@@ -146,15 +207,26 @@ static int register_device_class(struct rtdm_device_class 
*class)
        if (class->device_count <= 0)
                return -EINVAL;
 
+       kclass = class_create(THIS_MODULE, class->profile_info.name);
+       if (IS_ERR(kclass)) {
+               printk(XENO_WARN "cannot create device class %s\n",
+                      class->profile_info.name);
+               return PTR_ERR(kclass);
+       }
+       kclass->dev_groups = rtdm_groups;
+       class->kclass = kclass;
+
        if ((class->device_flags & RTDM_NAMED_DEVICE) == 0)
                goto done;
 
+       kclass->devnode = rtdm_devnode;
+
        ret = alloc_chrdev_region(&rdev, 0, class->device_count,
                                  class->profile_info.name);
        if (ret) {
                printk(XENO_WARN "cannot allocate chrdev region %s[0..%d]\n",
                       class->profile_info.name, class->device_count - 1);
-               return ret;
+               goto fail_chrdev;
        }
 
        cdev_init(&class->named.cdev, &rtdm_dumb_fops);
@@ -162,16 +234,6 @@ static int register_device_class(struct rtdm_device_class 
*class)
        if (ret)
                goto fail_cdev;
 
-       kclass = class_create(THIS_MODULE, class->profile_info.name);
-       if (IS_ERR(kclass)) {
-               printk(XENO_WARN "cannot create device class %s\n",
-                      class->profile_info.name);
-               ret = PTR_ERR(kclass);
-               goto fail_class;
-       }
-       kclass->devnode = rtdm_devnode;
-
-       class->named.kclass = kclass;
        class->named.major = MAJOR(rdev);
        atomic_set(&class->refcount, 1);
 done:
@@ -179,10 +241,10 @@ done:
 
        return 0;
 
-fail_class:
-       cdev_del(&class->named.cdev);
 fail_cdev:
        unregister_chrdev_region(rdev, class->device_count);
+fail_chrdev:
+       class_destroy(kclass);
 
        return ret;
 }
@@ -195,11 +257,12 @@ static void unregister_device_class(struct 
rtdm_device_class *class)
                return;
 
        if (class->device_flags & RTDM_NAMED_DEVICE) {
-               class_destroy(class->named.kclass);
                cdev_del(&class->named.cdev);
                unregister_chrdev_region(MKDEV(class->named.major, 0),
                                         class->device_count);
        }
+
+       class_destroy(class->kclass);
 }
 
 /**
@@ -233,8 +296,9 @@ int rtdm_dev_register(struct rtdm_device *device)
 {
        struct rtdm_device_class *class;
        int ret, pos, major, minor;
-       struct device *kdev;
+       struct device *kdev = NULL;
        xnkey_t id;
+       dev_t rdev;
        spl_t s;
 
        if (!realtime_core_enabled())
@@ -288,8 +352,8 @@ int rtdm_dev_register(struct rtdm_device *device)
                        goto fail;
                }
 
-               kdev = device_create(class->named.kclass, NULL,
-                                    MKDEV(major, minor),
+               rdev = MKDEV(major, minor);
+               kdev = device_create(class->kclass, NULL, rdev,
                                     device, device->label, minor);
                if (IS_ERR(kdev)) {
                        ret = PTR_ERR(kdev);
@@ -299,7 +363,7 @@ int rtdm_dev_register(struct rtdm_device *device)
                ret = xnregistry_enter(device->name, device,
                                       &device->named.handle, NULL);
                if (ret)
-                       goto fail_register;
+                       goto fail;
 
                xnlock_get_irqsave(&rt_dev_lock, s);
                list_add_tail(&device->named.entry, &rtdm_named_devices);
@@ -315,6 +379,15 @@ int rtdm_dev_register(struct rtdm_device *device)
                        ret = -ENOMEM;
                        goto fail;
                }
+
+               rdev = MKDEV(0, 0);
+               kdev = device_create(class->kclass, NULL, rdev,
+                                    device, device->name);
+               if (IS_ERR(kdev)) {
+                       ret = PTR_ERR(kdev);
+                       goto fail;
+               }
+
                id = get_proto_id(class->protocol_family, class->socket_type);
                xnlock_get_irqsave(&rt_dev_lock, s);
                ret = xnid_enter(&rtdm_protocol_devices, &device->proto.id, id);
@@ -331,6 +404,9 @@ int rtdm_dev_register(struct rtdm_device *device)
                }
        }
 
+       device->rdev = rdev;
+       device->kdev = kdev;
+
        up(&nrt_dev_lock);
 
        trace_cobalt_device_register(device);
@@ -338,9 +414,10 @@ int rtdm_dev_register(struct rtdm_device *device)
        return 0;
 fail_proc:
        xnregistry_remove(device->named.handle);
-fail_register:
-       device_destroy(class->named.kclass, MKDEV(major, minor));
 fail:
+       if (kdev)
+               device_destroy(class->kclass, rdev);
+
        unregister_device_class(class);
 
        up(&nrt_dev_lock);
@@ -412,12 +489,10 @@ int rtdm_dev_unregister(struct rtdm_device *device, 
unsigned int poll_delay)
 
        rtdm_proc_unregister_device(device);
 
-       if (handle) {
+       if (handle)
                xnregistry_remove(handle);
-               device_destroy(class->named.kclass,
-                              MKDEV(class->named.major,
-                                    device->minor));
-       }
+
+       device_destroy(class->kclass, device->rdev);
 
        unregister_device_class(class);
 


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

Reply via email to