xref: /titanic_53/usr/src/cmd/mdb/common/modules/genunix/mdi.c (revision 70ab954a5d6c4d36858fd6e7e3dd4498d06d2c40)
1*70ab954aSramat /*
2*70ab954aSramat  * CDDL HEADER START
3*70ab954aSramat  *
4*70ab954aSramat  * The contents of this file are subject to the terms of the
5*70ab954aSramat  * Common Development and Distribution License (the "License").
6*70ab954aSramat  * You may not use this file except in compliance with the License.
7*70ab954aSramat  *
8*70ab954aSramat  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*70ab954aSramat  * or http://www.opensolaris.org/os/licensing.
10*70ab954aSramat  * See the License for the specific language governing permissions
11*70ab954aSramat  * and limitations under the License.
12*70ab954aSramat  *
13*70ab954aSramat  * When distributing Covered Code, include this CDDL HEADER in each
14*70ab954aSramat  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*70ab954aSramat  * If applicable, add the following below this CDDL HEADER, with the
16*70ab954aSramat  * fields enclosed by brackets "[]" replaced with your own identifying
17*70ab954aSramat  * information: Portions Copyright [yyyy] [name of copyright owner]
18*70ab954aSramat  *
19*70ab954aSramat  * CDDL HEADER END
20*70ab954aSramat  */
21*70ab954aSramat /*
22*70ab954aSramat  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*70ab954aSramat  * Use is subject to license terms.
24*70ab954aSramat  */
25*70ab954aSramat 
26*70ab954aSramat #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*70ab954aSramat 
28*70ab954aSramat #include <sys/kmem.h>
29*70ab954aSramat #include <sys/proc.h>
30*70ab954aSramat #include <sys/time.h>
31*70ab954aSramat #include <sys/conf.h>
32*70ab954aSramat #include <sys/file.h>
33*70ab954aSramat #include <sys/ddi.h>
34*70ab954aSramat #include <sys/ddi_impldefs.h>
35*70ab954aSramat #include <sys/modctl.h>
36*70ab954aSramat #include <sys/sunddi.h>
37*70ab954aSramat #include <sys/scsi/scsi.h>
38*70ab954aSramat #include <sys/scsi/impl/scsi_reset_notify.h>
39*70ab954aSramat #include <sys/sunmdi.h>
40*70ab954aSramat #include <sys/mdi_impldefs.h>
41*70ab954aSramat #include <sys/scsi/adapters/scsi_vhci.h>
42*70ab954aSramat #include <sys/scsi/scsi_types.h>
43*70ab954aSramat #include <sys/disp.h>
44*70ab954aSramat #include <sys/types.h>
45*70ab954aSramat #include <sys/mdb_modapi.h>
46*70ab954aSramat #include "mdi.h"
47*70ab954aSramat 
48*70ab954aSramat #define	FT(var, typ)	(*((typ *)(&(var))))
49*70ab954aSramat 
50*70ab954aSramat /* Utils */
51*70ab954aSramat static int get_mdbstr(uintptr_t addr, char *name);
52*70ab954aSramat static void dump_flags(unsigned long long flags, char **strings);
53*70ab954aSramat static void dump_mutex(kmutex_t m, char *name);
54*70ab954aSramat static void dump_condvar(kcondvar_t c, char *name);
55*70ab954aSramat static void dump_string(uintptr_t addr, char *name);
56*70ab954aSramat static void dump_state_str(char *name, uintptr_t addr, char **strings);
57*70ab954aSramat 
58*70ab954aSramat static int mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata);
59*70ab954aSramat 
60*70ab954aSramat static char *client_lb_str[] =
61*70ab954aSramat {
62*70ab954aSramat 	"NONE",
63*70ab954aSramat 	"RR",
64*70ab954aSramat 	"LBA",
65*70ab954aSramat 	NULL
66*70ab954aSramat };
67*70ab954aSramat 
68*70ab954aSramat static char *mdi_pathinfo_states[] =
69*70ab954aSramat {
70*70ab954aSramat 	"MDI_PATHINFO_STATE_INIT",
71*70ab954aSramat 	"MDI_PATHINFO_STATE_ONLINE",
72*70ab954aSramat 	"MDI_PATHINFO_STATE_STANDBY",
73*70ab954aSramat 	"MDI_PATHINFO_STATE_FAULT",
74*70ab954aSramat 	"MDI_PATHINFO_STATE_OFFLINE",
75*70ab954aSramat 	NULL
76*70ab954aSramat };
77*70ab954aSramat 
78*70ab954aSramat static char *mdi_pathinfo_ext_states[] =
79*70ab954aSramat {
80*70ab954aSramat 	"MDI_PATHINFO_STATE_USER_DISABLE",
81*70ab954aSramat 	"MDI_PATHINFO_STATE_DRV_DISABLE",
82*70ab954aSramat 	"MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT",
83*70ab954aSramat 	NULL
84*70ab954aSramat };
85*70ab954aSramat 
86*70ab954aSramat static char *mdi_phci_flags[] =
87*70ab954aSramat {
88*70ab954aSramat 	"MDI_PHCI_FLAGS_OFFLINE",
89*70ab954aSramat 	"MDI_PHCI_FLAGS_SUSPEND",
90*70ab954aSramat 	"MDI_PHCI_FLAGS_POWER_DOWN",
91*70ab954aSramat 	"MDI_PHCI_FLAGS_DETACH",
92*70ab954aSramat 	"MDI_PHCI_FLAGS_USER_DISABLE",
93*70ab954aSramat 	"MDI_PHCI_FLAGS_D_DISABLE",
94*70ab954aSramat 	"MDI_PHCI_FLAGS_D_DISABLE_TRANS",
95*70ab954aSramat 	"MDI_PHCI_FLAGS_POWER_TRANSITION",
96*70ab954aSramat 	NULL
97*70ab954aSramat };
98*70ab954aSramat 
99*70ab954aSramat static uintptr_t firstaddr = 0;
100*70ab954aSramat static char mdipathinfo_cb_str[] = "::print struct mdi_pathinfo";
101*70ab954aSramat static char mdiphci_cb_str[] = "::print struct mdi_phci";
102*70ab954aSramat 
103*70ab954aSramat /*
104*70ab954aSramat  * mdipi()
105*70ab954aSramat  *
106*70ab954aSramat  * Given a path, dump mdi_pathinfo struct and detailed pi_prop list.
107*70ab954aSramat  */
108*70ab954aSramat /* ARGSUSED */
109*70ab954aSramat int
mdipi(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)110*70ab954aSramat mdipi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
111*70ab954aSramat {
112*70ab954aSramat 	struct mdi_pathinfo	value;
113*70ab954aSramat 
114*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
115*70ab954aSramat 		mdb_warn("mdipi: requires an address");
116*70ab954aSramat 		return (DCMD_ERR);
117*70ab954aSramat 	}
118*70ab954aSramat 
119*70ab954aSramat 	if (mdb_vread(&value, sizeof (struct mdi_pathinfo), addr) !=
120*70ab954aSramat 	    sizeof (struct mdi_pathinfo)) {
121*70ab954aSramat 		mdb_warn("mdipi: Failed read on %l#r\n", addr);
122*70ab954aSramat 		return (DCMD_ERR);
123*70ab954aSramat 	}
124*70ab954aSramat 	mdb_printf("------------- mdi_pathinfo @ %#lr ----------\n", addr);
125*70ab954aSramat 
126*70ab954aSramat 	dump_string((uintptr_t)value.pi_addr, "PWWN,LUN (pi_addr)");
127*70ab954aSramat 
128*70ab954aSramat 	mdb_printf("\n");
129*70ab954aSramat 	mdb_printf("pi_client: %25l#r::print struct mdi_client\n",
130*70ab954aSramat 	    value.pi_client);
131*70ab954aSramat 	mdb_printf("pi_phci: %27l#r::print struct mdi_phci\n", value.pi_phci);
132*70ab954aSramat 	mdb_printf("pi_pprivate: %23l#r\n", value.pi_pprivate);
133*70ab954aSramat 	mdb_printf("pi_client_link: %20l#r::print struct mdi_pathinfo\n",
134*70ab954aSramat 	    value.pi_client_link);
135*70ab954aSramat 	mdb_printf("pi_phci_link: %22l#r::print struct mdi_pathinfo\n",
136*70ab954aSramat 	    value.pi_phci_link);
137*70ab954aSramat 	mdb_printf("pi_prop: %27l#r::print struct nv_list\n", value.pi_prop);
138*70ab954aSramat 
139*70ab954aSramat 	mdiprops((uintptr_t)value.pi_prop, flags, 0, NULL);
140*70ab954aSramat 
141*70ab954aSramat 	mdb_printf("\n");
142*70ab954aSramat 	dump_state_str("Pathinfo State (pi_state)        ",
143*70ab954aSramat 	    MDI_PI_STATE(&value), mdi_pathinfo_states);
144*70ab954aSramat 	if (MDI_PI_IS_TRANSIENT(&value)) {
145*70ab954aSramat 		mdb_printf("Pathinfo State is TRANSIENT\n");
146*70ab954aSramat 	}
147*70ab954aSramat 	if (MDI_PI_EXT_STATE(&value)) {
148*70ab954aSramat 		mdb_printf("      Extended (pi_state)        : ");
149*70ab954aSramat 		/*
150*70ab954aSramat 		 * Need to shift right 20 bits to match mdi_pathinfo_ext_states
151*70ab954aSramat 		 * array.
152*70ab954aSramat 		 */
153*70ab954aSramat 		dump_flags((unsigned long long)MDI_PI_EXT_STATE(&value) >> 20,
154*70ab954aSramat 		    mdi_pathinfo_ext_states);
155*70ab954aSramat 	}
156*70ab954aSramat 	dump_state_str("Old Pathinfo State (pi_old_state)",
157*70ab954aSramat 	    MDI_PI_OLD_STATE(&value), mdi_pathinfo_states);
158*70ab954aSramat 	if (MDI_PI_OLD_EXT_STATE(&value)) {
159*70ab954aSramat 		mdb_printf("      Extended (pi_old_state)    : ");
160*70ab954aSramat 		/*
161*70ab954aSramat 		 * Need to shift right 20 bits to match mdi_pathinfo_ext_states
162*70ab954aSramat 		 * array.
163*70ab954aSramat 		 */
164*70ab954aSramat 		dump_flags((unsigned long long)MDI_PI_OLD_EXT_STATE(&value)
165*70ab954aSramat 		>> 20, mdi_pathinfo_ext_states);
166*70ab954aSramat 	}
167*70ab954aSramat 	dump_mutex(value.pi_mutex, "per-path mutex (pi_mutex):");
168*70ab954aSramat 	dump_condvar(value.pi_state_cv, "Path state (pi_state_cv)");
169*70ab954aSramat 
170*70ab954aSramat 	mdb_printf("\n");
171*70ab954aSramat 	mdb_printf("pi_ref_cnt: %d\n", value.pi_ref_cnt);
172*70ab954aSramat 	dump_condvar(value.pi_ref_cv, "pi_ref_cv");
173*70ab954aSramat 
174*70ab954aSramat 	mdb_printf("\n");
175*70ab954aSramat 	mdb_printf("pi_kstats: %25l#r::print struct mdi_pi_kstats\n",
176*70ab954aSramat 	    value.pi_kstats);
177*70ab954aSramat 	mdb_printf("pi_cprivate UNUSED: %16l#r \n", value.pi_cprivate);
178*70ab954aSramat 
179*70ab954aSramat 	return (DCMD_OK);
180*70ab954aSramat }
181*70ab954aSramat 
182*70ab954aSramat /*
183*70ab954aSramat  * mdiprops()
184*70ab954aSramat  *
185*70ab954aSramat  * Given a pi_prop, dump the pi_prop list.
186*70ab954aSramat  */
187*70ab954aSramat /* ARGSUSED */
188*70ab954aSramat int
mdiprops(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)189*70ab954aSramat mdiprops(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
190*70ab954aSramat {
191*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
192*70ab954aSramat 		mdb_warn("mdiprops: requires an address");
193*70ab954aSramat 		return (DCMD_ERR);
194*70ab954aSramat 	}
195*70ab954aSramat 
196*70ab954aSramat 	mdb_printf("\tnvpairs @ %#lr:\n", addr);
197*70ab954aSramat 	mdb_pwalk_dcmd("nvpair", "nvpair", argc, argv, addr);
198*70ab954aSramat 	mdb_printf("\n");
199*70ab954aSramat 
200*70ab954aSramat 	return (DCMD_OK);
201*70ab954aSramat }
202*70ab954aSramat 
203*70ab954aSramat /*
204*70ab954aSramat  * mdiphci()
205*70ab954aSramat  *
206*70ab954aSramat  * Given a phci, dump mdi_phci struct.
207*70ab954aSramat  */
208*70ab954aSramat /* ARGSUSED */
209*70ab954aSramat int
mdiphci(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)210*70ab954aSramat mdiphci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
211*70ab954aSramat {
212*70ab954aSramat 	struct mdi_phci value;
213*70ab954aSramat 
214*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
215*70ab954aSramat 		mdb_warn("mdiphci: requires an address");
216*70ab954aSramat 		return (DCMD_ERR);
217*70ab954aSramat 	}
218*70ab954aSramat 
219*70ab954aSramat 	if (mdb_vread(&value, sizeof (struct mdi_phci), addr) !=
220*70ab954aSramat 	    sizeof (struct mdi_phci)) {
221*70ab954aSramat 		mdb_warn("mdiphci: Failed read on %l#r\n", addr);
222*70ab954aSramat 		return (DCMD_ERR);
223*70ab954aSramat 	}
224*70ab954aSramat 	mdb_printf("---------------- mdi_phci @ %#lr ----------\n", addr);
225*70ab954aSramat 
226*70ab954aSramat 	mdb_printf("ph_next: %27l#r::print struct mdi_phci\n", value.ph_next);
227*70ab954aSramat 	mdb_printf("ph_prev: %27l#r::print struct mdi_phci\n", value.ph_prev);
228*70ab954aSramat 	mdb_printf("ph_vhci: %27l#r::print struct mdi_vhci\n", value.ph_vhci);
229*70ab954aSramat 	mdb_printf("ph_dip: %28l#r::print struct dev_info\n", value.ph_dip);
230*70ab954aSramat 	mdb_printf("\nph_path_head: %22l#r::print struct mdi_pathinfo\n",
231*70ab954aSramat 	    value.ph_path_head);
232*70ab954aSramat 	mdb_printf("ph_path_tail: %22l#r::print struct mdi_pathinfo\n",
233*70ab954aSramat 	    value.ph_path_tail);
234*70ab954aSramat 	mdb_printf("ph_path_count: %21d\n", value.ph_path_count);
235*70ab954aSramat 	mdb_printf("List of paths:\n");
236*70ab954aSramat 	mdb_pwalk("mdipi_phci_list", (mdb_walk_cb_t)mpxio_walk_cb,
237*70ab954aSramat 			mdipathinfo_cb_str, (uintptr_t)value.ph_path_head);
238*70ab954aSramat 
239*70ab954aSramat 	mdb_printf("\n");
240*70ab954aSramat 	mdb_printf("ph_flags: %26d\n", value.ph_flags);
241*70ab954aSramat 	if (value.ph_flags) {
242*70ab954aSramat 		dump_flags((unsigned long long)value.ph_flags, mdi_phci_flags);
243*70ab954aSramat 	}
244*70ab954aSramat 	dump_mutex(value.ph_mutex, "per-pHCI mutex (ph_mutex):");
245*70ab954aSramat 	dump_condvar(value.ph_unstable_cv,
246*70ab954aSramat 	    "Paths in transient state (ph_unstable_cv)");
247*70ab954aSramat 	mdb_printf("ph_unstable: %23d\n", value.ph_unstable);
248*70ab954aSramat 
249*70ab954aSramat 	return (DCMD_OK);
250*70ab954aSramat }
251*70ab954aSramat 
252*70ab954aSramat /*
253*70ab954aSramat  * mdivhci()
254*70ab954aSramat  *
255*70ab954aSramat  * Given a vhci, dump mdi_vhci struct and list all phcis.
256*70ab954aSramat  */
257*70ab954aSramat /* ARGSUSED */
258*70ab954aSramat int
mdivhci(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)259*70ab954aSramat mdivhci(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
260*70ab954aSramat {
261*70ab954aSramat 	struct mdi_vhci value;
262*70ab954aSramat 
263*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
264*70ab954aSramat 		mdb_warn("mdivhci: requires an address");
265*70ab954aSramat 		return (DCMD_ERR);
266*70ab954aSramat 	}
267*70ab954aSramat 
268*70ab954aSramat 	if (mdb_vread(&value, sizeof (struct mdi_vhci), addr) !=
269*70ab954aSramat 	    sizeof (struct mdi_vhci)) {
270*70ab954aSramat 		mdb_warn("mdivhci: Failed read on %l#r\n", addr);
271*70ab954aSramat 		return (DCMD_ERR);
272*70ab954aSramat 	}
273*70ab954aSramat 	mdb_printf("----------------- mdi_vhci @ %#lr ----------\n", addr);
274*70ab954aSramat 
275*70ab954aSramat 	dump_string((uintptr_t)value.vh_class, "Class name (vh_class)");
276*70ab954aSramat 	mdb_printf("vh_refcnt: %19d\n", value.vh_refcnt);
277*70ab954aSramat 	mdb_printf("vh_dip: %28l#r::print struct dev_info\n", value.vh_dip);
278*70ab954aSramat 	mdb_printf("vh_next: %27l#r::print struct mdi_vhci\n", value.vh_next);
279*70ab954aSramat 	mdb_printf("vh_prev: %27l#r::print struct mdi_vhci\n", value.vh_prev);
280*70ab954aSramat 	dump_state_str("Load Balance (vh_lb)", value.vh_lb, client_lb_str);
281*70ab954aSramat 	mdb_printf("vh_ops: %28l#r::print struct mdi_vhci_ops\n",
282*70ab954aSramat 	    value.vh_ops);
283*70ab954aSramat 
284*70ab954aSramat 	dump_mutex(value.vh_phci_mutex, "phci mutex (vh_phci_mutex):");
285*70ab954aSramat 	mdb_printf("vh_phci_count: %21d\n", value.vh_phci_count);
286*70ab954aSramat 	mdb_printf("\nvh_phci_head: %22l#r::print struct mdi_phci\n",
287*70ab954aSramat 	    value.vh_phci_head);
288*70ab954aSramat 	mdb_printf("vh_phci_tail: %22l#r::print struct mdi_phci\n",
289*70ab954aSramat 	    value.vh_phci_tail);
290*70ab954aSramat 
291*70ab954aSramat 	dump_mutex(value.vh_phci_mutex, "client mutex (vh_client_mutex):");
292*70ab954aSramat 	mdb_printf("vh_client_count: %19d\n", value.vh_client_count);
293*70ab954aSramat 	mdb_printf("vh_client_table: %19l#r::print struct client_hash\n",
294*70ab954aSramat 	    value.vh_client_table);
295*70ab954aSramat 
296*70ab954aSramat 	mdb_printf("List of pHCIs:\n");
297*70ab954aSramat 	mdb_pwalk("mdiphci_list", (mdb_walk_cb_t)mpxio_walk_cb,
298*70ab954aSramat 			mdiphci_cb_str, (uintptr_t)value.vh_phci_head);
299*70ab954aSramat 	mdb_printf("\n");
300*70ab954aSramat 	return (DCMD_OK);
301*70ab954aSramat }
302*70ab954aSramat 
303*70ab954aSramat /* mdi_pathinfo client walker */
304*70ab954aSramat 
305*70ab954aSramat /* ARGUSED */
306*70ab954aSramat int
mdi_pi_client_link_walk_init(mdb_walk_state_t * wsp)307*70ab954aSramat mdi_pi_client_link_walk_init(mdb_walk_state_t *wsp)
308*70ab954aSramat {
309*70ab954aSramat 	if (wsp->walk_addr == NULL) {
310*70ab954aSramat 		mdb_warn("Address is required");
311*70ab954aSramat 		return (WALK_ERR);
312*70ab954aSramat 	}
313*70ab954aSramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP);
314*70ab954aSramat 	firstaddr = wsp->walk_addr;
315*70ab954aSramat 	return (WALK_NEXT);
316*70ab954aSramat }
317*70ab954aSramat 
318*70ab954aSramat /* ARGUSED */
319*70ab954aSramat int
mdi_pi_client_link_walk_step(mdb_walk_state_t * wsp)320*70ab954aSramat mdi_pi_client_link_walk_step(mdb_walk_state_t *wsp)
321*70ab954aSramat {
322*70ab954aSramat 	int 		status = 0;
323*70ab954aSramat 	static int	counts = 0;
324*70ab954aSramat 
325*70ab954aSramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
326*70ab954aSramat 		counts = 0;
327*70ab954aSramat 		return (WALK_DONE);
328*70ab954aSramat 	}
329*70ab954aSramat 	if (wsp->walk_addr == NULL) {
330*70ab954aSramat 		counts = 0;
331*70ab954aSramat 		return (WALK_DONE);
332*70ab954aSramat 	}
333*70ab954aSramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo),
334*70ab954aSramat 	    wsp->walk_addr) == -1) {
335*70ab954aSramat 		mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr);
336*70ab954aSramat 		return (WALK_DONE);
337*70ab954aSramat 	}
338*70ab954aSramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
339*70ab954aSramat 	    wsp->walk_cbdata);
340*70ab954aSramat 	wsp->walk_addr = (uintptr_t)
341*70ab954aSramat 	    (((struct mdi_pathinfo *)wsp->walk_data)->pi_client_link);
342*70ab954aSramat 	counts++;
343*70ab954aSramat 	return (status);
344*70ab954aSramat }
345*70ab954aSramat 
346*70ab954aSramat /* ARGUSED */
347*70ab954aSramat void
mdi_pi_client_link_walk_fini(mdb_walk_state_t * wsp)348*70ab954aSramat mdi_pi_client_link_walk_fini(mdb_walk_state_t *wsp)
349*70ab954aSramat {
350*70ab954aSramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo));
351*70ab954aSramat }
352*70ab954aSramat 
353*70ab954aSramat /*
354*70ab954aSramat  * mdiclient_paths()
355*70ab954aSramat  *
356*70ab954aSramat  * Given a path, walk through mdi_pathinfo client links.
357*70ab954aSramat  */
358*70ab954aSramat /* ARGUSED */
359*70ab954aSramat int
mdiclient_paths(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)360*70ab954aSramat mdiclient_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
361*70ab954aSramat {
362*70ab954aSramat 	int status;
363*70ab954aSramat 	if (argc != 0)
364*70ab954aSramat 		return (DCMD_USAGE);
365*70ab954aSramat 
366*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
367*70ab954aSramat 		mdb_warn("Address needs to be specified");
368*70ab954aSramat 		return (DCMD_ERR);
369*70ab954aSramat 	}
370*70ab954aSramat 	status =
371*70ab954aSramat 	    mdb_pwalk_dcmd("mdipi_client_list", "mdipi", argc, argv, addr);
372*70ab954aSramat 	return (status);
373*70ab954aSramat }
374*70ab954aSramat 
375*70ab954aSramat /* mdi_pathinfo phci walker */
376*70ab954aSramat int
mdi_pi_phci_link_walk_init(mdb_walk_state_t * wsp)377*70ab954aSramat mdi_pi_phci_link_walk_init(mdb_walk_state_t *wsp)
378*70ab954aSramat {
379*70ab954aSramat 	if (wsp->walk_addr == NULL) {
380*70ab954aSramat 		mdb_warn("Address is required");
381*70ab954aSramat 		return (WALK_ERR);
382*70ab954aSramat 	}
383*70ab954aSramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_pathinfo), UM_SLEEP);
384*70ab954aSramat 	firstaddr = wsp->walk_addr;
385*70ab954aSramat 	return (WALK_NEXT);
386*70ab954aSramat }
387*70ab954aSramat 
388*70ab954aSramat int
mdi_pi_phci_link_walk_step(mdb_walk_state_t * wsp)389*70ab954aSramat mdi_pi_phci_link_walk_step(mdb_walk_state_t *wsp)
390*70ab954aSramat {
391*70ab954aSramat 	int status;
392*70ab954aSramat 	static int	counts = 0;
393*70ab954aSramat 
394*70ab954aSramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
395*70ab954aSramat 		counts = 0;
396*70ab954aSramat 		return (WALK_DONE);
397*70ab954aSramat 	}
398*70ab954aSramat 	if (wsp->walk_addr == NULL) {
399*70ab954aSramat 		counts = 0;
400*70ab954aSramat 		return (WALK_DONE);
401*70ab954aSramat 	}
402*70ab954aSramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_pathinfo),
403*70ab954aSramat 	    wsp->walk_addr) == -1) {
404*70ab954aSramat 		mdb_warn("failed to read mdi_pathinfo at %p", wsp->walk_addr);
405*70ab954aSramat 		return (WALK_DONE);
406*70ab954aSramat 	}
407*70ab954aSramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
408*70ab954aSramat 	    wsp->walk_cbdata);
409*70ab954aSramat 	wsp->walk_addr = (uintptr_t)
410*70ab954aSramat 	    (((struct mdi_pathinfo *)wsp->walk_data)->pi_phci_link);
411*70ab954aSramat 	counts++;
412*70ab954aSramat 	return (status);
413*70ab954aSramat }
414*70ab954aSramat 
415*70ab954aSramat void
mdi_pi_phci_link_walk_fini(mdb_walk_state_t * wsp)416*70ab954aSramat mdi_pi_phci_link_walk_fini(mdb_walk_state_t *wsp)
417*70ab954aSramat {
418*70ab954aSramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_pathinfo));
419*70ab954aSramat }
420*70ab954aSramat 
421*70ab954aSramat /*
422*70ab954aSramat  * mdiphci_paths()
423*70ab954aSramat  *
424*70ab954aSramat  * Given a path, walk through mdi_pathinfo phci links.
425*70ab954aSramat  */
426*70ab954aSramat int
mdiphci_paths(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)427*70ab954aSramat mdiphci_paths(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
428*70ab954aSramat {
429*70ab954aSramat 	int status;
430*70ab954aSramat 	if (argc != 0)
431*70ab954aSramat 		return (DCMD_USAGE);
432*70ab954aSramat 
433*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
434*70ab954aSramat 		mdb_warn("Address needs to be specified");
435*70ab954aSramat 		return (DCMD_ERR);
436*70ab954aSramat 	}
437*70ab954aSramat 	status =
438*70ab954aSramat 	    mdb_pwalk_dcmd("mdipi_phci_list", "mdipi", argc, argv, addr);
439*70ab954aSramat 	return (status);
440*70ab954aSramat }
441*70ab954aSramat 
442*70ab954aSramat /* mdi_phci walker */
443*70ab954aSramat int
mdi_phci_ph_next_walk_init(mdb_walk_state_t * wsp)444*70ab954aSramat mdi_phci_ph_next_walk_init(mdb_walk_state_t *wsp)
445*70ab954aSramat {
446*70ab954aSramat 	if (wsp->walk_addr == NULL) {
447*70ab954aSramat 		mdb_warn("Address is required");
448*70ab954aSramat 		return (WALK_ERR);
449*70ab954aSramat 	}
450*70ab954aSramat 	wsp->walk_data = mdb_alloc(sizeof (struct mdi_phci), UM_SLEEP);
451*70ab954aSramat 	firstaddr = wsp->walk_addr;
452*70ab954aSramat 	return (WALK_NEXT);
453*70ab954aSramat }
454*70ab954aSramat 
455*70ab954aSramat int
mdi_phci_ph_next_walk_step(mdb_walk_state_t * wsp)456*70ab954aSramat mdi_phci_ph_next_walk_step(mdb_walk_state_t *wsp)
457*70ab954aSramat {
458*70ab954aSramat 	int status;
459*70ab954aSramat 	static int counts = 0;
460*70ab954aSramat 
461*70ab954aSramat 	if (firstaddr == wsp->walk_addr && counts != 0) {
462*70ab954aSramat 		counts = 0;
463*70ab954aSramat 		return (WALK_DONE);
464*70ab954aSramat 	}
465*70ab954aSramat 	if (wsp->walk_addr == NULL) {
466*70ab954aSramat 		counts = 0;
467*70ab954aSramat 		return (WALK_DONE);
468*70ab954aSramat 	}
469*70ab954aSramat 	if (mdb_vread(wsp->walk_data, sizeof (struct mdi_phci), wsp->walk_addr)
470*70ab954aSramat 	    == -1) {
471*70ab954aSramat 		mdb_warn("failed to read mdi_phci at %p", wsp->walk_addr);
472*70ab954aSramat 		return (WALK_DONE);
473*70ab954aSramat 	}
474*70ab954aSramat 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
475*70ab954aSramat 	    wsp->walk_cbdata);
476*70ab954aSramat 	wsp->walk_addr = (uintptr_t)
477*70ab954aSramat 	    (((struct mdi_phci *)wsp->walk_data)->ph_next);
478*70ab954aSramat 	counts++;
479*70ab954aSramat 	return (status);
480*70ab954aSramat }
481*70ab954aSramat 
482*70ab954aSramat void
mdi_phci_ph_next_walk_fini(mdb_walk_state_t * wsp)483*70ab954aSramat mdi_phci_ph_next_walk_fini(mdb_walk_state_t *wsp)
484*70ab954aSramat {
485*70ab954aSramat 	mdb_free(wsp->walk_data, sizeof (struct mdi_phci));
486*70ab954aSramat }
487*70ab954aSramat 
488*70ab954aSramat /*
489*70ab954aSramat  * mdiphcis()
490*70ab954aSramat  *
491*70ab954aSramat  * Given a phci, walk through mdi_phci ph_next links.
492*70ab954aSramat  */
493*70ab954aSramat int
mdiphcis(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)494*70ab954aSramat mdiphcis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
495*70ab954aSramat {
496*70ab954aSramat 	int status;
497*70ab954aSramat 	if (argc != 0)
498*70ab954aSramat 		return (DCMD_USAGE);
499*70ab954aSramat 
500*70ab954aSramat 	if (!(flags & DCMD_ADDRSPEC)) {
501*70ab954aSramat 		mdb_warn("Address needs to be specified");
502*70ab954aSramat 		return (DCMD_ERR);
503*70ab954aSramat 	}
504*70ab954aSramat 	status =
505*70ab954aSramat 	    mdb_pwalk_dcmd("mdiphci_list", "mdiphci", argc, argv, addr);
506*70ab954aSramat 	return (status);
507*70ab954aSramat }
508*70ab954aSramat 
509*70ab954aSramat /*
510*70ab954aSramat  * Print the flag name by comparing flags to the mask variable.
511*70ab954aSramat  */
512*70ab954aSramat static void
dump_flags(unsigned long long flags,char ** strings)513*70ab954aSramat dump_flags(unsigned long long flags, char **strings)
514*70ab954aSramat {
515*70ab954aSramat 	int i, linel = 8, first = 1;
516*70ab954aSramat 	unsigned long long mask = 1;
517*70ab954aSramat 
518*70ab954aSramat 	for (i = 0; i < 64; i++) {
519*70ab954aSramat 		if (strings[i] == NULL)
520*70ab954aSramat 			break;
521*70ab954aSramat 		if (flags & mask) {
522*70ab954aSramat 			if (!first) {
523*70ab954aSramat 				mdb_printf(" | ");
524*70ab954aSramat 			} else {
525*70ab954aSramat 				first = 0;
526*70ab954aSramat 			}
527*70ab954aSramat 			/* make output pretty */
528*70ab954aSramat 			linel += strlen(strings[i]) + 3;
529*70ab954aSramat 			if (linel > 80) {
530*70ab954aSramat 				mdb_printf("\n\t");
531*70ab954aSramat 				linel = strlen(strings[i]) + 1 + 8;
532*70ab954aSramat 			}
533*70ab954aSramat 			mdb_printf("%s", strings[i]);
534*70ab954aSramat 		}
535*70ab954aSramat 		mask <<= 1;
536*70ab954aSramat 	}
537*70ab954aSramat 	mdb_printf("\n");
538*70ab954aSramat }
539*70ab954aSramat 
540*70ab954aSramat static void
dump_mutex(kmutex_t m,char * name)541*70ab954aSramat dump_mutex(kmutex_t m, char *name)
542*70ab954aSramat {
543*70ab954aSramat 	mdb_printf("%s is%s held\n", name, FT(m, uint64_t) == 0 ? " not" : "");
544*70ab954aSramat }
545*70ab954aSramat 
546*70ab954aSramat static void
dump_condvar(kcondvar_t c,char * name)547*70ab954aSramat dump_condvar(kcondvar_t c, char *name)
548*70ab954aSramat {
549*70ab954aSramat 	mdb_printf("Threads sleeping on %s = %d\n", name, (int)FT(c, ushort_t));
550*70ab954aSramat }
551*70ab954aSramat 
552*70ab954aSramat static int
get_mdbstr(uintptr_t addr,char * string_val)553*70ab954aSramat get_mdbstr(uintptr_t addr, char *string_val)
554*70ab954aSramat {
555*70ab954aSramat 	if (mdb_readstr(string_val, MAXNAMELEN, addr) == -1) {
556*70ab954aSramat 		mdb_warn("Error Reading String from %l#r\n", addr);
557*70ab954aSramat 		return (1);
558*70ab954aSramat 	}
559*70ab954aSramat 
560*70ab954aSramat 	return (0);
561*70ab954aSramat }
562*70ab954aSramat 
563*70ab954aSramat static void
dump_string(uintptr_t addr,char * name)564*70ab954aSramat dump_string(uintptr_t addr, char *name)
565*70ab954aSramat {
566*70ab954aSramat 	char string_val[MAXNAMELEN];
567*70ab954aSramat 
568*70ab954aSramat 	if (get_mdbstr(addr, string_val)) {
569*70ab954aSramat 		return;
570*70ab954aSramat 	}
571*70ab954aSramat 	mdb_printf("%s: %s (%l#r)\n", name, string_val, addr);
572*70ab954aSramat }
573*70ab954aSramat 
574*70ab954aSramat static void
dump_state_str(char * name,uintptr_t addr,char ** strings)575*70ab954aSramat dump_state_str(char *name, uintptr_t addr, char **strings)
576*70ab954aSramat {
577*70ab954aSramat 	mdb_printf("%s: %s (%l#r)\n", name, strings[(unsigned long)addr], addr);
578*70ab954aSramat }
579*70ab954aSramat 
580*70ab954aSramat /* ARGSUSED */
581*70ab954aSramat static int
mpxio_walk_cb(uintptr_t addr,const void * data,void * cbdata)582*70ab954aSramat mpxio_walk_cb(uintptr_t addr, const void *data, void *cbdata)
583*70ab954aSramat {
584*70ab954aSramat 	mdb_printf("%t%l#r%s\n", addr, (char *)cbdata);
585*70ab954aSramat 	return (0);
586*70ab954aSramat }
587