xref: /onnv-gate/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_debug.c (revision 12414:c6b8d642b079)
112198SEiji.Ota@Sun.COM /*
212198SEiji.Ota@Sun.COM  * CDDL HEADER START
312198SEiji.Ota@Sun.COM  *
412198SEiji.Ota@Sun.COM  * The contents of this file are subject to the terms of the
512198SEiji.Ota@Sun.COM  * Common Development and Distribution License (the "License").
612198SEiji.Ota@Sun.COM  * You may not use this file except in compliance with the License.
712198SEiji.Ota@Sun.COM  *
812198SEiji.Ota@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912198SEiji.Ota@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1012198SEiji.Ota@Sun.COM  * See the License for the specific language governing permissions
1112198SEiji.Ota@Sun.COM  * and limitations under the License.
1212198SEiji.Ota@Sun.COM  *
1312198SEiji.Ota@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1412198SEiji.Ota@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512198SEiji.Ota@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1612198SEiji.Ota@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1712198SEiji.Ota@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1812198SEiji.Ota@Sun.COM  *
1912198SEiji.Ota@Sun.COM  * CDDL HEADER END
2012198SEiji.Ota@Sun.COM  */
2112198SEiji.Ota@Sun.COM /*
2212198SEiji.Ota@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2312198SEiji.Ota@Sun.COM  */
2412198SEiji.Ota@Sun.COM #include <sys/types.h>
2512198SEiji.Ota@Sun.COM #include <sys/varargs.h>
2612198SEiji.Ota@Sun.COM #include <sys/cmn_err.h>
2712198SEiji.Ota@Sun.COM #include <sys/ddi.h>
2812198SEiji.Ota@Sun.COM #include <sys/sunddi.h>
29*12414SEiji.Ota@Sun.COM #include <sys/time.h>
3012198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
3112198SEiji.Ota@Sun.COM 
3212198SEiji.Ota@Sun.COM /*
3312198SEiji.Ota@Sun.COM  * This file contains the debug defines and routines.
3412198SEiji.Ota@Sun.COM  * Debugging information is collected in a circular kernel buffer. Debug
3512198SEiji.Ota@Sun.COM  * messages with level lower than rdsv3dbglvl are ignored. The size of the
3612198SEiji.Ota@Sun.COM  * of the debug buffer can be changed by setting 'rdsv3_debug_buf_size' in
3712198SEiji.Ota@Sun.COM  * bytes in /etc/system.
3812198SEiji.Ota@Sun.COM  *
3912198SEiji.Ota@Sun.COM  * The debug buffer can be cleared by setting 'rdsv3_clear_debug_buf_flag = 1'
4012198SEiji.Ota@Sun.COM  * on a running system.
4112198SEiji.Ota@Sun.COM  */
4212198SEiji.Ota@Sun.COM 
4312198SEiji.Ota@Sun.COM #define	RDSV3_DEBUG_SIZE_EXTRA_ALLOC	8
4412198SEiji.Ota@Sun.COM #define	RDSV3_MIN_DEBUG_BUF_SIZE		0x1000
4512198SEiji.Ota@Sun.COM #define	RDSV3_FUNCNAME_LEN		40
4612198SEiji.Ota@Sun.COM #define	RDSV3_PRINTBUF_LEN		4096
4712198SEiji.Ota@Sun.COM #ifdef	DEBUG
4812198SEiji.Ota@Sun.COM #define	RDSV3_DEBUG_BUF_SIZE		0x200000	/* 2M size */
4912198SEiji.Ota@Sun.COM #else
5012198SEiji.Ota@Sun.COM #define	RDSV3_DEBUG_BUF_SIZE		0x2000
5112198SEiji.Ota@Sun.COM #endif	/* DEBUG */
5212198SEiji.Ota@Sun.COM 
5312198SEiji.Ota@Sun.COM /* Max length of a debug statement */
5412198SEiji.Ota@Sun.COM #define	RDSV3_PRINT_BUF_LEN	4096
5512198SEiji.Ota@Sun.COM 
5612198SEiji.Ota@Sun.COM static int rdsv3_suppress_dprintf;	/* Suppress debug printing */
5712198SEiji.Ota@Sun.COM static int rdsv3_buffer_dprintf = 1;	/* Use debug buffer (0 == console) */
5812198SEiji.Ota@Sun.COM static int rdsv3_debug_buf_size = RDSV3_DEBUG_BUF_SIZE; /* Sz of Debug buf */
5912198SEiji.Ota@Sun.COM static int rdsv3_allow_intr_msgs = 0;	/* log "intr" messages */
6012198SEiji.Ota@Sun.COM char *rdsv3_debug_buf = NULL;	/* The Debug Buf */
6112198SEiji.Ota@Sun.COM char *rdsv3_buf_sptr, *rdsv3_buf_eptr;	/* debug buffer temp pointer */
6212198SEiji.Ota@Sun.COM int rdsv3_clear_debug_buf_flag = 0;	/* Clear debug buffer */
6312198SEiji.Ota@Sun.COM uint_t	rdsv3dbglvl = RDSV3_LOG_L4;
6412198SEiji.Ota@Sun.COM 
6512198SEiji.Ota@Sun.COM /*
6612198SEiji.Ota@Sun.COM  * Print Buffer protected by mutex for debug stuff. The mutex also
6712198SEiji.Ota@Sun.COM  * ensures serializing debug messages.
6812198SEiji.Ota@Sun.COM  */
6912198SEiji.Ota@Sun.COM static kmutex_t	rdsv3_debug_mutex;
7012198SEiji.Ota@Sun.COM static char	rdsv3_print_buf[RDSV3_PRINT_BUF_LEN];
7112198SEiji.Ota@Sun.COM 
7212198SEiji.Ota@Sun.COM /* Function Prototypes */
7312198SEiji.Ota@Sun.COM static void	rdsv3_clear_print_buf();
7412198SEiji.Ota@Sun.COM 
7512198SEiji.Ota@Sun.COM /* RDS logging init */
7612198SEiji.Ota@Sun.COM void
rdsv3_logging_initialization()7712198SEiji.Ota@Sun.COM rdsv3_logging_initialization()
7812198SEiji.Ota@Sun.COM {
7912198SEiji.Ota@Sun.COM 	boolean_t flag = B_FALSE;
8012198SEiji.Ota@Sun.COM 
8112198SEiji.Ota@Sun.COM 	mutex_init(&rdsv3_debug_mutex, NULL, MUTEX_DRIVER, NULL);
8212198SEiji.Ota@Sun.COM 	mutex_enter(&rdsv3_debug_mutex);
8312198SEiji.Ota@Sun.COM 
8412198SEiji.Ota@Sun.COM 	if (rdsv3_debug_buf_size <= RDSV3_DEBUG_SIZE_EXTRA_ALLOC) {
8512198SEiji.Ota@Sun.COM 		rdsv3_debug_buf_size = RDSV3_MIN_DEBUG_BUF_SIZE;
8612198SEiji.Ota@Sun.COM 		flag = B_TRUE;
8712198SEiji.Ota@Sun.COM 	}
8812198SEiji.Ota@Sun.COM 
8912198SEiji.Ota@Sun.COM 	/* if it is less that RDSV3_MIN_DEBUG_BUF_SIZE, adjust it */
9012198SEiji.Ota@Sun.COM 	rdsv3_debug_buf_size = max(RDSV3_MIN_DEBUG_BUF_SIZE,
9112198SEiji.Ota@Sun.COM 	    rdsv3_debug_buf_size);
9212198SEiji.Ota@Sun.COM 
9312198SEiji.Ota@Sun.COM 	rdsv3_debug_buf = (char *)kmem_alloc(rdsv3_debug_buf_size, KM_SLEEP);
9412198SEiji.Ota@Sun.COM 	rdsv3_clear_print_buf();
9512198SEiji.Ota@Sun.COM 	mutex_exit(&rdsv3_debug_mutex);
9612198SEiji.Ota@Sun.COM 
9712198SEiji.Ota@Sun.COM 	if (flag == B_TRUE) {
9812198SEiji.Ota@Sun.COM 		RDSV3_DPRINTF2("RDS", "rdsv3_debug_buf_size was too small, "
9912198SEiji.Ota@Sun.COM 		    "adjusted to %x", rdsv3_debug_buf_size);
10012198SEiji.Ota@Sun.COM 	}
10112198SEiji.Ota@Sun.COM }
10212198SEiji.Ota@Sun.COM 
10312198SEiji.Ota@Sun.COM 
10412198SEiji.Ota@Sun.COM /* RDS logging destroy */
10512198SEiji.Ota@Sun.COM void
rdsv3_logging_destroy()10612198SEiji.Ota@Sun.COM rdsv3_logging_destroy()
10712198SEiji.Ota@Sun.COM {
10812198SEiji.Ota@Sun.COM 	mutex_enter(&rdsv3_debug_mutex);
10912198SEiji.Ota@Sun.COM 	if (rdsv3_debug_buf) {
11012198SEiji.Ota@Sun.COM 		kmem_free(rdsv3_debug_buf, rdsv3_debug_buf_size);
11112198SEiji.Ota@Sun.COM 		rdsv3_debug_buf = NULL;
11212198SEiji.Ota@Sun.COM 	}
11312198SEiji.Ota@Sun.COM 	mutex_exit(&rdsv3_debug_mutex);
11412198SEiji.Ota@Sun.COM 	mutex_destroy(&rdsv3_debug_mutex);
11512198SEiji.Ota@Sun.COM }
11612198SEiji.Ota@Sun.COM 
11712198SEiji.Ota@Sun.COM 
11812198SEiji.Ota@Sun.COM /*
11912198SEiji.Ota@Sun.COM  * debug, log, and console message handling
12012198SEiji.Ota@Sun.COM  */
12112198SEiji.Ota@Sun.COM 
12212198SEiji.Ota@Sun.COM /*
12312198SEiji.Ota@Sun.COM  * clear the RDS debug buffer
12412198SEiji.Ota@Sun.COM  */
12512198SEiji.Ota@Sun.COM static void
rdsv3_clear_print_buf()12612198SEiji.Ota@Sun.COM rdsv3_clear_print_buf()
12712198SEiji.Ota@Sun.COM {
12812198SEiji.Ota@Sun.COM 	ASSERT(MUTEX_HELD(&rdsv3_debug_mutex));
12912198SEiji.Ota@Sun.COM 	if (rdsv3_debug_buf) {
13012198SEiji.Ota@Sun.COM 		rdsv3_buf_sptr = rdsv3_debug_buf;
13112198SEiji.Ota@Sun.COM 		rdsv3_buf_eptr = rdsv3_debug_buf + rdsv3_debug_buf_size -
13212198SEiji.Ota@Sun.COM 		    RDSV3_DEBUG_SIZE_EXTRA_ALLOC;
13312198SEiji.Ota@Sun.COM 
13412198SEiji.Ota@Sun.COM 		bzero(rdsv3_debug_buf, rdsv3_debug_buf_size);
13512198SEiji.Ota@Sun.COM 	}
13612198SEiji.Ota@Sun.COM }
13712198SEiji.Ota@Sun.COM 
13812198SEiji.Ota@Sun.COM 
13912198SEiji.Ota@Sun.COM static void
rdsv3_vlog(char * name,uint_t level,char * fmt,va_list ap)14012198SEiji.Ota@Sun.COM rdsv3_vlog(char *name, uint_t level, char *fmt, va_list ap)
14112198SEiji.Ota@Sun.COM {
14212198SEiji.Ota@Sun.COM 	char	*label = (name == NULL) ? "rds" : name;
14312198SEiji.Ota@Sun.COM 	char	*msg_ptr;
14412198SEiji.Ota@Sun.COM 	size_t	len;
14512198SEiji.Ota@Sun.COM 
14612198SEiji.Ota@Sun.COM 	mutex_enter(&rdsv3_debug_mutex);
14712198SEiji.Ota@Sun.COM 
14812198SEiji.Ota@Sun.COM 	/* if not using logging scheme; quit */
14912198SEiji.Ota@Sun.COM 	if (rdsv3_suppress_dprintf || (rdsv3_debug_buf == NULL)) {
15012198SEiji.Ota@Sun.COM 		mutex_exit(&rdsv3_debug_mutex);
15112198SEiji.Ota@Sun.COM 		return;
15212198SEiji.Ota@Sun.COM 	}
15312198SEiji.Ota@Sun.COM 
15412198SEiji.Ota@Sun.COM 	/* If user requests to clear debug buffer, go ahead */
15512198SEiji.Ota@Sun.COM 	if (rdsv3_clear_debug_buf_flag != 0) {
15612198SEiji.Ota@Sun.COM 		rdsv3_clear_print_buf();
15712198SEiji.Ota@Sun.COM 		rdsv3_clear_debug_buf_flag = 0;
15812198SEiji.Ota@Sun.COM 	}
15912198SEiji.Ota@Sun.COM 
16012198SEiji.Ota@Sun.COM 	/*
16112198SEiji.Ota@Sun.COM 	 * put "label" into the buffer
16212198SEiji.Ota@Sun.COM 	 */
16312198SEiji.Ota@Sun.COM 	len = snprintf(rdsv3_print_buf, RDSV3_FUNCNAME_LEN, "%s:\t", label);
16412198SEiji.Ota@Sun.COM 
16512198SEiji.Ota@Sun.COM 	msg_ptr = rdsv3_print_buf + len;
16612198SEiji.Ota@Sun.COM 	len += vsnprintf(msg_ptr, RDSV3_PRINT_BUF_LEN - len - 2, fmt, ap);
16712198SEiji.Ota@Sun.COM 
16812198SEiji.Ota@Sun.COM 	len = min(len, RDSV3_PRINT_BUF_LEN - 2);
16912198SEiji.Ota@Sun.COM 	ASSERT(len == strlen(rdsv3_print_buf));
17012198SEiji.Ota@Sun.COM 	rdsv3_print_buf[len++] = '\n';
17112198SEiji.Ota@Sun.COM 	rdsv3_print_buf[len] = '\0';
17212198SEiji.Ota@Sun.COM 
17312198SEiji.Ota@Sun.COM 	/*
17412198SEiji.Ota@Sun.COM 	 * stuff the message in the debug buf
17512198SEiji.Ota@Sun.COM 	 */
17612198SEiji.Ota@Sun.COM 	if (rdsv3_buffer_dprintf) {
17712198SEiji.Ota@Sun.COM 
17812198SEiji.Ota@Sun.COM 		/*
17912198SEiji.Ota@Sun.COM 		 * overwrite >>>> that might be over the end of the
18012198SEiji.Ota@Sun.COM 		 * the buffer
18112198SEiji.Ota@Sun.COM 		 */
18212198SEiji.Ota@Sun.COM 		*rdsv3_buf_sptr = '\0';
18312198SEiji.Ota@Sun.COM 
18412198SEiji.Ota@Sun.COM 		if (rdsv3_buf_sptr + len > rdsv3_buf_eptr) {
18512198SEiji.Ota@Sun.COM 			size_t left = (uintptr_t)rdsv3_buf_eptr -
18612198SEiji.Ota@Sun.COM 			    (uintptr_t)rdsv3_buf_sptr;
18712198SEiji.Ota@Sun.COM 
18812198SEiji.Ota@Sun.COM 			bcopy((caddr_t)rdsv3_print_buf,
18912198SEiji.Ota@Sun.COM 			    (caddr_t)rdsv3_buf_sptr, left);
19012198SEiji.Ota@Sun.COM 			bcopy((caddr_t)rdsv3_print_buf + left,
19112198SEiji.Ota@Sun.COM 			    (caddr_t)rdsv3_debug_buf, len - left);
19212198SEiji.Ota@Sun.COM 			rdsv3_buf_sptr = rdsv3_debug_buf + len - left;
19312198SEiji.Ota@Sun.COM 		} else {
19412198SEiji.Ota@Sun.COM 			bcopy((caddr_t)rdsv3_print_buf, rdsv3_buf_sptr, len);
19512198SEiji.Ota@Sun.COM 			rdsv3_buf_sptr += len;
19612198SEiji.Ota@Sun.COM 		}
19712198SEiji.Ota@Sun.COM 
19812198SEiji.Ota@Sun.COM 		/* add marker */
19912198SEiji.Ota@Sun.COM 		(void) sprintf(rdsv3_buf_sptr, ">>>>");
20012198SEiji.Ota@Sun.COM 	}
20112198SEiji.Ota@Sun.COM 
20212198SEiji.Ota@Sun.COM 	/*
20312198SEiji.Ota@Sun.COM 	 * LINTR, L5-L2 message may go to the rdsv3_debug_buf
20412198SEiji.Ota@Sun.COM 	 * L1 messages will go to the /var/adm/messages (debug & non-debug).
20512198SEiji.Ota@Sun.COM 	 * L0 messages will go to console (debug & non-debug).
20612198SEiji.Ota@Sun.COM 	 */
20712198SEiji.Ota@Sun.COM 	switch (level) {
20812198SEiji.Ota@Sun.COM 	case RDSV3_LOG_LINTR:
20912198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L5:
21012198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L4:
21112198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L3:
21212198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L2:
21312198SEiji.Ota@Sun.COM 		if (!rdsv3_buffer_dprintf) {
21412198SEiji.Ota@Sun.COM 			cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
21512198SEiji.Ota@Sun.COM 		}
21612198SEiji.Ota@Sun.COM 		break;
21712198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L1:
21812198SEiji.Ota@Sun.COM 		if (!rdsv3_buffer_dprintf) {
21912198SEiji.Ota@Sun.COM 			cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
22012198SEiji.Ota@Sun.COM 		} else {
22112198SEiji.Ota@Sun.COM 			/* go to messages file */
22212198SEiji.Ota@Sun.COM 			cmn_err(CE_CONT, "!%s", rdsv3_print_buf);
22312198SEiji.Ota@Sun.COM 		}
22412198SEiji.Ota@Sun.COM 		break;
22512198SEiji.Ota@Sun.COM 	case RDSV3_LOG_L0:
22612198SEiji.Ota@Sun.COM 		/* Strip the "\n" added earlier */
22712198SEiji.Ota@Sun.COM 		if (rdsv3_print_buf[len - 1] == '\n') {
22812198SEiji.Ota@Sun.COM 			rdsv3_print_buf[len - 1] = '\0';
22912198SEiji.Ota@Sun.COM 		}
23012198SEiji.Ota@Sun.COM 		if (msg_ptr[len - 1] == '\n') {
23112198SEiji.Ota@Sun.COM 			msg_ptr[len - 1] = '\0';
23212198SEiji.Ota@Sun.COM 		}
23312198SEiji.Ota@Sun.COM 		/* go to console */
23412198SEiji.Ota@Sun.COM 		cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
23512198SEiji.Ota@Sun.COM 		break;
23612198SEiji.Ota@Sun.COM 	}
23712198SEiji.Ota@Sun.COM 
23812198SEiji.Ota@Sun.COM 	mutex_exit(&rdsv3_debug_mutex);
23912198SEiji.Ota@Sun.COM }
24012198SEiji.Ota@Sun.COM 
24112198SEiji.Ota@Sun.COM void
rdsv3_dprintf_intr(char * name,char * fmt,...)24212198SEiji.Ota@Sun.COM rdsv3_dprintf_intr(char *name, char *fmt, ...)
24312198SEiji.Ota@Sun.COM {
24412198SEiji.Ota@Sun.COM 	va_list ap;
24512198SEiji.Ota@Sun.COM 
24612198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
24712198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_LINTR, fmt, ap);
24812198SEiji.Ota@Sun.COM 	va_end(ap);
24912198SEiji.Ota@Sun.COM }
25012198SEiji.Ota@Sun.COM 
25112198SEiji.Ota@Sun.COM /*
25212198SEiji.Ota@Sun.COM  * Check individual subsystem err levels
25312198SEiji.Ota@Sun.COM  */
25412198SEiji.Ota@Sun.COM #define	RDSV3_CHECK_ERR_LEVEL(level)		\
25512198SEiji.Ota@Sun.COM 	if (rdsv3dbglvl < level)		\
25612198SEiji.Ota@Sun.COM 		return;				\
25712198SEiji.Ota@Sun.COM 
25812198SEiji.Ota@Sun.COM void
rdsv3_dprintf5(char * name,char * fmt,...)25912198SEiji.Ota@Sun.COM rdsv3_dprintf5(char *name, char *fmt, ...)
26012198SEiji.Ota@Sun.COM {
26112198SEiji.Ota@Sun.COM 	va_list ap;
26212198SEiji.Ota@Sun.COM 
26312198SEiji.Ota@Sun.COM 	RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L5);
26412198SEiji.Ota@Sun.COM 
26512198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
26612198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L5, fmt, ap);
26712198SEiji.Ota@Sun.COM 	va_end(ap);
26812198SEiji.Ota@Sun.COM }
26912198SEiji.Ota@Sun.COM 
27012198SEiji.Ota@Sun.COM void
rdsv3_dprintf4(char * name,char * fmt,...)27112198SEiji.Ota@Sun.COM rdsv3_dprintf4(char *name, char *fmt, ...)
27212198SEiji.Ota@Sun.COM {
27312198SEiji.Ota@Sun.COM 	va_list ap;
27412198SEiji.Ota@Sun.COM 
27512198SEiji.Ota@Sun.COM 	RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L4);
27612198SEiji.Ota@Sun.COM 
27712198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
27812198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L4, fmt, ap);
27912198SEiji.Ota@Sun.COM 	va_end(ap);
28012198SEiji.Ota@Sun.COM }
28112198SEiji.Ota@Sun.COM 
28212198SEiji.Ota@Sun.COM void
rdsv3_dprintf3(char * name,char * fmt,...)28312198SEiji.Ota@Sun.COM rdsv3_dprintf3(char *name, char *fmt, ...)
28412198SEiji.Ota@Sun.COM {
28512198SEiji.Ota@Sun.COM 	va_list ap;
28612198SEiji.Ota@Sun.COM 
28712198SEiji.Ota@Sun.COM 	RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L3);
28812198SEiji.Ota@Sun.COM 
28912198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
29012198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L3, fmt, ap);
29112198SEiji.Ota@Sun.COM 	va_end(ap);
29212198SEiji.Ota@Sun.COM }
29312198SEiji.Ota@Sun.COM 
29412198SEiji.Ota@Sun.COM void
rdsv3_dprintf2(char * name,char * fmt,...)29512198SEiji.Ota@Sun.COM rdsv3_dprintf2(char *name, char *fmt, ...)
29612198SEiji.Ota@Sun.COM {
29712198SEiji.Ota@Sun.COM 	va_list ap;
29812198SEiji.Ota@Sun.COM 
29912198SEiji.Ota@Sun.COM 	RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L2);
30012198SEiji.Ota@Sun.COM 
30112198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
30212198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L2, fmt, ap);
30312198SEiji.Ota@Sun.COM 	va_end(ap);
30412198SEiji.Ota@Sun.COM }
30512198SEiji.Ota@Sun.COM 
30612198SEiji.Ota@Sun.COM void
rdsv3_dprintf1(char * name,char * fmt,...)30712198SEiji.Ota@Sun.COM rdsv3_dprintf1(char *name, char *fmt, ...)
30812198SEiji.Ota@Sun.COM {
30912198SEiji.Ota@Sun.COM 	va_list ap;
31012198SEiji.Ota@Sun.COM 
31112198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
31212198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L1, fmt, ap);
31312198SEiji.Ota@Sun.COM 	va_end(ap);
31412198SEiji.Ota@Sun.COM }
31512198SEiji.Ota@Sun.COM 
31612198SEiji.Ota@Sun.COM 
31712198SEiji.Ota@Sun.COM /*
31812198SEiji.Ota@Sun.COM  * Function:
31912198SEiji.Ota@Sun.COM  *      rdsv3_dprintf0
32012198SEiji.Ota@Sun.COM  * Input:
32112198SEiji.Ota@Sun.COM  *      name	- Name of the function generating the debug message
32212198SEiji.Ota@Sun.COM  *  	fmt	- The message to be displayed.
32312198SEiji.Ota@Sun.COM  * Output:
32412198SEiji.Ota@Sun.COM  *      none
32512198SEiji.Ota@Sun.COM  * Returns:
32612198SEiji.Ota@Sun.COM  *      none
32712198SEiji.Ota@Sun.COM  * Description:
32812198SEiji.Ota@Sun.COM  *  	A generic log function to display RDS debug messages.
32912198SEiji.Ota@Sun.COM  */
33012198SEiji.Ota@Sun.COM void
rdsv3_dprintf0(char * name,char * fmt,...)33112198SEiji.Ota@Sun.COM rdsv3_dprintf0(char *name, char *fmt, ...)
33212198SEiji.Ota@Sun.COM {
33312198SEiji.Ota@Sun.COM 	va_list ap;
33412198SEiji.Ota@Sun.COM 
33512198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
33612198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, RDSV3_LOG_L0, fmt, ap);
33712198SEiji.Ota@Sun.COM 	va_end(ap);
33812198SEiji.Ota@Sun.COM }
33912198SEiji.Ota@Sun.COM 
34012198SEiji.Ota@Sun.COM /* For ofed rdstrace */
34112198SEiji.Ota@Sun.COM void
rdsv3_trace(char * name,uint8_t lvl,char * fmt,...)34212198SEiji.Ota@Sun.COM rdsv3_trace(char *name, uint8_t lvl, char *fmt, ...)
34312198SEiji.Ota@Sun.COM {
34412198SEiji.Ota@Sun.COM 	va_list ap;
34512198SEiji.Ota@Sun.COM 
34612198SEiji.Ota@Sun.COM 	va_start(ap, fmt);
34712198SEiji.Ota@Sun.COM 	rdsv3_vlog(name, lvl, fmt, ap);
34812198SEiji.Ota@Sun.COM 	va_end(ap);
34912198SEiji.Ota@Sun.COM }
350*12414SEiji.Ota@Sun.COM 
351*12414SEiji.Ota@Sun.COM #define	DEFAULT_RATELIMIT_INTERVAL	5
352*12414SEiji.Ota@Sun.COM #define	DEFAULT_RATELIMIT_BURST	10
353*12414SEiji.Ota@Sun.COM 
354*12414SEiji.Ota@Sun.COM struct ratelimit_state {
355*12414SEiji.Ota@Sun.COM 	clock_t interval;
356*12414SEiji.Ota@Sun.COM 	int burst;
357*12414SEiji.Ota@Sun.COM 	int printed;
358*12414SEiji.Ota@Sun.COM 	int missed;
359*12414SEiji.Ota@Sun.COM 	hrtime_t begin;
360*12414SEiji.Ota@Sun.COM 	kmutex_t lock;
361*12414SEiji.Ota@Sun.COM };
362*12414SEiji.Ota@Sun.COM 
363*12414SEiji.Ota@Sun.COM #define	DEFINE_RATELIMIT_STATE(name, interval, burst)		\
364*12414SEiji.Ota@Sun.COM 	static struct ratelimit_state name = {interval, burst, }
365*12414SEiji.Ota@Sun.COM 
366*12414SEiji.Ota@Sun.COM DEFINE_RATELIMIT_STATE(rdsv3_printk_ratelimit_state,
367*12414SEiji.Ota@Sun.COM     DEFAULT_RATELIMIT_INTERVAL,
368*12414SEiji.Ota@Sun.COM     DEFAULT_RATELIMIT_BURST);
369*12414SEiji.Ota@Sun.COM 
370*12414SEiji.Ota@Sun.COM int
rdsv3_printk_ratelimit(void)371*12414SEiji.Ota@Sun.COM rdsv3_printk_ratelimit(void)
372*12414SEiji.Ota@Sun.COM {
373*12414SEiji.Ota@Sun.COM 	struct ratelimit_state *rs = &rdsv3_printk_ratelimit_state;
374*12414SEiji.Ota@Sun.COM 	hrtime_t current = gethrtime();
375*12414SEiji.Ota@Sun.COM 	int rtn = 0;
376*12414SEiji.Ota@Sun.COM 
377*12414SEiji.Ota@Sun.COM 	if (rs->interval) {
378*12414SEiji.Ota@Sun.COM 		return (1);
379*12414SEiji.Ota@Sun.COM 	}
380*12414SEiji.Ota@Sun.COM 	mutex_enter(&rs->lock);
381*12414SEiji.Ota@Sun.COM 	if (!rs->begin) {
382*12414SEiji.Ota@Sun.COM 		rs->begin = current;
383*12414SEiji.Ota@Sun.COM 	}
384*12414SEiji.Ota@Sun.COM 	if (current < rs->begin + TICK_TO_NSEC(rs->interval)) {
385*12414SEiji.Ota@Sun.COM 		if (rs->missed) {
386*12414SEiji.Ota@Sun.COM 			RDSV3_DPRINTF0("rdsv3_printk_ratelimit: ",
387*12414SEiji.Ota@Sun.COM 			    "%d callbacks suppressed\n", rs->missed);
388*12414SEiji.Ota@Sun.COM 			rs->begin = 0;
389*12414SEiji.Ota@Sun.COM 			rs->printed = 0;
390*12414SEiji.Ota@Sun.COM 			rs->missed = 0;
391*12414SEiji.Ota@Sun.COM 		}
392*12414SEiji.Ota@Sun.COM 	}
393*12414SEiji.Ota@Sun.COM 	if (rs->burst && rs->burst > rs->printed) {
394*12414SEiji.Ota@Sun.COM 		rs->printed++;
395*12414SEiji.Ota@Sun.COM 		rtn = 1;
396*12414SEiji.Ota@Sun.COM 	} else {
397*12414SEiji.Ota@Sun.COM 		rs->missed++;
398*12414SEiji.Ota@Sun.COM 	}
399*12414SEiji.Ota@Sun.COM 	mutex_exit(&rs->lock);
400*12414SEiji.Ota@Sun.COM 	return (rtn);
401*12414SEiji.Ota@Sun.COM }
402