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/enx_impl.h>
36
37 /*
38 * Defaults
39 */
40 uint_t enx_log_size = ENX_LOGSZ_DEFAULT;
41 int enx_log_level = ENX_MSGS_DEFAULT | ENX_MSGS_DEBUG;
42 int enx_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 enx_debug_buf_lock;
49 static uint8_t *enx_debug_buf;
50 static uint32_t enx_debug_buf_ndx;
51 static uint_t enx_debug_buf_sz;
52
53 static void eibnx_log(char *);
54
55 void
eibnx_debug_init(void)56 eibnx_debug_init(void)
57 {
58 enx_debug_buf_ndx = 0;
59 enx_debug_buf_sz = enx_log_size;
60 enx_debug_buf = kmem_zalloc(enx_debug_buf_sz, KM_SLEEP);
61
62 mutex_init(&enx_debug_buf_lock, NULL, MUTEX_DRIVER, NULL);
63 }
64
65 void
eibnx_debug_fini(void)66 eibnx_debug_fini(void)
67 {
68 mutex_destroy(&enx_debug_buf_lock);
69
70 if (enx_debug_buf && enx_debug_buf_sz) {
71 kmem_free(enx_debug_buf, enx_debug_buf_sz);
72 enx_debug_buf = NULL;
73 }
74 enx_debug_buf_sz = 0;
75 enx_debug_buf_ndx = 0;
76 }
77
78 void
eibnx_log(char * msg)79 eibnx_log(char *msg)
80 {
81 uint32_t off;
82 int msglen;
83 char msgbuf[ENX_MAX_LINE];
84
85 if (enx_debug_buf == NULL)
86 return;
87
88 if (enx_log_timestamps) {
89 msglen = snprintf(msgbuf, ENX_MAX_LINE, "%llx: %s",
90 (unsigned long long)ddi_get_lbolt64(), msg);
91 } else {
92 msglen = snprintf(msgbuf, ENX_MAX_LINE, "%s", msg);
93 }
94
95 if (msglen < 0)
96 return;
97 else if (msglen >= ENX_MAX_LINE)
98 msglen = ENX_MAX_LINE - 1;
99
100 mutex_enter(&enx_debug_buf_lock);
101
102 if ((enx_debug_buf_ndx == 0) ||
103 (enx_debug_buf[enx_debug_buf_ndx-1] != '\n')) {
104 enx_debug_buf[enx_debug_buf_ndx] = '\n';
105 enx_debug_buf_ndx++;
106 }
107
108 off = enx_debug_buf_ndx; /* current msg should go here */
109
110 enx_debug_buf_ndx += msglen; /* next msg should start here */
111 enx_debug_buf[enx_debug_buf_ndx] = 0; /* terminate current msg */
112
113 if (enx_debug_buf_ndx >= (enx_debug_buf_sz - 2 * ENX_MAX_LINE))
114 enx_debug_buf_ndx = 0;
115
116 mutex_exit(&enx_debug_buf_lock);
117
118 bcopy(msgbuf, enx_debug_buf+off, msglen); /* no lock needed */
119 }
120
121 #ifdef ENX_DEBUG
122 void
eibnx_dprintf_verbose(const char * fmt,...)123 eibnx_dprintf_verbose(const char *fmt, ...)
124 {
125 va_list ap;
126 int msglen;
127 char msgbuf[ENX_MAX_LINE];
128 char newfmt[ENX_MAX_LINE];
129
130 if ((enx_log_level & ENX_MSGS_VERBOSE) != ENX_MSGS_VERBOSE)
131 return;
132
133 (void) snprintf(newfmt, ENX_MAX_LINE, "..........%s", fmt);
134
135 va_start(ap, fmt);
136 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, newfmt, ap);
137 va_end(ap);
138
139 if (msglen > 0) {
140 eibnx_log(msgbuf);
141 }
142 }
143
144 void
eibnx_dprintf_args(const char * fmt,...)145 eibnx_dprintf_args(const char *fmt, ...)
146 {
147 va_list ap;
148 int msglen;
149 char msgbuf[ENX_MAX_LINE];
150 char newfmt[ENX_MAX_LINE];
151
152 if ((enx_log_level & ENX_MSGS_ARGS) != ENX_MSGS_ARGS)
153 return;
154
155 (void) snprintf(newfmt, ENX_MAX_LINE, "........%s", fmt);
156
157 va_start(ap, fmt);
158 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, newfmt, ap);
159 va_end(ap);
160
161 if (msglen > 0) {
162 eibnx_log(msgbuf);
163 }
164 }
165
166 void
eibnx_dprintf_debug(const char * fmt,...)167 eibnx_dprintf_debug(const char *fmt, ...)
168 {
169 va_list ap;
170 int msglen;
171 char msgbuf[ENX_MAX_LINE];
172 char newfmt[ENX_MAX_LINE];
173
174 if ((enx_log_level & ENX_MSGS_DEBUG) != ENX_MSGS_DEBUG)
175 return;
176
177 (void) snprintf(newfmt, ENX_MAX_LINE, "......%s", fmt);
178
179 va_start(ap, fmt);
180 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, newfmt, ap);
181 va_end(ap);
182
183 if (msglen > 0) {
184 eibnx_log(msgbuf);
185 }
186 }
187 #endif
188
189 void
eibnx_dprintf_warn(const char * fmt,...)190 eibnx_dprintf_warn(const char *fmt, ...)
191 {
192 va_list ap;
193 int msglen;
194 char msgbuf[ENX_MAX_LINE];
195 char newfmt[ENX_MAX_LINE];
196
197 if ((enx_log_level & ENX_MSGS_WARN) != ENX_MSGS_WARN)
198 return;
199
200 (void) snprintf(newfmt, ENX_MAX_LINE, "....%s", fmt);
201
202 va_start(ap, fmt);
203 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, newfmt, ap);
204 va_end(ap);
205
206 if (msglen > 0) {
207 eibnx_log(msgbuf);
208 }
209 }
210
211 void
eibnx_dprintf_err(const char * fmt,...)212 eibnx_dprintf_err(const char *fmt, ...)
213 {
214 va_list ap;
215 int msglen;
216 char msgbuf[ENX_MAX_LINE];
217 char newfmt[ENX_MAX_LINE];
218
219 if ((enx_log_level & ENX_MSGS_ERR) != ENX_MSGS_ERR)
220 return;
221
222 (void) snprintf(newfmt, ENX_MAX_LINE, "..%s", fmt);
223
224 va_start(ap, fmt);
225 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, newfmt, ap);
226 va_end(ap);
227
228 if (msglen > 0) {
229 eibnx_log(msgbuf);
230 cmn_err(CE_WARN, "!%s\n", msgbuf);
231 }
232 }
233
234 void
eibnx_dprintf_crit(const char * fmt,...)235 eibnx_dprintf_crit(const char *fmt, ...)
236 {
237 va_list ap;
238 int msglen;
239 char msgbuf[ENX_MAX_LINE];
240
241 if ((enx_log_level & ENX_MSGS_CRIT) != ENX_MSGS_CRIT)
242 return;
243
244 va_start(ap, fmt);
245 msglen = vsnprintf(msgbuf, ENX_MAX_LINE, fmt, ap);
246 va_end(ap);
247
248 if (msglen > 0) {
249 eibnx_log(msgbuf);
250 cmn_err(CE_PANIC, "!%s\n", msgbuf);
251 }
252 }
253