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