Added tracing facilities and also memory allocation and URB tracking.
This is for debugging purposes and is all optional and can be switched
out at compile time.
Signed-off-by: Chris Kelly <ckelly@ozmodevices.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * This file contains debug allocation and free functions. These are turned on
+ * by the configuration switch WANT_DEBUG_KMALLOC. This flags should be turned
+ * off in the release version but facilitate memory leak and corruption during
+ * development.
+ * -----------------------------------------------------------------------------
+ */
+#include <linux/module.h>
+#include "ozconfig.h"
+#include "ozalloc.h"
+#include "oztrace.h"
+#ifdef WANT_DEBUG_KMALLOC
+/*------------------------------------------------------------------------------
+ */
+#define MAGIC_1 0x12848796
+#define MAGIC_2 0x87465920
+#define MAGIC_3 0x80288264
+/*------------------------------------------------------------------------------
+ */
+struct oz_alloc_hdr {
+ int size;
+ int line;
+ unsigned magic;
+ struct list_head link;
+};
+/*------------------------------------------------------------------------------
+ */
+static unsigned long g_total_alloc_size;
+static int g_alloc_count;
+static DEFINE_SPINLOCK(g_alloc_lock);
+static LIST_HEAD(g_alloc_list);
+/*------------------------------------------------------------------------------
+ * Context: any
+ */
+void *oz_alloc_debug(size_t size, gfp_t flags, int line)
+{
+ struct oz_alloc_hdr *hdr = (struct oz_alloc_hdr *)
+ kmalloc(size + sizeof(struct oz_alloc_hdr) +
+ sizeof(unsigned), flags);
+ if (hdr) {
+ unsigned long irq_state;
+ hdr->size = size;
+ hdr->line = line;
+ hdr->magic = MAGIC_1;
+ *(unsigned *)(((u8 *)(hdr + 1)) + size) = MAGIC_2;
+ spin_lock_irqsave(&g_alloc_lock, irq_state);
+ g_total_alloc_size += size;
+ g_alloc_count++;
+ list_add_tail(&hdr->link, &g_alloc_list);
+ spin_unlock_irqrestore(&g_alloc_lock, irq_state);
+ return hdr + 1;
+ }
+ return 0;
+}
+/*------------------------------------------------------------------------------
+ * Context: any
+ */
+void oz_free_debug(void *p)
+{
+ if (p) {
+ struct oz_alloc_hdr *hdr = (struct oz_alloc_hdr *)
+ (((unsigned char *)p) - sizeof(struct oz_alloc_hdr));
+ if (hdr->magic == MAGIC_1) {
+ unsigned long irq_state;
+ if (*(unsigned *)(((u8 *)(hdr + 1)) + hdr->size)
+ != MAGIC_2) {
+ oz_trace("oz_free_debug: Corrupted beyond"
+ " %p size %d\n", hdr+1, hdr->size);
+ return;
+ }
+ spin_lock_irqsave(&g_alloc_lock, irq_state);
+ g_total_alloc_size -= hdr->size;
+ g_alloc_count--;
+ list_del(&hdr->link);
+ spin_unlock_irqrestore(&g_alloc_lock, irq_state);
+ hdr->magic = MAGIC_3;
+ kfree(hdr);
+ } else {
+ oz_trace("oz_free_debug: Invalid magic number %u\n",
+ hdr->magic);
+ }
+ }
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_trace_leaks(void)
+{
+#ifdef WANT_TRACE
+ struct list_head *e;
+ oz_trace("Total alloc size:%ld Alloc count:%d\n",
+ g_total_alloc_size, g_alloc_count);
+ if (g_alloc_count)
+ oz_trace("Trace of leaks.\n");
+ else
+ oz_trace("No memory leaks.\n");
+ list_for_each(e, &g_alloc_list) {
+ struct oz_alloc_hdr *hdr =
+ container_of(e, struct oz_alloc_hdr, link);
+ oz_trace("LEAK size %d line %d\n", hdr->size, hdr->line);
+ }
+#endif /* #ifdef WANT_TRACE */
+}
+#endif /* #ifdef WANT_DEBUG_KMALLOC */
+
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#ifndef _OZALLOC_H
+#define _OZALLOC_H
+
+#include <linux/slab.h>
+
+#ifdef WANT_DEBUG_KMALLOC
+
+void *oz_alloc_debug(size_t size, gfp_t flags, int line);
+void oz_free_debug(void *p);
+void oz_trace_leaks(void);
+#define oz_alloc(__s, __f) oz_alloc_debug(__s, __f, __LINE__)
+#define oz_free oz_free_debug
+
+#else
+
+
+#define oz_alloc kmalloc
+#define oz_free kfree
+#define oz_trace_leaks()
+
+#endif /* #ifdef WANT_DEBUG_KMALLOC */
+
+#endif /* _OZALLOC_H */
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#include "ozconfig.h"
+#include "oztrace.h"
+
+#ifdef WANT_VERBOSE_TRACE
+unsigned long trace_flags =
+ 0
+#ifdef WANT_TRACE_STREAM
+ | OZ_TRACE_STREAM
+#endif /* WANT_TRACE_STREAM */
+#ifdef WANT_TRACE_URB
+ | OZ_TRACE_URB
+#endif /* WANT_TRACE_URB */
+
+#ifdef WANT_TRACE_CTRL_DETAIL
+ | OZ_TRACE_CTRL_DETAIL
+#endif /* WANT_TRACE_CTRL_DETAIL */
+
+#ifdef WANT_TRACE_HUB
+ | OZ_TRACE_HUB
+#endif /* WANT_TRACE_HUB */
+
+#ifdef WANT_TRACE_RX_FRAMES
+ | OZ_TRACE_RX_FRAMES
+#endif /* WANT_TRACE_RX_FRAMES */
+
+#ifdef WANT_TRACE_TX_FRAMES
+ | OZ_TRACE_TX_FRAMES
+#endif /* WANT_TRACE_TX_FRAMES */
+ ;
+#endif /* WANT_VERBOSE_TRACE */
+
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#ifndef _OZTRACE_H_
+#define _OZTRACE_H_
+#include "ozconfig.h"
+
+#define TRACE_PREFIX KERN_ALERT "OZWPAN: "
+
+#ifdef WANT_TRACE
+#define oz_trace(...) printk(TRACE_PREFIX __VA_ARGS__)
+#ifdef WANT_VERBOSE_TRACE
+extern unsigned long trace_flags;
+#define oz_trace2(_flag, ...) \
+ do { if (trace_flags & _flag) printk(TRACE_PREFIX __VA_ARGS__); \
+ } while (0)
+#else
+#define oz_trace2(...)
+#endif /* #ifdef WANT_VERBOSE_TRACE */
+#else
+#define oz_trace(...)
+#define oz_trace2(...)
+#endif /* #ifdef WANT_TRACE */
+
+#define OZ_TRACE_STREAM 0x1
+#define OZ_TRACE_URB 0x2
+#define OZ_TRACE_CTRL_DETAIL 0x4
+#define OZ_TRACE_HUB 0x8
+#define OZ_TRACE_RX_FRAMES 0x10
+#define OZ_TRACE_TX_FRAMES 0x20
+
+#endif /* Sentry */
+
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#include <linux/usb.h>
+#include "ozconfig.h"
+#ifdef WANT_URB_PARANOIA
+#include "ozurbparanoia.h"
+#include "oztrace.h"
+/*-----------------------------------------------------------------------------
+ */
+#define OZ_MAX_URBS 1000
+struct urb *g_urb_memory[OZ_MAX_URBS];
+int g_nb_urbs;
+DEFINE_SPINLOCK(g_urb_mem_lock);
+/*-----------------------------------------------------------------------------
+ */
+void oz_remember_urb(struct urb *urb)
+{
+ unsigned long irq_state;
+ spin_lock_irqsave(&g_urb_mem_lock, irq_state);
+ if (g_nb_urbs < OZ_MAX_URBS) {
+ g_urb_memory[g_nb_urbs++] = urb;
+ oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
+ } else {
+ oz_trace("ERROR urb buffer full\n");
+ }
+ spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
+}
+/*------------------------------------------------------------------------------
+ */
+int oz_forget_urb(struct urb *urb)
+{
+ unsigned long irq_state;
+ int i;
+ int rc = -1;
+ spin_lock_irqsave(&g_urb_mem_lock, irq_state);
+ for (i = 0; i < g_nb_urbs; i++) {
+ if (g_urb_memory[i] == urb) {
+ rc = 0;
+ if (--g_nb_urbs > i)
+ memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
+ (g_nb_urbs - i) * sizeof(struct urb *));
+ oz_trace("%lu: urb down = %d %p\n",
+ jiffies, g_nb_urbs, urb);
+ }
+ }
+ spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
+ return rc;
+}
+#endif /* #ifdef WANT_URB_PARANOIA */
+
--- /dev/null
+#ifndef _OZURBPARANOIA_H
+#define _OZURBPARANOIA_H
+/* -----------------------------------------------------------------------------
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * Copyright (c) 2011 Ozmo Inc
+ * -----------------------------------------------------------------------------
+ */
+
+#ifdef WANT_URB_PARANOIA
+void oz_remember_urb(struct urb *urb);
+int oz_forget_urb(struct urb *urb);
+#else
+#define oz_remember_urb(__x)
+#define oz_forget_urb(__x) 0
+#endif /* WANT_URB_PARANOIA */
+
+
+#endif /* _OZURBPARANOIA_H */
+