xref: /titanic_50/usr/src/uts/i86pc/io/dr/dr_io.c (revision a31148363f598def767ac48c5d82e1572e44b935)
1*a3114836SGerry Liu /*
2*a3114836SGerry Liu  * CDDL HEADER START
3*a3114836SGerry Liu  *
4*a3114836SGerry Liu  * The contents of this file are subject to the terms of the
5*a3114836SGerry Liu  * Common Development and Distribution License (the "License").
6*a3114836SGerry Liu  * You may not use this file except in compliance with the License.
7*a3114836SGerry Liu  *
8*a3114836SGerry Liu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*a3114836SGerry Liu  * or http://www.opensolaris.org/os/licensing.
10*a3114836SGerry Liu  * See the License for the specific language governing permissions
11*a3114836SGerry Liu  * and limitations under the License.
12*a3114836SGerry Liu  *
13*a3114836SGerry Liu  * When distributing Covered Code, include this CDDL HEADER in each
14*a3114836SGerry Liu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*a3114836SGerry Liu  * If applicable, add the following below this CDDL HEADER, with the
16*a3114836SGerry Liu  * fields enclosed by brackets "[]" replaced with your own identifying
17*a3114836SGerry Liu  * information: Portions Copyright [yyyy] [name of copyright owner]
18*a3114836SGerry Liu  *
19*a3114836SGerry Liu  * CDDL HEADER END
20*a3114836SGerry Liu  */
21*a3114836SGerry Liu 
22*a3114836SGerry Liu /*
23*a3114836SGerry Liu  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*a3114836SGerry Liu  * Use is subject to license terms.
25*a3114836SGerry Liu  */
26*a3114836SGerry Liu 
27*a3114836SGerry Liu /*
28*a3114836SGerry Liu  * I/O support routines for DR
29*a3114836SGerry Liu  */
30*a3114836SGerry Liu 
31*a3114836SGerry Liu #include <sys/types.h>
32*a3114836SGerry Liu #include <sys/cmn_err.h>
33*a3114836SGerry Liu #include <sys/debug.h>
34*a3114836SGerry Liu #include <sys/errno.h>
35*a3114836SGerry Liu #include <sys/dditypes.h>
36*a3114836SGerry Liu #include <sys/ddi.h>
37*a3114836SGerry Liu #include <sys/sunddi.h>
38*a3114836SGerry Liu #include <sys/sunndi.h>
39*a3114836SGerry Liu #include <sys/ndi_impldefs.h>
40*a3114836SGerry Liu #include <sys/kmem.h>
41*a3114836SGerry Liu #include <sys/promif.h>
42*a3114836SGerry Liu #include <sys/sysmacros.h>
43*a3114836SGerry Liu #include <sys/archsystm.h>
44*a3114836SGerry Liu #include <sys/machsystm.h>
45*a3114836SGerry Liu 
46*a3114836SGerry Liu #include <sys/dr.h>
47*a3114836SGerry Liu #include <sys/dr_util.h>
48*a3114836SGerry Liu #include <sys/drmach.h>
49*a3114836SGerry Liu 
50*a3114836SGerry Liu void
dr_init_io_unit(dr_io_unit_t * ip)51*a3114836SGerry Liu dr_init_io_unit(dr_io_unit_t *ip)
52*a3114836SGerry Liu {
53*a3114836SGerry Liu 	dr_state_t	new_state;
54*a3114836SGerry Liu 
55*a3114836SGerry Liu 	if (DR_DEV_IS_ATTACHED(&ip->sbi_cm)) {
56*a3114836SGerry Liu 		new_state = DR_STATE_CONFIGURED;
57*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
58*a3114836SGerry Liu 	} else if (DR_DEV_IS_PRESENT(&ip->sbi_cm)) {
59*a3114836SGerry Liu 		new_state = DR_STATE_CONNECTED;
60*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
61*a3114836SGerry Liu 	} else {
62*a3114836SGerry Liu 		new_state = DR_STATE_EMPTY;
63*a3114836SGerry Liu 	}
64*a3114836SGerry Liu 	dr_device_transition(&ip->sbi_cm, new_state);
65*a3114836SGerry Liu }
66*a3114836SGerry Liu 
67*a3114836SGerry Liu /*ARGSUSED*/
68*a3114836SGerry Liu void
dr_attach_io(dr_handle_t * hp,dr_common_unit_t * cp)69*a3114836SGerry Liu dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp)
70*a3114836SGerry Liu {
71*a3114836SGerry Liu 	sbd_error_t *err;
72*a3114836SGerry Liu 
73*a3114836SGerry Liu 	dr_lock_status(hp->h_bd);
74*a3114836SGerry Liu 	err = drmach_configure(cp->sbdev_id, 0);
75*a3114836SGerry Liu 	dr_unlock_status(hp->h_bd);
76*a3114836SGerry Liu 
77*a3114836SGerry Liu 	if (!err)
78*a3114836SGerry Liu 		err = drmach_io_post_attach(cp->sbdev_id);
79*a3114836SGerry Liu 
80*a3114836SGerry Liu 	if (err)
81*a3114836SGerry Liu 		DRERR_SET_C(&cp->sbdev_error, &err);
82*a3114836SGerry Liu }
83*a3114836SGerry Liu 
84*a3114836SGerry Liu /*
85*a3114836SGerry Liu  * remove device nodes for the branch indicated by cp
86*a3114836SGerry Liu  */
87*a3114836SGerry Liu /*ARGSUSED*/
88*a3114836SGerry Liu void
dr_detach_io(dr_handle_t * hp,dr_common_unit_t * cp)89*a3114836SGerry Liu dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp)
90*a3114836SGerry Liu {
91*a3114836SGerry Liu 	sbd_error_t *err;
92*a3114836SGerry Liu 
93*a3114836SGerry Liu 	err = drmach_unconfigure(cp->sbdev_id, 0);
94*a3114836SGerry Liu 
95*a3114836SGerry Liu 	if (!err)
96*a3114836SGerry Liu 		err = drmach_unconfigure(cp->sbdev_id, DEVI_BRANCH_DESTROY);
97*a3114836SGerry Liu 
98*a3114836SGerry Liu 	if (!err)
99*a3114836SGerry Liu 		err = drmach_io_post_release(cp->sbdev_id);
100*a3114836SGerry Liu 
101*a3114836SGerry Liu 	if (err) {
102*a3114836SGerry Liu 		dr_device_transition(cp, DR_STATE_CONFIGURED);
103*a3114836SGerry Liu 		DRERR_SET_C(&cp->sbdev_error, &err);
104*a3114836SGerry Liu 	}
105*a3114836SGerry Liu }
106*a3114836SGerry Liu 
107*a3114836SGerry Liu /*ARGSUSED*/
108*a3114836SGerry Liu int
dr_disconnect_io(dr_io_unit_t * ip)109*a3114836SGerry Liu dr_disconnect_io(dr_io_unit_t *ip)
110*a3114836SGerry Liu {
111*a3114836SGerry Liu 	return (0);
112*a3114836SGerry Liu }
113*a3114836SGerry Liu 
114*a3114836SGerry Liu /*ARGSUSED*/
115*a3114836SGerry Liu int
dr_pre_attach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)116*a3114836SGerry Liu dr_pre_attach_io(dr_handle_t *hp,
117*a3114836SGerry Liu 	dr_common_unit_t **devlist, int devnum)
118*a3114836SGerry Liu {
119*a3114836SGerry Liu 	int		d;
120*a3114836SGerry Liu 
121*a3114836SGerry Liu 	for (d = 0; d < devnum; d++) {
122*a3114836SGerry Liu 		dr_common_unit_t *cp = devlist[d];
123*a3114836SGerry Liu 
124*a3114836SGerry Liu 		cmn_err(CE_CONT, "OS configure %s", cp->sbdev_path);
125*a3114836SGerry Liu 	}
126*a3114836SGerry Liu 
127*a3114836SGerry Liu 	return (0);
128*a3114836SGerry Liu }
129*a3114836SGerry Liu 
130*a3114836SGerry Liu /*ARGSUSED*/
131*a3114836SGerry Liu int
dr_post_attach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)132*a3114836SGerry Liu dr_post_attach_io(dr_handle_t *hp,
133*a3114836SGerry Liu 	dr_common_unit_t **devlist, int devnum)
134*a3114836SGerry Liu {
135*a3114836SGerry Liu 	return (0);
136*a3114836SGerry Liu }
137*a3114836SGerry Liu 
138*a3114836SGerry Liu static int
dr_check_io_refs(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)139*a3114836SGerry Liu dr_check_io_refs(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
140*a3114836SGerry Liu {
141*a3114836SGerry Liu 	register int	i, reftotal = 0;
142*a3114836SGerry Liu 	static fn_t	f = "dr_check_io_refs";
143*a3114836SGerry Liu 
144*a3114836SGerry Liu 	for (i = 0; i < devnum; i++) {
145*a3114836SGerry Liu 		dr_io_unit_t	*ip = (dr_io_unit_t *)devlist[i];
146*a3114836SGerry Liu 		dev_info_t	*dip;
147*a3114836SGerry Liu 		int		ref;
148*a3114836SGerry Liu 		int		refcount_non_gldv3;
149*a3114836SGerry Liu 		sbd_error_t	*err;
150*a3114836SGerry Liu 
151*a3114836SGerry Liu 		err = drmach_get_dip(ip->sbi_cm.sbdev_id, &dip);
152*a3114836SGerry Liu 		if (err)
153*a3114836SGerry Liu 			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
154*a3114836SGerry Liu 		else if (dip != NULL) {
155*a3114836SGerry Liu 			ref = 0;
156*a3114836SGerry Liu 			refcount_non_gldv3 = 0;
157*a3114836SGerry Liu 			ASSERT(e_ddi_branch_held(dip));
158*a3114836SGerry Liu 			dr_check_devices(dip, &ref, hp, NULL, NULL,
159*a3114836SGerry Liu 			    0, &refcount_non_gldv3);
160*a3114836SGerry Liu 			ASSERT(refcount_non_gldv3 >= 0);
161*a3114836SGerry Liu 			ASSERT(ref >= refcount_non_gldv3);
162*a3114836SGerry Liu 			/*
163*a3114836SGerry Liu 			 * Ignore reference counts of non-gldv3 network devices
164*a3114836SGerry Liu 			 * as Crossbow creates reference counts for non-active
165*a3114836SGerry Liu 			 * (unplumbed) instances.  Reference count check in
166*a3114836SGerry Liu 			 * detach() known to prevent device from detaching
167*a3114836SGerry Liu 			 * as necessary.
168*a3114836SGerry Liu 			 */
169*a3114836SGerry Liu 			ref -= refcount_non_gldv3;
170*a3114836SGerry Liu 			hp->h_err = NULL;
171*a3114836SGerry Liu 			if (ref) {
172*a3114836SGerry Liu 				dr_dev_err(CE_WARN, &ip->sbi_cm, ESBD_BUSY);
173*a3114836SGerry Liu 			}
174*a3114836SGerry Liu 			PR_IO("%s: dip(%s) ref = %d\n",
175*a3114836SGerry Liu 			    f, ddi_get_name(dip), ref);
176*a3114836SGerry Liu 			reftotal += ref;
177*a3114836SGerry Liu 		} else {
178*a3114836SGerry Liu 			PR_IO("%s: NO dip for id (0x%x)\n",
179*a3114836SGerry Liu 			    f, (uint_t)(uintptr_t)ip->sbi_cm.sbdev_id);
180*a3114836SGerry Liu 		}
181*a3114836SGerry Liu 	}
182*a3114836SGerry Liu 
183*a3114836SGerry Liu 	return (reftotal);
184*a3114836SGerry Liu }
185*a3114836SGerry Liu 
186*a3114836SGerry Liu int
dr_pre_release_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)187*a3114836SGerry Liu dr_pre_release_io(dr_handle_t *hp,
188*a3114836SGerry Liu 	dr_common_unit_t **devlist, int devnum)
189*a3114836SGerry Liu {
190*a3114836SGerry Liu 	static fn_t	f = "dr_pre_release_io";
191*a3114836SGerry Liu 	int	d;
192*a3114836SGerry Liu 
193*a3114836SGerry Liu 	ASSERT(devnum > 0);
194*a3114836SGerry Liu 
195*a3114836SGerry Liu 	/* fail if any I/O device pre-release fails */
196*a3114836SGerry Liu 	for (d = 0; d < devnum; d++) {
197*a3114836SGerry Liu 		dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
198*a3114836SGerry Liu 
199*a3114836SGerry Liu 		if ((hp->h_err = drmach_io_pre_release(
200*a3114836SGerry Liu 		    ip->sbi_cm.sbdev_id)) != 0) {
201*a3114836SGerry Liu 			return (-1);
202*a3114836SGerry Liu 		}
203*a3114836SGerry Liu 	}
204*a3114836SGerry Liu 
205*a3114836SGerry Liu 	for (d = 0; d < devnum; d++) {
206*a3114836SGerry Liu 		dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
207*a3114836SGerry Liu 		sbd_error_t *err;
208*a3114836SGerry Liu 
209*a3114836SGerry Liu 		err = drmach_release(ip->sbi_cm.sbdev_id);
210*a3114836SGerry Liu 		if (err) {
211*a3114836SGerry Liu 			DRERR_SET_C(&ip->sbi_cm.sbdev_error,
212*a3114836SGerry Liu 			    &err);
213*a3114836SGerry Liu 			return (-1);
214*a3114836SGerry Liu 		}
215*a3114836SGerry Liu 	}
216*a3114836SGerry Liu 
217*a3114836SGerry Liu 	/* fail if any I/O devices are still referenced */
218*a3114836SGerry Liu 	if (dr_check_io_refs(hp, devlist, devnum) > 0) {
219*a3114836SGerry Liu 		PR_IO("%s: failed - I/O devices ref'd\n", f);
220*a3114836SGerry Liu 
221*a3114836SGerry Liu 		/* recover before return error */
222*a3114836SGerry Liu 		for (d = 0; d < devnum; d++) {
223*a3114836SGerry Liu 			dr_io_unit_t *ip = (dr_io_unit_t *)devlist[d];
224*a3114836SGerry Liu 			sbd_error_t *err;
225*a3114836SGerry Liu 			err = drmach_io_unrelease(ip->sbi_cm.sbdev_id);
226*a3114836SGerry Liu 			if (err) {
227*a3114836SGerry Liu 				DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
228*a3114836SGerry Liu 				return (-1);
229*a3114836SGerry Liu 			}
230*a3114836SGerry Liu 		}
231*a3114836SGerry Liu 		return (-1);
232*a3114836SGerry Liu 	}
233*a3114836SGerry Liu 	return (0);
234*a3114836SGerry Liu }
235*a3114836SGerry Liu 
236*a3114836SGerry Liu /*ARGSUSED*/
237*a3114836SGerry Liu int
dr_pre_detach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)238*a3114836SGerry Liu dr_pre_detach_io(dr_handle_t *hp,
239*a3114836SGerry Liu 	dr_common_unit_t **devlist, int devnum)
240*a3114836SGerry Liu {
241*a3114836SGerry Liu 	int		d;
242*a3114836SGerry Liu 
243*a3114836SGerry Liu 	ASSERT(devnum > 0);
244*a3114836SGerry Liu 
245*a3114836SGerry Liu 	for (d = 0; d < devnum; d++) {
246*a3114836SGerry Liu 		dr_common_unit_t *cp = devlist[d];
247*a3114836SGerry Liu 
248*a3114836SGerry Liu 		cmn_err(CE_CONT, "OS unconfigure %s", cp->sbdev_path);
249*a3114836SGerry Liu 	}
250*a3114836SGerry Liu 
251*a3114836SGerry Liu 	return (0);
252*a3114836SGerry Liu }
253*a3114836SGerry Liu 
254*a3114836SGerry Liu /*ARGSUSED*/
255*a3114836SGerry Liu int
dr_post_detach_io(dr_handle_t * hp,dr_common_unit_t ** devlist,int devnum)256*a3114836SGerry Liu dr_post_detach_io(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
257*a3114836SGerry Liu {
258*a3114836SGerry Liu 	register int	i;
259*a3114836SGerry Liu 	int		rv = 0;
260*a3114836SGerry Liu 	static fn_t	f = "dr_post_detach_io";
261*a3114836SGerry Liu 
262*a3114836SGerry Liu 	ASSERT(devnum > 0);
263*a3114836SGerry Liu 	for (i = 0; i < devnum; i++) {
264*a3114836SGerry Liu 		dr_common_unit_t	*cp = devlist[i];
265*a3114836SGerry Liu 		if (cp->sbdev_error != NULL) {
266*a3114836SGerry Liu 			PR_IO("%s: Failed\n", f);
267*a3114836SGerry Liu 			rv = -1;
268*a3114836SGerry Liu 			break;
269*a3114836SGerry Liu 		}
270*a3114836SGerry Liu 	}
271*a3114836SGerry Liu 	return (rv);
272*a3114836SGerry Liu }
273*a3114836SGerry Liu 
274*a3114836SGerry Liu static void
dr_get_comp_cond(dr_io_unit_t * ip,dev_info_t * dip)275*a3114836SGerry Liu dr_get_comp_cond(dr_io_unit_t *ip, dev_info_t *dip)
276*a3114836SGerry Liu {
277*a3114836SGerry Liu 	if (dip == NULL) {
278*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_UNKNOWN;
279*a3114836SGerry Liu 		return;
280*a3114836SGerry Liu 	}
281*a3114836SGerry Liu 
282*a3114836SGerry Liu 	if (DEVI(dip)->devi_flags & DEVI_RETIRED) {
283*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_FAILED;
284*a3114836SGerry Liu 		return;
285*a3114836SGerry Liu 	}
286*a3114836SGerry Liu 
287*a3114836SGerry Liu 	if (DR_DEV_IS_ATTACHED(&ip->sbi_cm)) {
288*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
289*a3114836SGerry Liu 	} else if (DR_DEV_IS_PRESENT(&ip->sbi_cm)) {
290*a3114836SGerry Liu 		ip->sbi_cm.sbdev_cond = SBD_COND_OK;
291*a3114836SGerry Liu 	}
292*a3114836SGerry Liu }
293*a3114836SGerry Liu 
294*a3114836SGerry Liu int
dr_io_status(dr_handle_t * hp,dr_devset_t devset,sbd_dev_stat_t * dsp)295*a3114836SGerry Liu dr_io_status(dr_handle_t *hp, dr_devset_t devset, sbd_dev_stat_t *dsp)
296*a3114836SGerry Liu {
297*a3114836SGerry Liu 	int		i, ix;
298*a3114836SGerry Liu 	dr_board_t	*bp;
299*a3114836SGerry Liu 	sbd_io_stat_t	*isp;
300*a3114836SGerry Liu 	dr_io_unit_t	*ip;
301*a3114836SGerry Liu 
302*a3114836SGerry Liu 	bp = hp->h_bd;
303*a3114836SGerry Liu 
304*a3114836SGerry Liu 	/*
305*a3114836SGerry Liu 	 * Only look for requested devices that are actually present.
306*a3114836SGerry Liu 	 */
307*a3114836SGerry Liu 	devset &= DR_DEVS_PRESENT(bp);
308*a3114836SGerry Liu 
309*a3114836SGerry Liu 	for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) {
310*a3114836SGerry Liu 		drmachid_t	 id;
311*a3114836SGerry Liu 		dev_info_t	*dip;
312*a3114836SGerry Liu 		sbd_error_t	*err;
313*a3114836SGerry Liu 		drmach_status_t	 pstat;
314*a3114836SGerry Liu 
315*a3114836SGerry Liu 		if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0)
316*a3114836SGerry Liu 			continue;
317*a3114836SGerry Liu 
318*a3114836SGerry Liu 		ip = dr_get_io_unit(bp, i);
319*a3114836SGerry Liu 
320*a3114836SGerry Liu 		if (ip->sbi_cm.sbdev_state == DR_STATE_EMPTY) {
321*a3114836SGerry Liu 			/* present, but not fully initialized */
322*a3114836SGerry Liu 			continue;
323*a3114836SGerry Liu 		}
324*a3114836SGerry Liu 
325*a3114836SGerry Liu 		id = ip->sbi_cm.sbdev_id;
326*a3114836SGerry Liu 		if (id == (drmachid_t)0)
327*a3114836SGerry Liu 			continue;
328*a3114836SGerry Liu 
329*a3114836SGerry Liu 		err = drmach_status(ip->sbi_cm.sbdev_id, &pstat);
330*a3114836SGerry Liu 		if (err) {
331*a3114836SGerry Liu 			DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
332*a3114836SGerry Liu 			return (-1);
333*a3114836SGerry Liu 		}
334*a3114836SGerry Liu 
335*a3114836SGerry Liu 		dip = NULL;
336*a3114836SGerry Liu 		err = drmach_get_dip(id, &dip);
337*a3114836SGerry Liu 		if (err) {
338*a3114836SGerry Liu 			/* catch this in debug kernels */
339*a3114836SGerry Liu 			ASSERT(0);
340*a3114836SGerry Liu 
341*a3114836SGerry Liu 			sbd_err_clear(&err);
342*a3114836SGerry Liu 			continue;
343*a3114836SGerry Liu 		}
344*a3114836SGerry Liu 
345*a3114836SGerry Liu 		isp = &dsp->d_io;
346*a3114836SGerry Liu 		bzero((caddr_t)isp, sizeof (*isp));
347*a3114836SGerry Liu 
348*a3114836SGerry Liu 		isp->is_cm.c_id.c_type = ip->sbi_cm.sbdev_type;
349*a3114836SGerry Liu 		isp->is_cm.c_id.c_unit = ip->sbi_cm.sbdev_unum;
350*a3114836SGerry Liu 		(void) strlcpy(isp->is_cm.c_id.c_name, pstat.type,
351*a3114836SGerry Liu 		    sizeof (isp->is_cm.c_id.c_name));
352*a3114836SGerry Liu 
353*a3114836SGerry Liu 		dr_get_comp_cond(ip, dip);
354*a3114836SGerry Liu 		isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond;
355*a3114836SGerry Liu 		isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy | pstat.busy;
356*a3114836SGerry Liu 		isp->is_cm.c_time = ip->sbi_cm.sbdev_time;
357*a3114836SGerry Liu 		isp->is_cm.c_ostate = ip->sbi_cm.sbdev_ostate;
358*a3114836SGerry Liu 		isp->is_cm.c_sflags = 0;
359*a3114836SGerry Liu 
360*a3114836SGerry Liu 		if (dip == NULL) {
361*a3114836SGerry Liu 			isp->is_pathname[0] = '\0';
362*a3114836SGerry Liu 			isp->is_referenced = 0;
363*a3114836SGerry Liu 			isp->is_unsafe_count = 0;
364*a3114836SGerry Liu 		} else {
365*a3114836SGerry Liu 			int		refcount = 0, idx = 0;
366*a3114836SGerry Liu 			uint64_t	unsafe_devs[SBD_MAX_UNSAFE];
367*a3114836SGerry Liu 
368*a3114836SGerry Liu 			ASSERT(e_ddi_branch_held(dip));
369*a3114836SGerry Liu 			(void) ddi_pathname(dip, isp->is_pathname);
370*a3114836SGerry Liu 
371*a3114836SGerry Liu 			/* check reference and unsafe counts on devices */
372*a3114836SGerry Liu 			isp->is_unsafe_count = 0;
373*a3114836SGerry Liu 			dr_check_devices(dip, &refcount, hp, unsafe_devs,
374*a3114836SGerry Liu 			    &idx, SBD_MAX_UNSAFE, NULL);
375*a3114836SGerry Liu 			while (idx > 0) {
376*a3114836SGerry Liu 				isp->is_unsafe_list[idx-1] = unsafe_devs[idx-1];
377*a3114836SGerry Liu 				--idx;
378*a3114836SGerry Liu 			}
379*a3114836SGerry Liu 
380*a3114836SGerry Liu 			isp->is_referenced = (refcount == 0) ? 0 : 1;
381*a3114836SGerry Liu 
382*a3114836SGerry Liu 			hp->h_err = NULL;
383*a3114836SGerry Liu 		}
384*a3114836SGerry Liu 		ix++;
385*a3114836SGerry Liu 		dsp++;
386*a3114836SGerry Liu 	}
387*a3114836SGerry Liu 
388*a3114836SGerry Liu 	return (ix);
389*a3114836SGerry Liu }
390