xref: /onnv-gate/usr/src/uts/sun4/io/px/px_debug.c (revision 3274:b750a4e2f4f5)
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 /*
221772Sjl139090  * Copyright 2006 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>
35*3274Set142600 #include <sys/archsystm.h>	/* getpil() */
36*3274Set142600 #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 
116*3274Set142600 /* Tunables */
117*3274Set142600 static int px_dbg_msg_size = 16;		/* # of Qs.  Must be ^2 */
118*3274Set142600 
119*3274Set142600 /* Non-Tunables */
120*3274Set142600 static int px_dbg_qmask = 0xFFFF;		/* Mask based on Q size */
121*3274Set142600 static px_dbg_msg_t *px_dbg_msgq = NULL;	/* Debug Msg Queue */
122*3274Set142600 static uint8_t px_dbg_reference = 0;		/* Reference Counter */
123*3274Set142600 static kmutex_t px_dbg_mutex;			/* Mutex for dequeuing */
124*3274Set142600 static uint8_t px_dbg_qtail = 0;		/* Pointer to q tail */
125*3274Set142600 static uint8_t px_dbg_qhead = 0;		/* Pointer to q head */
126*3274Set142600 static uint_t px_dbg_qsize = 0;			/* # of pending messages */
127*3274Set142600 static uint_t px_dbg_failed = 0;		/* # of overflows */
128*3274Set142600 
129*3274Set142600 /* Forward Declarations */
130*3274Set142600 static void px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
131*3274Set142600     va_list args);
132*3274Set142600 static void px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
133*3274Set142600     va_list args);
134*3274Set142600 static uint_t px_dbg_drain(caddr_t arg1, caddr_t arg2);
135*3274Set142600 
136*3274Set142600 /*
137*3274Set142600  * Print function called either directly by px_dbg or through soft interrupt.
138*3274Set142600  * This function cannot be called directly in threads with PIL above clock.
139*3274Set142600  */
140*3274Set142600 static void
141*3274Set142600 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:
154*3274Set142600 	if (args)
155*3274Set142600 		prom_vprintf(fmt, args);
156*3274Set142600 	else
157*3274Set142600 		prom_printf(fmt);
158*3274Set142600 }
159*3274Set142600 
160*3274Set142600 /*
161*3274Set142600  * Queueing mechanism to log px_dbg messages if calling thread is running with a
162*3274Set142600  * PIL above clock. It's Multithreaded safe.
163*3274Set142600  */
164*3274Set142600 static void
165*3274Set142600 px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
166*3274Set142600 {
167*3274Set142600 	int		instance = DIP_TO_INST(dip);
168*3274Set142600 	px_t		*px_p = INST_TO_STATE(instance);
169*3274Set142600 	uint8_t		q_no;
170*3274Set142600 	px_dbg_msg_t	*msg_p;
171*3274Set142600 
172*3274Set142600 	/* Check to make sure the queue hasn't overflowed */
173*3274Set142600 	if (atomic_inc_uint_nv(&px_dbg_qsize) >= px_dbg_msg_size) {
174*3274Set142600 		px_dbg_failed++;
175*3274Set142600 		atomic_dec_uint(&px_dbg_qsize);
176*3274Set142600 		return;
177*3274Set142600 	}
178*3274Set142600 
179*3274Set142600 	/*
180*3274Set142600 	 * Grab the next available queue bucket. Incrementing the tail here
181*3274Set142600 	 * doesn't need to be protected, as it is guaranteed to not overflow.
182*3274Set142600 	 */
183*3274Set142600 	q_no = ++px_dbg_qtail & px_dbg_qmask;
184*3274Set142600 	msg_p = &px_dbg_msgq[q_no];
185*3274Set142600 
186*3274Set142600 	ASSERT(msg_p->active == B_FALSE);
187*3274Set142600 
188*3274Set142600 	/* Print the message in the buffer */
189*3274Set142600 	vsnprintf(msg_p->msg, DBG_MSG_SIZE, fmt, args);
190*3274Set142600 	msg_p->bit = bit;
191*3274Set142600 	msg_p->dip = dip;
192*3274Set142600 	msg_p->active = B_TRUE;
193*3274Set142600 
194*3274Set142600 	/* Trigger Soft Int */
195*3274Set142600 	ddi_intr_trigger_softint(px_p->px_dbg_hdl, (caddr_t)NULL);
196*3274Set142600 }
197*3274Set142600 
198*3274Set142600 /*
199*3274Set142600  * Callback function for queuing px_dbg in high PIL by soft intr.  This code
200*3274Set142600  * assumes it will be called serially for every msg.
201*3274Set142600  */
202*3274Set142600 static uint_t
203*3274Set142600 px_dbg_drain(caddr_t arg1, caddr_t arg2) {
204*3274Set142600 	uint8_t		q_no;
205*3274Set142600 	px_dbg_msg_t	*msg_p;
206*3274Set142600 	uint_t		ret = DDI_INTR_UNCLAIMED;
207*3274Set142600 
208*3274Set142600 	mutex_enter(&px_dbg_mutex);
209*3274Set142600 	while (px_dbg_qsize) {
210*3274Set142600 		atomic_dec_uint(&px_dbg_qsize);
211*3274Set142600 		if (px_dbg_failed) {
212*3274Set142600 			cmn_err(CE_WARN, "%d msg(s) were lost",
213*3274Set142600 			    px_dbg_failed);
214*3274Set142600 			px_dbg_failed = 0;
215*3274Set142600 		}
216*3274Set142600 
217*3274Set142600 		q_no = ++px_dbg_qhead & px_dbg_qmask;
218*3274Set142600 		msg_p = &px_dbg_msgq[q_no];
219*3274Set142600 
220*3274Set142600 		if (msg_p->active) {
221*3274Set142600 			px_dbg_print(msg_p->bit, msg_p->dip, msg_p->msg, NULL);
222*3274Set142600 			msg_p->active = B_FALSE;
223*3274Set142600 		}
224*3274Set142600 		ret = DDI_INTR_CLAIMED;
225*3274Set142600 	}
226*3274Set142600 
227*3274Set142600 	mutex_exit(&px_dbg_mutex);
228*3274Set142600 	return (ret);
229*3274Set142600 }
230*3274Set142600 
231*3274Set142600 void
232*3274Set142600 px_dbg(px_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
233*3274Set142600 {
234*3274Set142600 	va_list ap;
235*3274Set142600 
236*3274Set142600 	bit &= DBG_MASK;
237*3274Set142600 	if (bit >= sizeof (px_debug_sym) / sizeof (char *))
238*3274Set142600 		return;
239*3274Set142600 	if (!(1ull << bit & px_debug_flags))
240*3274Set142600 		return;
241*3274Set142600 
2420Sstevel@tonic-gate 	va_start(ap, fmt);
243*3274Set142600 	if (getpil() > LOCK_LEVEL)
244*3274Set142600 		px_dbg_queue(bit, dip, fmt, ap);
245*3274Set142600 	else
246*3274Set142600 		px_dbg_print(bit, dip, fmt, ap);
2470Sstevel@tonic-gate 	va_end(ap);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate #endif	/* DEBUG */
250*3274Set142600 
251*3274Set142600 void
252*3274Set142600 px_dbg_attach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
253*3274Set142600 {
254*3274Set142600 #ifdef	DEBUG
255*3274Set142600 	if (px_dbg_reference++ == 0) {
256*3274Set142600 		int size = px_dbg_msg_size;
257*3274Set142600 
258*3274Set142600 		/* Check if px_dbg_msg_size is ^2 */
259*3274Set142600 		size = (size & (size - 1)) ? ((size | ~size) + 1) : size;
260*3274Set142600 		px_dbg_msg_size = size;
261*3274Set142600 		px_dbg_qmask = size - 1;
262*3274Set142600 		px_dbg_msgq = kmem_zalloc(sizeof (px_dbg_msg_t) * size,
263*3274Set142600 		    KM_SLEEP);
264*3274Set142600 
265*3274Set142600 		mutex_init(&px_dbg_mutex, NULL, MUTEX_DRIVER, NULL);
266*3274Set142600 	}
267*3274Set142600 
268*3274Set142600 	if (ddi_intr_add_softint(dip, dbg_hdl,
269*3274Set142600 		DDI_INTR_SOFTPRI_MAX, px_dbg_drain, NULL) != DDI_SUCCESS) {
270*3274Set142600 		DBG(DBG_ATTACH, dip,
271*3274Set142600 		    "Unable to allocate soft int for DBG printing.\n");
272*3274Set142600 		dbg_hdl = NULL;
273*3274Set142600 	}
274*3274Set142600 #endif	/* DEBUG */
275*3274Set142600 }
276*3274Set142600 
277*3274Set142600 /* ARGSUSED */
278*3274Set142600 void
279*3274Set142600 px_dbg_detach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
280*3274Set142600 {
281*3274Set142600 #ifdef	DEBUG
282*3274Set142600 	if (--px_dbg_reference == 0) {
283*3274Set142600 		if (dbg_hdl != NULL)
284*3274Set142600 			(void) ddi_intr_remove_softint(*dbg_hdl);
285*3274Set142600 		if (px_dbg_msgq != NULL)
286*3274Set142600 			kmem_free(px_dbg_msgq,
287*3274Set142600 			    sizeof (px_dbg_msg_t) * px_dbg_msg_size);
288*3274Set142600 		mutex_destroy(&px_dbg_mutex);
289*3274Set142600 	}
290*3274Set142600 #endif	/* DEBUG */
291*3274Set142600 }
292