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