1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <sys/types.h>
27 #include <sys/kmem.h>
28 #include <sys/cmn_err.h>
29 #include <sys/conf.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/ksynch.h>
33 #include <sys/varargs.h>
34
35 #include <sys/ib/clients/eoib/eib_impl.h>
36
37 /*
38 * Defaults
39 */
40 uint_t eib_log_size = EIB_LOGSZ_DEFAULT;
41 int eib_log_level = EIB_MSGS_DEFAULT | EIB_MSGS_DEBUG;
42 int eib_log_timestamps = 0;
43
44 /*
45 * Debug variables, should not be tunables so allocated debug buffer
46 * and its size remain consistent.
47 */
48 static kmutex_t eib_debug_buf_lock;
49 static uint8_t *eib_debug_buf;
50 static uint32_t eib_debug_buf_ndx;
51 static uint_t eib_debug_buf_sz = 0;
52
53 /*
54 * Local declarations
55 */
56 static void eib_log(char *);
57
58 void
eib_debug_init(void)59 eib_debug_init(void)
60 {
61 eib_debug_buf_ndx = 0;
62 eib_debug_buf_sz = eib_log_size;
63 eib_debug_buf = kmem_zalloc(eib_debug_buf_sz, KM_SLEEP);
64
65 mutex_init(&eib_debug_buf_lock, NULL, MUTEX_DRIVER, NULL);
66 }
67
68 void
eib_debug_fini(void)69 eib_debug_fini(void)
70 {
71 mutex_destroy(&eib_debug_buf_lock);
72
73 if (eib_debug_buf && eib_debug_buf_sz) {
74 kmem_free(eib_debug_buf, eib_debug_buf_sz);
75 eib_debug_buf = NULL;
76 }
77 eib_debug_buf_sz = 0;
78 eib_debug_buf_ndx = 0;
79 }
80
81 void
eib_log(char * msg)82 eib_log(char *msg)
83 {
84 uint32_t off;
85 int msglen;
86 char msgbuf[EIB_MAX_LINE];
87
88 if (eib_debug_buf == NULL)
89 return;
90
91 if (eib_log_timestamps) {
92 msglen = snprintf(msgbuf, EIB_MAX_LINE, "%llx: %s",
93 (unsigned long long)ddi_get_lbolt64(), msg);
94 } else {
95 msglen = snprintf(msgbuf, EIB_MAX_LINE, "%s", msg);
96 }
97
98 if (msglen < 0)
99 return;
100 else if (msglen >= EIB_MAX_LINE)
101 msglen = EIB_MAX_LINE - 1;
102
103 mutex_enter(&eib_debug_buf_lock);
104 if ((eib_debug_buf_ndx == 0) ||
105 (eib_debug_buf[eib_debug_buf_ndx-1] != '\n')) {
106 eib_debug_buf[eib_debug_buf_ndx] = '\n';
107 eib_debug_buf_ndx++;
108 }
109
110 off = eib_debug_buf_ndx; /* current msg should go here */
111
112 eib_debug_buf_ndx += msglen; /* next msg should start here */
113 eib_debug_buf[eib_debug_buf_ndx] = 0; /* terminate current msg */
114
115 if (eib_debug_buf_ndx >= (eib_debug_buf_sz - 2 * EIB_MAX_LINE))
116 eib_debug_buf_ndx = 0;
117
118 mutex_exit(&eib_debug_buf_lock);
119
120 bcopy(msgbuf, eib_debug_buf+off, msglen); /* no lock needed */
121 }
122
123 #ifdef EIB_DEBUG
124 void
eib_dprintf_verbose(int inst,const char * fmt,...)125 eib_dprintf_verbose(int inst, const char *fmt, ...)
126 {
127 va_list ap;
128 int msglen;
129 char msgbuf[EIB_MAX_LINE];
130 char newfmt[EIB_MAX_LINE];
131
132 if ((eib_log_level & EIB_MSGS_VERBOSE) != EIB_MSGS_VERBOSE)
133 return;
134
135 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
136
137 va_start(ap, fmt);
138 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
139 va_end(ap);
140
141 if (msglen > 0) {
142 eib_log(msgbuf);
143 }
144 }
145
146 void
eib_dprintf_pkt(int inst,uint8_t * pkt,uint_t sz)147 eib_dprintf_pkt(int inst, uint8_t *pkt, uint_t sz)
148 {
149 char msgbuf[EIB_MAX_LINE];
150 char *bufp;
151 uint8_t *p = pkt;
152 uint_t len;
153 uint_t i;
154
155 if ((eib_log_level & EIB_MSGS_PKT) != EIB_MSGS_PKT)
156 return;
157
158 while (sz >= 16) {
159 (void) snprintf(msgbuf, EIB_MAX_LINE,
160 "eoib%02d__%02x %02x %02x %02x %02x %02x %02x %02x "
161 "%02x %02x %02x %02x %02x %02x %02x %02x\n", inst,
162 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
163 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
164
165 eib_log(msgbuf);
166
167 p += 16;
168 sz -= 16;
169 }
170
171 len = EIB_MAX_LINE;
172 bufp = msgbuf;
173 for (i = 0; i < sz; i++) {
174 if (i == 0) {
175 (void) snprintf(bufp, len, "eoib%02d__%02x ",
176 inst, p[i]);
177 len -= 11;
178 bufp += 11;
179 } else if (i < (sz - 1)) {
180 (void) snprintf(bufp, len, "%02x ", p[i]);
181 len -= 3;
182 bufp += 3;
183 } else {
184 (void) snprintf(bufp, len, "%02x\n", p[i]);
185 len -= 3;
186 bufp += 3;
187 }
188 }
189
190 eib_log(msgbuf);
191 }
192
193 void
eib_dprintf_args(int inst,const char * fmt,...)194 eib_dprintf_args(int inst, const char *fmt, ...)
195 {
196 va_list ap;
197 int msglen;
198 char msgbuf[EIB_MAX_LINE];
199 char newfmt[EIB_MAX_LINE];
200
201 if ((eib_log_level & EIB_MSGS_ARGS) != EIB_MSGS_ARGS)
202 return;
203
204 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
205
206 va_start(ap, fmt);
207 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
208 va_end(ap);
209
210 if (msglen > 0) {
211 eib_log(msgbuf);
212 }
213 }
214
215 void
eib_dprintf_debug(int inst,const char * fmt,...)216 eib_dprintf_debug(int inst, const char *fmt, ...)
217 {
218 va_list ap;
219 int msglen;
220 char msgbuf[EIB_MAX_LINE];
221 char newfmt[EIB_MAX_LINE];
222
223 if ((eib_log_level & EIB_MSGS_DEBUG) != EIB_MSGS_DEBUG)
224 return;
225
226 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
227
228 va_start(ap, fmt);
229 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
230 va_end(ap);
231
232 if (msglen > 0) {
233 eib_log(msgbuf);
234 }
235 }
236 #endif
237
238 void
eib_dprintf_warn(int inst,const char * fmt,...)239 eib_dprintf_warn(int inst, const char *fmt, ...)
240 {
241 va_list ap;
242 int msglen;
243 char msgbuf[EIB_MAX_LINE];
244 char newfmt[EIB_MAX_LINE];
245
246 if ((eib_log_level & EIB_MSGS_WARN) != EIB_MSGS_WARN)
247 return;
248
249 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
250
251 va_start(ap, fmt);
252 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
253 va_end(ap);
254
255 if (msglen > 0) {
256 eib_log(msgbuf);
257 }
258 }
259
260 void
eib_dprintf_err(int inst,const char * fmt,...)261 eib_dprintf_err(int inst, const char *fmt, ...)
262 {
263 va_list ap;
264 int msglen;
265 char msgbuf[EIB_MAX_LINE];
266 char newfmt[EIB_MAX_LINE];
267
268 if ((eib_log_level & EIB_MSGS_ERR) != EIB_MSGS_ERR)
269 return;
270
271 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
272
273 va_start(ap, fmt);
274 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
275 va_end(ap);
276
277 if (msglen > 0) {
278 eib_log(msgbuf);
279 cmn_err(CE_WARN, "!%s\n", msgbuf);
280 }
281 }
282
283 void
eib_dprintf_crit(int inst,const char * fmt,...)284 eib_dprintf_crit(int inst, const char *fmt, ...)
285 {
286 va_list ap;
287 int msglen;
288 char msgbuf[EIB_MAX_LINE];
289 char newfmt[EIB_MAX_LINE];
290
291 if ((eib_log_level & EIB_MSGS_CRIT) != EIB_MSGS_CRIT)
292 return;
293
294 (void) snprintf(newfmt, EIB_MAX_LINE, "eoib%d__%s", inst, fmt);
295
296 va_start(ap, fmt);
297 msglen = vsnprintf(msgbuf, EIB_MAX_LINE, newfmt, ap);
298 va_end(ap);
299
300 if (msglen > 0) {
301 eib_log(msgbuf);
302 cmn_err(CE_PANIC, "!%s\n", msgbuf);
303 }
304 }
305