]> Pileus Git - ~andy/linux/blob - drivers/staging/dgnc/dgnc_trace.c
Merge branch 'acpi-bind'
[~andy/linux] / drivers / staging / dgnc / dgnc_trace.c
1 /*
2  * Copyright 2003 Digi International (www.digi.com)
3  *      Scott H Kilau <Scott_Kilau at digi dot com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  * PURPOSE.  See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE!
21  *
22  *      This is shared code between Digi's CVS archive and the
23  *      Linux Kernel sources.
24  *      Changing the source just for reformatting needlessly breaks
25  *      our CVS diff history.
26  *
27  *      Send any bug fixes/changes to:  Eng.Linux at digi dot com.
28  *      Thank you.
29  *
30  */
31
32 #include <linux/kernel.h>
33 #include <linux/sched.h>        /* For jiffies, task states */
34 #include <linux/interrupt.h>    /* For tasklet and interrupt structs/defines */
35 #include <linux/vmalloc.h>
36
37 #include "dgnc_driver.h"
38
39 #define TRC_TO_CONSOLE 1
40
41 /* file level globals */
42 static char *dgnc_trcbuf;               /* the ringbuffer */
43
44 #if defined(TRC_TO_KMEM)
45 static int dgnc_trcbufi = 0;            /* index of the tilde at the end of */
46 #endif
47
48 #if defined(TRC_TO_KMEM)
49 static DEFINE_SPINLOCK(dgnc_tracef_lock);
50 #endif
51
52
53 #if 0
54
55 #if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
56
57 void dgnc_tracef(const char *fmt, ...)
58 {
59         return;
60 }
61
62 #else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
63
64 void dgnc_tracef(const char *fmt, ...)
65 {
66         va_list          ap;
67         char             buf[TRC_MAXMSG+1];
68         size_t           lenbuf;
69         int              i;
70         static int       failed = FALSE;
71 # if defined(TRC_TO_KMEM)
72         unsigned long    flags;
73 #endif
74
75         if(failed)
76                 return;
77 # if defined(TRC_TO_KMEM)
78         DGNC_LOCK(dgnc_tracef_lock, flags);
79 #endif
80
81         /* Format buf using fmt and arguments contained in ap. */
82         va_start(ap, fmt);
83         i = vsprintf(buf, fmt,  ap);
84         va_end(ap);
85         lenbuf = strlen(buf);
86
87 # if defined(TRC_TO_KMEM)
88         {
89                 static int       initd=0;
90
91                 /*
92                  * Now, in addition to (or instead of) printing this stuff out
93                  * (which is a buffered operation), also tuck it away into a
94                  * corner of memory which can be examined post-crash in kdb.
95                  */
96                 if (!initd) {
97                         dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size);
98                         if(!dgnc_trcbuf) {
99                                 failed = TRUE;
100                                 printk("dgnc: tracing init failed!\n");
101                                 return;
102                         }
103
104                         memset(dgnc_trcbuf, '\0',  dgnc_trcbuf_size);
105                         dgnc_trcbufi = 0;
106                         initd++;
107
108                         printk("dgnc: tracing enabled - " TRC_DTRC
109                                 " 0x%lx 0x%x\n",
110                                 (unsigned long)dgnc_trcbuf,
111                                 dgnc_trcbuf_size);
112                 }
113
114 #  if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
115                 /*
116                  * This is the less CPU-intensive way to do things.  We simply
117                  * wrap around before we fall off the end of the buffer.  A
118                  * tilde (~) demarcates the current end of the trace.
119                  *
120                  * This method should be used if you are concerned about race
121                  * conditions as it is less likely to affect the timing of
122                  * things.
123                  */
124
125                 if (dgnc_trcbufi + lenbuf >= dgnc_trcbuf_size) {
126                         /* We are wrapping, so wipe out the last tilde. */
127                         dgnc_trcbuf[dgnc_trcbufi] = '\0';
128                         /* put the new string at the beginning of the buffer */
129                         dgnc_trcbufi = 0;
130                 }
131
132                 strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
133                 dgnc_trcbufi += lenbuf;
134                 dgnc_trcbuf[dgnc_trcbufi] = '~';
135
136 #  elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
137                 /*
138                  * This is the more CPU-intensive way to do things.  If we
139                  * venture into the last 1/8 of the buffer, we shift the
140                  * last 7/8 of the buffer forward, wiping out the first 1/8.
141                  * Advantage: No wrap-around, only truncation from the
142                  * beginning.
143                  *
144                  * This method should not be used if you are concerned about
145                  * timing changes affecting the behaviour of the driver (ie,
146                  * race conditions).
147                  */
148                 strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
149                 dgnc_trcbufi += lenbuf;
150                 dgnc_trcbuf[dgnc_trcbufi] = '~';
151                 dgnc_trcbuf[dgnc_trcbufi+1] = '\0';
152
153                 /* If we're near the end of the trace buffer... */
154                 if (dgnc_trcbufi > (dgnc_trcbuf_size/8)*7) {
155                         /* Wipe out the first eighth to make some more room. */
156                         strcpy(dgnc_trcbuf, &dgnc_trcbuf[dgnc_trcbuf_size/8]);
157                         dgnc_trcbufi = strlen(dgnc_trcbuf)-1;
158                         /* Plop overflow message at the top of the buffer. */
159                         bcopy(TRC_OVERFLOW, dgnc_trcbuf, strlen(TRC_OVERFLOW));
160                 }
161 #  else
162 #   error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
163 #  endif
164         }
165         DGNC_UNLOCK(dgnc_tracef_lock, flags);
166
167 # endif /* defined(TRC_TO_KMEM) */
168 }
169
170 #endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
171
172 #endif
173
174
175 /*
176  * dgnc_tracer_free()
177  *
178  *
179  */
180 void dgnc_tracer_free(void)
181 {
182         if(dgnc_trcbuf)
183                 vfree(dgnc_trcbuf);
184 }