17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 525e8c5aaSvikram * Common Development and Distribution License (the "License"). 625e8c5aaSvikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*df3cd224SVijay S Balakrishna * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/debug.h> 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/errno.h> 297c478bd9Sstevel@tonic-gate #include <sys/cred.h> 307c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 327c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 337c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 357c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 367c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 377c478bd9Sstevel@tonic-gate #include <sys/note.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <sys/sbdpriv.h> 407c478bd9Sstevel@tonic-gate #include <sys/sbd_io.h> 417c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate extern void sbd_errno_decode(int err, sbderror_t *ep, dev_info_t *dip); 457c478bd9Sstevel@tonic-gate extern sbd_state_t ostate_cvt(sbd_istate_t); 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * Given a dev_info_t of a branch root, walk down the 497c478bd9Sstevel@tonic-gate * branch to attach drivers 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 527c478bd9Sstevel@tonic-gate void 537c478bd9Sstevel@tonic-gate sbd_attach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate (void) e_ddi_branch_configure(dip, NULL, 0); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate ASSERT(sbp->sb_iopath[unit] != NULL); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, sbp->sb_iopath[unit]); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * remove device nodes for the branch indicated by dip 687c478bd9Sstevel@tonic-gate * Hold the status lock so that status can safely do ddi_pathname(). 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 717c478bd9Sstevel@tonic-gate void 727c478bd9Sstevel@tonic-gate sbd_detach_io(sbd_handle_t *hp, sbderror_t *ep, dev_info_t *dip, int unit) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate int rv; 757c478bd9Sstevel@tonic-gate dev_info_t *fdip = NULL; 767c478bd9Sstevel@tonic-gate sbd_board_t *sbp = SBDH2BD(hp->h_sbd); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate ASSERT(e_ddi_branch_held(dip)); 797c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 807c478bd9Sstevel@tonic-gate rv = e_ddi_branch_unconfigure(dip, &fdip, DEVI_BRANCH_EVENT); 817c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 827c478bd9Sstevel@tonic-gate if (rv) { 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * If non-NULL, fdip is returned held and must be released. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate if (fdip != NULL) { 877c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, fdip); 887c478bd9Sstevel@tonic-gate ddi_release_devi(fdip); 897c478bd9Sstevel@tonic-gate } else { 907c478bd9Sstevel@tonic-gate sbd_errno_decode(rv, ep, dip); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 967c478bd9Sstevel@tonic-gate void 977c478bd9Sstevel@tonic-gate sbd_init_io_unit(sbd_board_t *sbp, int unit) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate sbd_istate_t new_state; 1007c478bd9Sstevel@tonic-gate sbd_io_unit_t *ip; 1017c478bd9Sstevel@tonic-gate dev_info_t *dip; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (SBD_DEV_IS_ATTACHED(sbp, SBD_COMP_IO, unit)) { 1067c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONFIGURED; 1077c478bd9Sstevel@tonic-gate } else if (SBD_DEV_IS_PRESENT(sbp, SBD_COMP_IO, unit)) { 1087c478bd9Sstevel@tonic-gate new_state = SBD_STATE_CONNECTED; 1097c478bd9Sstevel@tonic-gate } else { 1107c478bd9Sstevel@tonic-gate new_state = SBD_STATE_EMPTY; 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][unit]; 1137c478bd9Sstevel@tonic-gate ip->sbi_cm.sbdev_cond = sbd_get_comp_cond(dip); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Any changes to this io component should be performed above 1177c478bd9Sstevel@tonic-gate * this call to ensure the component is fully initialized 1187c478bd9Sstevel@tonic-gate * before transitioning to the new state. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate SBD_DEVICE_TRANSITION(sbp, SBD_COMP_IO, unit, new_state); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1247c478bd9Sstevel@tonic-gate int 1257c478bd9Sstevel@tonic-gate sbd_disconnect_io(sbd_handle_t *hp, int unit) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate return (0); 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate int 1317c478bd9Sstevel@tonic-gate sbd_pre_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(hp)) 1347c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist)) 1357c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum)) 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate return (0); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1417c478bd9Sstevel@tonic-gate int 1427c478bd9Sstevel@tonic-gate sbd_pre_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 1437c478bd9Sstevel@tonic-gate { 1447c478bd9Sstevel@tonic-gate fn_t f = "sbd_pre_detach_io"; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate PR_IO("%s...\n", f); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (devnum <= 0) 1497c478bd9Sstevel@tonic-gate return (-1); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* fail if any I/O devices are referenced */ 1527c478bd9Sstevel@tonic-gate if (sbd_check_io_refs(hp, devlist, devnum) > 0) { 1537c478bd9Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f); 1547c478bd9Sstevel@tonic-gate return (-1); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate return (0); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1617c478bd9Sstevel@tonic-gate int 1627c478bd9Sstevel@tonic-gate sbd_post_attach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(hp)) 1657c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devlist)) 1667c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(devnum)) 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate return (0); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1727c478bd9Sstevel@tonic-gate int 1737c478bd9Sstevel@tonic-gate sbd_post_detach_io(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate return (0); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1797c478bd9Sstevel@tonic-gate int 1807c478bd9Sstevel@tonic-gate sbd_io_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate int i, ix; 1837c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 1847c478bd9Sstevel@tonic-gate sbd_io_stat_t *isp; 1857c478bd9Sstevel@tonic-gate sbd_io_unit_t *ip; 1867c478bd9Sstevel@tonic-gate sbd_istate_t dstate; 1877c478bd9Sstevel@tonic-gate sbdp_handle_t *hdp; 1887c478bd9Sstevel@tonic-gate sbderror_t *ep; 1897c478bd9Sstevel@tonic-gate sbd_error_t *sep; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp); 1977c478bd9Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 1987c478bd9Sstevel@tonic-gate hdp = sbd_get_sbdp_handle(sbp, hp); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Concurrent status and unconfigure, disconnect are allowed. 2027c478bd9Sstevel@tonic-gate * To prevent DR code from accessing stale dips, check the 2037c478bd9Sstevel@tonic-gate * present devset and access the dips with status lock held. 2047c478bd9Sstevel@tonic-gate * Disconnect and unconfigure code change dip state with 2057c478bd9Sstevel@tonic-gate * status lock (sb_slock) held. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate mutex_enter(&sbp->sb_slock); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 2127c478bd9Sstevel@tonic-gate dev_info_t *dip; 2137c478bd9Sstevel@tonic-gate int unit; 2147c478bd9Sstevel@tonic-gate int namelen; 2157c478bd9Sstevel@tonic-gate int refcount = 0; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0) 2187c478bd9Sstevel@tonic-gate continue; 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Check to make sure the io component is in a state 2217c478bd9Sstevel@tonic-gate * where its fully initialized. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate if (SBD_DEVICE_STATE(sbp, SBD_COMP_IO, i) == SBD_STATE_EMPTY) 2247c478bd9Sstevel@tonic-gate continue; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 2277c478bd9Sstevel@tonic-gate if (dip == NULL) 2287c478bd9Sstevel@tonic-gate continue; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate isp = &dsp->d_io; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate bzero((caddr_t)isp, sizeof (*isp)); 2337c478bd9Sstevel@tonic-gate namelen = sizeof (isp->is_name); 2347c478bd9Sstevel@tonic-gate (void) ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 2357c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, OBP_DEVICETYPE, 2367c478bd9Sstevel@tonic-gate (caddr_t)isp->is_name, &namelen); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate isp->is_unit = sbdp_get_unit_num(hdp, dip); 2397c478bd9Sstevel@tonic-gate if (isp->is_unit < 0) { 2407c478bd9Sstevel@tonic-gate if (hp->h_flags & SBD_IOCTL_FLAG_FORCE) 2417c478bd9Sstevel@tonic-gate continue; 2427c478bd9Sstevel@tonic-gate else { 2437c478bd9Sstevel@tonic-gate SBD_GET_PERR(hdp->h_err, SBD_HD2ERR(hp)); 2447c478bd9Sstevel@tonic-gate break; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate unit = isp->is_unit; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate dstate = SBD_DEVICE_STATE(sbp, SBD_COMP_IO, unit); 2507c478bd9Sstevel@tonic-gate isp->is_ostate = ostate_cvt(dstate); 2517c478bd9Sstevel@tonic-gate isp->is_type = SBD_COMP_IO; 2527c478bd9Sstevel@tonic-gate ip = SBD_GET_BOARD_IOUNIT(sbp, unit); 25325e8c5aaSvikram ip->sbi_cm.sbdev_cond = sbd_get_comp_cond(dip); 2547c478bd9Sstevel@tonic-gate isp->is_cm.c_cond = ip->sbi_cm.sbdev_cond; 2557c478bd9Sstevel@tonic-gate isp->is_cm.c_busy = ip->sbi_cm.sbdev_busy; 2567c478bd9Sstevel@tonic-gate isp->is_cm.c_time = ip->sbi_cm.sbdev_time; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * This is safe to do as unconfigure and disconnect 2617c478bd9Sstevel@tonic-gate * hold the status lock while changing dip state. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate (void) ddi_pathname(dip, isp->is_pathname); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2667c478bd9Sstevel@tonic-gate * We use a dummy handle in which to collect 2677c478bd9Sstevel@tonic-gate * the major numbers of unsafe devices. 2687c478bd9Sstevel@tonic-gate */ 269*df3cd224SVijay S Balakrishna sbdp_check_devices(dip, &refcount, sep, NULL); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate isp->is_referenced = (refcount == 0) ? 0 : 1; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate isp->is_unsafe_count = 0; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * Reset error field since we don't care about 2777c478bd9Sstevel@tonic-gate * errors at this level. The unsafe devices 2787c478bd9Sstevel@tonic-gate * will be reported in the structure. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate SBD_SET_ERR(ep, ESBD_NOERROR); 2817c478bd9Sstevel@tonic-gate ep->e_rsc[0] = '\0'; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate ix++; 2847c478bd9Sstevel@tonic-gate dsp++; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate mutex_exit(&sbp->sb_slock); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t)); 2907c478bd9Sstevel@tonic-gate sbd_release_sbdp_handle(hdp); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate return (ix); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2967c478bd9Sstevel@tonic-gate int 2977c478bd9Sstevel@tonic-gate sbd_io_cnt(sbd_handle_t *hp, sbd_devset_t devset) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate int i, ix; 3007c478bd9Sstevel@tonic-gate sbd_board_t *sbp; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate sbp = SBDH2BD(hp->h_sbd); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * Only look for requested devices that are actually present. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate devset &= SBD_DEVS_PRESENT(sbp); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate for (i = ix = 0; i < MAX_IO_UNITS_PER_BOARD; i++) { 3107c478bd9Sstevel@tonic-gate dev_info_t *dip; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if (DEVSET_IN_SET(devset, SBD_COMP_IO, i) == 0) 3137c478bd9Sstevel@tonic-gate continue; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate dip = sbp->sb_devlist[NIX(SBD_COMP_IO)][i]; 3167c478bd9Sstevel@tonic-gate if (dip == NULL) 3177c478bd9Sstevel@tonic-gate continue; 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate ix++; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate return (ix); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate int 3267c478bd9Sstevel@tonic-gate sbd_check_io_refs(sbd_handle_t *hp, sbd_devlist_t devlist[], int devnum) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate register int i, reftotal = 0; 3297c478bd9Sstevel@tonic-gate fn_t f = "sbd_check_io_refs"; 3307c478bd9Sstevel@tonic-gate sbd_error_t *sep; 3317c478bd9Sstevel@tonic-gate sbderror_t *ep; 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate sep = kmem_zalloc(sizeof (sbd_error_t), KM_SLEEP); 3347c478bd9Sstevel@tonic-gate ep = HD2MACHERR(hp); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 3377c478bd9Sstevel@tonic-gate dev_info_t *dip; 3387c478bd9Sstevel@tonic-gate int ref; 339*df3cd224SVijay S Balakrishna int refcount_non_gldv3; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate dip = devlist[i].dv_dip; 3427c478bd9Sstevel@tonic-gate ref = 0; 343*df3cd224SVijay S Balakrishna refcount_non_gldv3 = 0; 344*df3cd224SVijay S Balakrishna sbdp_check_devices(dip, &ref, sep, &refcount_non_gldv3); 345*df3cd224SVijay S Balakrishna ASSERT(refcount_non_gldv3 >= 0); 346*df3cd224SVijay S Balakrishna ASSERT(ref >= refcount_non_gldv3); 347*df3cd224SVijay S Balakrishna /* 348*df3cd224SVijay S Balakrishna * Ignore reference counts of non-gldv3 network devices 349*df3cd224SVijay S Balakrishna * as Crossbow creates reference counts for non-active 350*df3cd224SVijay S Balakrishna * (unplumbed) instances. Reference count check in 351*df3cd224SVijay S Balakrishna * detach() known to prevent device from detaching 352*df3cd224SVijay S Balakrishna * as necessary. 353*df3cd224SVijay S Balakrishna */ 354*df3cd224SVijay S Balakrishna ref -= refcount_non_gldv3; 3557c478bd9Sstevel@tonic-gate if (ref) { 3567c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(ep) == 0) { 3577c478bd9Sstevel@tonic-gate SBD_GET_PERR(sep, ep); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate SBD_GET_PERR(sep, &devlist[i].dv_error); 3607c478bd9Sstevel@tonic-gate } 361*df3cd224SVijay S Balakrishna PR_IO("%s: dip(%s) ref = %d\n", f, ddi_get_name(dip), ref); 3627c478bd9Sstevel@tonic-gate reftotal += ref; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate kmem_free(sep, sizeof (sbd_error_t)); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate return (reftotal); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate int 3717c478bd9Sstevel@tonic-gate sbd_check_io_attached(dev_info_t *dip, void *arg) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate dev_info_t **tdip; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate tdip = (dev_info_t **)arg; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (dip == *tdip) { 3787c478bd9Sstevel@tonic-gate int state; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate state = ddi_get_devstate(dip); 381737d277aScth if (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP)) { 3827c478bd9Sstevel@tonic-gate *tdip = NULL; 3837c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate int 3907c478bd9Sstevel@tonic-gate sbd_pre_release_io(sbd_handle_t *hp, 3917c478bd9Sstevel@tonic-gate sbd_devlist_t *devlist, int devnum) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate fn_t f = "sbd_pre_release_io"; 3947c478bd9Sstevel@tonic-gate int rv = 0; 3957c478bd9Sstevel@tonic-gate int i; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate ASSERT(devnum > 0); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* fail if any I/O devices are referenced */ 4007c478bd9Sstevel@tonic-gate if ((rv = sbd_check_io_refs(hp, devlist, devnum)) > 0) { 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * One of the devices may have failed check to see which 4037c478bd9Sstevel@tonic-gate * and set in the main handle 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate for (i = 0; i < devnum; i++) { 4067c478bd9Sstevel@tonic-gate if (SBD_GET_ERR(&devlist[i].dv_error) != 0) { 4077c478bd9Sstevel@tonic-gate (void) sbd_set_err_in_hdl(hp, 4087c478bd9Sstevel@tonic-gate &devlist[i].dv_error); 4097c478bd9Sstevel@tonic-gate break; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate PR_IO("%s: failed - I/O devices ref'd\n", f); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate return (rv); 4167c478bd9Sstevel@tonic-gate } 417