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 m, int target) 154 { 155 struct dev_info d; 156 struct mdi_phci p; 157 158 if (mdb_vread(&d, sizeof (d), (uintptr_t)m.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) 305 { 306 mptsas_target_t *ptgt; 307 mptsas_smp_t *psmp; 308 309 mdb_printf("\n"); 310 mdb_printf("The SCSI target information\n"); 311 for (ptgt = (mptsas_target_t *)krefhash_first((uintptr_t)mp->m_targets); 312 ptgt != NULL; 313 ptgt = krefhash_next((uintptr_t)mp->m_targets, ptgt)) { 314 mdb_printf("\n"); 315 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x," 316 "devinfo %x\n", ptgt->m_devhdl, ptgt->m_addr.mta_wwn, 317 ptgt->m_addr.mta_phymask, ptgt->m_deviceinfo); 318 mdb_printf("throttle %x, dr_flag %x, m_t_ncmds %x, " 319 "enclosure %x, slot_num %x\n", ptgt->m_t_throttle, 320 ptgt->m_dr_flag, ptgt->m_t_ncmds, ptgt->m_enclosure, 321 ptgt->m_slot_num); 322 } 323 324 mdb_printf("\n"); 325 mdb_printf("The smp child information\n"); 326 for (psmp = (mptsas_smp_t *)krefhash_first( 327 (uintptr_t)mp->m_smp_targets); 328 psmp != NULL; 329 psmp = krefhash_next((uintptr_t)mp->m_smp_targets, psmp)) { 330 mdb_printf("\n"); 331 mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x \n", 332 psmp->m_devhdl, psmp->m_addr.mta_wwn, 333 psmp->m_addr.mta_phymask); 334 } 335 mdb_printf("\n"); 336 #if 0 337 mdb_printf("targ wwn ncmds throttle " 338 "dr_flag timeout dups\n"); 339 mdb_printf("-------------------------------" 340 "--------------------------------\n"); 341 for (i = 0; i < MPTSAS_MAX_TARGETS; i++) { 342 if (s->m_target[i].m_addr.mta_wwn || 343 s->m_target[i].m_deviceinfo) { 344 mdb_printf("%4d ", i); 345 if (s->m_target[i].m_addr.mta_wwn) 346 mdb_printf("%"PRIx64" ", 347 s->m_target[i].m_addr.mta_wwn); 348 mdb_printf("%3d", s->m_target[i].m_t_ncmds); 349 switch (s->m_target[i].m_t_throttle) { 350 case QFULL_THROTTLE: 351 mdb_printf(" QFULL "); 352 break; 353 case DRAIN_THROTTLE: 354 mdb_printf(" DRAIN "); 355 break; 356 case HOLD_THROTTLE: 357 mdb_printf(" HOLD "); 358 break; 359 case MAX_THROTTLE: 360 mdb_printf(" MAX "); 361 break; 362 case CHOKE_THROTTLE: 363 mdb_printf(" CHOKE "); 364 break; 365 default: 366 mdb_printf("%8d ", 367 s->m_target[i].m_t_throttle); 368 } 369 switch (s->m_target[i].m_dr_flag) { 370 case MPTSAS_DR_INACTIVE: 371 mdb_printf(" INACTIVE "); 372 break; 373 case MPTSAS_DR_PRE_OFFLINE_TIMEOUT: 374 mdb_printf(" TIMEOUT "); 375 break; 376 case MPTSAS_DR_PRE_OFFLINE_TIMEOUT_NO_CANCEL: 377 mdb_printf("TIMEOUT_NC "); 378 break; 379 case MPTSAS_DR_OFFLINE_IN_PROGRESS: 380 mdb_printf(" OFFLINING "); 381 break; 382 case MPTSAS_DR_ONLINE_IN_PROGRESS: 383 mdb_printf(" ONLINING "); 384 break; 385 default: 386 mdb_printf(" UNKNOWN "); 387 break; 388 } 389 mdb_printf("%3d/%-3d %d/%d\n", 390 s->m_target[i].m_dr_timeout, m.m_offline_delay, 391 s->m_target[i].m_dr_online_dups, 392 s->m_target[i].m_dr_offline_dups); 393 394 if (verbose) { 395 mdb_inc_indent(5); 396 if ((s->m_target[i].m_deviceinfo & 397 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 398 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) 399 mdb_printf("Fanout expander: "); 400 if ((s->m_target[i].m_deviceinfo & 401 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 402 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER) 403 mdb_printf("Edge expander: "); 404 if ((s->m_target[i].m_deviceinfo & 405 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 406 MPI2_SAS_DEVICE_INFO_END_DEVICE) 407 mdb_printf("End device: "); 408 if ((s->m_target[i].m_deviceinfo & 409 MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 410 MPI2_SAS_DEVICE_INFO_NO_DEVICE) 411 mdb_printf("No device "); 412 413 for (loop = 0, comma = 0; 414 loop < (sizeof (devinfo_array) / 415 sizeof (devinfo_array[0])); loop++) { 416 if (s->m_target[i].m_deviceinfo & 417 devinfo_array[loop].value) { 418 mdb_printf("%s%s", 419 (comma ? ", " : ""), 420 devinfo_array[loop].text); 421 comma++; 422 } 423 } 424 mdb_printf("\n"); 425 426 if (s->m_target[i].m_tgt_dip) { 427 *target_path = 0; 428 if (construct_path((uintptr_t) 429 s->m_target[i].m_tgt_dip, 430 target_path) 431 == DCMD_OK) 432 mdb_printf("%s\n", target_path); 433 } 434 mdi_info(m, i); 435 mdb_dec_indent(5); 436 } 437 } 438 } 439 #endif 440 } 441 442 int 443 display_slotinfo() 444 { 445 #if 0 446 int i, nslots; 447 struct mptsas_cmd c, *q, *slots; 448 int header_output = 0; 449 int rv = DCMD_OK; 450 int slots_in_use = 0; 451 int tcmds = 0; 452 int mismatch = 0; 453 int wq, dq; 454 int ncmds = 0; 455 ulong_t saved_indent; 456 457 nslots = s->m_n_normal; 458 459 slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP); 460 461 for (i = 0; i < nslots; i++) 462 if (s->m_slot[i]) { 463 slots_in_use++; 464 if (mdb_vread(&slots[i], sizeof (mptsas_cmd_t), 465 (uintptr_t)s->m_slot[i]) == -1) { 466 mdb_warn("couldn't read slot"); 467 s->m_slot[i] = NULL; 468 } 469 if ((slots[i].cmd_flags & CFLAG_CMDIOC) == 0) 470 tcmds++; 471 if (i != slots[i].cmd_slot) 472 mismatch++; 473 } 474 475 for (q = m.m_waitq, wq = 0; q; q = c.cmd_linkp, wq++) 476 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 477 mdb_warn("couldn't follow m_waitq"); 478 rv = DCMD_ERR; 479 goto exit; 480 } 481 482 for (q = m.m_doneq, dq = 0; q; q = c.cmd_linkp, dq++) 483 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 484 mdb_warn("couldn't follow m_doneq"); 485 rv = DCMD_ERR; 486 goto exit; 487 } 488 489 for (i = 0; i < MPTSAS_MAX_TARGETS; i++) 490 ncmds += s->m_target[i].m_t_ncmds; 491 492 mdb_printf("\n"); 493 mdb_printf(" mpt. slot mptsas_slots slot"); 494 mdb_printf("\n"); 495 mdb_printf("m_ncmds total" 496 " targ throttle m_t_ncmds targ_tot wq dq"); 497 mdb_printf("\n"); 498 mdb_printf("----------------------------------------------------"); 499 mdb_printf("\n"); 500 501 mdb_printf("%7d ", m.m_ncmds); 502 mdb_printf("%s", (m.m_ncmds == slots_in_use ? " " : "!=")); 503 mdb_printf("%3d total %3d ", slots_in_use, ncmds); 504 mdb_printf("%s", (tcmds == ncmds ? " " : " !=")); 505 mdb_printf("%3d %2d %2d\n", tcmds, wq, dq); 506 507 saved_indent = mdb_dec_indent(0); 508 mdb_dec_indent(saved_indent); 509 510 for (i = 0; i < s->m_n_normal; i++) 511 if (s->m_slot[i]) { 512 if (!header_output) { 513 mdb_printf("\n"); 514 mdb_printf("mptsas_cmd slot cmd_slot " 515 "cmd_flags cmd_pkt_flags scsi_pkt " 516 " targ,lun [ pkt_cdbp ...\n"); 517 mdb_printf("-------------------------------" 518 "--------------------------------------" 519 "--------------------------------------" 520 "------\n"); 521 header_output = 1; 522 } 523 mdb_printf("%16p %4d %s %4d %8x %8x %16p ", 524 s->m_slot[i], i, 525 (i == slots[i].cmd_slot?" ":"BAD"), 526 slots[i].cmd_slot, 527 slots[i].cmd_flags, 528 slots[i].cmd_pkt_flags, 529 slots[i].cmd_pkt); 530 (void) print_cdb(&slots[i]); 531 } 532 533 /* print the wait queue */ 534 535 for (q = m.m_waitq; q; q = c.cmd_linkp) { 536 if (q == m.m_waitq) 537 mdb_printf("\n"); 538 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) 539 == -1) { 540 mdb_warn("couldn't follow m_waitq"); 541 rv = DCMD_ERR; 542 goto exit; 543 } 544 mdb_printf("%16p wait n/a %4d %8x %8x %16p ", 545 q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags, 546 c.cmd_pkt); 547 print_cdb(&c); 548 } 549 550 /* print the done queue */ 551 552 for (q = m.m_doneq; q; q = c.cmd_linkp) { 553 if (q == m.m_doneq) 554 mdb_printf("\n"); 555 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) 556 == -1) { 557 mdb_warn("couldn't follow m_doneq"); 558 rv = DCMD_ERR; 559 goto exit; 560 } 561 mdb_printf("%16p done n/a %4d %8x %8x %16p ", 562 q, c.cmd_slot, c.cmd_flags, c.cmd_pkt_flags, 563 c.cmd_pkt); 564 print_cdb(&c); 565 } 566 567 mdb_inc_indent(saved_indent); 568 569 if (m.m_ncmds != slots_in_use) 570 mdb_printf("WARNING: mpt.m_ncmds does not match the number of " 571 "slots in use\n"); 572 573 if (tcmds != ncmds) 574 mdb_printf("WARNING: the total of m_target[].m_t_ncmds does " 575 "not match the slots in use\n"); 576 577 if (mismatch) 578 mdb_printf("WARNING: corruption in slot table, " 579 "m_slot[].cmd_slot incorrect\n"); 580 581 /* now check for corruptions */ 582 583 for (q = m.m_waitq; q; q = c.cmd_linkp) { 584 for (i = 0; i < nslots; i++) 585 if (s->m_slot[i] == q) 586 mdb_printf("WARNING: m_waitq entry" 587 "(mptsas_cmd_t) %p is in m_slot[%i]\n", 588 q, i); 589 590 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 591 mdb_warn("couldn't follow m_waitq"); 592 rv = DCMD_ERR; 593 goto exit; 594 } 595 } 596 597 for (q = m.m_doneq; q; q = c.cmd_linkp) { 598 for (i = 0; i < nslots; i++) 599 if (s->m_slot[i] == q) 600 mdb_printf("WARNING: m_doneq entry " 601 "(mptsas_cmd_t) %p is in m_slot[%i]\n", q, i); 602 603 if (mdb_vread(&c, sizeof (mptsas_cmd_t), (uintptr_t)q) == -1) { 604 mdb_warn("couldn't follow m_doneq"); 605 rv = DCMD_ERR; 606 goto exit; 607 } 608 if ((c.cmd_flags & CFLAG_FINISHED) == 0) 609 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 610 "should have CFLAG_FINISHED set\n", q); 611 if (c.cmd_flags & CFLAG_IN_TRANSPORT) 612 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 613 "should not have CFLAG_IN_TRANSPORT set\n", q); 614 if (c.cmd_flags & CFLAG_CMDARQ) 615 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 616 "should not have CFLAG_CMDARQ set\n", q); 617 if (c.cmd_flags & CFLAG_COMPLETED) 618 mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p " 619 "should not have CFLAG_COMPLETED set\n", q); 620 } 621 622 exit: 623 mdb_free(slots, sizeof (mptsas_cmd_t) * nslots); 624 return (rv); 625 #endif 626 mdb_printf("\n"); 627 mdb_printf("The slot information is not implemented yet\n"); 628 return (0); 629 } 630 631 void 632 display_deviceinfo(struct mptsas *mp) 633 { 634 char device_path[PATH_MAX]; 635 636 *device_path = 0; 637 if (construct_path((uintptr_t)mp->m_dip, device_path) != DCMD_OK) { 638 strcpy(device_path, "couldn't determine device path"); 639 } 640 641 mdb_printf("\n"); 642 mdb_printf("Path in device tree %s\n", device_path); 643 #if 0 644 mdb_printf("base_wwid phys " 645 "mptid prodid devid revid ssid\n"); 646 mdb_printf("-----------------------------" 647 "----------------------------------\n"); 648 mdb_printf("%"PRIx64" %2d %3d " 649 "0x%04x 0x%04x ", m.un.m_base_wwid, m.m_num_phys, m.m_mptid, 650 m.m_productid, m.m_devid); 651 switch (m.m_devid) { 652 case MPTSAS_909: 653 mdb_printf("(909) "); 654 break; 655 case MPTSAS_929: 656 mdb_printf("(929) "); 657 break; 658 case MPTSAS_919: 659 mdb_printf("(919) "); 660 break; 661 case MPTSAS_1030: 662 mdb_printf("(1030) "); 663 break; 664 case MPTSAS_1064: 665 mdb_printf("(1064) "); 666 break; 667 case MPTSAS_1068: 668 mdb_printf("(1068) "); 669 break; 670 case MPTSAS_1064E: 671 mdb_printf("(1064E) "); 672 break; 673 case MPTSAS_1068E: 674 mdb_printf("(1068E) "); 675 break; 676 default: 677 mdb_printf("(?????) "); 678 break; 679 } 680 mdb_printf("0x%02x 0x%04x\n", m.m_revid, m.m_ssid); 681 mdb_printf("%s\n", device_path); 682 683 for (i = 0; i < MAX_MPI2_PORTS; i++) { 684 if (i%4 == 0) 685 mdb_printf("\n"); 686 687 mdb_printf("%d:", i); 688 689 switch (m.m_port_type[i]) { 690 case MPI2_PORTFACTS_PORTTYPE_INACTIVE: 691 mdb_printf("inactive ", 692 m.m_protocol_flags[i]); 693 break; 694 case MPI2_PORTFACTS_PORTTYPE_SCSI: 695 mdb_printf("SCSI (0x%1x) ", 696 m.m_protocol_flags[i]); 697 break; 698 case MPI2_PORTFACTS_PORTTYPE_FC: 699 mdb_printf("FC (0x%1x) ", 700 m.m_protocol_flags[i]); 701 break; 702 case MPI2_PORTFACTS_PORTTYPE_ISCSI: 703 mdb_printf("iSCSI (0x%1x) ", 704 m.m_protocol_flags[i]); 705 break; 706 case MPI2_PORTFACTS_PORTTYPE_SAS: 707 mdb_printf("SAS (0x%1x) ", 708 m.m_protocol_flags[i]); 709 break; 710 default: 711 mdb_printf("unknown "); 712 } 713 } 714 #endif 715 mdb_printf("\n"); 716 } 717 718 static int 719 mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 720 { 721 struct mptsas m; 722 struct mptsas_slots *s; 723 724 int nslots; 725 int slot_size = 0; 726 uint_t verbose = FALSE; 727 uint_t target_info = FALSE; 728 uint_t slot_info = FALSE; 729 uint_t device_info = FALSE; 730 uint_t port_info = FALSE; 731 int rv = DCMD_OK; 732 void *mptsas_state; 733 734 if (!(flags & DCMD_ADDRSPEC)) { 735 mptsas_state = NULL; 736 if (mdb_readvar(&mptsas_state, "mptsas_state") == -1) { 737 mdb_warn("can't read mptsas_state"); 738 return (DCMD_ERR); 739 } 740 if (mdb_pwalk_dcmd("genunix`softstate", "mpt_sas`mptsas", argc, 741 argv, (uintptr_t)mptsas_state) == -1) { 742 mdb_warn("mdb_pwalk_dcmd failed"); 743 return (DCMD_ERR); 744 } 745 return (DCMD_OK); 746 } 747 748 if (mdb_getopts(argc, argv, 749 's', MDB_OPT_SETBITS, TRUE, &slot_info, 750 'd', MDB_OPT_SETBITS, TRUE, &device_info, 751 't', MDB_OPT_SETBITS, TRUE, &target_info, 752 'p', MDB_OPT_SETBITS, TRUE, &port_info, 753 'v', MDB_OPT_SETBITS, TRUE, &verbose, 754 NULL) != argc) 755 return (DCMD_USAGE); 756 757 758 if (mdb_vread(&m, sizeof (m), addr) == -1) { 759 mdb_warn("couldn't read mpt struct at 0x%p", addr); 760 return (DCMD_ERR); 761 } 762 763 s = mdb_alloc(sizeof (mptsas_slots_t), UM_SLEEP); 764 765 if (mdb_vread(s, sizeof (mptsas_slots_t), 766 (uintptr_t)m.m_active) == -1) { 767 mdb_warn("couldn't read small mptsas_slots_t at 0x%p", 768 m.m_active); 769 mdb_free(s, sizeof (mptsas_slots_t)); 770 return (DCMD_ERR); 771 } 772 773 nslots = s->m_n_normal; 774 775 mdb_free(s, sizeof (mptsas_slots_t)); 776 777 slot_size = sizeof (mptsas_slots_t) + 778 (sizeof (mptsas_cmd_t *) * (nslots-1)); 779 780 s = mdb_alloc(slot_size, UM_SLEEP); 781 782 if (mdb_vread(s, slot_size, (uintptr_t)m.m_active) == -1) { 783 mdb_warn("couldn't read large mptsas_slots_t at 0x%p", 784 m.m_active); 785 mdb_free(s, slot_size); 786 return (DCMD_ERR); 787 } 788 789 /* processing completed */ 790 791 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) || 792 (flags & DCMD_LOOPFIRST) || slot_info || device_info || 793 target_info) { 794 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST)) 795 mdb_printf("\n"); 796 mdb_printf(" mptsas_t inst ncmds suspend power"); 797 mdb_printf("\n"); 798 mdb_printf("=========================================" 799 "======================================="); 800 mdb_printf("\n"); 801 } 802 803 mdb_printf("%16p %4d %5d ", addr, m.m_instance, m.m_ncmds); 804 mdb_printf("%7d", m.m_suspended); 805 switch (m.m_power_level) { 806 case PM_LEVEL_D0: 807 mdb_printf(" ON=D0 "); 808 break; 809 case PM_LEVEL_D1: 810 mdb_printf(" D1 "); 811 break; 812 case PM_LEVEL_D2: 813 mdb_printf(" D2 "); 814 break; 815 case PM_LEVEL_D3: 816 mdb_printf("OFF=D3 "); 817 break; 818 default: 819 mdb_printf("INVALD "); 820 } 821 mdb_printf("\n"); 822 823 mdb_inc_indent(17); 824 825 if (target_info) 826 display_targets(&m); 827 828 if (port_info) 829 display_ports(&m); 830 831 if (device_info) 832 display_deviceinfo(&m); 833 834 if (slot_info) 835 display_slotinfo(); 836 837 mdb_dec_indent(17); 838 839 mdb_free(s, slot_size); 840 841 return (rv); 842 } 843 844 void 845 mptsas_help() 846 { 847 mdb_printf("Prints summary information about each mpt_sas instance, " 848 "including warning\nmessages when slot usage doesn't match " 849 "summary information.\n" 850 "Without the address of a \"struct mptsas\", prints every " 851 "instance.\n\n" 852 "Switches:\n" 853 " -t includes information about targets\n" 854 " -p includes information about port\n" 855 " -d includes information about the hardware\n"); 856 } 857 858 static const mdb_dcmd_t dcmds[] = { 859 { "mptsas", "?[-tpd]", "print mpt_sas information", mptsas_dcmd, 860 mptsas_help}, { NULL } 861 }; 862 863 static const mdb_modinfo_t modinfo = { 864 MDB_API_VERSION, dcmds, NULL 865 }; 866 867 const mdb_modinfo_t * 868 _mdb_init(void) 869 { 870 return (&modinfo); 871 }