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