1 /* -----------------------------------------------------------------------------
2 * Copyright (c) 2011 Ozmo Inc
3 * Released under the GNU General Public License Version 2 (GPLv2).
4 * -----------------------------------------------------------------------------
7 #ifdef WANT_EVENT_TRACE
8 #include <linux/module.h>
9 #include <linux/debugfs.h>
10 #include <linux/jiffies.h>
11 #include <linux/uaccess.h>
15 /*------------------------------------------------------------------------------
16 * Although the event mask is logically part of the oz_evtdev structure, it is
17 * needed outside of this file so define it seperately to avoid the need to
18 * export definition of struct oz_evtdev.
21 /*------------------------------------------------------------------------------
23 #define OZ_MAX_EVTS 2048 /* Must be power of 2 */
25 struct dentry *root_dir;
32 struct oz_event evts[OZ_MAX_EVTS];
35 static struct oz_evtdev g_evtdev;
37 /*------------------------------------------------------------------------------
40 void oz_event_init(void)
42 /* Because g_evtdev is static external all fields initally zero so no
43 * need to reinitialised those.
45 oz_trace("Event tracing initialized\n");
46 spin_lock_init(&g_evtdev.lock);
47 atomic_set(&g_evtdev.users, 0);
49 /*------------------------------------------------------------------------------
52 void oz_event_term(void)
54 oz_trace("Event tracing terminated\n");
56 /*------------------------------------------------------------------------------
59 void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
61 unsigned long irqstate;
63 spin_lock_irqsave(&g_evtdev.lock, irqstate);
64 ix = (g_evtdev.evt_in + 1) & (OZ_MAX_EVTS - 1);
65 if (ix != g_evtdev.evt_out) {
66 struct oz_event *e = &g_evtdev.evts[g_evtdev.evt_in];
71 e->ctx3 = (__u32)(unsigned long)ctx3;
75 g_evtdev.missed_events++;
77 spin_unlock_irqrestore(&g_evtdev.lock, irqstate);
79 /*------------------------------------------------------------------------------
82 static void oz_events_clear(struct oz_evtdev *dev)
84 unsigned long irqstate;
85 oz_trace("Clearing events\n");
86 spin_lock_irqsave(&dev->lock, irqstate);
87 dev->evt_in = dev->evt_out = 0;
88 dev->missed_events = 0;
89 spin_unlock_irqrestore(&dev->lock, irqstate);
91 #ifdef CONFIG_DEBUG_FS
92 /*------------------------------------------------------------------------------
95 int oz_events_open(struct inode *inode, struct file *filp)
97 oz_trace("oz_evt_open()\n");
98 oz_trace("Open flags: 0x%x\n", filp->f_flags);
99 if (atomic_add_return(1, &g_evtdev.users) == 1) {
100 oz_events_clear(&g_evtdev);
101 return nonseekable_open(inode, filp);
103 atomic_dec(&g_evtdev.users);
107 /*------------------------------------------------------------------------------
110 int oz_events_release(struct inode *inode, struct file *filp)
112 oz_events_clear(&g_evtdev);
113 atomic_dec(&g_evtdev.users);
115 oz_trace("oz_evt_release()\n");
118 /*------------------------------------------------------------------------------
121 ssize_t oz_events_read(struct file *filp, char __user *buf, size_t count,
124 struct oz_evtdev *dev = &g_evtdev;
126 int nb_evts = count / sizeof(struct oz_event);
130 n = dev->evt_in - dev->evt_out;
137 n = OZ_MAX_EVTS - dev->evt_out;
140 sz = n * sizeof(struct oz_event);
141 if (copy_to_user(buf, &dev->evts[dev->evt_out], sz)) {
148 if (copy_to_user(buf + sz, dev->evts, n * sizeof(struct oz_event))) {
153 dev->evt_out = (dev->evt_out + nb_evts) & (OZ_MAX_EVTS - 1);
154 rc = nb_evts * sizeof(struct oz_event);
158 /*------------------------------------------------------------------------------
160 const struct file_operations oz_events_fops = {
161 .owner = THIS_MODULE,
162 .open = oz_events_open,
163 .release = oz_events_release,
164 .read = oz_events_read,
166 /*------------------------------------------------------------------------------
169 void oz_debugfs_init(void)
171 struct dentry *parent;
173 parent = debugfs_create_dir("ozwpan", NULL);
174 if (parent == NULL) {
175 oz_trace("Failed to create debugfs directory ozmo\n");
178 g_evtdev.root_dir = parent;
179 if (debugfs_create_file("events", S_IRUSR, parent, NULL,
180 &oz_events_fops) == NULL)
181 oz_trace("Failed to create file ozmo/events\n");
182 if (debugfs_create_x32("event_mask", S_IRUSR | S_IWUSR, parent,
183 &g_evt_mask) == NULL)
184 oz_trace("Failed to create file ozmo/event_mask\n");
187 /*------------------------------------------------------------------------------
190 void oz_debugfs_remove(void)
192 debugfs_remove_recursive(g_evtdev.root_dir);
194 #endif /* CONFIG_DEBUG_FS */
195 #endif /* WANT_EVENT_TRACE */