xref: /onnv-gate/usr/src/uts/sun4/io/px/px_debug.c (revision 3790:129fe0da02b8)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3790Set142600  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * PCI nexus driver general debug support
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate #include <sys/async.h>
320Sstevel@tonic-gate #include <sys/sunddi.h>		/* dev_info_t */
330Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
340Sstevel@tonic-gate #include <sys/disp.h>
353274Set142600 #include <sys/archsystm.h>	/* getpil() */
363274Set142600 #include "px_obj.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*LINTLIBRARY*/
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #ifdef	DEBUG
41332Sjchu uint64_t px_debug_flags = 0;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate static char *px_debug_sym [] = {	/* same sequence as px_debug_bit */
440Sstevel@tonic-gate 	/*  0 */ "attach",
450Sstevel@tonic-gate 	/*  1 */ "detach",
460Sstevel@tonic-gate 	/*  2 */ "map",
470Sstevel@tonic-gate 	/*  3 */ "nex-ctlops",
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	/*  4 */ "introps",
500Sstevel@tonic-gate 	/*  5 */ "intx-add",
510Sstevel@tonic-gate 	/*  6 */ "intx-rem",
520Sstevel@tonic-gate 	/*  7 */ "intx-intr",
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	/*  8 */ "msiq",
550Sstevel@tonic-gate 	/*  9 */ "msiq-intr",
560Sstevel@tonic-gate 	/* 10 */ "msg",
570Sstevel@tonic-gate 	/* 11 */ "msg-intr",
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	/* 12 */ "msix-add",
600Sstevel@tonic-gate 	/* 13 */ "msix-rem",
610Sstevel@tonic-gate 	/* 14 */ "msix-intr",
620Sstevel@tonic-gate 	/* 15 */ "err",
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	/* 16 */ "dma-alloc",
650Sstevel@tonic-gate 	/* 17 */ "dma-free",
660Sstevel@tonic-gate 	/* 18 */ "dma-bind",
670Sstevel@tonic-gate 	/* 19 */ "dma-unbind",
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	/* 20 */ "chk-dma-mode",
700Sstevel@tonic-gate 	/* 21 */ "bypass-dma",
710Sstevel@tonic-gate 	/* 22 */ "fast-dvma",
720Sstevel@tonic-gate 	/* 23 */ "init_child",
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	/* 24 */ "dma-map",
750Sstevel@tonic-gate 	/* 25 */ "dma-win",
760Sstevel@tonic-gate 	/* 26 */ "map-win",
770Sstevel@tonic-gate 	/* 27 */ "unmap-win",
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	/* 28 */ "dma-ctl",
800Sstevel@tonic-gate 	/* 29 */ "dma-sync",
810Sstevel@tonic-gate 	/* 30 */ NULL,
820Sstevel@tonic-gate 	/* 31 */ NULL,
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	/* 32 */ "ib",
850Sstevel@tonic-gate 	/* 33 */ "cb",
860Sstevel@tonic-gate 	/* 34 */ "dmc",
870Sstevel@tonic-gate 	/* 35 */ "pec",
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	/* 36 */ "ilu",
900Sstevel@tonic-gate 	/* 37 */ "tlu",
910Sstevel@tonic-gate 	/* 38 */ "lpu",
921772Sjl139090 	/* 39 */ "mmu",
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	/* 40 */ "open",
950Sstevel@tonic-gate 	/* 41 */ "close",
960Sstevel@tonic-gate 	/* 42 */ "ioctl",
970Sstevel@tonic-gate 	/* 43 */ "pwr",
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	/* 44 */ "lib-cfg",
1000Sstevel@tonic-gate 	/* 45 */ "lib-intr",
1010Sstevel@tonic-gate 	/* 46 */ "lib-dma",
1020Sstevel@tonic-gate 	/* 47 */ "lib-msiq",
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	/* 48 */ "lib-msi",
1050Sstevel@tonic-gate 	/* 49 */ "lib-msg",
1060Sstevel@tonic-gate 	/* 50 */ "NULL",
1070Sstevel@tonic-gate 	/* 51 */ "NULL",
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	/* 52 */ "tools",
1100Sstevel@tonic-gate 	/* 53 */ "phys_acc",
1111786Sjj156685 
1121786Sjj156685 	/* 54 */ "hotplug",
1130Sstevel@tonic-gate 	/* LAST */ "unknown"
1140Sstevel@tonic-gate };
1150Sstevel@tonic-gate 
1163274Set142600 /* Tunables */
1173274Set142600 static int px_dbg_msg_size = 16;		/* # of Qs.  Must be ^2 */
1183274Set142600 
1193274Set142600 /* Non-Tunables */
1203274Set142600 static int px_dbg_qmask = 0xFFFF;		/* Mask based on Q size */
1213274Set142600 static px_dbg_msg_t *px_dbg_msgq = NULL;	/* Debug Msg Queue */
1223274Set142600 static uint8_t px_dbg_reference = 0;		/* Reference Counter */
1233274Set142600 static kmutex_t px_dbg_mutex;			/* Mutex for dequeuing */
1243274Set142600 static uint8_t px_dbg_qtail = 0;		/* Pointer to q tail */
1253274Set142600 static uint8_t px_dbg_qhead = 0;		/* Pointer to q head */
1263274Set142600 static uint_t px_dbg_qsize = 0;			/* # of pending messages */
1273274Set142600 static uint_t px_dbg_failed = 0;		/* # of overflows */
1283274Set142600 
1293274Set142600 /* Forward Declarations */
1303274Set142600 static void px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
1313274Set142600     va_list args);
1323274Set142600 static void px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
1333274Set142600     va_list args);
1343274Set142600 static uint_t px_dbg_drain(caddr_t arg1, caddr_t arg2);
1353274Set142600 
1363274Set142600 /*
1373274Set142600  * Print function called either directly by px_dbg or through soft interrupt.
1383274Set142600  * This function cannot be called directly in threads with PIL above clock.
1393274Set142600  */
1403274Set142600 static void
px_dbg_print(px_debug_bit_t bit,dev_info_t * dip,char * fmt,va_list args)1413274Set142600 px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
1420Sstevel@tonic-gate {
1430Sstevel@tonic-gate 	int cont = bit >> DBG_BITS;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	if (cont)
1460Sstevel@tonic-gate 		goto body;
147332Sjchu 
148332Sjchu 	if (dip)
149332Sjchu 		prom_printf("%s(%d): %s: ", ddi_driver_name(dip),
150332Sjchu 		    ddi_get_instance(dip), px_debug_sym[bit]);
151332Sjchu 	else
152332Sjchu 		prom_printf("px: %s: ", px_debug_sym[bit]);
1530Sstevel@tonic-gate body:
1543274Set142600 	if (args)
1553274Set142600 		prom_vprintf(fmt, args);
1563274Set142600 	else
1573274Set142600 		prom_printf(fmt);
1583274Set142600 }
1593274Set142600 
1603274Set142600 /*
1613274Set142600  * Queueing mechanism to log px_dbg messages if calling thread is running with a
1623274Set142600  * PIL above clock. It's Multithreaded safe.
1633274Set142600  */
1643274Set142600 static void
px_dbg_queue(px_debug_bit_t bit,dev_info_t * dip,char * fmt,va_list args)1653274Set142600 px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
1663274Set142600 {
1673274Set142600 	int		instance = DIP_TO_INST(dip);
1683274Set142600 	px_t		*px_p = INST_TO_STATE(instance);
1693274Set142600 	uint8_t		q_no;
1703274Set142600 	px_dbg_msg_t	*msg_p;
1713274Set142600 
1723274Set142600 	/* Check to make sure the queue hasn't overflowed */
1733274Set142600 	if (atomic_inc_uint_nv(&px_dbg_qsize) >= px_dbg_msg_size) {
1743274Set142600 		px_dbg_failed++;
1753274Set142600 		atomic_dec_uint(&px_dbg_qsize);
1763274Set142600 		return;
1773274Set142600 	}
1783274Set142600 
1793274Set142600 	/*
1803274Set142600 	 * Grab the next available queue bucket. Incrementing the tail here
1813274Set142600 	 * doesn't need to be protected, as it is guaranteed to not overflow.
1823274Set142600 	 */
1833274Set142600 	q_no = ++px_dbg_qtail & px_dbg_qmask;
1843274Set142600 	msg_p = &px_dbg_msgq[q_no];
1853274Set142600 
1863274Set142600 	ASSERT(msg_p->active == B_FALSE);
1873274Set142600 
1883274Set142600 	/* Print the message in the buffer */
1893274Set142600 	vsnprintf(msg_p->msg, DBG_MSG_SIZE, fmt, args);
1903274Set142600 	msg_p->bit = bit;
1913274Set142600 	msg_p->dip = dip;
1923274Set142600 	msg_p->active = B_TRUE;
1933274Set142600 
1943274Set142600 	/* Trigger Soft Int */
1953274Set142600 	ddi_intr_trigger_softint(px_p->px_dbg_hdl, (caddr_t)NULL);
1963274Set142600 }
1973274Set142600 
1983274Set142600 /*
1993274Set142600  * Callback function for queuing px_dbg in high PIL by soft intr.  This code
2003274Set142600  * assumes it will be called serially for every msg.
2013274Set142600  */
2023274Set142600 static uint_t
px_dbg_drain(caddr_t arg1,caddr_t arg2)2033274Set142600 px_dbg_drain(caddr_t arg1, caddr_t arg2) {
2043274Set142600 	uint8_t		q_no;
2053274Set142600 	px_dbg_msg_t	*msg_p;
2063274Set142600 	uint_t		ret = DDI_INTR_UNCLAIMED;
2073274Set142600 
2083274Set142600 	mutex_enter(&px_dbg_mutex);
2093274Set142600 	while (px_dbg_qsize) {
2103274Set142600 		atomic_dec_uint(&px_dbg_qsize);
2113274Set142600 		if (px_dbg_failed) {
2123274Set142600 			cmn_err(CE_WARN, "%d msg(s) were lost",
2133274Set142600 			    px_dbg_failed);
2143274Set142600 			px_dbg_failed = 0;
2153274Set142600 		}
2163274Set142600 
2173274Set142600 		q_no = ++px_dbg_qhead & px_dbg_qmask;
2183274Set142600 		msg_p = &px_dbg_msgq[q_no];
2193274Set142600 
2203274Set142600 		if (msg_p->active) {
2213274Set142600 			px_dbg_print(msg_p->bit, msg_p->dip, msg_p->msg, NULL);
2223274Set142600 			msg_p->active = B_FALSE;
2233274Set142600 		}
2243274Set142600 		ret = DDI_INTR_CLAIMED;
2253274Set142600 	}
2263274Set142600 
2273274Set142600 	mutex_exit(&px_dbg_mutex);
2283274Set142600 	return (ret);
2293274Set142600 }
2303274Set142600 
2313274Set142600 void
px_dbg(px_debug_bit_t bit,dev_info_t * dip,char * fmt,...)2323274Set142600 px_dbg(px_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
2333274Set142600 {
2343274Set142600 	va_list ap;
2353274Set142600 
2363274Set142600 	bit &= DBG_MASK;
2373274Set142600 	if (bit >= sizeof (px_debug_sym) / sizeof (char *))
2383274Set142600 		return;
2393274Set142600 	if (!(1ull << bit & px_debug_flags))
2403274Set142600 		return;
2413274Set142600 
2420Sstevel@tonic-gate 	va_start(ap, fmt);
2433274Set142600 	if (getpil() > LOCK_LEVEL)
2443274Set142600 		px_dbg_queue(bit, dip, fmt, ap);
2453274Set142600 	else
2463274Set142600 		px_dbg_print(bit, dip, fmt, ap);
2470Sstevel@tonic-gate 	va_end(ap);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate #endif	/* DEBUG */
2503274Set142600 
2513274Set142600 void
px_dbg_attach(dev_info_t * dip,ddi_softint_handle_t * dbg_hdl)2523274Set142600 px_dbg_attach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
2533274Set142600 {
2543274Set142600 #ifdef	DEBUG
2553274Set142600 	if (px_dbg_reference++ == 0) {
2563274Set142600 		int size = px_dbg_msg_size;
2573274Set142600 
2583274Set142600 		/* Check if px_dbg_msg_size is ^2 */
2593274Set142600 		size = (size & (size - 1)) ? ((size | ~size) + 1) : size;
2603274Set142600 		px_dbg_msg_size = size;
2613274Set142600 		px_dbg_qmask = size - 1;
2623274Set142600 		px_dbg_msgq = kmem_zalloc(sizeof (px_dbg_msg_t) * size,
2633274Set142600 		    KM_SLEEP);
2643274Set142600 
2653274Set142600 		mutex_init(&px_dbg_mutex, NULL, MUTEX_DRIVER, NULL);
2663274Set142600 	}
2673274Set142600 
2683274Set142600 	if (ddi_intr_add_softint(dip, dbg_hdl,
2693274Set142600 		DDI_INTR_SOFTPRI_MAX, px_dbg_drain, NULL) != DDI_SUCCESS) {
2703274Set142600 		DBG(DBG_ATTACH, dip,
2713274Set142600 		    "Unable to allocate soft int for DBG printing.\n");
2723274Set142600 		dbg_hdl = NULL;
2733274Set142600 	}
2743274Set142600 #endif	/* DEBUG */
2753274Set142600 }
2763274Set142600 
2773274Set142600 /* ARGSUSED */
2783274Set142600 void
px_dbg_detach(dev_info_t * dip,ddi_softint_handle_t * dbg_hdl)2793274Set142600 px_dbg_detach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
2803274Set142600 {
2813274Set142600 #ifdef	DEBUG
282*3790Set142600 	if (dbg_hdl != NULL)
283*3790Set142600 		(void) ddi_intr_remove_softint(*dbg_hdl);
284*3790Set142600 
2853274Set142600 	if (--px_dbg_reference == 0) {
2863274Set142600 		if (px_dbg_msgq != NULL)
2873274Set142600 			kmem_free(px_dbg_msgq,
2883274Set142600 			    sizeof (px_dbg_msg_t) * px_dbg_msg_size);
2893274Set142600 		mutex_destroy(&px_dbg_mutex);
2903274Set142600 	}
2913274Set142600 #endif	/* DEBUG */
2923274Set142600 }
293