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 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 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 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 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 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 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 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 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 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