1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 2017 Joyent, Inc. 28 * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. 29 */ 30 31 #include <limits.h> 32 #include <sys/mdb_modapi.h> 33 #include <sys/sysinfo.h> 34 #include <sys/sunmdi.h> 35 #include <sys/list.h> 36 #include <sys/scsi/scsi.h> 37 38 #pragma pack(1) 39 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> 40 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> 41 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h> 42 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> 43 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h> 44 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h> 45 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h> 46 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h> 47 #pragma pack() 48 49 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> 50 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h> 51 52 struct { 53 int value; 54 char *text; 55 } devinfo_array[] = { 56 { MPI2_SAS_DEVICE_INFO_SEP, "SEP" }, 57 { MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE, "ATAPI device" }, 58 { MPI2_SAS_DEVICE_INFO_LSI_DEVICE, "LSI device" }, 59 { MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH, "direct attach" }, 60 { MPI2_SAS_DEVICE_INFO_SSP_TARGET, "SSP tgt" }, 61 { MPI2_SAS_DEVICE_INFO_STP_TARGET, "STP tgt" }, 62 { MPI2_SAS_DEVICE_INFO_SMP_TARGET, "SMP tgt" }, 63 { MPI2_SAS_DEVICE_INFO_SATA_DEVICE, "SATA dev" }, 64 { MPI2_SAS_DEVICE_INFO_SSP_INITIATOR, "SSP init" }, 65 { MPI2_SAS_DEVICE_INFO_STP_INITIATOR, "STP init" }, 66 { MPI2_SAS_DEVICE_INFO_SMP_INITIATOR, "SMP init" }, 67 { MPI2_SAS_DEVICE_INFO_SATA_HOST, "SATA host" } 68 }; 69 70 int 71 construct_path(uintptr_t addr, char *result) 72 { 73 struct dev_info d; 74 char devi_node[PATH_MAX]; 75 char devi_addr[PATH_MAX]; 76 77 if (mdb_vread(&d, sizeof (d), addr) == -1) { 78 mdb_warn("couldn't read dev_info"); 79 return (DCMD_ERR); 80 } 81 82 if (d.devi_parent) { 83 construct_path((uintptr_t)d.devi_parent, result); 84 mdb_readstr(devi_node, sizeof (devi_node), 85 (uintptr_t)d.devi_node_name); 86 mdb_readstr(devi_addr, sizeof (devi_addr), 87 (uintptr_t)d.devi_addr); 88 mdb_snprintf(result+strlen(result), 89 PATH_MAX-strlen(result), 90 "/%s%s%s", devi_node, (*devi_addr ? "@" : ""), 91 devi_addr); 92 } 93 return (DCMD_OK); 94 } 95 96 /* ARGSUSED */ 97 int 98 mdi_info_cb(uintptr_t addr, const void *data, void *cbdata) 99 { 100 struct mdi_pathinfo pi; 101 struct mdi_client c; 102 char dev_path[PATH_MAX]; 103 char string[PATH_MAX]; 104 int mdi_target = 0, mdi_lun = 0; 105 int target = *(int *)cbdata; 106 107 if (mdb_vread(&pi, sizeof (pi), addr) == -1) { 108 mdb_warn("couldn't read mdi_pathinfo"); 109 return (DCMD_ERR); 110 } 111 mdb_readstr(string, sizeof (string), (uintptr_t)pi.pi_addr); 112 mdi_target = (int)mdb_strtoull(string); 113 mdi_lun = (int)mdb_strtoull(strchr(string, ',') + 1); 114 if (target != mdi_target) 115 return (0); 116 117 if (mdb_vread(&c, sizeof (c), (uintptr_t)pi.pi_client) == -1) { 118 mdb_warn("couldn't read mdi_client"); 119 return (-1); 120 } 121 122 *dev_path = NULL; 123 if (construct_path((uintptr_t)c.ct_dip, dev_path) != DCMD_OK) 124 strcpy(dev_path, "unknown"); 125 126 mdb_printf("LUN %d: %s\n", mdi_lun, dev_path); 127 mdb_printf(" dip: %p %s path", c.ct_dip, 128 (pi.pi_preferred ? "preferred" : "")); 129 switch (pi.pi_state & MDI_PATHINFO_STATE_MASK) { 130 case MDI_PATHINFO_STATE_INIT: 131 mdb_printf(" initializing"); 132 break; 133 case MDI_PATHINFO_STATE_ONLINE: 134 mdb_printf(" online"); 135 break; 136 case MDI_PATHINFO_STATE_STANDBY: 137 mdb_printf(" standby"); 138 break; 139 case MDI_PATHINFO_STATE_FAULT: 140 mdb_printf(" fault"); 141 break; 142 case MDI_PATHINFO_STATE_OFFLINE: 143 mdb_printf(" offline"); 144 break; 145 default: 146 mdb_printf(" invalid state"); 147 break; 148 } 149 mdb_printf("\n"); 150 return (0); 151 } 152 153 void 154 mdi_info(struct mptsas *mp, int target) 155 { 156 struct dev_info d; 157 struct mdi_phci p; 158 159 if (mdb_vread(&d, sizeof (d), (uintptr_t)mp->m_dip) == -1) { 160 mdb_warn("couldn't read m_dip"); 161 return; 162 } 163 164 if (MDI_PHCI(&d)) { 165 if (mdb_vread(&p, sizeof (p), (uintptr_t)d.devi_mdi_xhci) 166 == -1) { 167 mdb_warn("couldn't read m_dip.devi_mdi_xhci"); 168 return; 169 } 170 if (p.ph_path_head) 171 mdb_pwalk("mdipi_phci_list", (mdb_walk_cb_t)mdi_info_cb, 172 &target, (uintptr_t)p.ph_path_head); 173 return; 174 } 175 } 176 177 void 178 print_cdb(mptsas_cmd_t *m) 179 { 180 struct scsi_pkt pkt; 181 uchar_t cdb[512]; /* an arbitrarily large number */ 182 int j; 183 184 if (mdb_vread(&pkt, sizeof (pkt), (uintptr_t)m->cmd_pkt) == -1) { 185 mdb_warn("couldn't read cmd_pkt"); 186 return; 187 } 188 189 /* 190 * We use cmd_cdblen here because 5.10 doesn't 191 * have the cdb length in the pkt 192 */ 193 if (mdb_vread(&cdb, m->cmd_cdblen, (uintptr_t)pkt.pkt_cdbp) == -1) { 194 mdb_warn("couldn't read pkt_cdbp"); 195 return; 196 } 197 198 mdb_printf("%3d,%-3d [ ", 199 pkt.pkt_address.a_target, pkt.pkt_address.a_lun); 200 201 for (j = 0; j < m->cmd_cdblen; j++) 202 mdb_printf("%02x ", cdb[j]); 203 204 mdb_printf("]\n"); 205 } 206 207 208 void 209 display_ports(struct mptsas *mp) 210 { 211 int i; 212 mdb_printf("\n"); 213 mdb_printf("phy number and port mapping table\n"); 214 for (i = 0; i < MPTSAS_MAX_PHYS; i++) { 215 if (mp->m_phy_info[i].attached_devhdl) { 216 mdb_printf("phy %x --> port %x, phymask %x," 217 "attached_devhdl %x\n", i, mp->m_phy_info[i].port_num, 218 mp->m_phy_info[i].phy_mask, 219 mp->m_phy_info[i].attached_devhdl); 220 } 221 } 222 mdb_printf("\n"); 223 } 224 225 static uintptr_t 226 klist_head(list_t *lp, uintptr_t klp) 227 { 228 if ((uintptr_t)lp->list_head.list_next == 229 klp + offsetof(struct list, list_head)) 230 return (NULL); 231 232 return ((uintptr_t)(((char *)lp->list_head.list_next) - 233 lp->list_offset)); 234 } 235 236 static uintptr_t 237 klist_next(list_t *lp, uintptr_t klp, void *op) 238 { 239 /* LINTED E_BAD_PTR_CAST_ALIG */ 240 struct list_node *np = (struct list_node *)(((char *)op) + 241 lp->list_offset); 242 243 if ((uintptr_t)np->list_next == klp + offsetof(struct list, list_head)) 244 return (NULL); 245 246 return (((uintptr_t)(np->list_next)) - lp->list_offset); 247 } 248 249 static void * 250 krefhash_first(uintptr_t khp, uintptr_t *addr) 251 { 252 refhash_t mh; 253 uintptr_t klp; 254 uintptr_t kop; 255 void *rp; 256 257 mdb_vread(&mh, sizeof (mh), khp); 258 klp = klist_head(&mh.rh_objs, khp + offsetof(refhash_t, rh_objs)); 259 if (klp == 0) 260 return (NULL); 261 262 kop = klp - mh.rh_link_off; 263 if (addr) 264 *addr = kop; 265 rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP); 266 mdb_vread(rp, mh.rh_obj_size, kop); 267 268 return (rp); 269 } 270 271 static void * 272 krefhash_next(uintptr_t khp, void *op, uintptr_t *addr) 273 { 274 refhash_t mh; 275 void *prev = op; 276 refhash_link_t *lp; 277 uintptr_t klp; 278 uintptr_t kop; 279 refhash_link_t ml; 280 void *rp; 281 282 mdb_vread(&mh, sizeof (mh), khp); 283 /* LINTED E_BAD_PTR_CAST_ALIG */ 284 lp = (refhash_link_t *)(((char *)(op)) + mh.rh_link_off); 285 ml = *lp; 286 while ((klp = klist_next(&mh.rh_objs, 287 khp + offsetof(refhash_t, rh_objs), &ml)) != NULL) { 288 mdb_vread(&ml, sizeof (ml), klp); 289 if (!(ml.rhl_flags & RHL_F_DEAD)) 290 break; 291 } 292 293 if (klp == 0) { 294 mdb_free(prev, mh.rh_obj_size); 295 return (NULL); 296 } 297 298 kop = klp - mh.rh_link_off; 299 if (addr) 300 *addr = kop; 301 rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP); 302 mdb_vread(rp, mh.rh_obj_size, kop); 303 304 mdb_free(prev, mh.rh_obj_size); 305 return (rp); 306 } 307 308 void 309 display_targets(struct mptsas *mp, uint_t verbose) 310 { 311 mptsas_target_t *ptgt; 312 mptsas_smp_t *psmp; 313 int loop, comma; 314 uintptr_t p_addr; 315 316 mdb_printf("\n"); 317 mdb_printf(" mptsas_target_t slot devhdl wwn ncmds throttle " 318 "dr_flag dups\n"); 319 mdb_printf("---------------------------------------" 320 "-------------------------------\n"); 321 for (ptgt = krefhash_first((uintptr_t)mp->m_targets, &p_addr); 322 ptgt != NULL; 323 ptgt = krefhash_next((uintptr_t)mp->m_targets, ptgt, &p_addr)) { 324 if (ptgt->m_addr.mta_wwn || 325 ptgt->m_deviceinfo) { 326 mdb_printf("%16p ", p_addr); 327 mdb_printf("%4d ", ptgt->m_slot_num); 328 mdb_printf("%4d ", ptgt->m_devhdl); 329 if (ptgt->m_addr.mta_wwn) 330 mdb_printf("%"PRIx64" ", 331 ptgt->m_addr.mta_wwn); 332 mdb_printf("%3d", ptgt->m_t_ncmds); 333 switch (ptgt->m_t_throttle) { 334 case QFULL_THROTTLE: 335 mdb_printf(" QFULL "); 336 break; 337 case DRAIN_THROTTLE: 338 mdb_printf(" DRAIN "); 339 break; 340 case HOLD_THROTTLE: 341 mdb_printf(" HOLD "); 342 break; 343 case MAX_THROTTLE: 344 mdb_printf(" MAX "); 345 break; 346 default: 347 mdb_printf("%8d ", 348 ptgt->m_t_throttle); 349 } 350 switch (ptgt->m_dr_flag) { 351 case MPTSAS_DR_INACTIVE: 352 mdb_printf(" INACTIVE "); 353 break; 354 case MPTSAS_DR_INTRANSITION: 355 mdb_printf("TRANSITION "); 356 break; 357 default: 358 mdb_printf(" UNKNOWN "); 359 break; 360 } 361 mdb_printf("%d\n", 362 ptgt->m_dups); 363 364 if (verbose) { 365 mdb_inc_indent(5); 366 if ((ptgt->m_deviceinfo & 367 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 368 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) 369 mdb_printf("Fanout expander: "); 370 if ((ptgt->m_deviceinfo & 371 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 372 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER) 373 mdb_printf("Edge expander: "); 374 if ((ptgt->m_deviceinfo & 375 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 376 MPI2_SAS_DEVICE_INFO_END_DEVICE) 377 mdb_printf("End device: "); 378 if ((ptgt->m_deviceinfo & 379 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 380 MPI2_SAS_DEVICE_INFO_NO_DEVICE) 381 mdb_printf("No device "); 382 383 for (loop = 0, comma = 0; 384 loop < (sizeof (devinfo_array) / 385 sizeof (devinfo_array[0])); loop++) { 386 if (ptgt->m_deviceinfo & 387 devinfo_array[loop].value) { 388 mdb_printf("%s%s", 389 (comma ? ", " : ""), 390 devinfo_array[loop].text); 391 comma++; 392 } 393 } 394 mdb_printf("\n"); 395 mdi_info(mp, ptgt->m_slot_num); 396 mdb_dec_indent(5); 397 } 398 } 399 } 400 401 mdb_printf("\n"); 402 mdb_printf(" mptsas_smp_t devhdl wwn phymask\n"); 403 mdb_printf("---------------------------------------" 404 "------------------\n"); 405 for (psmp = (mptsas_smp_t *)krefhash_first( 406 (uintptr_t)mp->m_smp_targets, &p_addr); 407 psmp != NULL; 408 psmp = krefhash_next((uintptr_t)mp->m_smp_targets, psmp, 409 &p_addr)) { 410 mdb_printf("%16p ", p_addr); 411 mdb_printf("%4d %"PRIx64" %04x\n", 412 psmp->m_devhdl, psmp->m_addr.mta_wwn, 413 psmp->m_addr.mta_phymask); 414 415 if (!verbose) 416 continue; 417 418 mdb_inc_indent(5); 419 if ((psmp->m_deviceinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) 420 == MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) 421 mdb_printf("Fanout expander: "); 422 if ((psmp->m_deviceinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) 423 == MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER) 424 mdb_printf("Edge expander: "); 425 if ((psmp->m_deviceinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) 426 == MPI2_SAS_DEVICE_INFO_END_DEVICE) 427 mdb_printf("End device: "); 428 if ((psmp->m_deviceinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) 429 == MPI2_SAS_DEVICE_INFO_NO_DEVICE) 430 mdb_printf("No device "); 431 432 for (loop = 0, comma = 0; 433 loop < (sizeof (devinfo_array) 434 / sizeof (devinfo_array[0])); 435 loop++) { 436 if (psmp->m_deviceinfo & 437 devinfo_array[loop].value) { 438 mdb_printf("%s%s", 439 (comma ? ", " : ""), 440 devinfo_array[loop].text); 441 comma++; 442 } 443 } 444 mdb_printf("\n"); 445 mdb_dec_indent(5); 446 } 447 } 448 449 int 450 display_slotinfo(struct mptsas *mp, struct mptsas_slots *s) 451 { 452 int i, nslots; 453 struct mptsas_cmd c, *q, *slots; 454 mptsas_target_t *ptgt; 455 int header_output = 0; 456 int rv = DCMD_OK; 457 int slots_in_use = 0; 458 int tcmds = 0; 459 int mismatch = 0; 460 int wq, dq; 461 int ncmds = 0; 462 ulong_t saved_indent; 463 uintptr_t panicstr; 464 int state; 465 466 if ((state = mdb_get_state()) == MDB_STATE_RUNNING) { 467 mdb_warn("mptsas: slot info can only be displayed on a system " 468 "dump or under kmdb\n"); 469 return (DCMD_ERR); 470 } 471 472 if (mdb_readvar(&panicstr, "panicstr") == -1) { 473 mdb_warn("can't read variable 'panicstr'"); 474 return (DCMD_ERR); 475 } 476 477 if (state != MDB_STATE_STOPPED && panicstr == NULL) { 478 mdb_warn("mptsas: slot info not available for live dump\n"); 479 return (DCMD_ERR); 480 } 481 482 nslots = s->m_n_normal; 483 slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP); 484 485 for (i = 0; i < nslots; i++) 486 if (s->m_slot[i]) { 487 slots_in_use++; 488 if (mdb_vread(&slots[i], sizeof (mptsas_cmd_t), 489 (uintptr_t)s->m_slot[i]) == -1) { 490 mdb_warn("couldn't read slot"); 491 s->m_slot[i] = NULL; 492 } 493 if ((slots[i].cmd_flags & CFLAG_CMDIOC) == 0) 494 tcmds++; 495 if (i != slots[i].cmd_slot) 496 mismatch++; 497 } 498 499 for (q = mp->m_waitq, wq = 0; q; q = c.cmd_linkp, wq++) 500 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 501 mdb_warn("couldn't follow m_waitq"); 502 rv = DCMD_ERR; 503 goto exit; 504 } 505 506 for (q = mp->m_doneq, dq = 0; q; q = c.cmd_linkp, dq++) 507 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 508 mdb_warn("couldn't follow m_doneq"); 509 rv = DCMD_ERR; 510 goto exit; 511 } 512 513 for (ptgt = krefhash_first((uintptr_t)mp->m_targets, NULL); 514 ptgt != NULL; 515 ptgt = krefhash_next((uintptr_t)mp->m_targets, ptgt, NULL)) { 516 if (ptgt->m_addr.mta_wwn || 517 ptgt->m_deviceinfo) { 518 ncmds += ptgt->m_t_ncmds; 519 } 520 } 521 522 mdb_printf("\n"); 523 mdb_printf(" mpt. slot mptsas_slots slot"); 524 mdb_printf("\n"); 525 mdb_printf("m_ncmds total" 526 " targ throttle m_t_ncmds targ_tot wq dq"); 527 mdb_printf("\n"); 528 mdb_printf("----------------------------------------------------"); 529 mdb_printf("\n"); 530 531 mdb_printf("%7d ", mp->m_ncmds); 532 mdb_printf("%s", (mp->m_ncmds == slots_in_use ? " " : "!=")); 533 mdb_printf("%3d total %3d ", slots_in_use, ncmds); 534 mdb_printf("%s", (tcmds == ncmds ? " " : " !=")); 535 mdb_printf("%3d %2d %2d\n", tcmds, wq, dq); 536 537 saved_indent = mdb_dec_indent(0); 538 mdb_dec_indent(saved_indent); 539 540 for (i = 0; i < s->m_n_normal; i++) 541 if (s->m_slot[i]) { 542 if (!header_output) { 543 mdb_printf("\n"); 544 mdb_printf("mptsas_cmd slot cmd_slot " 545 "cmd_flags cmd_pkt_flags scsi_pkt " 546 " targ,lun [ pkt_cdbp ...\n"); 547 mdb_printf("-------------------------------" 548 "--------------------------------------" 549 "--------------------------------------" 550 "------\n"); 551 header_output = 1; 552 } 553 mdb_printf("%16p %4d %s %4d %8x %8x %16p ", 554 s->m_slot[i], i, 555 (i == slots[i].cmd_slot?" ":"BAD"), 556 slots[i].cmd_slot, 557 slots[i].cmd_flags, 558 slots[i].cmd_pkt_flags, 559 slots[i].cmd_pkt); 560 (void) print_cdb(&slots[i]); 561 } 562 563 /* print the wait queue */ 564 565 for (q = mp->m_waitq; q; q = c.cmd_linkp) { 566 if (q == mp->m_waitq) 567 mdb_printf("\n"); 568 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) 569 == -1) { 570 mdb_warn("couldn't follow m_waitq"); 571 rv = DCMD_ERR; 572 goto exit; 573 } 574 mdb_printf("%16p wait n/a %4d %8x %8x %16p ", 575 q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags, 576 c.cmd_pkt); 577 print_cdb(&c); 578 } 579 580 /* print the done queue */ 581 582 for (q = mp->m_doneq; q; q = c.cmd_linkp) { 583 if (q == mp->m_doneq) 584 mdb_printf("\n"); 585 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) 586 == -1) { 587 mdb_warn("couldn't follow m_doneq"); 588 rv = DCMD_ERR; 589 goto exit; 590 } 591 mdb_printf("%16p done n/a %4d %8x %8x %16p ", 592 q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags, 593 c.cmd_pkt); 594 print_cdb(&c); 595 } 596 597 mdb_inc_indent(saved_indent); 598 599 if (mp->m_ncmds != slots_in_use) 600 mdb_printf("WARNING: mpt.m_ncmds does not match the number of " 601 "slots in use\n"); 602 603 if (tcmds != ncmds) 604 mdb_printf("WARNING: the total of m_target[].m_t_ncmds does " 605 "not match the slots in use\n"); 606 607 if (mismatch) 608 mdb_printf("WARNING: corruption in slot table, " 609 "m_slot[].cmd_slot incorrect\n"); 610 611 /* now check for corruptions */ 612 613 for (q = mp->m_waitq; q; q = c.cmd_linkp) { 614 for (i = 0; i < nslots; i++) 615 if (s->m_slot[i] == q) 616 mdb_printf("WARNING: m_waitq entry" 617 "(mptsas_cmd_t) %p is in m_slot[%i]\n", 618 q, i); 619 620 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 621 mdb_warn("couldn't follow m_waitq"); 622 rv = DCMD_ERR; 623 goto exit; 624 } 625 } 626 627 for (q = mp->m_doneq; q; q = c.cmd_linkp) { 628 for (i = 0; i < nslots; i++) 629 if (s->m_slot[i] == q) 630 mdb_printf("WARNING: m_doneq entry " 631 "(mptsas_cmd_t) %p is in m_slot[%i]\n", q, i); 632 633 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 634 mdb_warn("couldn't follow m_doneq"); 635 rv = DCMD_ERR; 636 goto exit; 637 } 638 if ((c.cmd_flags & CFLAG_FINISHED) == 0) 639 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 640 "should have CFLAG_FINISHED set\n", q); 641 if (c.cmd_flags & CFLAG_IN_TRANSPORT) 642 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 643 "should not have CFLAG_IN_TRANSPORT set\n", q); 644 if (c.cmd_flags & CFLAG_CMDARQ) 645 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 646 "should not have CFLAG_CMDARQ set\n", q); 647 if (c.cmd_flags & CFLAG_COMPLETED) 648 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 649 "should not have CFLAG_COMPLETED set\n", q); 650 } 651 652 exit: 653 mdb_free(slots, sizeof (mptsas_cmd_t) * nslots); 654 return (rv); 655 } 656 657 void 658 display_deviceinfo(struct mptsas *mp) 659 { 660 char device_path[PATH_MAX]; 661 662 *device_path = 0; 663 if (construct_path((uintptr_t)mp->m_dip, device_path) != DCMD_OK) { 664 strcpy(device_path, "couldn't determine device path"); 665 } 666 667 mdb_printf("\n"); 668 mdb_printf("base_wwid phys " 669 " prodid devid revid ssid\n"); 670 mdb_printf("-----------------------------" 671 "----------------------------------\n"); 672 mdb_printf("%"PRIx64" %2d " 673 "0x%04x 0x%04x ", mp->un.m_base_wwid, mp->m_num_phys, 674 mp->m_productid, mp->m_devid); 675 switch (mp->m_devid) { 676 case MPI2_MFGPAGE_DEVID_SAS2004: 677 mdb_printf("(SAS2004) "); 678 break; 679 case MPI2_MFGPAGE_DEVID_SAS2008: 680 mdb_printf("(SAS2008) "); 681 break; 682 case MPI2_MFGPAGE_DEVID_SAS2108_1: 683 case MPI2_MFGPAGE_DEVID_SAS2108_2: 684 case MPI2_MFGPAGE_DEVID_SAS2108_3: 685 mdb_printf("(SAS2108) "); 686 break; 687 case MPI2_MFGPAGE_DEVID_SAS2116_1: 688 case MPI2_MFGPAGE_DEVID_SAS2116_2: 689 mdb_printf("(SAS2116) "); 690 break; 691 case MPI2_MFGPAGE_DEVID_SSS6200: 692 mdb_printf("(SSS6200) "); 693 break; 694 case MPI2_MFGPAGE_DEVID_SAS2208_1: 695 case MPI2_MFGPAGE_DEVID_SAS2208_2: 696 case MPI2_MFGPAGE_DEVID_SAS2208_3: 697 case MPI2_MFGPAGE_DEVID_SAS2208_4: 698 case MPI2_MFGPAGE_DEVID_SAS2208_5: 699 case MPI2_MFGPAGE_DEVID_SAS2208_6: 700 mdb_printf("(SAS2208) "); 701 break; 702 case MPI2_MFGPAGE_DEVID_SAS2308_1: 703 case MPI2_MFGPAGE_DEVID_SAS2308_2: 704 case MPI2_MFGPAGE_DEVID_SAS2308_3: 705 mdb_printf("(SAS2308) "); 706 break; 707 case MPI25_MFGPAGE_DEVID_SAS3004: 708 mdb_printf("(SAS3004) "); 709 break; 710 case MPI25_MFGPAGE_DEVID_SAS3008: 711 mdb_printf("(SAS3008) "); 712 break; 713 case MPI25_MFGPAGE_DEVID_SAS3108_1: 714 case MPI25_MFGPAGE_DEVID_SAS3108_2: 715 case MPI25_MFGPAGE_DEVID_SAS3108_5: 716 case MPI25_MFGPAGE_DEVID_SAS3108_6: 717 mdb_printf("(SAS3108) "); 718 break; 719 case MPI26_MFGPAGE_DEVID_SAS3216: 720 case MPI26_MFGPAGE_DEVID_SAS3316_1: 721 case MPI26_MFGPAGE_DEVID_SAS3316_2: 722 case MPI26_MFGPAGE_DEVID_SAS3316_3: 723 case MPI26_MFGPAGE_DEVID_SAS3316_4: 724 mdb_printf("(SAS3216) "); 725 break; 726 case MPI26_MFGPAGE_DEVID_SAS3224: 727 case MPI26_MFGPAGE_DEVID_SAS3324_1: 728 case MPI26_MFGPAGE_DEVID_SAS3324_2: 729 case MPI26_MFGPAGE_DEVID_SAS3324_3: 730 case MPI26_MFGPAGE_DEVID_SAS3324_4: 731 mdb_printf("(SAS3224) "); 732 break; 733 case MPI26_MFGPAGE_DEVID_SAS3408: 734 mdb_printf("(SAS3408) "); 735 break; 736 case MPI26_MFGPAGE_DEVID_SAS3416: 737 mdb_printf("(SAS3416) "); 738 break; 739 case MPI26_MFGPAGE_DEVID_SAS3508: 740 case MPI26_MFGPAGE_DEVID_SAS3508_1: 741 mdb_printf("(SAS3508) "); 742 break; 743 case MPI26_MFGPAGE_DEVID_SAS3516: 744 case MPI26_MFGPAGE_DEVID_SAS3516_1: 745 mdb_printf("(SAS3516) "); 746 break; 747 case MPI26_MFGPAGE_DEVID_SAS3616: 748 mdb_printf("(SAS3616) "); 749 break; 750 case MPI26_MFGPAGE_DEVID_SAS3708: 751 mdb_printf("(SAS3708) "); 752 break; 753 case MPI26_MFGPAGE_DEVID_SAS3716: 754 mdb_printf("(SAS3716) "); 755 break; 756 case MPI26_MFGPAGE_DEVID_SAS4008: 757 mdb_printf("(SAS4008) "); 758 break; 759 default: 760 mdb_printf("(SAS????) "); 761 break; 762 } 763 mdb_printf("0x%02x 0x%04x\n", mp->m_revid, mp->m_ssid); 764 mdb_printf("%s\n", device_path); 765 766 } 767 768 void 769 dump_debug_log(void) 770 { 771 uint32_t idx; 772 size_t linecnt, linelen; 773 char *logbuf; 774 int i; 775 776 if (mdb_readsym(&idx, sizeof (uint32_t), "mptsas_dbglog_idx") == -1) { 777 mdb_warn("No debug log buffer present"); 778 return; 779 } 780 if (mdb_readsym(&linecnt, sizeof (size_t), "mptsas_dbglog_linecnt") 781 == -1) { 782 mdb_warn("No debug linecnt present"); 783 return; 784 } 785 if (mdb_readsym(&linelen, sizeof (size_t), "mptsas_dbglog_linelen") 786 == -1) { 787 mdb_warn("No debug linelen present"); 788 return; 789 } 790 logbuf = mdb_alloc(linelen * linecnt, UM_SLEEP); 791 792 if (mdb_readsym(logbuf, linelen * linecnt, "mptsas_dbglog_bufs") 793 == -1) { 794 mdb_warn("No debug log buffer present"); 795 return; 796 } 797 mdb_printf("\n"); 798 idx &= linecnt - 1; 799 for (i = 0; i < linecnt; i++) { 800 mdb_printf("%s\n", &logbuf[idx * linelen]); 801 idx++; 802 idx &= linecnt - 1; 803 } 804 mdb_free(logbuf, linelen * linecnt); 805 } 806 807 static int 808 mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 809 { 810 struct mptsas m; 811 struct mptsas_slots *s; 812 813 int nslots; 814 int slot_size = 0; 815 uint_t verbose = FALSE; 816 uint_t target_info = FALSE; 817 uint_t slot_info = FALSE; 818 uint_t device_info = FALSE; 819 uint_t port_info = FALSE; 820 uint_t debug_log = FALSE; 821 int rv = DCMD_OK; 822 823 if (!(flags & DCMD_ADDRSPEC)) { 824 void *mptsas_state = NULL; 825 826 if (mdb_readvar(&mptsas_state, "mptsas_state") == -1) { 827 mdb_warn("can't read mptsas_state"); 828 return (DCMD_ERR); 829 } 830 if (mdb_pwalk_dcmd("genunix`softstate", "mpt_sas`mptsas", argc, 831 argv, (uintptr_t)mptsas_state) == -1) { 832 mdb_warn("mdb_pwalk_dcmd failed"); 833 return (DCMD_ERR); 834 } 835 return (DCMD_OK); 836 } 837 838 if (mdb_getopts(argc, argv, 839 's', MDB_OPT_SETBITS, TRUE, &slot_info, 840 'd', MDB_OPT_SETBITS, TRUE, &device_info, 841 't', MDB_OPT_SETBITS, TRUE, &target_info, 842 'p', MDB_OPT_SETBITS, TRUE, &port_info, 843 'v', MDB_OPT_SETBITS, TRUE, &verbose, 844 'D', MDB_OPT_SETBITS, TRUE, &debug_log, 845 NULL) != argc) 846 return (DCMD_USAGE); 847 848 849 if (mdb_vread(&m, sizeof (m), addr) == -1) { 850 mdb_warn("couldn't read mpt struct at 0x%p", addr); 851 return (DCMD_ERR); 852 } 853 854 s = mdb_alloc(sizeof (mptsas_slots_t), UM_SLEEP); 855 856 if (mdb_vread(s, sizeof (mptsas_slots_t), 857 (uintptr_t)m.m_active) == -1) { 858 mdb_warn("couldn't read small mptsas_slots_t at 0x%p", 859 m.m_active); 860 mdb_free(s, sizeof (mptsas_slots_t)); 861 return (DCMD_ERR); 862 } 863 864 nslots = s->m_n_normal; 865 866 mdb_free(s, sizeof (mptsas_slots_t)); 867 868 slot_size = sizeof (mptsas_slots_t) + 869 (sizeof (mptsas_cmd_t *) * (nslots-1)); 870 871 s = mdb_alloc(slot_size, UM_SLEEP); 872 873 if (mdb_vread(s, slot_size, (uintptr_t)m.m_active) == -1) { 874 mdb_warn("couldn't read large mptsas_slots_t at 0x%p", 875 m.m_active); 876 mdb_free(s, slot_size); 877 return (DCMD_ERR); 878 } 879 880 /* processing completed */ 881 882 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) || 883 (flags & DCMD_LOOPFIRST) || slot_info || device_info || 884 target_info) { 885 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST)) 886 mdb_printf("\n"); 887 mdb_printf(" mptsas_t inst ncmds suspend power"); 888 mdb_printf("\n"); 889 mdb_printf("=========================================" 890 "======================================="); 891 mdb_printf("\n"); 892 } 893 894 mdb_printf("%16p %4d %5d ", addr, m.m_instance, m.m_ncmds); 895 mdb_printf("%7d", m.m_suspended); 896 switch (m.m_power_level) { 897 case PM_LEVEL_D0: 898 mdb_printf(" ON=D0 "); 899 break; 900 case PM_LEVEL_D1: 901 mdb_printf(" D1 "); 902 break; 903 case PM_LEVEL_D2: 904 mdb_printf(" D2 "); 905 break; 906 case PM_LEVEL_D3: 907 mdb_printf("OFF=D3 "); 908 break; 909 default: 910 mdb_printf("INVALD "); 911 } 912 mdb_printf("\n"); 913 914 mdb_inc_indent(17); 915 916 if (target_info) 917 display_targets(&m, verbose); 918 919 if (port_info) 920 display_ports(&m); 921 922 if (device_info) 923 display_deviceinfo(&m); 924 925 if (slot_info) 926 display_slotinfo(&m, s); 927 928 if (debug_log) 929 dump_debug_log(); 930 931 mdb_dec_indent(17); 932 933 mdb_free(s, slot_size); 934 935 return (rv); 936 } 937 938 void 939 mptsas_help() 940 { 941 mdb_printf("Prints summary information about each mpt_sas instance, " 942 "including warning\nmessages when slot usage doesn't match " 943 "summary information.\n" 944 "Without the address of a \"struct mptsas\", prints every " 945 "instance.\n\n" 946 "Switches:\n" 947 " -t[v] includes information about targets, v = be more verbose\n" 948 " -p includes information about port\n" 949 " -s includes information about mpt slots\n" 950 " -d includes information about the hardware\n" 951 " -D print the mptsas specific debug log\n"); 952 } 953 954 static const mdb_dcmd_t dcmds[] = { 955 { "mptsas", "?[-tpsdD]", "print mpt_sas information", mptsas_dcmd, 956 mptsas_help}, { NULL } 957 }; 958 959 static const mdb_modinfo_t modinfo = { 960 MDB_API_VERSION, dcmds, NULL 961 }; 962 963 const mdb_modinfo_t * 964 _mdb_init(void) 965 { 966 return (&modinfo); 967 } 968