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