diff options
Diffstat (limited to 'drivers/staging/ozwpan/ozevent.c')
-rw-r--r-- | drivers/staging/ozwpan/ozevent.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/staging/ozwpan/ozevent.c b/drivers/staging/ozwpan/ozevent.c new file mode 100644 index 00000000000..73703d3e96b --- /dev/null +++ b/drivers/staging/ozwpan/ozevent.c @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2011 Ozmo Inc + * Released under the GNU General Public License Version 2 (GPLv2). + * ----------------------------------------------------------------------------- + */ +#include "ozconfig.h" +#ifdef WANT_EVENT_TRACE +#include <linux/jiffies.h> +#include <linux/uaccess.h> +#include "oztrace.h" +#include "ozevent.h" +/*------------------------------------------------------------------------------ + */ +unsigned long g_evt_mask = 0xffffffff; +/*------------------------------------------------------------------------------ + */ +#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]; +/*------------------------------------------------------------------------------ + * Context: process + */ +void oz_event_init(void) +{ + oz_trace("Event tracing initialized\n"); + g_evt_in = g_evt_out = 0; + g_missed_events = 0; +} +/*------------------------------------------------------------------------------ + * Context: process + */ +void oz_event_term(void) +{ + oz_trace("Event tracing terminated\n"); +} +/*------------------------------------------------------------------------------ + * Context: any + */ +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]; + e->jiffies = jiffies; + e->evt = evt; + e->ctx1 = ctx1; + e->ctx2 = ctx2; + e->ctx3 = ctx3; + e->ctx4 = ctx4; + g_evt_in = ix; + } else { + g_missed_events++; + } + spin_unlock_irqrestore(&g_eventlock, irqstate); +} +/*------------------------------------------------------------------------------ + * Context: process + */ +int oz_events_copy(struct oz_evtlist __user *lst) +{ + 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; + } + } + ix += hdr.count; + if (ix >= OZ_MAX_EVTS) + ix -= OZ_MAX_EVTS; + g_evt_out = ix; + return 0; +} +/*------------------------------------------------------------------------------ + * Context: process + */ +void oz_events_clear(void) +{ + 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); +} +#endif /* WANT_EVENT_TRACE */ + |