]>
Commit | Line | Data |
---|---|---|
c84b8b50 S |
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 | * | |
364014fd | 20 | * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! |
c84b8b50 S |
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 | * | |
364014fd MI |
27 | * Send any bug fixes/changes to: Eng.Linux at digi dot com. |
28 | * Thank you. | |
c84b8b50 S |
29 | * |
30 | */ | |
31 | ||
32 | /* $Id: dgap_trace.c,v 1.1 2009/10/23 14:01:57 markh Exp $ */ | |
33 | ||
34 | #include <linux/kernel.h> | |
c84b8b50 S |
35 | #include <linux/sched.h> /* For jiffies, task states */ |
36 | #include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */ | |
37 | #include <linux/vmalloc.h> | |
38 | ||
39 | #include "dgap_driver.h" | |
9c5f1791 | 40 | #include "dgap_trace.h" |
c84b8b50 S |
41 | |
42 | #define TRC_TO_CONSOLE 1 | |
43 | ||
44 | /* file level globals */ | |
45 | static char *dgap_trcbuf; /* the ringbuffer */ | |
46 | ||
47 | #if defined(TRC_TO_KMEM) | |
48 | static int dgap_trcbufi = 0; /* index of the tilde at the end of */ | |
49 | #endif | |
50 | ||
51 | extern int dgap_trcbuf_size; /* size of the ringbuffer */ | |
52 | ||
53 | #if defined(TRC_TO_KMEM) | |
54 | static DEFINE_SPINLOCK(dgap_tracef_lock); | |
55 | #endif | |
56 | ||
57 | #if 0 | |
58 | ||
59 | #if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) | |
60 | void dgap_tracef(const char *fmt, ...) | |
61 | { | |
62 | return; | |
63 | } | |
64 | ||
65 | #else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */ | |
66 | ||
67 | void dgap_tracef(const char *fmt, ...) | |
68 | { | |
69 | va_list ap; | |
70 | char buf[TRC_MAXMSG+1]; | |
71 | size_t lenbuf; | |
72 | int i; | |
73 | static int failed = FALSE; | |
74 | # if defined(TRC_TO_KMEM) | |
75 | unsigned long flags; | |
76 | #endif | |
77 | ||
78 | if(failed) | |
79 | return; | |
80 | # if defined(TRC_TO_KMEM) | |
81 | DGAP_LOCK(dgap_tracef_lock, flags); | |
82 | #endif | |
83 | ||
84 | /* Format buf using fmt and arguments contained in ap. */ | |
85 | va_start(ap, fmt); | |
86 | i = vsprintf(buf, fmt, ap); | |
87 | va_end(ap); | |
88 | lenbuf = strlen(buf); | |
89 | ||
90 | # if defined(TRC_TO_KMEM) | |
91 | { | |
92 | static int initd=0; | |
93 | ||
94 | /* | |
95 | * Now, in addition to (or instead of) printing this stuff out | |
96 | * (which is a buffered operation), also tuck it away into a | |
97 | * corner of memory which can be examined post-crash in kdb. | |
98 | */ | |
99 | if (!initd) { | |
100 | dgap_trcbuf = (char *) vmalloc(dgap_trcbuf_size); | |
101 | if(!dgap_trcbuf) { | |
102 | failed = TRUE; | |
103 | printk("dgap: tracing init failed!\n"); | |
104 | return; | |
105 | } | |
106 | ||
107 | memset(dgap_trcbuf, '\0', dgap_trcbuf_size); | |
108 | dgap_trcbufi = 0; | |
109 | initd++; | |
110 | ||
364014fd | 111 | printk("dgap: tracing enabled - " TRC_DTRC |
c84b8b50 | 112 | " 0x%lx 0x%x\n", |
364014fd | 113 | (unsigned long)dgap_trcbuf, |
c84b8b50 S |
114 | dgap_trcbuf_size); |
115 | } | |
116 | ||
117 | # if defined(TRC_ON_OVERFLOW_WRAP_AROUND) | |
118 | /* | |
119 | * This is the less CPU-intensive way to do things. We simply | |
364014fd | 120 | * wrap around before we fall off the end of the buffer. A |
c84b8b50 S |
121 | * tilde (~) demarcates the current end of the trace. |
122 | * | |
123 | * This method should be used if you are concerned about race | |
124 | * conditions as it is less likely to affect the timing of | |
125 | * things. | |
126 | */ | |
127 | ||
128 | if (dgap_trcbufi + lenbuf >= dgap_trcbuf_size) { | |
129 | /* We are wrapping, so wipe out the last tilde. */ | |
130 | dgap_trcbuf[dgap_trcbufi] = '\0'; | |
131 | /* put the new string at the beginning of the buffer */ | |
132 | dgap_trcbufi = 0; | |
133 | } | |
134 | ||
364014fd | 135 | strcpy(&dgap_trcbuf[dgap_trcbufi], buf); |
c84b8b50 S |
136 | dgap_trcbufi += lenbuf; |
137 | dgap_trcbuf[dgap_trcbufi] = '~'; | |
138 | ||
139 | # elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER) | |
140 | /* | |
141 | * This is the more CPU-intensive way to do things. If we | |
364014fd | 142 | * venture into the last 1/8 of the buffer, we shift the |
c84b8b50 S |
143 | * last 7/8 of the buffer forward, wiping out the first 1/8. |
144 | * Advantage: No wrap-around, only truncation from the | |
145 | * beginning. | |
146 | * | |
147 | * This method should not be used if you are concerned about | |
148 | * timing changes affecting the behaviour of the driver (ie, | |
149 | * race conditions). | |
150 | */ | |
151 | strcpy(&dgap_trcbuf[dgap_trcbufi], buf); | |
152 | dgap_trcbufi += lenbuf; | |
153 | dgap_trcbuf[dgap_trcbufi] = '~'; | |
154 | dgap_trcbuf[dgap_trcbufi+1] = '\0'; | |
155 | ||
156 | /* If we're near the end of the trace buffer... */ | |
157 | if (dgap_trcbufi > (dgap_trcbuf_size/8)*7) { | |
158 | /* Wipe out the first eighth to make some more room. */ | |
159 | strcpy(dgap_trcbuf, &dgap_trcbuf[dgap_trcbuf_size/8]); | |
160 | dgap_trcbufi = strlen(dgap_trcbuf)-1; | |
161 | /* Plop overflow message at the top of the buffer. */ | |
162 | bcopy(TRC_OVERFLOW, dgap_trcbuf, strlen(TRC_OVERFLOW)); | |
163 | } | |
164 | # else | |
165 | # error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?" | |
166 | # endif | |
167 | } | |
168 | DGAP_UNLOCK(dgap_tracef_lock, flags); | |
169 | ||
170 | # endif /* defined(TRC_TO_KMEM) */ | |
171 | } | |
172 | ||
173 | #endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */ | |
174 | ||
175 | #endif | |
176 | ||
177 | /* | |
178 | * dgap_tracer_free() | |
179 | * | |
180 | * | |
181 | */ | |
182 | void dgap_tracer_free(void) | |
183 | { | |
184 | if(dgap_trcbuf) | |
185 | vfree(dgap_trcbuf); | |
186 | } |