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