staging: ozwpan: Replace existing event logging mechanism
authorRupesh Gujare <rgujare@ozmodevices.com>
Thu, 29 Mar 2012 12:11:50 +0000 (13:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Apr 2012 16:40:52 +0000 (09:40 -0700)
This patch replaces existing event logging mechanism from ioctl to debugfs.
This patch replaces previous patch submitted by Chris Kelly. Previous patch can
be found at :-
http://article.gmane.org/gmane.linux.usb.general/60026/

Signed-off-by: Rupesh Gujare <rgujare@ozmodevices.com>
Signed-off-by: Chris Kelly <ckelly@ozmodevices.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/ozwpan/ozappif.h
drivers/staging/ozwpan/ozcdev.c
drivers/staging/ozwpan/ozevent.c
drivers/staging/ozwpan/ozevent.h
drivers/staging/ozwpan/ozeventdef.h
drivers/staging/ozwpan/ozmain.c

index af0273293872d321754f58e883773423d66ff170..1b59b0748c6b4247ef7e5f60dbccf070e32a5417 100644 (file)
 #define OZ_IOCTL_MAGIC 0xf4
 
 struct oz_mac_addr {
-       unsigned char a[6];
+       __u8 a[6];
 };
 
 #define OZ_MAX_PDS     8
 
 struct oz_pd_list {
-       int count;
+       __u32 count;
        struct oz_mac_addr addr[OZ_MAX_PDS];
 };
 
@@ -27,18 +27,10 @@ struct oz_binding_info {
        char name[OZ_MAX_BINDING_LEN];
 };
 
-struct oz_test {
-       int action;
-};
-
 #define OZ_IOCTL_GET_PD_LIST   _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list)
 #define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr)
 #define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr)
-#define OZ_IOCTL_CLEAR_EVENTS  _IO(OZ_IOCTL_MAGIC, 3)
-#define OZ_IOCTL_GET_EVENTS    _IOR(OZ_IOCTL_MAGIC, 4, struct oz_evtlist)
 #define OZ_IOCTL_ADD_BINDING   _IOW(OZ_IOCTL_MAGIC, 5, struct oz_binding_info)
-#define OZ_IOCTL_TEST          _IOWR(OZ_IOCTL_MAGIC, 6, struct oz_test)
-#define OZ_IOCTL_SET_EVENT_MASK        _IOW(OZ_IOCTL_MAGIC, 7, unsigned long)
 #define OZ_IOCTL_REMOVE_BINDING        _IOW(OZ_IOCTL_MAGIC, 8, struct oz_binding_info)
 #define OZ_IOCTL_MAX           9
 
index 1c380d6879639a90b0d5d3b251538342888eebda..27325f74ecdc3dd4faf0110a36d993ed09f98365 100644 (file)
@@ -39,9 +39,6 @@ struct oz_serial_ctx {
        int rd_in;
        int rd_out;
 };
-/*------------------------------------------------------------------------------
- */
-int g_taction;
 /*------------------------------------------------------------------------------
  */
 static struct oz_cdev g_cdev;
@@ -276,20 +273,6 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                return -EFAULT;
                }
                break;
-#ifdef WANT_EVENT_TRACE
-       case OZ_IOCTL_CLEAR_EVENTS:
-               oz_events_clear();
-               break;
-       case OZ_IOCTL_GET_EVENTS:
-               rc = oz_events_copy((void __user *)arg);
-               break;
-       case OZ_IOCTL_SET_EVENT_MASK:
-               if (copy_from_user(&g_evt_mask, (void __user *)arg,
-                       sizeof(unsigned long))) {
-                       return -EFAULT;
-               }
-               break;
-#endif /* WANT_EVENT_TRACE */
        case OZ_IOCTL_ADD_BINDING:
        case OZ_IOCTL_REMOVE_BINDING: {
                        struct oz_binding_info b;
index 73703d3e96bd9b0ec5e5a198a18cfc29030043f1..7f66b4f19b0102420d74f18934b3b940dcb63a2d 100644 (file)
@@ -5,29 +5,46 @@
  */
 #include "ozconfig.h"
 #ifdef WANT_EVENT_TRACE
+#include <linux/module.h>
+#include <linux/debugfs.h>
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 #include "oztrace.h"
 #include "ozevent.h"
+#include "ozappif.h"
 /*------------------------------------------------------------------------------
+ * Although the event mask is logically part of the oz_evtdev structure, it is
+ * needed outside of this file so define it seperately to avoid the need to
+ * export definition of struct oz_evtdev.
  */
-unsigned long g_evt_mask = 0xffffffff;
+u32 g_evt_mask;
 /*------------------------------------------------------------------------------
  */
 #define OZ_MAX_EVTS    2048    /* Must be power of 2 */
-DEFINE_SPINLOCK(g_eventlock);
-static int g_evt_in;
-static int g_evt_out;
-static int g_missed_events;
-static struct oz_event g_events[OZ_MAX_EVTS];
+struct oz_evtdev {
+       struct dentry *root_dir;
+       int evt_in;
+       int evt_out;
+       int missed_events;
+       int present;
+       atomic_t users;
+       spinlock_t lock;
+       struct oz_event evts[OZ_MAX_EVTS];
+};
+
+static struct oz_evtdev g_evtdev;
+
 /*------------------------------------------------------------------------------
  * Context: process
  */
 void oz_event_init(void)
 {
+       /* Because g_evtdev is static external all fields initally zero so no
+        * need to reinitialised those.
+        */
        oz_trace("Event tracing initialized\n");
-       g_evt_in = g_evt_out = 0;
-       g_missed_events = 0;
+       spin_lock_init(&g_evtdev.lock);
+       atomic_set(&g_evtdev.users, 0);
 }
 /*------------------------------------------------------------------------------
  * Context: process
@@ -43,74 +60,136 @@ void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
 {
        unsigned long irqstate;
        int ix;
-       spin_lock_irqsave(&g_eventlock, irqstate);
-       ix = (g_evt_in + 1) & (OZ_MAX_EVTS - 1);
-       if (ix != g_evt_out) {
-               struct oz_event *e = &g_events[g_evt_in];
+       spin_lock_irqsave(&g_evtdev.lock, irqstate);
+       ix = (g_evtdev.evt_in + 1) & (OZ_MAX_EVTS - 1);
+       if (ix != g_evtdev.evt_out) {
+               struct oz_event *e = &g_evtdev.evts[g_evtdev.evt_in];
                e->jiffies = jiffies;
                e->evt = evt;
                e->ctx1 = ctx1;
                e->ctx2 = ctx2;
-               e->ctx3 = ctx3;
+               e->ctx3 = (__u32)(unsigned long)ctx3;
                e->ctx4 = ctx4;
-               g_evt_in = ix;
+               g_evtdev.evt_in = ix;
        } else {
-               g_missed_events++;
+               g_evtdev.missed_events++;
        }
-       spin_unlock_irqrestore(&g_eventlock, irqstate);
+       spin_unlock_irqrestore(&g_evtdev.lock, irqstate);
 }
 /*------------------------------------------------------------------------------
  * Context: process
  */
-int oz_events_copy(struct oz_evtlist __user *lst)
+static void oz_events_clear(struct oz_evtdev *dev)
 {
-       int first;
-       int ix;
-       struct hdr {
-               int count;
-               int missed;
-       } hdr;
-       ix = g_evt_out;
-       hdr.count = g_evt_in - ix;
-       if (hdr.count < 0)
-               hdr.count += OZ_MAX_EVTS;
-       if (hdr.count > OZ_EVT_LIST_SZ)
-               hdr.count = OZ_EVT_LIST_SZ;
-       hdr.missed = g_missed_events;
-       g_missed_events = 0;
-       if (copy_to_user((void __user *)lst, &hdr, sizeof(hdr)))
-               return -EFAULT;
-       first = OZ_MAX_EVTS - ix;
-       if (first > hdr.count)
-               first = hdr.count;
-       if (first) {
-               int sz = first*sizeof(struct oz_event);
-               void __user *p = (void __user *)lst->evts;
-               if (copy_to_user(p, &g_events[ix], sz))
-                       return -EFAULT;
-               if (hdr.count > first) {
-                       p = (void __user *)&lst->evts[first];
-                       sz = (hdr.count-first)*sizeof(struct oz_event);
-                       if (copy_to_user(p, g_events, sz))
-                               return -EFAULT;
-               }
+       unsigned long irqstate;
+       oz_trace("Clearing events\n");
+       spin_lock_irqsave(&dev->lock, irqstate);
+       dev->evt_in = dev->evt_out = 0;
+       dev->missed_events = 0;
+       spin_unlock_irqrestore(&dev->lock, irqstate);
+}
+#ifdef CONFIG_DEBUG_FS
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_events_open(struct inode *inode, struct file *filp)
+{
+       oz_trace("oz_evt_open()\n");
+       oz_trace("Open flags: 0x%x\n", filp->f_flags);
+       if (atomic_add_return(1, &g_evtdev.users) == 1) {
+               oz_events_clear(&g_evtdev);
+               return nonseekable_open(inode, filp);
+       } else {
+               atomic_dec(&g_evtdev.users);
+               return -EBUSY;
        }
-       ix += hdr.count;
-       if (ix >= OZ_MAX_EVTS)
-               ix -= OZ_MAX_EVTS;
-       g_evt_out = ix;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_events_release(struct inode *inode, struct file *filp)
+{
+       oz_events_clear(&g_evtdev);
+       atomic_dec(&g_evtdev.users);
+       g_evt_mask = 0;
+       oz_trace("oz_evt_release()\n");
        return 0;
 }
 /*------------------------------------------------------------------------------
  * Context: process
  */
-void oz_events_clear(void)
+ssize_t oz_events_read(struct file *filp, char __user *buf, size_t count,
+               loff_t *fpos)
 {
-       unsigned long irqstate;
-       spin_lock_irqsave(&g_eventlock, irqstate);
-       g_evt_in = g_evt_out = 0;
-       g_missed_events = 0;
-       spin_unlock_irqrestore(&g_eventlock, irqstate);
+       struct oz_evtdev *dev = &g_evtdev;
+       int rc = 0;
+       int nb_evts = count / sizeof(struct oz_event);
+       int n;
+       int sz;
+
+       n = dev->evt_in - dev->evt_out;
+       if (n < 0)
+               n += OZ_MAX_EVTS;
+       if (nb_evts > n)
+               nb_evts = n;
+       if (nb_evts == 0)
+               goto out;
+       n = OZ_MAX_EVTS - dev->evt_out;
+       if (n > nb_evts)
+               n = nb_evts;
+       sz = n * sizeof(struct oz_event);
+       if (copy_to_user(buf, &dev->evts[dev->evt_out], sz)) {
+               rc = -EFAULT;
+               goto out;
+       }
+       if (n == nb_evts)
+               goto out2;
+       n = nb_evts - n;
+       if (copy_to_user(buf + sz, dev->evts, n * sizeof(struct oz_event))) {
+               rc = -EFAULT;
+               goto out;
+       }
+out2:
+       dev->evt_out = (dev->evt_out + nb_evts) & (OZ_MAX_EVTS - 1);
+       rc = nb_evts * sizeof(struct oz_event);
+out:
+       return rc;
 }
-#endif /* WANT_EVENT_TRACE */
+/*------------------------------------------------------------------------------
+ */
+const struct file_operations oz_events_fops = {
+       .owner =        THIS_MODULE,
+       .open =         oz_events_open,
+       .release =      oz_events_release,
+       .read =         oz_events_read,
+};
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_debugfs_init(void)
+{
+       struct dentry *parent;
 
+       parent = debugfs_create_dir("ozwpan", NULL);
+       if (parent  == NULL) {
+               oz_trace("Failed to create debugfs directory ozmo\n");
+               return;
+       } else {
+               g_evtdev.root_dir = parent;
+               if (debugfs_create_file("events", S_IRUSR, parent, NULL,
+                                               &oz_events_fops) == NULL)
+                       oz_trace("Failed to create file ozmo/events\n");
+               if (debugfs_create_x32("event_mask", S_IRUSR | S_IWUSR, parent,
+                                                       &g_evt_mask) == NULL)
+                       oz_trace("Failed to create file ozmo/event_mask\n");
+       }
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_debugfs_remove(void)
+{
+       debugfs_remove_recursive(g_evtdev.root_dir);
+}
+#endif /* CONFIG_DEBUG_FS */
+#endif /* WANT_EVENT_TRACE */
index f033d014c6f3e6ed2f1b2b9a890e0c10fb595c7d..32f6f9859c4150207f18efef3c6ef02fbdf1b3be 100644 (file)
@@ -9,23 +9,24 @@
 #include "ozeventdef.h"
 
 #ifdef WANT_EVENT_TRACE
-extern unsigned long g_evt_mask;
+extern u32 g_evt_mask;
 void oz_event_init(void);
 void oz_event_term(void);
 void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4);
+void oz_debugfs_init(void);
+void oz_debugfs_remove(void);
 #define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4) \
        do { \
                if ((1<<(__evt)) & g_evt_mask) \
                        oz_event_log2(__evt, __ctx1, __ctx2, __ctx3, __ctx4); \
        } while (0)
-int oz_events_copy(struct oz_evtlist __user *lst);
-void oz_events_clear(void);
+
 #else
 #define oz_event_init()
 #define oz_event_term()
 #define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4)
-#define oz_events_copy(__lst)
-#define oz_events_clear()
+#define oz_debugfs_init()
+#define oz_debugfs_remove()
 #endif /* WANT_EVENT_TRACE */
 
 #endif /* _OZEVENT_H */
index a880288bab11d73035faf914caaff9ee4f292a04..4b938981671abb27e09bd0757301c3171319c9fe 100644 (file)
 #define OZ_EVT_DEBUG           20
 
 struct oz_event {
-       unsigned long jiffies;
-       unsigned char evt;
-       unsigned char ctx1;
-       unsigned short ctx2;
-       void *ctx3;
-       unsigned ctx4;
-};
-
-#define OZ_EVT_LIST_SZ 64
-struct oz_evtlist {
-       int count;
-       int missed;
-       struct oz_event evts[OZ_EVT_LIST_SZ];
+       __u32 jiffies;
+       __u8 evt;
+       __u8 ctx1;
+       __u16 ctx2;
+       __u32 ctx3;
+       __u32 ctx4;
 };
 
 #endif /* _OZEVENTDEF_H */
index aaf2ccc0bcfbdd3f45dc29bf251f26f53e8a3c4a..7579645d642a0d98c06e4737cd535d1f26111a44 100644 (file)
@@ -33,6 +33,9 @@ static int __init ozwpan_init(void)
        oz_protocol_init(g_net_dev);
        oz_app_enable(OZ_APPID_USB, 1);
        oz_apps_init();
+#ifdef CONFIG_DEBUG_FS
+       oz_debugfs_init();
+#endif
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -44,6 +47,9 @@ static void __exit ozwpan_exit(void)
        oz_apps_term();
        oz_cdev_deregister();
        oz_event_term();
+#ifdef CONFIG_DEBUG_FS
+       oz_debugfs_remove();
+#endif
 }
 /*------------------------------------------------------------------------------
  */
@@ -53,6 +59,6 @@ module_exit(ozwpan_exit);
 
 MODULE_AUTHOR("Chris Kelly");
 MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.8");
+MODULE_VERSION("1.0.9");
 MODULE_LICENSE("GPL");