/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2014 Joyent, Inc. All rights reserved.
* Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
*/
#include <limits.h>
#include <sys/mdb_modapi.h>
#pragma pack(1)
#pragma pack()
struct {
int value;
char *text;
} devinfo_array[] = {
{ MPI2_SAS_DEVICE_INFO_SEP, "SEP" },
{ MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE, "ATAPI device" },
{ MPI2_SAS_DEVICE_INFO_LSI_DEVICE, "LSI device" },
{ MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH, "direct attach" },
{ MPI2_SAS_DEVICE_INFO_SSP_TARGET, "SSP tgt" },
{ MPI2_SAS_DEVICE_INFO_STP_TARGET, "STP tgt" },
{ MPI2_SAS_DEVICE_INFO_SMP_TARGET, "SMP tgt" },
{ MPI2_SAS_DEVICE_INFO_SATA_DEVICE, "SATA dev" },
{ MPI2_SAS_DEVICE_INFO_SSP_INITIATOR, "SSP init" },
{ MPI2_SAS_DEVICE_INFO_STP_INITIATOR, "STP init" },
{ MPI2_SAS_DEVICE_INFO_SMP_INITIATOR, "SMP init" },
{ MPI2_SAS_DEVICE_INFO_SATA_HOST, "SATA host" }
};
int
{
struct dev_info d;
mdb_warn("couldn't read dev_info");
return (DCMD_ERR);
}
if (d.devi_parent) {
(uintptr_t)d.devi_node_name);
}
return (DCMD_OK);
}
/* ARGSUSED */
int
{
struct mdi_client c;
mdb_warn("couldn't read mdi_pathinfo");
return (DCMD_ERR);
}
if (target != mdi_target)
return (0);
mdb_warn("couldn't read mdi_client");
return (-1);
}
case MDI_PATHINFO_STATE_INIT:
mdb_printf(" initializing");
break;
mdb_printf(" online");
break;
mdb_printf(" standby");
break;
case MDI_PATHINFO_STATE_FAULT:
mdb_printf(" fault");
break;
mdb_printf(" offline");
break;
default:
mdb_printf(" invalid state");
break;
}
mdb_printf("\n");
return (0);
}
void
{
struct dev_info d;
struct mdi_phci p;
mdb_warn("couldn't read m_dip");
return;
}
if (MDI_PHCI(&d)) {
== -1) {
mdb_warn("couldn't read m_dip.devi_mdi_xhci");
return;
}
if (p.ph_path_head)
return;
}
}
void
{
int j;
mdb_warn("couldn't read cmd_pkt");
return;
}
/*
* We use cmd_cdblen here because 5.10 doesn't
* have the cdb length in the pkt
*/
mdb_warn("couldn't read pkt_cdbp");
return;
}
mdb_printf("%3d,%-3d [ ",
for (j = 0; j < m->cmd_cdblen; j++)
mdb_printf("]\n");
}
void
{
int i;
mdb_printf("\n");
mdb_printf("phy number and port mapping table\n");
for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
mdb_printf("phy %x --> port %x, phymask %x,"
}
}
mdb_printf("\n");
}
static uintptr_t
{
return (NULL);
lp->list_offset));
}
static uintptr_t
{
/* LINTED E_BAD_PTR_CAST_ALIG */
lp->list_offset);
return (NULL);
}
static void *
{
void *rp;
if (klp == 0)
return (NULL);
if (addr)
return (rp);
}
static void *
{
void *rp;
/* LINTED E_BAD_PTR_CAST_ALIG */
break;
}
if (klp == 0) {
return (NULL);
}
if (addr)
return (rp);
}
void
{
mdb_printf("\n");
mdb_printf(" mptsas_target_t slot devhdl wwn ncmds throttle "
"dr_flag dups\n");
mdb_printf("---------------------------------------"
"-------------------------------\n");
ptgt->m_deviceinfo) {
switch (ptgt->m_t_throttle) {
case QFULL_THROTTLE:
mdb_printf(" QFULL ");
break;
case DRAIN_THROTTLE:
mdb_printf(" DRAIN ");
break;
case HOLD_THROTTLE:
mdb_printf(" HOLD ");
break;
case MAX_THROTTLE:
mdb_printf(" MAX ");
break;
default:
mdb_printf("%8d ",
ptgt->m_t_throttle);
}
case MPTSAS_DR_INACTIVE:
mdb_printf(" INACTIVE ");
break;
case MPTSAS_DR_INTRANSITION:
mdb_printf("TRANSITION ");
break;
default:
mdb_printf(" UNKNOWN ");
break;
}
mdb_printf("%d\n",
if (verbose) {
mdb_inc_indent(5);
if ((ptgt->m_deviceinfo &
mdb_printf("Fanout expander: ");
if ((ptgt->m_deviceinfo &
mdb_printf("Edge expander: ");
if ((ptgt->m_deviceinfo &
mdb_printf("End device: ");
if ((ptgt->m_deviceinfo &
mdb_printf("No device ");
loop < (sizeof (devinfo_array) /
sizeof (devinfo_array[0])); loop++) {
if (ptgt->m_deviceinfo &
mdb_printf("%s%s",
comma++;
}
}
mdb_printf("\n");
mdb_dec_indent(5);
}
}
}
mdb_printf("\n");
mdb_printf(" mptsas_smp_t devhdl wwn phymask\n");
mdb_printf("---------------------------------------"
"------------------\n");
&p_addr)) {
if (!verbose)
continue;
mdb_inc_indent(5);
mdb_printf("Fanout expander: ");
mdb_printf("Edge expander: ");
mdb_printf("End device: ");
mdb_printf("No device ");
loop < (sizeof (devinfo_array)
/ sizeof (devinfo_array[0]));
loop++) {
if (psmp->m_deviceinfo &
mdb_printf("%s%s",
comma++;
}
}
mdb_printf("\n");
mdb_dec_indent(5);
}
}
int
{
int i, nslots;
int header_output = 0;
int slots_in_use = 0;
int tcmds = 0;
int mismatch = 0;
int ncmds = 0;
int state;
mdb_warn("mptsas: slot info can only be displayed on a system "
"dump or under kmdb\n");
return (DCMD_ERR);
}
mdb_warn("can't read variable 'panicstr'");
return (DCMD_ERR);
}
mdb_warn("mptsas: slot info not available for live dump\n");
return (DCMD_ERR);
}
nslots = s->m_n_normal;
for (i = 0; i < nslots; i++)
if (s->m_slot[i]) {
slots_in_use++;
mdb_warn("couldn't read slot");
}
tcmds++;
mismatch++;
}
mdb_warn("couldn't follow m_waitq");
goto exit;
}
mdb_warn("couldn't follow m_doneq");
goto exit;
}
ptgt->m_deviceinfo) {
}
}
mdb_printf("\n");
mdb_printf(" mpt. slot mptsas_slots slot");
mdb_printf("\n");
mdb_printf("m_ncmds total"
" targ throttle m_t_ncmds targ_tot wq dq");
mdb_printf("\n");
mdb_printf("----------------------------------------------------");
mdb_printf("\n");
saved_indent = mdb_dec_indent(0);
for (i = 0; i < s->m_n_normal; i++)
if (s->m_slot[i]) {
if (!header_output) {
mdb_printf("\n");
mdb_printf("mptsas_cmd slot cmd_slot "
"cmd_flags cmd_pkt_flags scsi_pkt "
" targ,lun [ pkt_cdbp ...\n");
mdb_printf("-------------------------------"
"--------------------------------------"
"--------------------------------------"
"------\n");
header_output = 1;
}
mdb_printf("%16p %4d %s %4d %8x %8x %16p ",
s->m_slot[i], i,
slots[i].cmd_pkt_flags,
}
/* print the wait queue */
mdb_printf("\n");
== -1) {
mdb_warn("couldn't follow m_waitq");
goto exit;
}
mdb_printf("%16p wait n/a %4d %8x %8x %16p ",
c.cmd_pkt);
print_cdb(&c);
}
/* print the done queue */
mdb_printf("\n");
== -1) {
mdb_warn("couldn't follow m_doneq");
goto exit;
}
mdb_printf("%16p done n/a %4d %8x %8x %16p ",
c.cmd_pkt);
print_cdb(&c);
}
mdb_printf("WARNING: mpt.m_ncmds does not match the number of "
"slots in use\n");
mdb_printf("WARNING: the total of m_target[].m_t_ncmds does "
"not match the slots in use\n");
if (mismatch)
mdb_printf("WARNING: corruption in slot table, "
"m_slot[].cmd_slot incorrect\n");
/* now check for corruptions */
for (i = 0; i < nslots; i++)
if (s->m_slot[i] == q)
mdb_printf("WARNING: m_waitq entry"
"(mptsas_cmd_t) %p is in m_slot[%i]\n",
q, i);
mdb_warn("couldn't follow m_waitq");
goto exit;
}
}
for (i = 0; i < nslots; i++)
if (s->m_slot[i] == q)
mdb_printf("WARNING: m_doneq entry "
"(mptsas_cmd_t) %p is in m_slot[%i]\n", q, i);
mdb_warn("couldn't follow m_doneq");
goto exit;
}
if ((c.cmd_flags & CFLAG_FINISHED) == 0)
mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
"should have CFLAG_FINISHED set\n", q);
if (c.cmd_flags & CFLAG_IN_TRANSPORT)
mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
"should not have CFLAG_IN_TRANSPORT set\n", q);
if (c.cmd_flags & CFLAG_CMDARQ)
mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
"should not have CFLAG_CMDARQ set\n", q);
if (c.cmd_flags & CFLAG_COMPLETED)
mdb_printf("WARNING: m_doneq entry (mptsas_cmd_t) %p "
"should not have CFLAG_COMPLETED set\n", q);
}
exit:
return (rv);
}
void
{
*device_path = 0;
}
mdb_printf("\n");
mdb_printf("base_wwid phys "
" prodid devid revid ssid\n");
mdb_printf("-----------------------------"
"----------------------------------\n");
mdb_printf("(SAS2004) ");
break;
mdb_printf("(SAS2008) ");
break;
mdb_printf("(SAS2108) ");
break;
mdb_printf("(SAS2116) ");
break;
mdb_printf("(SSS6200) ");
break;
mdb_printf("(SAS2208) ");
break;
mdb_printf("(SAS2308) ");
break;
mdb_printf("(SAS3004) ");
break;
mdb_printf("(SAS3008) ");
break;
mdb_printf("(SAS3108) ");
break;
default:
mdb_printf("(SAS????) ");
break;
}
}
void
dump_debug_log(void)
{
char *logbuf;
int i;
mdb_warn("No debug log buffer present");
return;
}
== -1) {
mdb_warn("No debug linecnt present");
return;
}
== -1) {
mdb_warn("No debug linelen present");
return;
}
== -1) {
mdb_warn("No debug log buffer present");
return;
}
mdb_printf("\n");
for (i = 0; i < linecnt; i++) {
idx++;
}
}
static int
{
struct mptsas m;
struct mptsas_slots *s;
int nslots;
int slot_size = 0;
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't read mptsas_state");
return (DCMD_ERR);
}
mdb_warn("mdb_pwalk_dcmd failed");
return (DCMD_ERR);
}
return (DCMD_OK);
}
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (mdb_vread(s, sizeof (mptsas_slots_t),
mdb_warn("couldn't read small mptsas_slots_t at 0x%p",
m.m_active);
mdb_free(s, sizeof (mptsas_slots_t));
return (DCMD_ERR);
}
nslots = s->m_n_normal;
mdb_free(s, sizeof (mptsas_slots_t));
slot_size = sizeof (mptsas_slots_t) +
mdb_warn("couldn't read large mptsas_slots_t at 0x%p",
m.m_active);
return (DCMD_ERR);
}
/* processing completed */
target_info) {
mdb_printf("\n");
mdb_printf(" mptsas_t inst ncmds suspend power");
mdb_printf("\n");
mdb_printf("========================================="
"=======================================");
mdb_printf("\n");
}
switch (m.m_power_level) {
case PM_LEVEL_D0:
mdb_printf(" ON=D0 ");
break;
case PM_LEVEL_D1:
mdb_printf(" D1 ");
break;
case PM_LEVEL_D2:
mdb_printf(" D2 ");
break;
case PM_LEVEL_D3:
mdb_printf("OFF=D3 ");
break;
default:
mdb_printf("INVALD ");
}
mdb_printf("\n");
mdb_inc_indent(17);
if (target_info)
display_targets(&m, verbose);
if (port_info)
display_ports(&m);
if (device_info)
display_deviceinfo(&m);
if (slot_info)
display_slotinfo(&m, s);
if (debug_log)
mdb_dec_indent(17);
return (rv);
}
void
{
mdb_printf("Prints summary information about each mpt_sas instance, "
"including warning\nmessages when slot usage doesn't match "
"summary information.\n"
"Without the address of a \"struct mptsas\", prints every "
"instance.\n\n"
"Switches:\n"
" -t[v] includes information about targets, v = be more verbose\n"
" -p includes information about port\n"
" -s includes information about mpt slots\n"
" -d includes information about the hardware\n"
" -D print the mptsas specific debug log\n");
}
mptsas_help}, { NULL }
};
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}