]> Pileus Git - ~andy/linux/blob - drivers/staging/ozwpan/ozevent.c
Merge branch 'i2c-embedded/for-current' of git://git.pengutronix.de/git/wsa/linux
[~andy/linux] / drivers / staging / ozwpan / ozevent.c
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  */
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  */
35 void oz_event_term(void)
36 {
37         oz_trace("Event tracing terminated\n");
38 }
39 /*------------------------------------------------------------------------------
40  * Context: any
41  */
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  */
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  */
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