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 */