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