xref: /illumos-gate/usr/src/uts/sun4/io/px/px_debug.c (revision 0716b62f878e855b94635ef4793ef5f7f2abb8e4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
525cf1a30Sjl139090  * Common Development and Distribution License (the "License").
625cf1a30Sjl139090  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2230ef5f63Set142600  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * PCI nexus driver general debug support
287c478bd9Sstevel@tonic-gate  */
29de710d24SJosef 'Jeff' Sipek #include <sys/sysmacros.h>
307c478bd9Sstevel@tonic-gate #include <sys/async.h>
317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>		/* dev_info_t */
327c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
337c478bd9Sstevel@tonic-gate #include <sys/disp.h>
34bf8fc234Set142600 #include <sys/archsystm.h>	/* getpil() */
35bf8fc234Set142600 #include "px_obj.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #ifdef	DEBUG
406b2ad4beSjchu uint64_t px_debug_flags = 0;
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate static char *px_debug_sym [] = {	/* same sequence as px_debug_bit */
437c478bd9Sstevel@tonic-gate 	/*  0 */ "attach",
447c478bd9Sstevel@tonic-gate 	/*  1 */ "detach",
457c478bd9Sstevel@tonic-gate 	/*  2 */ "map",
467c478bd9Sstevel@tonic-gate 	/*  3 */ "nex-ctlops",
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	/*  4 */ "introps",
497c478bd9Sstevel@tonic-gate 	/*  5 */ "intx-add",
507c478bd9Sstevel@tonic-gate 	/*  6 */ "intx-rem",
517c478bd9Sstevel@tonic-gate 	/*  7 */ "intx-intr",
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 	/*  8 */ "msiq",
547c478bd9Sstevel@tonic-gate 	/*  9 */ "msiq-intr",
557c478bd9Sstevel@tonic-gate 	/* 10 */ "msg",
567c478bd9Sstevel@tonic-gate 	/* 11 */ "msg-intr",
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	/* 12 */ "msix-add",
597c478bd9Sstevel@tonic-gate 	/* 13 */ "msix-rem",
607c478bd9Sstevel@tonic-gate 	/* 14 */ "msix-intr",
617c478bd9Sstevel@tonic-gate 	/* 15 */ "err",
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	/* 16 */ "dma-alloc",
647c478bd9Sstevel@tonic-gate 	/* 17 */ "dma-free",
657c478bd9Sstevel@tonic-gate 	/* 18 */ "dma-bind",
667c478bd9Sstevel@tonic-gate 	/* 19 */ "dma-unbind",
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	/* 20 */ "chk-dma-mode",
697c478bd9Sstevel@tonic-gate 	/* 21 */ "bypass-dma",
707c478bd9Sstevel@tonic-gate 	/* 22 */ "fast-dvma",
717c478bd9Sstevel@tonic-gate 	/* 23 */ "init_child",
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	/* 24 */ "dma-map",
747c478bd9Sstevel@tonic-gate 	/* 25 */ "dma-win",
757c478bd9Sstevel@tonic-gate 	/* 26 */ "map-win",
767c478bd9Sstevel@tonic-gate 	/* 27 */ "unmap-win",
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	/* 28 */ "dma-ctl",
797c478bd9Sstevel@tonic-gate 	/* 29 */ "dma-sync",
807c478bd9Sstevel@tonic-gate 	/* 30 */ NULL,
817c478bd9Sstevel@tonic-gate 	/* 31 */ NULL,
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	/* 32 */ "ib",
847c478bd9Sstevel@tonic-gate 	/* 33 */ "cb",
857c478bd9Sstevel@tonic-gate 	/* 34 */ "dmc",
867c478bd9Sstevel@tonic-gate 	/* 35 */ "pec",
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	/* 36 */ "ilu",
897c478bd9Sstevel@tonic-gate 	/* 37 */ "tlu",
907c478bd9Sstevel@tonic-gate 	/* 38 */ "lpu",
9125cf1a30Sjl139090 	/* 39 */ "mmu",
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	/* 40 */ "open",
947c478bd9Sstevel@tonic-gate 	/* 41 */ "close",
957c478bd9Sstevel@tonic-gate 	/* 42 */ "ioctl",
967c478bd9Sstevel@tonic-gate 	/* 43 */ "pwr",
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	/* 44 */ "lib-cfg",
997c478bd9Sstevel@tonic-gate 	/* 45 */ "lib-intr",
1007c478bd9Sstevel@tonic-gate 	/* 46 */ "lib-dma",
1017c478bd9Sstevel@tonic-gate 	/* 47 */ "lib-msiq",
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* 48 */ "lib-msi",
1047c478bd9Sstevel@tonic-gate 	/* 49 */ "lib-msg",
1057c478bd9Sstevel@tonic-gate 	/* 50 */ "NULL",
1067c478bd9Sstevel@tonic-gate 	/* 51 */ "NULL",
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/* 52 */ "tools",
1097c478bd9Sstevel@tonic-gate 	/* 53 */ "phys_acc",
110f94c6026Sjj156685 
111f94c6026Sjj156685 	/* 54 */ "hotplug",
1127c478bd9Sstevel@tonic-gate 	/* LAST */ "unknown"
1137c478bd9Sstevel@tonic-gate };
1147c478bd9Sstevel@tonic-gate 
115bf8fc234Set142600 /* Tunables */
116bf8fc234Set142600 static int px_dbg_msg_size = 16;		/* # of Qs.  Must be ^2 */
117bf8fc234Set142600 
118bf8fc234Set142600 /* Non-Tunables */
119bf8fc234Set142600 static int px_dbg_qmask = 0xFFFF;		/* Mask based on Q size */
120bf8fc234Set142600 static px_dbg_msg_t *px_dbg_msgq = NULL;	/* Debug Msg Queue */
121bf8fc234Set142600 static uint8_t px_dbg_reference = 0;		/* Reference Counter */
122bf8fc234Set142600 static kmutex_t px_dbg_mutex;			/* Mutex for dequeuing */
123bf8fc234Set142600 static uint8_t px_dbg_qtail = 0;		/* Pointer to q tail */
124bf8fc234Set142600 static uint8_t px_dbg_qhead = 0;		/* Pointer to q head */
125bf8fc234Set142600 static uint_t px_dbg_qsize = 0;			/* # of pending messages */
126bf8fc234Set142600 static uint_t px_dbg_failed = 0;		/* # of overflows */
127bf8fc234Set142600 
128bf8fc234Set142600 /* Forward Declarations */
129bf8fc234Set142600 static void px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
130bf8fc234Set142600     va_list args);
131bf8fc234Set142600 static void px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
132bf8fc234Set142600     va_list args);
133bf8fc234Set142600 static uint_t px_dbg_drain(caddr_t arg1, caddr_t arg2);
134bf8fc234Set142600 
135bf8fc234Set142600 /*
136bf8fc234Set142600  * Print function called either directly by px_dbg or through soft interrupt.
137bf8fc234Set142600  * This function cannot be called directly in threads with PIL above clock.
138bf8fc234Set142600  */
139bf8fc234Set142600 static void
px_dbg_print(px_debug_bit_t bit,dev_info_t * dip,char * fmt,va_list args)140bf8fc234Set142600 px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	int cont = bit >> DBG_BITS;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (cont)
1457c478bd9Sstevel@tonic-gate 		goto body;
146f8d2de6bSjchu 
1477c478bd9Sstevel@tonic-gate 	if (dip)
1486b2ad4beSjchu 		prom_printf("%s(%d): %s: ", ddi_driver_name(dip),
1496b2ad4beSjchu 		    ddi_get_instance(dip), px_debug_sym[bit]);
1507c478bd9Sstevel@tonic-gate 	else
1516b2ad4beSjchu 		prom_printf("px: %s: ", px_debug_sym[bit]);
1526b2ad4beSjchu body:
153bf8fc234Set142600 	if (args)
154bf8fc234Set142600 		prom_vprintf(fmt, args);
155bf8fc234Set142600 	else
156bf8fc234Set142600 		prom_printf(fmt);
157bf8fc234Set142600 }
158bf8fc234Set142600 
159bf8fc234Set142600 /*
160bf8fc234Set142600  * Queueing mechanism to log px_dbg messages if calling thread is running with a
161bf8fc234Set142600  * PIL above clock. It's Multithreaded safe.
162bf8fc234Set142600  */
163bf8fc234Set142600 static void
px_dbg_queue(px_debug_bit_t bit,dev_info_t * dip,char * fmt,va_list args)164bf8fc234Set142600 px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
165bf8fc234Set142600 {
166bf8fc234Set142600 	int		instance = DIP_TO_INST(dip);
167bf8fc234Set142600 	px_t		*px_p = INST_TO_STATE(instance);
168bf8fc234Set142600 	uint8_t		q_no;
169bf8fc234Set142600 	px_dbg_msg_t	*msg_p;
170bf8fc234Set142600 
171bf8fc234Set142600 	/* Check to make sure the queue hasn't overflowed */
172bf8fc234Set142600 	if (atomic_inc_uint_nv(&px_dbg_qsize) >= px_dbg_msg_size) {
173bf8fc234Set142600 		px_dbg_failed++;
174bf8fc234Set142600 		atomic_dec_uint(&px_dbg_qsize);
175bf8fc234Set142600 		return;
176bf8fc234Set142600 	}
177bf8fc234Set142600 
178bf8fc234Set142600 	/*
179bf8fc234Set142600 	 * Grab the next available queue bucket. Incrementing the tail here
180bf8fc234Set142600 	 * doesn't need to be protected, as it is guaranteed to not overflow.
181bf8fc234Set142600 	 */
182bf8fc234Set142600 	q_no = ++px_dbg_qtail & px_dbg_qmask;
183bf8fc234Set142600 	msg_p = &px_dbg_msgq[q_no];
184bf8fc234Set142600 
185bf8fc234Set142600 	ASSERT(msg_p->active == B_FALSE);
186bf8fc234Set142600 
187bf8fc234Set142600 	/* Print the message in the buffer */
188bf8fc234Set142600 	vsnprintf(msg_p->msg, DBG_MSG_SIZE, fmt, args);
189bf8fc234Set142600 	msg_p->bit = bit;
190bf8fc234Set142600 	msg_p->dip = dip;
191bf8fc234Set142600 	msg_p->active = B_TRUE;
192bf8fc234Set142600 
193bf8fc234Set142600 	/* Trigger Soft Int */
194bf8fc234Set142600 	ddi_intr_trigger_softint(px_p->px_dbg_hdl, (caddr_t)NULL);
195bf8fc234Set142600 }
196bf8fc234Set142600 
197bf8fc234Set142600 /*
198bf8fc234Set142600  * Callback function for queuing px_dbg in high PIL by soft intr.  This code
199bf8fc234Set142600  * assumes it will be called serially for every msg.
200bf8fc234Set142600  */
201bf8fc234Set142600 static uint_t
px_dbg_drain(caddr_t arg1,caddr_t arg2)202bf8fc234Set142600 px_dbg_drain(caddr_t arg1, caddr_t arg2) {
203bf8fc234Set142600 	uint8_t		q_no;
204bf8fc234Set142600 	px_dbg_msg_t	*msg_p;
205bf8fc234Set142600 	uint_t		ret = DDI_INTR_UNCLAIMED;
206bf8fc234Set142600 
207bf8fc234Set142600 	mutex_enter(&px_dbg_mutex);
208bf8fc234Set142600 	while (px_dbg_qsize) {
209bf8fc234Set142600 		atomic_dec_uint(&px_dbg_qsize);
210bf8fc234Set142600 		if (px_dbg_failed) {
211bf8fc234Set142600 			cmn_err(CE_WARN, "%d msg(s) were lost",
212bf8fc234Set142600 			    px_dbg_failed);
213bf8fc234Set142600 			px_dbg_failed = 0;
214bf8fc234Set142600 		}
215bf8fc234Set142600 
216bf8fc234Set142600 		q_no = ++px_dbg_qhead & px_dbg_qmask;
217bf8fc234Set142600 		msg_p = &px_dbg_msgq[q_no];
218bf8fc234Set142600 
219bf8fc234Set142600 		if (msg_p->active) {
220bf8fc234Set142600 			px_dbg_print(msg_p->bit, msg_p->dip, msg_p->msg, NULL);
221bf8fc234Set142600 			msg_p->active = B_FALSE;
222bf8fc234Set142600 		}
223bf8fc234Set142600 		ret = DDI_INTR_CLAIMED;
224bf8fc234Set142600 	}
225bf8fc234Set142600 
226bf8fc234Set142600 	mutex_exit(&px_dbg_mutex);
227bf8fc234Set142600 	return (ret);
228bf8fc234Set142600 }
229bf8fc234Set142600 
230bf8fc234Set142600 void
px_dbg(px_debug_bit_t bit,dev_info_t * dip,char * fmt,...)231bf8fc234Set142600 px_dbg(px_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
232bf8fc234Set142600 {
233bf8fc234Set142600 	va_list ap;
234bf8fc234Set142600 
235bf8fc234Set142600 	bit &= DBG_MASK;
236bf8fc234Set142600 	if (bit >= sizeof (px_debug_sym) / sizeof (char *))
237bf8fc234Set142600 		return;
238bf8fc234Set142600 	if (!(1ull << bit & px_debug_flags))
239bf8fc234Set142600 		return;
240bf8fc234Set142600 
2417c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
242bf8fc234Set142600 	if (getpil() > LOCK_LEVEL)
243bf8fc234Set142600 		px_dbg_queue(bit, dip, fmt, ap);
244bf8fc234Set142600 	else
245bf8fc234Set142600 		px_dbg_print(bit, dip, fmt, ap);
2467c478bd9Sstevel@tonic-gate 	va_end(ap);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
249bf8fc234Set142600 
250bf8fc234Set142600 void
px_dbg_attach(dev_info_t * dip,ddi_softint_handle_t * dbg_hdl)251bf8fc234Set142600 px_dbg_attach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
252bf8fc234Set142600 {
253bf8fc234Set142600 #ifdef	DEBUG
254bf8fc234Set142600 	if (px_dbg_reference++ == 0) {
255bf8fc234Set142600 		int size = px_dbg_msg_size;
256bf8fc234Set142600 
257bf8fc234Set142600 		/* Check if px_dbg_msg_size is ^2 */
258*0716b62fSJosef 'Jeff' Sipek 		/*
259*0716b62fSJosef 'Jeff' Sipek 		 * WARNING: The bellow statement makes no sense.  If size is
260*0716b62fSJosef 'Jeff' Sipek 		 * not a power of 2, it will set size to zero.
261*0716b62fSJosef 'Jeff' Sipek 		 */
262de710d24SJosef 'Jeff' Sipek 		size = !ISP2(size) ? ((size | ~size) + 1) : size;
263bf8fc234Set142600 		px_dbg_msg_size = size;
264bf8fc234Set142600 		px_dbg_qmask = size - 1;
265bf8fc234Set142600 		px_dbg_msgq = kmem_zalloc(sizeof (px_dbg_msg_t) * size,
266bf8fc234Set142600 		    KM_SLEEP);
267bf8fc234Set142600 
268bf8fc234Set142600 		mutex_init(&px_dbg_mutex, NULL, MUTEX_DRIVER, NULL);
269bf8fc234Set142600 	}
270bf8fc234Set142600 
271bf8fc234Set142600 	if (ddi_intr_add_softint(dip, dbg_hdl,
272bf8fc234Set142600 		DDI_INTR_SOFTPRI_MAX, px_dbg_drain, NULL) != DDI_SUCCESS) {
273bf8fc234Set142600 		DBG(DBG_ATTACH, dip,
274bf8fc234Set142600 		    "Unable to allocate soft int for DBG printing.\n");
275bf8fc234Set142600 		dbg_hdl = NULL;
276bf8fc234Set142600 	}
277bf8fc234Set142600 #endif	/* DEBUG */
278bf8fc234Set142600 }
279bf8fc234Set142600 
280bf8fc234Set142600 /* ARGSUSED */
281bf8fc234Set142600 void
px_dbg_detach(dev_info_t * dip,ddi_softint_handle_t * dbg_hdl)282bf8fc234Set142600 px_dbg_detach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
283bf8fc234Set142600 {
284bf8fc234Set142600 #ifdef	DEBUG
285bf8fc234Set142600 	if (dbg_hdl != NULL)
286bf8fc234Set142600 		(void) ddi_intr_remove_softint(*dbg_hdl);
28730ef5f63Set142600 
28830ef5f63Set142600 	if (--px_dbg_reference == 0) {
289bf8fc234Set142600 		if (px_dbg_msgq != NULL)
290bf8fc234Set142600 			kmem_free(px_dbg_msgq,
291bf8fc234Set142600 			    sizeof (px_dbg_msg_t) * px_dbg_msg_size);
292bf8fc234Set142600 		mutex_destroy(&px_dbg_mutex);
293bf8fc234Set142600 	}
294bf8fc234Set142600 #endif	/* DEBUG */
295bf8fc234Set142600 }
296