170ab954aSramat /*
270ab954aSramat * CDDL HEADER START
370ab954aSramat *
470ab954aSramat * The contents of this file are subject to the terms of the
570ab954aSramat * Common Development and Distribution License (the "License").
670ab954aSramat * You may not use this file except in compliance with the License.
770ab954aSramat *
870ab954aSramat * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
970ab954aSramat * or http://www.opensolaris.org/os/licensing.
1070ab954aSramat * See the License for the specific language governing permissions
1170ab954aSramat * and limitations under the License.
1270ab954aSramat *
1370ab954aSramat * When distributing Covered Code, include this CDDL HEADER in each
1470ab954aSramat * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1570ab954aSramat * If applicable, add the following below this CDDL HEADER, with the
1670ab954aSramat * fields enclosed by brackets "[]" replaced with your own identifying
1770ab954aSramat * information: Portions Copyright [yyyy] [name of copyright owner]
1870ab954aSramat *
1970ab954aSramat * CDDL HEADER END
2070ab954aSramat */
2170ab954aSramat /*
2270ab954aSramat * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2370ab954aSramat * Use is subject to license terms.
24*3b442230SJordan Paige Hendricks *
25*3b442230SJordan Paige Hendricks * Copyright 2019 Joyent, Inc.
2670ab954aSramat */
2770ab954aSramat
2870ab954aSramat #include <sys/kmem.h>
2970ab954aSramat #include <sys/proc.h>
3070ab954aSramat #include <sys/time.h>
3170ab954aSramat #include <sys/conf.h>
3270ab954aSramat #include <sys/file.h>
3370ab954aSramat #include <sys/ddi.h>
3470ab954aSramat #include <sys/ddi_impldefs.h>
3570ab954aSramat #include <sys/modctl.h>
3670ab954aSramat #include <sys/sunddi.h>
3770ab954aSramat #include <sys/scsi/scsi.h>
3870ab954aSramat #include <sys/scsi/impl/scsi_reset_notify.h>
3970ab954aSramat #include <sys/sunmdi.h>
4070ab954aSramat #include <sys/mdi_impldefs.h>
4170ab954aSramat #include <sys/scsi/adapters/scsi_vhci.h>
4270ab954aSramat #include <sys/scsi/scsi_types.h>
4370ab954aSramat #include <sys/disp.h>
4470ab954aSramat #include <sys/types.h>
4570ab954aSramat #include <sys/mdb_modapi.h>
4670ab954aSramat
4770ab954aSramat #define FT(var, typ) (*((typ *)(&(var))))
4870ab954aSramat
4970ab954aSramat static int dump_states(uintptr_t array_vaddr, int verbose,
5070ab954aSramat struct i_ddi_soft_state *sp);
5170ab954aSramat static int i_vhci_states(uintptr_t addr, uint_t flags, int argc,
5270ab954aSramat const mdb_arg_t *argv, struct i_ddi_soft_state *sp);
5370ab954aSramat static int vhci_states(uintptr_t addr, uint_t flags, int argc,
5470ab954aSramat const mdb_arg_t *argv);
5570ab954aSramat
5670ab954aSramat static int mdiclient(uintptr_t addr, uint_t flags, int argc,
5770ab954aSramat const mdb_arg_t *argv);
5870ab954aSramat static int vhciguid(uintptr_t addr, uint_t flags, int argc,
5970ab954aSramat const mdb_arg_t *argv);
6070ab954aSramat static int vhcilun(uintptr_t addr, uint_t flags, int argc,
6170ab954aSramat const mdb_arg_t *argv);
6270ab954aSramat static int i_vhcilun(uintptr_t addr, uint_t display_single_guid, char *guid);
6370ab954aSramat
6470ab954aSramat /* Utils */
6570ab954aSramat static int get_mdbstr(uintptr_t addr, char *name);
6670ab954aSramat static void dump_mutex(kmutex_t m, char *name);
6770ab954aSramat static void dump_condvar(kcondvar_t c, char *name);
6870ab954aSramat static void dump_string(uintptr_t addr, char *name);
6970ab954aSramat static void dump_flags(unsigned long long flags, char **strings);
7070ab954aSramat static void dump_state_str(char *name, uintptr_t addr, char **strings);
7170ab954aSramat
7270ab954aSramat static int mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata);
7370ab954aSramat
7470ab954aSramat static const mdb_dcmd_t dcmds[] = {
7570ab954aSramat { "vhci_states", "[ -v ]", "dump all the vhci state pointers",
7670ab954aSramat vhci_states },
7770ab954aSramat { "vhciguid", NULL, "list all clients or given a guid, list one client",
7870ab954aSramat vhciguid },
7970ab954aSramat { NULL }
8070ab954aSramat };
8170ab954aSramat
8270ab954aSramat static const mdb_modinfo_t modinfo = {
8370ab954aSramat MDB_API_VERSION, dcmds, NULL
8470ab954aSramat };
8570ab954aSramat
8670ab954aSramat static char *client_lb_str[] =
8770ab954aSramat {
8870ab954aSramat "NONE",
8970ab954aSramat "RR",
9070ab954aSramat "LBA",
9170ab954aSramat NULL
9270ab954aSramat };
9370ab954aSramat
9470ab954aSramat static char *mdi_client_states[] =
9570ab954aSramat {
9670ab954aSramat NULL,
9770ab954aSramat "OPTIMAL",
9870ab954aSramat "DEGRADED",
9970ab954aSramat "FAILED",
10070ab954aSramat NULL
10170ab954aSramat };
10270ab954aSramat
10370ab954aSramat static char *client_flags[] =
10470ab954aSramat {
10570ab954aSramat "MDI_CLIENT_FLAGS_OFFLINE",
10670ab954aSramat "MDI_CLIENT_FLAGS_SUSPEND",
10770ab954aSramat "MDI_CLIENT_FLAGS_POWER_DOWN",
10870ab954aSramat "MDI_CLIENT_FLAGS_DETACH",
10970ab954aSramat "MDI_CLIENT_FLAGS_FAILOVER",
11070ab954aSramat "MDI_CLIENT_FLAGS_REPORT_DEV",
11170ab954aSramat "MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS",
11270ab954aSramat "MDI_CLIENT_FLAGS_ASYNC_FREE",
11370ab954aSramat "MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED",
11470ab954aSramat NULL
11570ab954aSramat };
11670ab954aSramat
11770ab954aSramat static char *vhci_conf_flags[] =
11870ab954aSramat {
11970ab954aSramat "VHCI_CONF_FLAGS_AUTO_FAILBACK",
12070ab954aSramat NULL
12170ab954aSramat };
12270ab954aSramat
12370ab954aSramat static char *svlun_flags[] =
12470ab954aSramat {
12570ab954aSramat "VLUN_TASK_D_ALIVE_FLG",
12670ab954aSramat "VLUN_RESERVE_ACTIVE_FLG",
12770ab954aSramat "VLUN_QUIESCED_FLG",
12870ab954aSramat NULL
12970ab954aSramat };
13070ab954aSramat
13170ab954aSramat static char mdipathinfo_cb_str[] = "::print struct mdi_pathinfo";
13270ab954aSramat
13370ab954aSramat const mdb_modinfo_t *
_mdb_init(void)13470ab954aSramat _mdb_init(void)
13570ab954aSramat {
13670ab954aSramat return (&modinfo);
13770ab954aSramat }
13870ab954aSramat
13970ab954aSramat /*
14070ab954aSramat * mdiclient()
14170ab954aSramat *
14270ab954aSramat * Dump mdi_client_t info and list all paths.
14370ab954aSramat */
14470ab954aSramat /* ARGSUSED */
14570ab954aSramat static int
mdiclient(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14670ab954aSramat mdiclient(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14770ab954aSramat {
14870ab954aSramat struct mdi_client value;
14970ab954aSramat
15070ab954aSramat if (!(flags & DCMD_ADDRSPEC)) {
15170ab954aSramat mdb_warn("mdiclient: requires an address");
15270ab954aSramat return (DCMD_ERR);
15370ab954aSramat }
15470ab954aSramat
15570ab954aSramat if (mdb_vread(&value, sizeof (struct mdi_client), addr)
15670ab954aSramat != sizeof (struct mdi_client)) {
15770ab954aSramat mdb_warn("mdiclient: Failed read on %l#r\n", addr);
15870ab954aSramat return (DCMD_ERR);
15970ab954aSramat }
16070ab954aSramat mdb_printf("----------------- mdi_client @ %#lr ----------\n", addr);
16170ab954aSramat dump_string((uintptr_t)value.ct_guid, "GUID (ct_guid)");
16270ab954aSramat dump_string((uintptr_t)value.ct_drvname, "Driver Name (ct_drvname)");
16370ab954aSramat dump_state_str("Load Balance (ct_lb)", value.ct_lb, client_lb_str);
16470ab954aSramat mdb_printf("\n");
16570ab954aSramat mdb_printf("ct_hnext: %26l#r::print struct mdi_client\n",
16670ab954aSramat value.ct_hnext);
16770ab954aSramat mdb_printf("ct_hprev: %26l#r::print struct mdi_client\n",
16870ab954aSramat value.ct_hprev);
16970ab954aSramat mdb_printf("ct_dip: %28l#r::print struct dev_info\n", value.ct_dip);
17070ab954aSramat mdb_printf("ct_vhci: %27l#r::print struct mdi_vhci\n", value.ct_vhci);
17170ab954aSramat mdb_printf("ct_cprivate: %23l#r\n", value.ct_cprivate);
17270ab954aSramat mdb_printf("\nct_path_head: %22l#r::print struct mdi_pathinfo\n",
17370ab954aSramat value.ct_path_head);
17470ab954aSramat mdb_printf("ct_path_tail: %22l#r::print struct mdi_pathinfo\n",
17570ab954aSramat value.ct_path_tail);
17670ab954aSramat mdb_printf("ct_path_last: %22l#r::print struct mdi_pathfinfo\n",
17770ab954aSramat value.ct_path_last);
17870ab954aSramat mdb_printf("ct_path_count: %21d\n", value.ct_path_count);
17970ab954aSramat mdb_printf("List of paths:\n");
18070ab954aSramat mdb_pwalk("mdipi_client_list", (mdb_walk_cb_t)mpxio_walk_cb,
18170ab954aSramat mdipathinfo_cb_str, (uintptr_t)value.ct_path_head);
18270ab954aSramat
18370ab954aSramat mdb_printf("\n");
18470ab954aSramat dump_state_str("Client State (ct_state)", value.ct_state,
18570ab954aSramat mdi_client_states);
18670ab954aSramat dump_mutex(value.ct_mutex, "per-client mutex (ct_mutex):");
18770ab954aSramat mdb_printf("ct_flags: %26d\n", value.ct_flags);
18870ab954aSramat if (value.ct_flags) {
18970ab954aSramat dump_flags((unsigned long long)value.ct_flags, client_flags);
19070ab954aSramat }
19170ab954aSramat mdb_printf("ct_unstable: %23d\n", value.ct_unstable);
19270ab954aSramat dump_condvar(value.ct_unstable_cv, "ct_unstable_cv");
19370ab954aSramat dump_condvar(value.ct_failover_cv, "ct_failover_cv");
19470ab954aSramat
19570ab954aSramat mdb_printf("\n");
196*3b442230SJordan Paige Hendricks mdb_printf("ct_failover_flags TEMP_VAR: %8d\n",
197*3b442230SJordan Paige Hendricks value.ct_failover_flags);
198*3b442230SJordan Paige Hendricks mdb_printf("ct_failover_status UNUSED: %9d\n",
199*3b442230SJordan Paige Hendricks value.ct_failover_status);
20070ab954aSramat
20170ab954aSramat return (DCMD_OK);
20270ab954aSramat }
20370ab954aSramat
20470ab954aSramat /*
20570ab954aSramat * vhcilun()
20670ab954aSramat *
20770ab954aSramat * Get client info given a guid.
20870ab954aSramat */
20970ab954aSramat /* ARGSUSED */
21070ab954aSramat static int
vhcilun(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)21170ab954aSramat vhcilun(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
21270ab954aSramat {
21370ab954aSramat if (!(flags & DCMD_ADDRSPEC)) {
21470ab954aSramat mdb_warn("sv_lun: requires an address");
21570ab954aSramat return (DCMD_ERR);
21670ab954aSramat }
21770ab954aSramat
21870ab954aSramat return (i_vhcilun(addr, 0 /* display_single_guid */, 0));
21970ab954aSramat }
22070ab954aSramat
22170ab954aSramat /*
22270ab954aSramat * vhciguid()
22370ab954aSramat *
22470ab954aSramat * List all the clients.
22570ab954aSramat */
22670ab954aSramat /* ARGSUSED */
22770ab954aSramat static int
vhciguid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)22870ab954aSramat vhciguid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
22970ab954aSramat {
23070ab954aSramat
23170ab954aSramat struct i_ddi_soft_state ss;
23270ab954aSramat int i;
23370ab954aSramat
23470ab954aSramat mdi_vhci_t *mdi_vhci_value;
23570ab954aSramat mdi_client_t *mdi_client_value;
23670ab954aSramat struct client_hash *ct_hash_val;
23770ab954aSramat struct client_hash *ct_hash_table_val;
23870ab954aSramat
23970ab954aSramat int len = strlen(MDI_HCI_CLASS_SCSI);
24070ab954aSramat int mdi_vhci_len = sizeof (*mdi_vhci_value);
24170ab954aSramat int mdi_client_len = sizeof (*mdi_client_value);
24270ab954aSramat int ct_hash_len = sizeof (*ct_hash_val);
24370ab954aSramat
24470ab954aSramat int ct_hash_count = 0;
24570ab954aSramat char *class;
24670ab954aSramat int found = 0;
24770ab954aSramat uintptr_t buf;
24870ab954aSramat uintptr_t temp;
24970ab954aSramat
25070ab954aSramat
25170ab954aSramat
25270ab954aSramat if (flags & DCMD_ADDRSPEC)
25370ab954aSramat mdb_warn("This command doesn't use an address\n");
25470ab954aSramat
25570ab954aSramat if (i_vhci_states(0, 0, 0, 0, &ss) != DCMD_OK)
25670ab954aSramat return (DCMD_ERR);
25770ab954aSramat
25870ab954aSramat if (mdb_readvar(&buf, "mdi_vhci_head") == -1) {
25970ab954aSramat mdb_warn("mdi driver variable mdi_vhci_head not found.\n");
26070ab954aSramat mdb_warn("Is the driver loaded ?\n");
26170ab954aSramat return (DCMD_ERR);
26270ab954aSramat }
26370ab954aSramat mdb_printf("----------------- mdi_vhci_head @ %#lr ----------\n", buf);
26470ab954aSramat mdi_vhci_value = (mdi_vhci_t *)mdb_alloc(mdi_vhci_len, UM_SLEEP|UM_GC);
26570ab954aSramat if (mdb_vread(mdi_vhci_value, mdi_vhci_len, buf) != mdi_vhci_len) {
26670ab954aSramat mdb_warn("vhciguid: Failed read on %l#r\n", mdi_vhci_value);
26770ab954aSramat mdb_free(mdi_vhci_value, mdi_vhci_len);
26870ab954aSramat return (DCMD_ERR);
26970ab954aSramat }
27070ab954aSramat temp = (uintptr_t)mdi_vhci_value->vh_class;
27170ab954aSramat class = (char *)mdb_alloc(len, UM_SLEEP|UM_GC);
27270ab954aSramat if (mdb_vread(class, strlen(MDI_HCI_CLASS_SCSI), temp)
27370ab954aSramat != strlen(MDI_HCI_CLASS_SCSI)) {
27470ab954aSramat mdb_warn("vhciguid: Failed read of class %l#r\n",
27570ab954aSramat mdi_vhci_value);
27670ab954aSramat mdb_free(mdi_vhci_value, mdi_vhci_len);
27770ab954aSramat mdb_free(class, len);
27870ab954aSramat return (DCMD_ERR);
27970ab954aSramat }
28070ab954aSramat class[len] = 0;
28170ab954aSramat mdb_printf("----------------- class @ %s----------\n", class);
28270ab954aSramat while (class) {
28370ab954aSramat if (strcmp(class, MDI_HCI_CLASS_SCSI) == 0) {
28470ab954aSramat found = 1;
28570ab954aSramat break;
28670ab954aSramat }
28770ab954aSramat if (mdi_vhci_value->vh_next == NULL) {
28870ab954aSramat break;
28970ab954aSramat }
29070ab954aSramat temp = (uintptr_t)mdi_vhci_value->vh_next;
29170ab954aSramat if (mdb_vread(mdi_vhci_value, mdi_vhci_len, temp)
29270ab954aSramat != mdi_vhci_len) {
29370ab954aSramat mdb_warn("vhciguid: Failed read on vh->next %l#r\n",
29470ab954aSramat mdi_vhci_value);
29570ab954aSramat break;
29670ab954aSramat }
29770ab954aSramat temp = (uintptr_t)mdi_vhci_value->vh_class;
29870ab954aSramat if (mdb_vread(class, strlen(MDI_HCI_CLASS_SCSI), temp) !=
29970ab954aSramat strlen(MDI_HCI_CLASS_SCSI)) {
30070ab954aSramat mdb_warn("vhciguid: Failed read on vh->next %l#r\n",
30170ab954aSramat mdi_vhci_value);
30270ab954aSramat break;
30370ab954aSramat }
30470ab954aSramat class[len] = 0;
30570ab954aSramat }
30670ab954aSramat
30770ab954aSramat if (found == 0) {
30870ab954aSramat mdb_warn("vhciguid: No scsi_vhci class found");
30970ab954aSramat mdb_free(mdi_vhci_value, mdi_vhci_len);
31070ab954aSramat mdb_free(class, len);
31170ab954aSramat return (DCMD_ERR);
31270ab954aSramat }
31370ab954aSramat mdb_printf("----- Number of devices found %d ----------\n",
31470ab954aSramat mdi_vhci_value->vh_client_count);
31570ab954aSramat for (i = 0; i < CLIENT_HASH_TABLE_SIZE; i++) {
31670ab954aSramat ct_hash_table_val = &mdi_vhci_value->vh_client_table[i];
31770ab954aSramat if (ct_hash_table_val == NULL)
31870ab954aSramat continue;
31970ab954aSramat
32070ab954aSramat /* Read client_hash structure */
32170ab954aSramat ct_hash_val = (struct client_hash *)mdb_alloc(ct_hash_len,
32270ab954aSramat UM_SLEEP|UM_GC);
32370ab954aSramat temp = (uintptr_t)ct_hash_table_val;
32470ab954aSramat if (mdb_vread(ct_hash_val, ct_hash_len, temp) != ct_hash_len) {
32570ab954aSramat mdb_warn("Failed read on hash %l#r\n",
32670ab954aSramat ct_hash_val);
32770ab954aSramat break;
32870ab954aSramat }
32970ab954aSramat mdb_printf("----hash[%d] %l#r: devices mapped = %d --\n",
33070ab954aSramat i, ct_hash_table_val, ct_hash_val->ct_hash_count);
33170ab954aSramat if (ct_hash_val->ct_hash_count == 0) {
33270ab954aSramat continue;
33370ab954aSramat }
33470ab954aSramat
33570ab954aSramat ct_hash_count = ct_hash_val->ct_hash_count;
33670ab954aSramat
33770ab954aSramat /* Read mdi_client structures */
33870ab954aSramat mdi_client_value = (mdi_client_t *)mdb_alloc(mdi_client_len,
33970ab954aSramat UM_SLEEP|UM_GC);
34070ab954aSramat temp = (uintptr_t)ct_hash_val->ct_hash_head;
34170ab954aSramat if (mdb_vread(mdi_client_value, mdi_client_len, temp)
34270ab954aSramat != mdi_client_len) {
34370ab954aSramat mdb_warn("Failed read on client %l#r\n",
34470ab954aSramat mdi_client_value);
34570ab954aSramat break;
34670ab954aSramat }
34770ab954aSramat mdb_printf("mdi_client %l#r %l#r ------\n",
34870ab954aSramat mdi_client_value, mdi_client_value->ct_vprivate);
34970ab954aSramat vhcilun((uintptr_t)mdi_client_value->ct_vprivate,
35070ab954aSramat DCMD_ADDRSPEC, 0, 0);
35170ab954aSramat
35270ab954aSramat while (--ct_hash_count) {
35370ab954aSramat temp = (uintptr_t)mdi_client_value->ct_hnext;
35470ab954aSramat if (mdb_vread(mdi_client_value, mdi_client_len,
35570ab954aSramat temp) != mdi_client_len) {
35670ab954aSramat mdb_warn("Failed read on client %l#r\n",
35770ab954aSramat mdi_client_value);
35870ab954aSramat break;
35970ab954aSramat }
36070ab954aSramat vhcilun((uintptr_t)mdi_client_value->ct_vprivate,
36170ab954aSramat DCMD_ADDRSPEC, 0, 0);
36270ab954aSramat }
36370ab954aSramat }
36470ab954aSramat mdb_printf("----------done----------\n");
36570ab954aSramat
36670ab954aSramat return (DCMD_OK);
36770ab954aSramat }
36870ab954aSramat
36970ab954aSramat /*
37070ab954aSramat * Print the flag name by comparing flags to the mask variable.
37170ab954aSramat */
37270ab954aSramat static void
dump_flags(unsigned long long flags,char ** strings)37370ab954aSramat dump_flags(unsigned long long flags, char **strings)
37470ab954aSramat {
37570ab954aSramat int i, linel = 8, first = 1;
37670ab954aSramat unsigned long long mask = 1;
37770ab954aSramat
37870ab954aSramat for (i = 0; i < 64; i++) {
37970ab954aSramat if (strings[i] == NULL)
38070ab954aSramat break;
38170ab954aSramat if (flags & mask) {
38270ab954aSramat if (!first) {
38370ab954aSramat mdb_printf(" | ");
38470ab954aSramat } else {
38570ab954aSramat first = 0;
38670ab954aSramat }
38770ab954aSramat /* make output pretty */
38870ab954aSramat linel += strlen(strings[i]) + 3;
38970ab954aSramat if (linel > 80) {
39070ab954aSramat mdb_printf("\n\t");
39170ab954aSramat linel = strlen(strings[i]) + 1 + 8;
39270ab954aSramat }
39370ab954aSramat mdb_printf("%s", strings[i]);
39470ab954aSramat }
39570ab954aSramat mask <<= 1;
39670ab954aSramat }
39770ab954aSramat mdb_printf("\n");
39870ab954aSramat }
39970ab954aSramat
40070ab954aSramat /* ARGSUSED */
40170ab954aSramat static int
vhci_states(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)40270ab954aSramat vhci_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
40370ab954aSramat {
40470ab954aSramat return (i_vhci_states(addr, flags, argc, argv, NULL));
40570ab954aSramat }
40670ab954aSramat
40770ab954aSramat /*
40870ab954aSramat * dump_states()
40970ab954aSramat *
41070ab954aSramat * Print the state information for vhci_states().
41170ab954aSramat */
41270ab954aSramat static int
dump_states(uintptr_t array_vaddr,int verbose,struct i_ddi_soft_state * sp)41370ab954aSramat dump_states(uintptr_t array_vaddr, int verbose, struct i_ddi_soft_state *sp)
41470ab954aSramat {
41570ab954aSramat int i;
41670ab954aSramat int array_size;
41770ab954aSramat struct i_ddi_soft_state *ss;
41870ab954aSramat struct scsi_vhci vhci;
41970ab954aSramat
42070ab954aSramat if (sp == NULL) {
42170ab954aSramat ss = (struct i_ddi_soft_state *)mdb_alloc(sizeof (*ss),
42270ab954aSramat UM_SLEEP|UM_GC);
42370ab954aSramat } else {
42470ab954aSramat ss = sp;
42570ab954aSramat }
42670ab954aSramat if (mdb_vread(ss, sizeof (*ss), array_vaddr) != sizeof (*ss)) {
42770ab954aSramat mdb_warn("Cannot read softstate struct (Invalid pointer?).\n");
42870ab954aSramat return (DCMD_ERR);
42970ab954aSramat }
43070ab954aSramat array_size = ss->n_items * (sizeof (void *));
43170ab954aSramat array_vaddr = (uintptr_t)ss->array;
43270ab954aSramat ss->array = mdb_alloc(array_size, UM_SLEEP|UM_GC);
43370ab954aSramat if (mdb_vread(ss->array, array_size, array_vaddr) != array_size) {
43470ab954aSramat mdb_warn("Corrupted softstate struct.\n");
43570ab954aSramat return (DCMD_ERR);
43670ab954aSramat }
43770ab954aSramat if (sp != NULL)
43870ab954aSramat return (DCMD_OK);
43970ab954aSramat if (verbose) {
44070ab954aSramat /*
44170ab954aSramat * ss->size is of type size_t which is 4 bytes and 8 bytes
44270ab954aSramat * on 32-bit and 64-bit systems respectively.
44370ab954aSramat */
44470ab954aSramat #ifdef _LP64
44570ab954aSramat mdb_printf("Softstate size is %lld(0x%llx) bytes.\n\n",
44670ab954aSramat ss->size, ss->size);
44770ab954aSramat #else
44870ab954aSramat mdb_printf("Softstate size is %ld(0x%lx) bytes.\n\n",
44970ab954aSramat ss->size, ss->size);
45070ab954aSramat #endif
45170ab954aSramat mdb_printf("state pointer\t\t\t\t\tinstance\n");
45270ab954aSramat mdb_printf("=============\t\t\t\t\t========\n");
45370ab954aSramat }
45470ab954aSramat for (i = 0; i < ss->n_items; i++) {
45570ab954aSramat if (ss->array[i] == 0)
45670ab954aSramat continue;
45770ab954aSramat
45870ab954aSramat if (mdb_vread(&vhci, sizeof (vhci), (uintptr_t)ss->array[i])
45970ab954aSramat != sizeof (vhci)) {
46070ab954aSramat mdb_warn("Corrupted softstate struct.\n");
46170ab954aSramat return (DCMD_ERR);
46270ab954aSramat }
46370ab954aSramat if (verbose) {
46470ab954aSramat mdb_printf("%l#r::print struct scsi_vhci\t\t %d\n",
46570ab954aSramat ss->array[i], i);
46670ab954aSramat mdb_printf("\nvhci_conf_flags: %d\n",
46770ab954aSramat vhci.vhci_conf_flags);
46870ab954aSramat if (vhci.vhci_conf_flags) {
46970ab954aSramat mdb_printf("\t");
47070ab954aSramat dump_flags((unsigned long long)
47170ab954aSramat vhci.vhci_conf_flags, vhci_conf_flags);
47270ab954aSramat }
47370ab954aSramat } else {
47470ab954aSramat mdb_printf("%l#r\n", ss->array[i]);
47570ab954aSramat }
47670ab954aSramat }
47770ab954aSramat return (DCMD_OK);
47870ab954aSramat }
47970ab954aSramat
48070ab954aSramat static int
get_mdbstr(uintptr_t addr,char * string_val)48170ab954aSramat get_mdbstr(uintptr_t addr, char *string_val)
48270ab954aSramat {
48370ab954aSramat if (mdb_readstr(string_val, MAXNAMELEN, addr) == -1) {
48470ab954aSramat mdb_warn("Error Reading String from %l#r\n", addr);
48570ab954aSramat return (1);
48670ab954aSramat }
48770ab954aSramat
48870ab954aSramat return (0);
48970ab954aSramat }
49070ab954aSramat
49170ab954aSramat static void
dump_state_str(char * name,uintptr_t addr,char ** strings)49270ab954aSramat dump_state_str(char *name, uintptr_t addr, char **strings)
49370ab954aSramat {
49470ab954aSramat mdb_printf("%s: %s (%l#r)\n", name, strings[(unsigned long)addr], addr);
49570ab954aSramat }
49670ab954aSramat
49770ab954aSramat /* VHCI UTILS */
49870ab954aSramat
49970ab954aSramat /*
50070ab954aSramat * i_vhci_states()
50170ab954aSramat *
50270ab954aSramat * Internal routine for vhci_states() to check for -v arg and then
50370ab954aSramat * print state info.
50470ab954aSramat */
50570ab954aSramat /* ARGSUSED */
50670ab954aSramat static int
i_vhci_states(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,struct i_ddi_soft_state * sp)50770ab954aSramat i_vhci_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
50870ab954aSramat struct i_ddi_soft_state *sp)
50970ab954aSramat {
51070ab954aSramat uintptr_t adr;
51170ab954aSramat int verbose = 0;
51270ab954aSramat
51370ab954aSramat if (mdb_readvar(&adr, "vhci_softstate") == -1) {
51470ab954aSramat mdb_warn("vhci driver variable vhci_softstate not found.\n");
51570ab954aSramat mdb_warn("Is the driver loaded ?\n");
51670ab954aSramat return (DCMD_ERR);
51770ab954aSramat }
51870ab954aSramat if (sp == NULL) {
51970ab954aSramat if (mdb_getopts(argc, argv,
520*3b442230SJordan Paige Hendricks 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) {
52170ab954aSramat return (DCMD_USAGE);
52270ab954aSramat }
52370ab954aSramat }
52470ab954aSramat
52570ab954aSramat return (dump_states(adr, verbose, sp));
52670ab954aSramat }
52770ab954aSramat
52870ab954aSramat /*
52970ab954aSramat * i_vhcilun()
53070ab954aSramat *
53170ab954aSramat * Internal routine for vhciguid() to print client info.
53270ab954aSramat */
53370ab954aSramat static int
i_vhcilun(uintptr_t addr,uint_t display_single_guid,char * guid)53470ab954aSramat i_vhcilun(uintptr_t addr, uint_t display_single_guid, char *guid)
53570ab954aSramat {
53670ab954aSramat
53770ab954aSramat scsi_vhci_lun_t value;
53870ab954aSramat struct dev_info dev_info_value;
53970ab954aSramat char string_val[MAXNAMELEN];
54070ab954aSramat int found = 0;
54170ab954aSramat struct mdi_client ct_value;
54270ab954aSramat uintptr_t temp_addr;
54370ab954aSramat
54470ab954aSramat do {
54570ab954aSramat if (mdb_vread(&value, sizeof (scsi_vhci_lun_t), addr) !=
54670ab954aSramat sizeof (scsi_vhci_lun_t)) {
54770ab954aSramat mdb_warn("sv_lun: Failed read on %l#r", addr);
54870ab954aSramat return (DCMD_ERR);
54970ab954aSramat }
55070ab954aSramat
55170ab954aSramat temp_addr = addr;
55270ab954aSramat addr = (uintptr_t)value.svl_hash_next;
55370ab954aSramat
55470ab954aSramat if (!get_mdbstr((uintptr_t)value.svl_lun_wwn, string_val)) {
55570ab954aSramat if (display_single_guid) {
55670ab954aSramat if (strcmp(string_val, guid) == 0) {
55770ab954aSramat found = 1;
55870ab954aSramat } else continue;
55970ab954aSramat }
56070ab954aSramat }
56170ab954aSramat
56270ab954aSramat mdb_printf("%t%l#r::print struct scsi_vhci_lun", temp_addr);
56370ab954aSramat
56470ab954aSramat if (mdb_vread(&dev_info_value, sizeof (struct dev_info),
56570ab954aSramat (uintptr_t)value.svl_dip) != sizeof (struct dev_info)) {
56670ab954aSramat mdb_warn("svl_dip: Failed read on %l#r",
56770ab954aSramat value.svl_dip);
56870ab954aSramat return (DCMD_ERR);
56970ab954aSramat }
57070ab954aSramat
57170ab954aSramat mdb_printf("\n%tGUID: %s\n", string_val);
57270ab954aSramat if (value.svl_active_pclass != NULL) {
57370ab954aSramat if (!get_mdbstr((uintptr_t)value.svl_active_pclass,
57470ab954aSramat string_val)) {
57570ab954aSramat mdb_printf("%tActv_cl: %s", string_val);
57670ab954aSramat }
57770ab954aSramat } else {
57870ab954aSramat mdb_printf(" No active pclass");
57970ab954aSramat }
58070ab954aSramat if (display_single_guid) {
58170ab954aSramat mdb_printf(" (%l#r)", value.svl_active_pclass);
58270ab954aSramat }
58370ab954aSramat
58470ab954aSramat mdb_printf("\n%t%l#r::print struct mdi_client",
58570ab954aSramat dev_info_value.devi_mdi_client);
58670ab954aSramat
58770ab954aSramat if (value.svl_flags) {
58870ab954aSramat mdb_printf("\t");
58970ab954aSramat dump_flags((unsigned long long)value.svl_flags,
59070ab954aSramat svlun_flags);
59170ab954aSramat } else {
59270ab954aSramat mdb_printf("\n");
59370ab954aSramat }
59470ab954aSramat
59570ab954aSramat if (found) {
59670ab954aSramat mdiclient((uintptr_t)dev_info_value.devi_mdi_client,
59770ab954aSramat DCMD_ADDRSPEC, 0, 0);
59870ab954aSramat } else {
59970ab954aSramat if (mdb_vread(&ct_value, sizeof (struct mdi_client),
60070ab954aSramat (uintptr_t)dev_info_value.devi_mdi_client) !=
60170ab954aSramat sizeof (struct mdi_client)) {
60270ab954aSramat mdb_warn("mdiclient: Failed read on %l#r",
60370ab954aSramat dev_info_value.devi_mdi_client);
60470ab954aSramat return (DCMD_ERR);
60570ab954aSramat }
60670ab954aSramat if (ct_value.ct_flags) {
60770ab954aSramat mdb_printf("\t");
60870ab954aSramat dump_flags((unsigned long long)
60970ab954aSramat ct_value.ct_flags, client_flags);
61070ab954aSramat }
61170ab954aSramat mdb_printf("%t");
61270ab954aSramat dump_state_str("LB", ct_value.ct_lb, client_lb_str);
61370ab954aSramat mdb_printf("\n");
61470ab954aSramat }
61570ab954aSramat } while (addr && !found);
61670ab954aSramat return (DCMD_OK);
61770ab954aSramat }
61870ab954aSramat
61970ab954aSramat static void
dump_mutex(kmutex_t m,char * name)62070ab954aSramat dump_mutex(kmutex_t m, char *name)
62170ab954aSramat {
62270ab954aSramat mdb_printf("%s is%s held\n", name, FT(m, uint64_t) == 0 ? " not" : "");
62370ab954aSramat }
62470ab954aSramat
62570ab954aSramat static void
dump_condvar(kcondvar_t c,char * name)62670ab954aSramat dump_condvar(kcondvar_t c, char *name)
62770ab954aSramat {
62870ab954aSramat mdb_printf("Threads sleeping on %s = %d\n", name, (int)FT(c, ushort_t));
62970ab954aSramat }
63070ab954aSramat
63170ab954aSramat static void
dump_string(uintptr_t addr,char * name)63270ab954aSramat dump_string(uintptr_t addr, char *name)
63370ab954aSramat {
63470ab954aSramat char string_val[MAXNAMELEN];
63570ab954aSramat
63670ab954aSramat if (get_mdbstr(addr, string_val)) {
63770ab954aSramat return;
63870ab954aSramat }
63970ab954aSramat mdb_printf("%s: %s (%l#r)\n", name, string_val, addr);
64070ab954aSramat }
64170ab954aSramat
64270ab954aSramat /* ARGSUSED */
64370ab954aSramat static int
mpxio_walk_cb(uintptr_t addr,const void * data,void * cbdata)64470ab954aSramat mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata)
64570ab954aSramat {
64670ab954aSramat mdb_printf("%t%l#r%s\n", addr, (char *)cbdata);
64770ab954aSramat return (0);
64870ab954aSramat }
649