1b86efd96Sagiri /*
2b86efd96Sagiri  * CDDL HEADER START
3b86efd96Sagiri  *
4b86efd96Sagiri  * The contents of this file are subject to the terms of the
5b86efd96Sagiri  * Common Development and Distribution License (the "License").
6b86efd96Sagiri  * You may not use this file except in compliance with the License.
7b86efd96Sagiri  *
8b86efd96Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b86efd96Sagiri  * or http://www.opensolaris.org/os/licensing.
10b86efd96Sagiri  * See the License for the specific language governing permissions
11b86efd96Sagiri  * and limitations under the License.
12b86efd96Sagiri  *
13b86efd96Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
14b86efd96Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b86efd96Sagiri  * If applicable, add the following below this CDDL HEADER, with the
16b86efd96Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
17b86efd96Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
18b86efd96Sagiri  *
19b86efd96Sagiri  * CDDL HEADER END
20b86efd96Sagiri  */
21b86efd96Sagiri /*
22*74242422Sagiri  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23b86efd96Sagiri  * Use is subject to license terms.
24b86efd96Sagiri  */
25b86efd96Sagiri 
26b86efd96Sagiri #include <sys/types.h>
27b86efd96Sagiri #include <sys/varargs.h>
28b86efd96Sagiri #include <sys/cmn_err.h>
29b86efd96Sagiri #include <sys/ddi.h>
30b86efd96Sagiri #include <sys/sunddi.h>
31b86efd96Sagiri #include <sys/ib/clients/rds/rdsib_debug.h>
32b86efd96Sagiri 
33b86efd96Sagiri /*
34b86efd96Sagiri  * This file contains the debug defines and routines.
35b86efd96Sagiri  * Debugging information is collected in a circular kernel buffer. Debug
36b86efd96Sagiri  * messages with level lower than rdsdbglvl are ignored. The size of the
37b86efd96Sagiri  * of the debug buffer can be changed by setting 'rds_debug_buf_size' in
38b86efd96Sagiri  * bytes in /etc/system.
39b86efd96Sagiri  *
40b86efd96Sagiri  * The debug buffer can be cleared by setting 'rds_clear_debug_buf_flag = 1'
41b86efd96Sagiri  * on a running system.
42b86efd96Sagiri  */
43b86efd96Sagiri 
44b86efd96Sagiri #define	RDS_DEBUG_SIZE_EXTRA_ALLOC	8
45b86efd96Sagiri #define	RDS_MIN_DEBUG_BUF_SIZE		0x1000
46b86efd96Sagiri #define	RDS_FUNCNAME_LEN		40
47b86efd96Sagiri #define	RDS_PRINTBUF_LEN		4096
48b86efd96Sagiri #ifdef	DEBUG
49b86efd96Sagiri #define	RDS_DEBUG_BUF_SIZE		0x10000
50b86efd96Sagiri #else
51b86efd96Sagiri #define	RDS_DEBUG_BUF_SIZE		0x2000
52b86efd96Sagiri #endif	/* DEBUG */
53b86efd96Sagiri 
54b86efd96Sagiri /* Max length of a debug statement */
55b86efd96Sagiri #define	RDS_PRINT_BUF_LEN	4096
56b86efd96Sagiri 
57b86efd96Sagiri int	rds_suppress_dprintf;		/* Suppress debug printing */
58b86efd96Sagiri int	rds_buffer_dprintf = 1;		/* Use debug buffer (0 == console) */
59b86efd96Sagiri int	rds_debug_buf_size = RDS_DEBUG_BUF_SIZE; /* Sz of Debug buf */
60b86efd96Sagiri int	rds_allow_intr_msgs = 0;	/* log "intr" messages */
61b86efd96Sagiri char	*rds_debug_buf = NULL;		/* The Debug Buf */
62b86efd96Sagiri char	*rds_buf_sptr, *rds_buf_eptr;	/* debug buffer temp pointer */
63b86efd96Sagiri int	rds_clear_debug_buf_flag = 0;	/* Clear debug buffer */
64b86efd96Sagiri extern uint_t	rdsdbglvl;
65b86efd96Sagiri 
66b86efd96Sagiri /*
67b86efd96Sagiri  * Print Buffer protected by mutex for debug stuff. The mutex also
68b86efd96Sagiri  * ensures serializing debug messages.
69b86efd96Sagiri  */
70b86efd96Sagiri static kmutex_t	rds_debug_mutex;
71b86efd96Sagiri static char	rds_print_buf[RDS_PRINT_BUF_LEN];
72b86efd96Sagiri 
73b86efd96Sagiri /* Function Prototypes */
74b86efd96Sagiri static void	rds_clear_print_buf();
75b86efd96Sagiri 
76b86efd96Sagiri /* RDS logging init */
77b86efd96Sagiri void
rds_logging_initialization()78b86efd96Sagiri rds_logging_initialization()
79b86efd96Sagiri {
80b86efd96Sagiri 	boolean_t flag = B_FALSE;
81b86efd96Sagiri 
82b86efd96Sagiri 	mutex_init(&rds_debug_mutex, NULL, MUTEX_DRIVER, NULL);
83b86efd96Sagiri 	mutex_enter(&rds_debug_mutex);
84b86efd96Sagiri 
85b86efd96Sagiri 	if (rds_debug_buf_size <= RDS_DEBUG_SIZE_EXTRA_ALLOC) {
86b86efd96Sagiri 		rds_debug_buf_size = RDS_MIN_DEBUG_BUF_SIZE;
87b86efd96Sagiri 		flag = B_TRUE;
88b86efd96Sagiri 	}
89b86efd96Sagiri 
90b86efd96Sagiri 	/* if it is less that RDS_MIN_DEBUG_BUF_SIZE, adjust it */
91b86efd96Sagiri 	rds_debug_buf_size = max(RDS_MIN_DEBUG_BUF_SIZE,
92b86efd96Sagiri 	    rds_debug_buf_size);
93b86efd96Sagiri 
94b86efd96Sagiri 	rds_debug_buf = (char *)kmem_alloc(rds_debug_buf_size, KM_SLEEP);
95b86efd96Sagiri 	rds_clear_print_buf();
96b86efd96Sagiri 	mutex_exit(&rds_debug_mutex);
97b86efd96Sagiri 
98b86efd96Sagiri 	if (flag == B_TRUE) {
99b86efd96Sagiri 		RDS_DPRINTF2("RDS", "rds_debug_buf_size was too small, "
100b86efd96Sagiri 		    "adjusted to %x", rds_debug_buf_size);
101b86efd96Sagiri 	}
102b86efd96Sagiri }
103b86efd96Sagiri 
104b86efd96Sagiri 
105b86efd96Sagiri /* RDS logging destroy */
106b86efd96Sagiri void
rds_logging_destroy()107b86efd96Sagiri rds_logging_destroy()
108b86efd96Sagiri {
109b86efd96Sagiri 	mutex_enter(&rds_debug_mutex);
110b86efd96Sagiri 	if (rds_debug_buf) {
111b86efd96Sagiri 		kmem_free(rds_debug_buf, rds_debug_buf_size);
112b86efd96Sagiri 		rds_debug_buf = NULL;
113b86efd96Sagiri 	}
114b86efd96Sagiri 	mutex_exit(&rds_debug_mutex);
115b86efd96Sagiri 	mutex_destroy(&rds_debug_mutex);
116b86efd96Sagiri }
117b86efd96Sagiri 
118b86efd96Sagiri 
119b86efd96Sagiri /*
120b86efd96Sagiri  * debug, log, and console message handling
121b86efd96Sagiri  */
122b86efd96Sagiri 
123b86efd96Sagiri /*
124b86efd96Sagiri  * clear the RDS debug buffer
125b86efd96Sagiri  */
126b86efd96Sagiri static void
rds_clear_print_buf()127b86efd96Sagiri rds_clear_print_buf()
128b86efd96Sagiri {
129b86efd96Sagiri 	ASSERT(MUTEX_HELD(&rds_debug_mutex));
130b86efd96Sagiri 	if (rds_debug_buf) {
131b86efd96Sagiri 		rds_buf_sptr = rds_debug_buf;
132b86efd96Sagiri 		rds_buf_eptr = rds_debug_buf + rds_debug_buf_size -
133b86efd96Sagiri 		    RDS_DEBUG_SIZE_EXTRA_ALLOC;
134b86efd96Sagiri 
135b86efd96Sagiri 		bzero(rds_debug_buf, rds_debug_buf_size);
136b86efd96Sagiri 	}
137b86efd96Sagiri }
138b86efd96Sagiri 
139b86efd96Sagiri 
140b86efd96Sagiri static void
rds_vlog(char * name,uint_t level,char * fmt,va_list ap)141b86efd96Sagiri rds_vlog(char *name, uint_t level, char *fmt, va_list ap)
142b86efd96Sagiri {
143b86efd96Sagiri 	char	*label = (name == NULL) ? "rds" : name;
144b86efd96Sagiri 	char	*msg_ptr;
145b86efd96Sagiri 	size_t	len;
146b86efd96Sagiri 
147b86efd96Sagiri 	mutex_enter(&rds_debug_mutex);
148b86efd96Sagiri 
149b86efd96Sagiri 	/* if not using logging scheme; quit */
150b86efd96Sagiri 	if (rds_suppress_dprintf || (rds_debug_buf == NULL)) {
151b86efd96Sagiri 		mutex_exit(&rds_debug_mutex);
152b86efd96Sagiri 		return;
153b86efd96Sagiri 	}
154b86efd96Sagiri 
155b86efd96Sagiri 	/* If user requests to clear debug buffer, go ahead */
156b86efd96Sagiri 	if (rds_clear_debug_buf_flag != 0) {
157b86efd96Sagiri 		rds_clear_print_buf();
158b86efd96Sagiri 		rds_clear_debug_buf_flag = 0;
159b86efd96Sagiri 	}
160b86efd96Sagiri 
161b86efd96Sagiri 	/*
162b86efd96Sagiri 	 * put "label" into the buffer
163b86efd96Sagiri 	 */
164b86efd96Sagiri 	len = snprintf(rds_print_buf, RDS_FUNCNAME_LEN, "%s:\t", label);
165b86efd96Sagiri 
166b86efd96Sagiri 	msg_ptr = rds_print_buf + len;
167b86efd96Sagiri 	len += vsnprintf(msg_ptr, RDS_PRINT_BUF_LEN - len - 2, fmt, ap);
168b86efd96Sagiri 
169b86efd96Sagiri 	len = min(len, RDS_PRINT_BUF_LEN - 2);
170b86efd96Sagiri 	ASSERT(len == strlen(rds_print_buf));
171b86efd96Sagiri 	rds_print_buf[len++] = '\n';
172b86efd96Sagiri 	rds_print_buf[len] = '\0';
173b86efd96Sagiri 
174b86efd96Sagiri 	/*
175b86efd96Sagiri 	 * stuff the message in the debug buf
176b86efd96Sagiri 	 */
177b86efd96Sagiri 	if (rds_buffer_dprintf) {
178b86efd96Sagiri 
179b86efd96Sagiri 		/*
180b86efd96Sagiri 		 * overwrite >>>> that might be over the end of the
181b86efd96Sagiri 		 * the buffer
182b86efd96Sagiri 		 */
183b86efd96Sagiri 		*rds_buf_sptr = '\0';
184b86efd96Sagiri 
185b86efd96Sagiri 		if (rds_buf_sptr + len > rds_buf_eptr) {
186b86efd96Sagiri 			size_t left = (uintptr_t)rds_buf_eptr -
187b86efd96Sagiri 			    (uintptr_t)rds_buf_sptr;
188b86efd96Sagiri 
189b86efd96Sagiri 			bcopy((caddr_t)rds_print_buf,
190*74242422Sagiri 			    (caddr_t)rds_buf_sptr, left);
191b86efd96Sagiri 			bcopy((caddr_t)rds_print_buf + left,
192*74242422Sagiri 			    (caddr_t)rds_debug_buf, len - left);
193b86efd96Sagiri 			rds_buf_sptr = rds_debug_buf + len - left;
194b86efd96Sagiri 		} else {
195b86efd96Sagiri 			bcopy((caddr_t)rds_print_buf, rds_buf_sptr, len);
196b86efd96Sagiri 			rds_buf_sptr += len;
197b86efd96Sagiri 		}
198b86efd96Sagiri 
199b86efd96Sagiri 		/* add marker */
200b86efd96Sagiri 		(void) sprintf(rds_buf_sptr, ">>>>");
201b86efd96Sagiri 	}
202b86efd96Sagiri 
203b86efd96Sagiri 	/*
204b86efd96Sagiri 	 * LINTR, L5-L2 message may go to the rds_debug_buf
205*74242422Sagiri 	 * L1 messages will go to the /var/adm/messages (debug & non-debug).
206*74242422Sagiri 	 * L0 messages will go to console (debug & non-debug).
207b86efd96Sagiri 	 */
208b86efd96Sagiri 	switch (level) {
209b86efd96Sagiri 	case RDS_LOG_LINTR:
210b86efd96Sagiri 	case RDS_LOG_L5:
211b86efd96Sagiri 	case RDS_LOG_L4:
212b86efd96Sagiri 	case RDS_LOG_L3:
213b86efd96Sagiri 	case RDS_LOG_L2:
214b86efd96Sagiri 		if (!rds_buffer_dprintf) {
215b86efd96Sagiri 			cmn_err(CE_CONT, "^%s", rds_print_buf);
216b86efd96Sagiri 		}
217b86efd96Sagiri 		break;
218b86efd96Sagiri 	case RDS_LOG_L1:
219b86efd96Sagiri 		if (!rds_buffer_dprintf) {
220b86efd96Sagiri 			cmn_err(CE_CONT, "^%s", rds_print_buf);
221*74242422Sagiri 		} else {
222*74242422Sagiri 			/* go to messages file */
223*74242422Sagiri 			cmn_err(CE_CONT, "!%s", rds_print_buf);
224b86efd96Sagiri 		}
225b86efd96Sagiri 		break;
226b86efd96Sagiri 	case RDS_LOG_L0:
227b86efd96Sagiri 		/* Strip the "\n" added earlier */
228b86efd96Sagiri 		if (rds_print_buf[len - 1] == '\n') {
229b86efd96Sagiri 			rds_print_buf[len - 1] = '\0';
230b86efd96Sagiri 		}
231b86efd96Sagiri 		if (msg_ptr[len - 1] == '\n') {
232b86efd96Sagiri 			msg_ptr[len - 1] = '\0';
233b86efd96Sagiri 		}
234*74242422Sagiri 		/* go to console */
235*74242422Sagiri 		cmn_err(CE_CONT, "^%s", rds_print_buf);
236b86efd96Sagiri 		break;
237b86efd96Sagiri 	}
238b86efd96Sagiri 
239b86efd96Sagiri 	mutex_exit(&rds_debug_mutex);
240b86efd96Sagiri }
241b86efd96Sagiri 
242b86efd96Sagiri void
rds_dprintf_intr(char * name,char * fmt,...)243b86efd96Sagiri rds_dprintf_intr(char *name, char *fmt, ...)
244b86efd96Sagiri {
245b86efd96Sagiri 	va_list ap;
246b86efd96Sagiri 
247b86efd96Sagiri 	va_start(ap, fmt);
248b86efd96Sagiri 	rds_vlog(name, RDS_LOG_LINTR, fmt, ap);
249b86efd96Sagiri 	va_end(ap);
250b86efd96Sagiri }
251b86efd96Sagiri 
252b86efd96Sagiri /*
253b86efd96Sagiri  * Check individual subsystem err levels
254b86efd96Sagiri  */
255b86efd96Sagiri #define	RDS_CHECK_ERR_LEVEL(level)		\
256b86efd96Sagiri 	if (rdsdbglvl < level)			\
257b86efd96Sagiri 		return;				\
258b86efd96Sagiri 
259b86efd96Sagiri void
rds_dprintf5(char * name,char * fmt,...)260b86efd96Sagiri rds_dprintf5(char *name, char *fmt, ...)
261b86efd96Sagiri {
262b86efd96Sagiri 	va_list ap;
263b86efd96Sagiri 
264b86efd96Sagiri 	RDS_CHECK_ERR_LEVEL(RDS_LOG_L5);
265b86efd96Sagiri 
266b86efd96Sagiri 	va_start(ap, fmt);
267b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L5, fmt, ap);
268b86efd96Sagiri 	va_end(ap);
269b86efd96Sagiri }
270b86efd96Sagiri 
271b86efd96Sagiri void
rds_dprintf4(char * name,char * fmt,...)272b86efd96Sagiri rds_dprintf4(char *name, char *fmt, ...)
273b86efd96Sagiri {
274b86efd96Sagiri 	va_list ap;
275b86efd96Sagiri 
276b86efd96Sagiri 	RDS_CHECK_ERR_LEVEL(RDS_LOG_L4);
277b86efd96Sagiri 
278b86efd96Sagiri 	va_start(ap, fmt);
279b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L4, fmt, ap);
280b86efd96Sagiri 	va_end(ap);
281b86efd96Sagiri }
282b86efd96Sagiri 
283b86efd96Sagiri void
rds_dprintf3(char * name,char * fmt,...)284b86efd96Sagiri rds_dprintf3(char *name, char *fmt, ...)
285b86efd96Sagiri {
286b86efd96Sagiri 	va_list ap;
287b86efd96Sagiri 
288b86efd96Sagiri 	RDS_CHECK_ERR_LEVEL(RDS_LOG_L3);
289b86efd96Sagiri 
290b86efd96Sagiri 	va_start(ap, fmt);
291b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L3, fmt, ap);
292b86efd96Sagiri 	va_end(ap);
293b86efd96Sagiri }
294b86efd96Sagiri 
295b86efd96Sagiri void
rds_dprintf2(char * name,char * fmt,...)296b86efd96Sagiri rds_dprintf2(char *name, char *fmt, ...)
297b86efd96Sagiri {
298b86efd96Sagiri 	va_list ap;
299b86efd96Sagiri 
300b86efd96Sagiri 	RDS_CHECK_ERR_LEVEL(RDS_LOG_L2);
301b86efd96Sagiri 
302b86efd96Sagiri 	va_start(ap, fmt);
303b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L2, fmt, ap);
304b86efd96Sagiri 	va_end(ap);
305b86efd96Sagiri }
306b86efd96Sagiri 
307b86efd96Sagiri void
rds_dprintf1(char * name,char * fmt,...)308b86efd96Sagiri rds_dprintf1(char *name, char *fmt, ...)
309b86efd96Sagiri {
310b86efd96Sagiri 	va_list ap;
311b86efd96Sagiri 
312b86efd96Sagiri 	va_start(ap, fmt);
313b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L1, fmt, ap);
314b86efd96Sagiri 	va_end(ap);
315b86efd96Sagiri }
316b86efd96Sagiri 
317b86efd96Sagiri 
318b86efd96Sagiri /*
319b86efd96Sagiri  * Function:
320b86efd96Sagiri  *      rds_dprintf0
321b86efd96Sagiri  * Input:
322b86efd96Sagiri  *      name	- Name of the function generating the debug message
323b86efd96Sagiri  *  	fmt	- The message to be displayed.
324b86efd96Sagiri  * Output:
325b86efd96Sagiri  *      none
326b86efd96Sagiri  * Returns:
327b86efd96Sagiri  *      none
328b86efd96Sagiri  * Description:
329b86efd96Sagiri  *  	A generic log function to display RDS debug messages.
330b86efd96Sagiri  */
331b86efd96Sagiri void
rds_dprintf0(char * name,char * fmt,...)332b86efd96Sagiri rds_dprintf0(char *name, char *fmt, ...)
333b86efd96Sagiri {
334b86efd96Sagiri 	va_list ap;
335b86efd96Sagiri 
336b86efd96Sagiri 	va_start(ap, fmt);
337b86efd96Sagiri 	rds_vlog(name, RDS_LOG_L0, fmt, ap);
338b86efd96Sagiri 	va_end(ap);
339b86efd96Sagiri }
340