1*70ab954aSramat /* 2*70ab954aSramat * CDDL HEADER START 3*70ab954aSramat * 4*70ab954aSramat * The contents of this file are subject to the terms of the 5*70ab954aSramat * Common Development and Distribution License (the "License"). 6*70ab954aSramat * You may not use this file except in compliance with the License. 7*70ab954aSramat * 8*70ab954aSramat * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*70ab954aSramat * or http://www.opensolaris.org/os/licensing. 10*70ab954aSramat * See the License for the specific language governing permissions 11*70ab954aSramat * and limitations under the License. 12*70ab954aSramat * 13*70ab954aSramat * When distributing Covered Code, include this CDDL HEADER in each 14*70ab954aSramat * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*70ab954aSramat * If applicable, add the following below this CDDL HEADER, with the 16*70ab954aSramat * fields enclosed by brackets "[]" replaced with your own identifying 17*70ab954aSramat * information: Portions Copyright [yyyy] [name of copyright owner] 18*70ab954aSramat * 19*70ab954aSramat * CDDL HEADER END 20*70ab954aSramat */ 21*70ab954aSramat /* 22*70ab954aSramat * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*70ab954aSramat * Use is subject to license terms. 24*70ab954aSramat */ 25*70ab954aSramat 26*70ab954aSramat #pragma ident "%Z%%M% %I% %E% SMI" 27*70ab954aSramat 28*70ab954aSramat #include <sys/kmem.h> 29*70ab954aSramat #include <sys/proc.h> 30*70ab954aSramat #include <sys/time.h> 31*70ab954aSramat #include <sys/conf.h> 32*70ab954aSramat #include <sys/file.h> 33*70ab954aSramat #include <sys/ddi.h> 34*70ab954aSramat #include <sys/ddi_impldefs.h> 35*70ab954aSramat #include <sys/modctl.h> 36*70ab954aSramat #include <sys/sunddi.h> 37*70ab954aSramat #include <sys/scsi/scsi.h> 38*70ab954aSramat #include <sys/scsi/impl/scsi_reset_notify.h> 39*70ab954aSramat #include <sys/sunmdi.h> 40*70ab954aSramat #include <sys/mdi_impldefs.h> 41*70ab954aSramat #include <sys/scsi/adapters/scsi_vhci.h> 42*70ab954aSramat #include <sys/scsi/scsi_types.h> 43*70ab954aSramat #include <sys/disp.h> 44*70ab954aSramat #include <sys/types.h> 45*70ab954aSramat #include <sys/mdb_modapi.h> 46*70ab954aSramat #include "mdi.h" 47*70ab954aSramat 48*70ab954aSramat #define FT(var, typ) (*((typ *)(&(var)))) 49*70ab954aSramat 50*70ab954aSramat /* Utils */ 51*70ab954aSramat static int get_mdbstr(uintptr_t addr, char *name); 52*70ab954aSramat static void dump_flags(unsigned long long flags, char **strings); 53*70ab954aSramat static void dump_mutex(kmutex_t m, char *name); 54*70ab954aSramat static void dump_condvar(kcondvar_t c, char *name); 55*70ab954aSramat static void dump_string(uintptr_t addr, char *name); 56*70ab954aSramat static void dump_state_str(char *name, uintptr_t addr, char **strings); 57*70ab954aSramat 58*70ab954aSramat static int mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata); 59*70ab954aSramat 60*70ab954aSramat static char *client_lb_str[] = 61*70ab954aSramat { 62*70ab954aSramat "NONE", 63*70ab954aSramat "RR", 64*70ab954aSramat "LBA", 65*70ab954aSramat NULL 66*70ab954aSramat }; 67*70ab954aSramat 68*70ab954aSramat static char *mdi_pathinfo_states[] = 69*70ab954aSramat { 70*70ab954aSramat "MDI_PATHINFO_STATE_INIT", 71*70ab954aSramat "MDI_PATHINFO_STATE_ONLINE", 72*70ab954aSramat "MDI_PATHINFO_STATE_STANDBY", 73*70ab954aSramat "MDI_PATHINFO_STATE_FAULT", 74*70ab954aSramat "MDI_PATHINFO_STATE_OFFLINE", 75*70ab954aSramat NULL 76*70ab954aSramat }; 77*70ab954aSramat 78*70ab954aSramat static char *mdi_pathinfo_ext_states[] = 79*70ab954aSramat { 80*70ab954aSramat "MDI_PATHINFO_STATE_USER_DISABLE", 81*70ab954aSramat "MDI_PATHINFO_STATE_DRV_DISABLE", 82*70ab954aSramat "MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT", 83*70ab954aSramat NULL 84*70ab954aSramat }; 85*70ab954aSramat 86*70ab954aSramat static char *mdi_phci_flags[] = 87*70ab954aSramat { 88*70ab954aSramat "MDI_PHCI_FLAGS_OFFLINE", 89*70ab954aSramat "MDI_PHCI_FLAGS_SUSPEND", 90*70ab954aSramat "MDI_PHCI_FLAGS_POWER_DOWN", 91*70ab954aSramat "MDI_PHCI_FLAGS_DETACH", 92*70ab954aSramat "MDI_PHCI_FLAGS_USER_DISABLE", 93*70ab954aSramat "MDI_PHCI_FLAGS_D_DISABLE", 94*70ab954aSramat "MDI_PHCI_FLAGS_D_DISABLE_TRANS", 95*70ab954aSramat "MDI_PHCI_FLAGS_POWER_TRANSITION", 96*70ab954aSramat NULL 97*70ab954aSramat }; 98*70ab954aSramat 99*70ab954aSramat static uintptr_t firstaddr = 0; 100*70ab954aSramat static char mdipathinfo_cb_str[] = "::print struct mdi_pathinfo"; 101*70ab954aSramat static char mdiphci_cb_str[] = "::print struct mdi_phci"; 102*70ab954aSramat 103*70ab954aSramat /* 104*70ab954aSramat * mdipi() 105*70ab954aSramat * 106*70ab954aSramat * Given a path, dump mdi_pathinfo struct and detailed pi_prop list. 107*70ab954aSramat */ 108*70ab954aSramat /* ARGSUSED */ 109*70ab954aSramat int 110*70ab954aSramat mdipi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 111*70ab954aSramat { 112*70ab954aSramat struct mdi_pathinfo value; 113*70ab954aSramat 114*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 115*70ab954aSramat mdb_warn("mdipi: requires an address"); 116*70ab954aSramat return (DCMD_ERR); 117*70ab954aSramat } 118*70ab954aSramat 119*70ab954aSramat if (mdb_vread(&value, sizeof (struct mdi_pathinfo), addr) != 120*70ab954aSramat sizeof (struct mdi_pathinfo)) { 121*70ab954aSramat mdb_warn("mdipi: Failed read on %l#r\n", addr); 122*70ab954aSramat return (DCMD_ERR); 123*70ab954aSramat } 124*70ab954aSramat mdb_printf("------------- mdi_pathinfo @ %#lr ----------\n", addr); 125*70ab954aSramat 126*70ab954aSramat dump_string((uintptr_t)value.pi_addr, "PWWN,LUN (pi_addr)"); 127*70ab954aSramat 128*70ab954aSramat mdb_printf("\n"); 129*70ab954aSramat mdb_printf("pi_client: %25l#r::print struct mdi_client\n", 130*70ab954aSramat value.pi_client); 131*70ab954aSramat mdb_printf("pi_phci: %27l#r::print struct mdi_phci\n", value.pi_phci); 132*70ab954aSramat mdb_printf("pi_pprivate: %23l#r\n", value.pi_pprivate); 133*70ab954aSramat mdb_printf("pi_client_link: %20l#r::print struct mdi_pathinfo\n", 134*70ab954aSramat value.pi_client_link); 135*70ab954aSramat mdb_printf("pi_phci_link: %22l#r::print struct mdi_pathinfo\n", 136*70ab954aSramat value.pi_phci_link); 137*70ab954aSramat mdb_printf("pi_prop: %27l#r::print struct nv_list\n", value.pi_prop); 138*70ab954aSramat 139*70ab954aSramat mdiprops((uintptr_t)value.pi_prop, flags, 0, NULL); 140*70ab954aSramat 141*70ab954aSramat mdb_printf("\n"); 142*70ab954aSramat dump_state_str("Pathinfo State (pi_state) ", 143*70ab954aSramat MDI_PI_STATE(&value), mdi_pathinfo_states); 144*70ab954aSramat if (MDI_PI_IS_TRANSIENT(&value)) { 145*70ab954aSramat mdb_printf("Pathinfo State is TRANSIENT\n"); 146*70ab954aSramat } 147*70ab954aSramat if (MDI_PI_EXT_STATE(&value)) { 148*70ab954aSramat mdb_printf(" Extended (pi_state) : "); 149*70ab954aSramat /* 150*70ab954aSramat * Need to shift right 20 bits to match mdi_pathinfo_ext_states 151*70ab954aSramat * array. 152*70ab954aSramat */ 153*70ab954aSramat dump_flags((unsigned long long)MDI_PI_EXT_STATE(&value) >> 20, 154*70ab954aSramat mdi_pathinfo_ext_states); 155*70ab954aSramat } 156*70ab954aSramat dump_state_str("Old Pathinfo State (pi_old_state)", 157*70ab954aSramat MDI_PI_OLD_STATE(&value), mdi_pathinfo_states); 158*70ab954aSramat if (MDI_PI_OLD_EXT_STATE(&value)) { 159*70ab954aSramat mdb_printf(" Extended (pi_old_state) : "); 160*70ab954aSramat /* 161*70ab954aSramat * Need to shift right 20 bits to match mdi_pathinfo_ext_states 162*70ab954aSramat * array. 163*70ab954aSramat */ 164*70ab954aSramat dump_flags((unsigned long long)MDI_PI_OLD_EXT_STATE(&value) 165*70ab954aSramat >> 20, mdi_pathinfo_ext_states); 166*70ab954aSramat } 167*70ab954aSramat dump_mutex(value.pi_mutex, "per-path mutex (pi_mutex):"); 168*70ab954aSramat dump_condvar(value.pi_state_cv, "Path state (pi_state_cv)"); 169*70ab954aSramat 170*70ab954aSramat mdb_printf("\n"); 171*70ab954aSramat mdb_printf("pi_ref_cnt: %d\n", value.pi_ref_cnt); 172*70ab954aSramat dump_condvar(value.pi_ref_cv, "pi_ref_cv"); 173*70ab954aSramat 174*70ab954aSramat mdb_printf("\n"); 175*70ab954aSramat mdb_printf("pi_kstats: %25l#r::print struct mdi_pi_kstats\n", 176*70ab954aSramat value.pi_kstats); 177*70ab954aSramat mdb_printf("pi_cprivate UNUSED: %16l#r \n", value.pi_cprivate); 178*70ab954aSramat 179*70ab954aSramat return (DCMD_OK); 180*70ab954aSramat } 181*70ab954aSramat 182*70ab954aSramat /* 183*70ab954aSramat * mdiprops() 184*70ab954aSramat * 185*70ab954aSramat * Given a pi_prop, dump the pi_prop list. 186*70ab954aSramat */ 187*70ab954aSramat /* ARGSUSED */ 188*70ab954aSramat int 189*70ab954aSramat mdiprops(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 190*70ab954aSramat { 191*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 192*70ab954aSramat mdb_warn("mdiprops: requires an address"); 193*70ab954aSramat return (DCMD_ERR); 194*70ab954aSramat } 195*70ab954aSramat 196*70ab954aSramat mdb_printf("\tnvpairs @ %#lr:\n", addr); 197*70ab954aSramat mdb_pwalk_dcmd("nvpair", "nvpair", argc, argv, addr); 198*70ab954aSramat mdb_printf("\n"); 199*70ab954aSramat 200*70ab954aSramat return (DCMD_OK); 201*70ab954aSramat } 202*70ab954aSramat 203*70ab954aSramat /* 204*70ab954aSramat * mdiphci() 205*70ab954aSramat * 206*70ab954aSramat * Given a phci, dump mdi_phci struct. 207*70ab954aSramat */ 208*70ab954aSramat /* ARGSUSED */ 209*70ab954aSramat int 210*70ab954aSramat mdiphci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 211*70ab954aSramat { 212*70ab954aSramat struct mdi_phci value; 213*70ab954aSramat 214*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 215*70ab954aSramat mdb_warn("mdiphci: requires an address"); 216*70ab954aSramat return (DCMD_ERR); 217*70ab954aSramat } 218*70ab954aSramat 219*70ab954aSramat if (mdb_vread(&value, sizeof (struct mdi_phci), addr) != 220*70ab954aSramat sizeof (struct mdi_phci)) { 221*70ab954aSramat mdb_warn("mdiphci: Failed read on %l#r\n", addr); 222*70ab954aSramat return (DCMD_ERR); 223*70ab954aSramat } 224*70ab954aSramat mdb_printf("---------------- mdi_phci @ %#lr ----------\n", addr); 225*70ab954aSramat 226*70ab954aSramat mdb_printf("ph_next: %27l#r::print struct mdi_phci\n", value.ph_next); 227*70ab954aSramat mdb_printf("ph_prev: %27l#r::print struct mdi_phci\n", value.ph_prev); 228*70ab954aSramat mdb_printf("ph_vhci: %27l#r::print struct mdi_vhci\n", value.ph_vhci); 229*70ab954aSramat mdb_printf("ph_dip: %28l#r::print struct dev_info\n", value.ph_dip); 230*70ab954aSramat mdb_printf("\nph_path_head: %22l#r::print struct mdi_pathinfo\n", 231*70ab954aSramat value.ph_path_head); 232*70ab954aSramat mdb_printf("ph_path_tail: %22l#r::print struct mdi_pathinfo\n", 233*70ab954aSramat value.ph_path_tail); 234*70ab954aSramat mdb_printf("ph_path_count: %21d\n", value.ph_path_count); 235*70ab954aSramat mdb_printf("List of paths:\n"); 236*70ab954aSramat mdb_pwalk("mdipi_phci_list", (mdb_walk_cb_t)mpxio_walk_cb, 237*70ab954aSramat mdipathinfo_cb_str, (uintptr_t)value.ph_path_head); 238*70ab954aSramat 239*70ab954aSramat mdb_printf("\n"); 240*70ab954aSramat mdb_printf("ph_flags: %26d\n", value.ph_flags); 241*70ab954aSramat if (value.ph_flags) { 242*70ab954aSramat dump_flags((unsigned long long)value.ph_flags, mdi_phci_flags); 243*70ab954aSramat } 244*70ab954aSramat dump_mutex(value.ph_mutex, "per-pHCI mutex (ph_mutex):"); 245*70ab954aSramat dump_condvar(value.ph_unstable_cv, 246*70ab954aSramat "Paths in transient state (ph_unstable_cv)"); 247*70ab954aSramat mdb_printf("ph_unstable: %23d\n", value.ph_unstable); 248*70ab954aSramat 249*70ab954aSramat return (DCMD_OK); 250*70ab954aSramat } 251*70ab954aSramat 252*70ab954aSramat /* 253*70ab954aSramat * mdivhci() 254*70ab954aSramat * 255*70ab954aSramat * Given a vhci, dump mdi_vhci struct and list all phcis. 256*70ab954aSramat */ 257*70ab954aSramat /* ARGSUSED */ 258*70ab954aSramat int 259*70ab954aSramat mdivhci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 260*70ab954aSramat { 261*70ab954aSramat struct mdi_vhci value; 262*70ab954aSramat 263*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 264*70ab954aSramat mdb_warn("mdivhci: requires an address"); 265*70ab954aSramat return (DCMD_ERR); 266*70ab954aSramat } 267*70ab954aSramat 268*70ab954aSramat if (mdb_vread(&value, sizeof (struct mdi_vhci), addr) != 269*70ab954aSramat sizeof (struct mdi_vhci)) { 270*70ab954aSramat mdb_warn("mdivhci: Failed read on %l#r\n", addr); 271*70ab954aSramat return (DCMD_ERR); 272*70ab954aSramat } 273*70ab954aSramat mdb_printf("----------------- mdi_vhci @ %#lr ----------\n", addr); 274*70ab954aSramat 275*70ab954aSramat dump_string((uintptr_t)value.vh_class, "Class name (vh_class)"); 276*70ab954aSramat mdb_printf("vh_refcnt: %19d\n", value.vh_refcnt); 277*70ab954aSramat mdb_printf("vh_dip: %28l#r::print struct dev_info\n", value.vh_dip); 278*70ab954aSramat mdb_printf("vh_next: %27l#r::print struct mdi_vhci\n", value.vh_next); 279*70ab954aSramat mdb_printf("vh_prev: %27l#r::print struct mdi_vhci\n", value.vh_prev); 280*70ab954aSramat dump_state_str("Load Balance (vh_lb)", value.vh_lb, client_lb_str); 281*70ab954aSramat mdb_printf("vh_ops: %28l#r::print struct mdi_vhci_ops\n", 282*70ab954aSramat value.vh_ops); 283*70ab954aSramat 284*70ab954aSramat dump_mutex(value.vh_phci_mutex, "phci mutex (vh_phci_mutex):"); 285*70ab954aSramat mdb_printf("vh_phci_count: %21d\n", value.vh_phci_count); 286*70ab954aSramat mdb_printf("\nvh_phci_head: %22l#r::print struct mdi_phci\n", 287*70ab954aSramat value.vh_phci_head); 288*70ab954aSramat mdb_printf("vh_phci_tail: %22l#r::print struct mdi_phci\n", 289*70ab954aSramat value.vh_phci_tail); 290*70ab954aSramat 291*70ab954aSramat dump_mutex(value.vh_phci_mutex, "client mutex (vh_client_mutex):"); 292*70ab954aSramat mdb_printf("vh_client_count: %19d\n", value.vh_client_count); 293*70ab954aSramat mdb_printf("vh_client_table: %19l#r::print struct client_hash\n", 294*70ab954aSramat value.vh_client_table); 295*70ab954aSramat 296*70ab954aSramat mdb_printf("List of pHCIs:\n"); 297*70ab954aSramat mdb_pwalk("mdiphci_list", (mdb_walk_cb_t)mpxio_walk_cb, 298*70ab954aSramat mdiphci_cb_str, (uintptr_t)value.vh_phci_head); 299*70ab954aSramat mdb_printf("\n"); 300*70ab954aSramat return (DCMD_OK); 301*70ab954aSramat } 302*70ab954aSramat 303*70ab954aSramat /* mdi_pathinfo client walker */ 304*70ab954aSramat 305*70ab954aSramat /* ARGUSED */ 306*70ab954aSramat int 307*70ab954aSramat mdi_pi_client_link_walk_init(mdb_walk_state_t *wsp) 308*70ab954aSramat { 309*70ab954aSramat if (wsp->walk_addr == NULL) { 310*70ab954aSramat mdb_warn("Address is required"); 311*70ab954aSramat return (WALK_ERR); 312*70ab954aSramat } 313*70ab954aSramat wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP); 314*70ab954aSramat firstaddr = wsp->walk_addr; 315*70ab954aSramat return (WALK_NEXT); 316*70ab954aSramat } 317*70ab954aSramat 318*70ab954aSramat /* ARGUSED */ 319*70ab954aSramat int 320*70ab954aSramat mdi_pi_client_link_walk_step(mdb_walk_state_t *wsp) 321*70ab954aSramat { 322*70ab954aSramat int status = 0; 323*70ab954aSramat static int counts = 0; 324*70ab954aSramat 325*70ab954aSramat if (firstaddr == wsp->walk_addr && counts != 0) { 326*70ab954aSramat counts = 0; 327*70ab954aSramat return (WALK_DONE); 328*70ab954aSramat } 329*70ab954aSramat if (wsp->walk_addr == NULL) { 330*70ab954aSramat counts = 0; 331*70ab954aSramat return (WALK_DONE); 332*70ab954aSramat } 333*70ab954aSramat if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo), 334*70ab954aSramat wsp->walk_addr) == -1) { 335*70ab954aSramat mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr); 336*70ab954aSramat return (WALK_DONE); 337*70ab954aSramat } 338*70ab954aSramat status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 339*70ab954aSramat wsp->walk_cbdata); 340*70ab954aSramat wsp->walk_addr = (uintptr_t) 341*70ab954aSramat (((struct mdi_pathinfo *)wsp->walk_data)->pi_client_link); 342*70ab954aSramat counts++; 343*70ab954aSramat return (status); 344*70ab954aSramat } 345*70ab954aSramat 346*70ab954aSramat /* ARGUSED */ 347*70ab954aSramat void 348*70ab954aSramat mdi_pi_client_link_walk_fini(mdb_walk_state_t *wsp) 349*70ab954aSramat { 350*70ab954aSramat mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo)); 351*70ab954aSramat } 352*70ab954aSramat 353*70ab954aSramat /* 354*70ab954aSramat * mdiclient_paths() 355*70ab954aSramat * 356*70ab954aSramat * Given a path, walk through mdi_pathinfo client links. 357*70ab954aSramat */ 358*70ab954aSramat /* ARGUSED */ 359*70ab954aSramat int 360*70ab954aSramat mdiclient_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 361*70ab954aSramat { 362*70ab954aSramat int status; 363*70ab954aSramat if (argc != 0) 364*70ab954aSramat return (DCMD_USAGE); 365*70ab954aSramat 366*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 367*70ab954aSramat mdb_warn("Address needs to be specified"); 368*70ab954aSramat return (DCMD_ERR); 369*70ab954aSramat } 370*70ab954aSramat status = 371*70ab954aSramat mdb_pwalk_dcmd("mdipi_client_list", "mdipi", argc, argv, addr); 372*70ab954aSramat return (status); 373*70ab954aSramat } 374*70ab954aSramat 375*70ab954aSramat /* mdi_pathinfo phci walker */ 376*70ab954aSramat int 377*70ab954aSramat mdi_pi_phci_link_walk_init(mdb_walk_state_t *wsp) 378*70ab954aSramat { 379*70ab954aSramat if (wsp->walk_addr == NULL) { 380*70ab954aSramat mdb_warn("Address is required"); 381*70ab954aSramat return (WALK_ERR); 382*70ab954aSramat } 383*70ab954aSramat wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP); 384*70ab954aSramat firstaddr = wsp->walk_addr; 385*70ab954aSramat return (WALK_NEXT); 386*70ab954aSramat } 387*70ab954aSramat 388*70ab954aSramat int 389*70ab954aSramat mdi_pi_phci_link_walk_step(mdb_walk_state_t *wsp) 390*70ab954aSramat { 391*70ab954aSramat int status; 392*70ab954aSramat static int counts = 0; 393*70ab954aSramat 394*70ab954aSramat if (firstaddr == wsp->walk_addr && counts != 0) { 395*70ab954aSramat counts = 0; 396*70ab954aSramat return (WALK_DONE); 397*70ab954aSramat } 398*70ab954aSramat if (wsp->walk_addr == NULL) { 399*70ab954aSramat counts = 0; 400*70ab954aSramat return (WALK_DONE); 401*70ab954aSramat } 402*70ab954aSramat if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo), 403*70ab954aSramat wsp->walk_addr) == -1) { 404*70ab954aSramat mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr); 405*70ab954aSramat return (WALK_DONE); 406*70ab954aSramat } 407*70ab954aSramat status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 408*70ab954aSramat wsp->walk_cbdata); 409*70ab954aSramat wsp->walk_addr = (uintptr_t) 410*70ab954aSramat (((struct mdi_pathinfo *)wsp->walk_data)->pi_phci_link); 411*70ab954aSramat counts++; 412*70ab954aSramat return (status); 413*70ab954aSramat } 414*70ab954aSramat 415*70ab954aSramat void 416*70ab954aSramat mdi_pi_phci_link_walk_fini(mdb_walk_state_t *wsp) 417*70ab954aSramat { 418*70ab954aSramat mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo)); 419*70ab954aSramat } 420*70ab954aSramat 421*70ab954aSramat /* 422*70ab954aSramat * mdiphci_paths() 423*70ab954aSramat * 424*70ab954aSramat * Given a path, walk through mdi_pathinfo phci links. 425*70ab954aSramat */ 426*70ab954aSramat int 427*70ab954aSramat mdiphci_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 428*70ab954aSramat { 429*70ab954aSramat int status; 430*70ab954aSramat if (argc != 0) 431*70ab954aSramat return (DCMD_USAGE); 432*70ab954aSramat 433*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 434*70ab954aSramat mdb_warn("Address needs to be specified"); 435*70ab954aSramat return (DCMD_ERR); 436*70ab954aSramat } 437*70ab954aSramat status = 438*70ab954aSramat mdb_pwalk_dcmd("mdipi_phci_list", "mdipi", argc, argv, addr); 439*70ab954aSramat return (status); 440*70ab954aSramat } 441*70ab954aSramat 442*70ab954aSramat /* mdi_phci walker */ 443*70ab954aSramat int 444*70ab954aSramat mdi_phci_ph_next_walk_init(mdb_walk_state_t *wsp) 445*70ab954aSramat { 446*70ab954aSramat if (wsp->walk_addr == NULL) { 447*70ab954aSramat mdb_warn("Address is required"); 448*70ab954aSramat return (WALK_ERR); 449*70ab954aSramat } 450*70ab954aSramat wsp->walk_data = mdb_alloc(sizeof (struct mdi_phci), UM_SLEEP); 451*70ab954aSramat firstaddr = wsp->walk_addr; 452*70ab954aSramat return (WALK_NEXT); 453*70ab954aSramat } 454*70ab954aSramat 455*70ab954aSramat int 456*70ab954aSramat mdi_phci_ph_next_walk_step(mdb_walk_state_t *wsp) 457*70ab954aSramat { 458*70ab954aSramat int status; 459*70ab954aSramat static int counts = 0; 460*70ab954aSramat 461*70ab954aSramat if (firstaddr == wsp->walk_addr && counts != 0) { 462*70ab954aSramat counts = 0; 463*70ab954aSramat return (WALK_DONE); 464*70ab954aSramat } 465*70ab954aSramat if (wsp->walk_addr == NULL) { 466*70ab954aSramat counts = 0; 467*70ab954aSramat return (WALK_DONE); 468*70ab954aSramat } 469*70ab954aSramat if (mdb_vread(wsp->walk_data, sizeof (struct mdi_phci), wsp->walk_addr) 470*70ab954aSramat == -1) { 471*70ab954aSramat mdb_warn("failed to read mdi_phci at %p", wsp->walk_addr); 472*70ab954aSramat return (WALK_DONE); 473*70ab954aSramat } 474*70ab954aSramat status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 475*70ab954aSramat wsp->walk_cbdata); 476*70ab954aSramat wsp->walk_addr = (uintptr_t) 477*70ab954aSramat (((struct mdi_phci *)wsp->walk_data)->ph_next); 478*70ab954aSramat counts++; 479*70ab954aSramat return (status); 480*70ab954aSramat } 481*70ab954aSramat 482*70ab954aSramat void 483*70ab954aSramat mdi_phci_ph_next_walk_fini(mdb_walk_state_t *wsp) 484*70ab954aSramat { 485*70ab954aSramat mdb_free(wsp->walk_data, sizeof (struct mdi_phci)); 486*70ab954aSramat } 487*70ab954aSramat 488*70ab954aSramat /* 489*70ab954aSramat * mdiphcis() 490*70ab954aSramat * 491*70ab954aSramat * Given a phci, walk through mdi_phci ph_next links. 492*70ab954aSramat */ 493*70ab954aSramat int 494*70ab954aSramat mdiphcis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 495*70ab954aSramat { 496*70ab954aSramat int status; 497*70ab954aSramat if (argc != 0) 498*70ab954aSramat return (DCMD_USAGE); 499*70ab954aSramat 500*70ab954aSramat if (!(flags & DCMD_ADDRSPEC)) { 501*70ab954aSramat mdb_warn("Address needs to be specified"); 502*70ab954aSramat return (DCMD_ERR); 503*70ab954aSramat } 504*70ab954aSramat status = 505*70ab954aSramat mdb_pwalk_dcmd("mdiphci_list", "mdiphci", argc, argv, addr); 506*70ab954aSramat return (status); 507*70ab954aSramat } 508*70ab954aSramat 509*70ab954aSramat /* 510*70ab954aSramat * Print the flag name by comparing flags to the mask variable. 511*70ab954aSramat */ 512*70ab954aSramat static void 513*70ab954aSramat dump_flags(unsigned long long flags, char **strings) 514*70ab954aSramat { 515*70ab954aSramat int i, linel = 8, first = 1; 516*70ab954aSramat unsigned long long mask = 1; 517*70ab954aSramat 518*70ab954aSramat for (i = 0; i < 64; i++) { 519*70ab954aSramat if (strings[i] == NULL) 520*70ab954aSramat break; 521*70ab954aSramat if (flags & mask) { 522*70ab954aSramat if (!first) { 523*70ab954aSramat mdb_printf(" | "); 524*70ab954aSramat } else { 525*70ab954aSramat first = 0; 526*70ab954aSramat } 527*70ab954aSramat /* make output pretty */ 528*70ab954aSramat linel += strlen(strings[i]) + 3; 529*70ab954aSramat if (linel > 80) { 530*70ab954aSramat mdb_printf("\n\t"); 531*70ab954aSramat linel = strlen(strings[i]) + 1 + 8; 532*70ab954aSramat } 533*70ab954aSramat mdb_printf("%s", strings[i]); 534*70ab954aSramat } 535*70ab954aSramat mask <<= 1; 536*70ab954aSramat } 537*70ab954aSramat mdb_printf("\n"); 538*70ab954aSramat } 539*70ab954aSramat 540*70ab954aSramat static void 541*70ab954aSramat dump_mutex(kmutex_t m, char *name) 542*70ab954aSramat { 543*70ab954aSramat mdb_printf("%s is%s held\n", name, FT(m, uint64_t) == 0 ? " not" : ""); 544*70ab954aSramat } 545*70ab954aSramat 546*70ab954aSramat static void 547*70ab954aSramat dump_condvar(kcondvar_t c, char *name) 548*70ab954aSramat { 549*70ab954aSramat mdb_printf("Threads sleeping on %s = %d\n", name, (int)FT(c, ushort_t)); 550*70ab954aSramat } 551*70ab954aSramat 552*70ab954aSramat static int 553*70ab954aSramat get_mdbstr(uintptr_t addr, char *string_val) 554*70ab954aSramat { 555*70ab954aSramat if (mdb_readstr(string_val, MAXNAMELEN, addr) == -1) { 556*70ab954aSramat mdb_warn("Error Reading String from %l#r\n", addr); 557*70ab954aSramat return (1); 558*70ab954aSramat } 559*70ab954aSramat 560*70ab954aSramat return (0); 561*70ab954aSramat } 562*70ab954aSramat 563*70ab954aSramat static void 564*70ab954aSramat dump_string(uintptr_t addr, char *name) 565*70ab954aSramat { 566*70ab954aSramat char string_val[MAXNAMELEN]; 567*70ab954aSramat 568*70ab954aSramat if (get_mdbstr(addr, string_val)) { 569*70ab954aSramat return; 570*70ab954aSramat } 571*70ab954aSramat mdb_printf("%s: %s (%l#r)\n", name, string_val, addr); 572*70ab954aSramat } 573*70ab954aSramat 574*70ab954aSramat static void 575*70ab954aSramat dump_state_str(char *name, uintptr_t addr, char **strings) 576*70ab954aSramat { 577*70ab954aSramat mdb_printf("%s: %s (%l#r)\n", name, strings[(unsigned long)addr], addr); 578*70ab954aSramat } 579*70ab954aSramat 580*70ab954aSramat /* ARGSUSED */ 581*70ab954aSramat static int 582*70ab954aSramat mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata) 583*70ab954aSramat { 584*70ab954aSramat mdb_printf("%t%l#r%s\n", addr, (char *)cbdata); 585*70ab954aSramat return (0); 586*70ab954aSramat } 587