1 /* -----------------------------------------------------------------------------
2 * Copyright (c) 2011 Ozmo Inc
3 * Released under the GNU General Public License Version 2 (GPLv2).
4 * -----------------------------------------------------------------------------
5 */
6 #include "ozconfig.h"
7 #ifdef WANT_EVENT_TRACE
8 #include <linux/jiffies.h>
9 #include <linux/uaccess.h>
10 #include "oztrace.h"
11 #include "ozevent.h"
12 /*------------------------------------------------------------------------------
13 */
14 unsigned long g_evt_mask = 0xffffffff;
15 /*------------------------------------------------------------------------------
16 */
17 #define OZ_MAX_EVTS 2048 /* Must be power of 2 */
18 DEFINE_SPINLOCK(g_eventlock);
19 static int g_evt_in;
20 static int g_evt_out;
21 static int g_missed_events;
22 static struct oz_event g_events[OZ_MAX_EVTS];
23 /*------------------------------------------------------------------------------
24 * Context: process
25 */
oz_event_init(void)26 void oz_event_init(void)
27 {
28 oz_trace("Event tracing initialized\n");
29 g_evt_in = g_evt_out = 0;
30 g_missed_events = 0;
31 }
32 /*------------------------------------------------------------------------------
33 * Context: process
34 */
oz_event_term(void)35 void oz_event_term(void)
36 {
37 oz_trace("Event tracing terminated\n");
38 }
39 /*------------------------------------------------------------------------------
40 * Context: any
41 */
oz_event_log2(u8 evt,u8 ctx1,u16 ctx2,void * ctx3,unsigned ctx4)42 void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
43 {
44 unsigned long irqstate;
45 int ix;
46 spin_lock_irqsave(&g_eventlock, irqstate);
47 ix = (g_evt_in + 1) & (OZ_MAX_EVTS - 1);
48 if (ix != g_evt_out) {
49 struct oz_event *e = &g_events[g_evt_in];
50 e->jiffies = jiffies;
51 e->evt = evt;
52 e->ctx1 = ctx1;
53 e->ctx2 = ctx2;
54 e->ctx3 = ctx3;
55 e->ctx4 = ctx4;
56 g_evt_in = ix;
57 } else {
58 g_missed_events++;
59 }
60 spin_unlock_irqrestore(&g_eventlock, irqstate);
61 }
62 /*------------------------------------------------------------------------------
63 * Context: process
64 */
oz_events_copy(struct oz_evtlist __user * lst)65 int oz_events_copy(struct oz_evtlist __user *lst)
66 {
67 int first;
68 int ix;
69 struct hdr {
70 int count;
71 int missed;
72 } hdr;
73 ix = g_evt_out;
74 hdr.count = g_evt_in - ix;
75 if (hdr.count < 0)
76 hdr.count += OZ_MAX_EVTS;
77 if (hdr.count > OZ_EVT_LIST_SZ)
78 hdr.count = OZ_EVT_LIST_SZ;
79 hdr.missed = g_missed_events;
80 g_missed_events = 0;
81 if (copy_to_user((void __user *)lst, &hdr, sizeof(hdr)))
82 return -EFAULT;
83 first = OZ_MAX_EVTS - ix;
84 if (first > hdr.count)
85 first = hdr.count;
86 if (first) {
87 int sz = first*sizeof(struct oz_event);
88 void __user *p = (void __user *)lst->evts;
89 if (copy_to_user(p, &g_events[ix], sz))
90 return -EFAULT;
91 if (hdr.count > first) {
92 p = (void __user *)&lst->evts[first];
93 sz = (hdr.count-first)*sizeof(struct oz_event);
94 if (copy_to_user(p, g_events, sz))
95 return -EFAULT;
96 }
97 }
98 ix += hdr.count;
99 if (ix >= OZ_MAX_EVTS)
100 ix -= OZ_MAX_EVTS;
101 g_evt_out = ix;
102 return 0;
103 }
104 /*------------------------------------------------------------------------------
105 * Context: process
106 */
oz_events_clear(void)107 void oz_events_clear(void)
108 {
109 unsigned long irqstate;
110 spin_lock_irqsave(&g_eventlock, irqstate);
111 g_evt_in = g_evt_out = 0;
112 g_missed_events = 0;
113 spin_unlock_irqrestore(&g_eventlock, irqstate);
114 }
115 #endif /* WANT_EVENT_TRACE */
116
117