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