6946938 SCSAv3: sometimes phymaps observations fail to activate
authorChris Horne <Chris.Horne@Sun.COM>
Thu, 13 May 2010 12:39:32 -0600
changeset 12399 64bb4582eeeb
parent 12398 d1a36c3701ab
child 12400 64b0dca82c21
6946938 SCSAv3: sometimes phymaps observations fail to activate 6950461 SCSAv3: should be able to modunload the pmcs driver 6951142 scsi_ifsetcap should always update dma_attr_granular when tran_setup_pkt is defined 6951267 fix for 6948076 can still double-allocate a preassigned instance number 6951616 sunmdi.c should avoid unnecessary use of ct_dip
usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c
usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c
usr/src/uts/common/io/scsi/impl/scsi_capabilities.c
usr/src/uts/common/io/scsi/impl/scsi_hba.c
usr/src/uts/common/os/damap.c
usr/src/uts/common/os/instance.c
usr/src/uts/common/os/sunmdi.c
--- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c	Thu May 13 12:39:32 2010 -0600
@@ -89,6 +89,16 @@
 static int disable_msi = 0;
 #endif
 
+/*
+ * DEBUG: testing: allow detach with an active port:
+ *
+ * # echo 'detach_driver_unconfig/W 10'		| mdb -kw
+ * # echo 'scsi_hba_bus_unconfig_remove/W 1'	| mdb -kw
+ * # echo 'pmcs`detach_with_active_port/W 1'	| mdb -kw
+ * # modunload -i <pmcs_driver_index>
+ */
+static int detach_with_active_port = 0;
+
 static uint16_t maxqdepth = 0xfffe;
 
 /*
@@ -114,7 +124,6 @@
 
 static void pmcs_create_all_phy_stats(pmcs_iport_t *);
 int pmcs_update_phy_stats(kstat_t *, int);
-static void pmcs_destroy_phy_stats(pmcs_iport_t *);
 
 static void pmcs_fm_fini(pmcs_hw_t *pwp);
 static void pmcs_fm_init(pmcs_hw_t *pwp);
@@ -805,9 +814,9 @@
 		num_threads = PMCS_MAX_CQ_THREADS;
 	}
 
-	pwp->cq_info.cq_thr_info = kmem_zalloc(sizeof (pmcs_cq_thr_info_t) *
-	    num_threads, KM_SLEEP);
 	pwp->cq_info.cq_threads = num_threads;
+	pwp->cq_info.cq_thr_info = kmem_zalloc(
+	    sizeof (pmcs_cq_thr_info_t) * pwp->cq_info.cq_threads, KM_SLEEP);
 	pwp->cq_info.cq_next_disp_thr = 0;
 	pwp->cq_info.cq_stop = B_FALSE;
 
@@ -1020,6 +1029,17 @@
 	}
 
 	/*
+	 * Create the iportmap for this HBA instance
+	 */
+	if (scsi_hba_iportmap_create(dip, iportmap_csync_usec,
+	    iportmap_stable_usec, &pwp->hss_iportmap) != DDI_SUCCESS) {
+		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
+		    "%s: pmcs%d iportmap_create failed", __func__, inst);
+		goto failure;
+	}
+	ASSERT(pwp->hss_iportmap);
+
+	/*
 	 * Create the phymap for this HBA instance
 	 */
 	if (sas_phymap_create(dip, phymap_stable_usec, PHYMAP_MODE_SIMPLE, NULL,
@@ -1032,17 +1052,6 @@
 	ASSERT(pwp->hss_phymap);
 
 	/*
-	 * Create the iportmap for this HBA instance
-	 */
-	if (scsi_hba_iportmap_create(dip, iportmap_csync_usec,
-	    iportmap_stable_usec, &pwp->hss_iportmap) != DDI_SUCCESS) {
-		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
-		    "%s: pmcs%d iportmap_create failed", __func__, inst);
-		goto failure;
-	}
-	ASSERT(pwp->hss_iportmap);
-
-	/*
 	 * Start the PHYs.
 	 */
 	if (pmcs_start_phys(pwp)) {
@@ -1155,7 +1164,6 @@
 			return (DDI_FAILURE);
 		}
 	}
-
 	switch (cmd) {
 	case DDI_DETACH:
 		if (iport) {
@@ -1229,7 +1237,8 @@
 	rw_enter(&pwp->iports_lock, RW_WRITER);
 	mutex_enter(&iport->lock);
 
-	if (iport->ua_state == UA_ACTIVE) {
+	if ((iport->ua_state == UA_ACTIVE) &&
+	    (detach_with_active_port == 0)) {
 		mutex_exit(&iport->lock);
 		rw_exit(&pwp->iports_lock);
 		pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
@@ -1279,8 +1288,6 @@
 	}
 	mutex_exit(&iport->refcnt_lock);
 
-	/* Delete kstats */
-	pmcs_destroy_phy_stats(iport);
 
 	/* Destroy the iport target map */
 	if (pmcs_iport_tgtmap_destroy(iport) == B_FALSE) {
@@ -1350,6 +1357,8 @@
 			}
 		}
 		mutex_exit(&pwp->cq_lock);
+		kmem_free(pwp->cq_info.cq_thr_info,
+		    sizeof (pmcs_cq_thr_info_t) * pwp->cq_info.cq_threads);
 
 		/*
 		 * Stop the interrupt coalescing timer thread
@@ -1430,41 +1439,21 @@
 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
 	}
 
+	if (pwp->hss_phymap != NULL) {
+		/* Destroy the phymap */
+		sas_phymap_destroy(pwp->hss_phymap);
+	}
+
 	if (pwp->hss_iportmap != NULL) {
 		/* Destroy the iportmap */
 		scsi_hba_iportmap_destroy(pwp->hss_iportmap);
 	}
 
-	if (pwp->hss_phymap != NULL) {
-		/* Destroy the phymap */
-		sas_phymap_destroy(pwp->hss_phymap);
-	}
-
 	/* Destroy the iports lock and list */
 	rw_destroy(&pwp->iports_lock);
 	ASSERT(list_is_empty(&pwp->iports));
 	list_destroy(&pwp->iports);
 
-	/* Destroy pwp's lock */
-	if (pwp->locks_initted) {
-		mutex_destroy(&pwp->lock);
-		mutex_destroy(&pwp->dma_lock);
-		mutex_destroy(&pwp->axil_lock);
-		mutex_destroy(&pwp->cq_lock);
-		mutex_destroy(&pwp->config_lock);
-		mutex_destroy(&pwp->ict_lock);
-		mutex_destroy(&pwp->wfree_lock);
-		mutex_destroy(&pwp->pfree_lock);
-		mutex_destroy(&pwp->dead_phylist_lock);
-#ifdef	DEBUG
-		mutex_destroy(&pwp->dbglock);
-#endif
-		cv_destroy(&pwp->config_cv);
-		cv_destroy(&pwp->ict_cv);
-		cv_destroy(&pwp->drain_cv);
-		pwp->locks_initted = 0;
-	}
-
 	/*
 	 * Free DMA handles and associated consistent memory
 	 */
@@ -1613,6 +1602,10 @@
 	/*
 	 * Do last property and SCSA cleanup
 	 */
+	if (pwp->smp_tran) {
+		smp_hba_tran_free(pwp->smp_tran);
+		pwp->smp_tran = NULL;
+	}
 	if (pwp->tran) {
 		scsi_hba_tran_free(pwp->tran);
 		pwp->tran = NULL;
@@ -1640,6 +1633,26 @@
 		pwp->iqpt = NULL;
 	}
 
+	/* Destroy pwp's lock */
+	if (pwp->locks_initted) {
+		mutex_destroy(&pwp->lock);
+		mutex_destroy(&pwp->dma_lock);
+		mutex_destroy(&pwp->axil_lock);
+		mutex_destroy(&pwp->cq_lock);
+		mutex_destroy(&pwp->config_lock);
+		mutex_destroy(&pwp->ict_lock);
+		mutex_destroy(&pwp->wfree_lock);
+		mutex_destroy(&pwp->pfree_lock);
+		mutex_destroy(&pwp->dead_phylist_lock);
+#ifdef	DEBUG
+		mutex_destroy(&pwp->dbglock);
+#endif
+		cv_destroy(&pwp->config_cv);
+		cv_destroy(&pwp->ict_cv);
+		cv_destroy(&pwp->drain_cv);
+		pwp->locks_initted = 0;
+	}
+
 	ddi_soft_state_free(pmcs_softc_state, ddi_get_instance(pwp->dip));
 	return (0);
 }
@@ -3151,34 +3164,6 @@
 	return (ret);
 }
 
-static void
-pmcs_destroy_phy_stats(pmcs_iport_t *iport)
-{
-	pmcs_phy_t		*phyp;
-
-	ASSERT(iport != NULL);
-	mutex_enter(&iport->lock);
-	phyp = iport->pptr;
-	if (phyp == NULL) {
-		mutex_exit(&iport->lock);
-		return;
-	}
-
-	for (phyp = list_head(&iport->phys);
-	    phyp != NULL;
-	    phyp = list_next(&iport->phys, phyp)) {
-
-		mutex_enter(&phyp->phy_lock);
-		if (phyp->phy_stats != NULL) {
-			kstat_delete(phyp->phy_stats);
-			phyp->phy_stats = NULL;
-		}
-		mutex_exit(&phyp->phy_lock);
-	}
-
-	mutex_exit(&iport->lock);
-}
-
 /*ARGSUSED*/
 static int
 pmcs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
--- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c	Thu May 13 12:39:32 2010 -0600
@@ -1419,15 +1419,17 @@
 	/*
 	 * Start at the maximum level and walk back to level 0.  This only
 	 * gets done during detach after all threads and timers have been
-	 * destroyed, so there's no need to hold the softstate or PHY lock.
+	 * destroyed.
 	 */
 	while (phyp) {
 		if (phyp->children) {
 			pmcs_deregister_devices(pwp, phyp->children);
 		}
+		pmcs_lock_phy(phyp);
 		if (phyp->valid_device_id) {
 			pmcs_deregister_device(pwp, phyp);
 		}
+		pmcs_unlock_phy(phyp);
 		phyp = phyp->sibling;
 	}
 }
@@ -7508,33 +7510,30 @@
 void
 pmcs_free_all_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
 {
-	pmcs_phy_t *tphyp, *nphyp;
+	pmcs_phy_t *tphyp, *nphyp, *cphyp;
 
 	if (phyp == NULL) {
 		return;
 	}
 
-	tphyp = phyp;
-	while (tphyp) {
+	for (tphyp = phyp; tphyp; tphyp = nphyp) {
 		nphyp = tphyp->sibling;
-
-		if (tphyp->children) {
-			pmcs_free_all_phys(pwp, tphyp->children);
+		cphyp = tphyp->children;
+
+		if (cphyp) {
 			tphyp->children = NULL;
-		}
+			pmcs_free_all_phys(pwp, cphyp);
+		}
+
 		if (!IS_ROOT_PHY(tphyp)) {
 			kmem_cache_free(pwp->phy_cache, tphyp);
 		}
-
-		tphyp = nphyp;
 	}
 
 	mutex_enter(&pwp->dead_phylist_lock);
-	tphyp = pwp->dead_phys;
-	while (tphyp) {
+	for (tphyp = pwp->dead_phys; tphyp; tphyp = nphyp) {
 		nphyp = tphyp->dead_next;
 		kmem_cache_free(pwp->phy_cache, tphyp);
-		tphyp = nphyp;
 	}
 	pwp->dead_phys = NULL;
 	mutex_exit(&pwp->dead_phylist_lock);
--- a/usr/src/uts/common/io/scsi/impl/scsi_capabilities.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/io/scsi/impl/scsi_capabilities.c	Thu May 13 12:39:32 2010 -0600
@@ -19,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  *
  * Generic Capabilities Routines
@@ -99,7 +96,7 @@
 	int cidx;
 
 	rval = (*A_TO_TRAN(ap)->tran_setcap)(ap, cap, value, whom);
-	if (rval == 1) {
+	if ((rval == 1) || A_TO_TRAN(ap)->tran_setup_pkt) {
 		cidx = scsi_hba_lookup_capstr(cap);
 		if (cidx == SCSI_CAP_SECTOR_SIZE) {
 			/*
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Thu May 13 12:39:32 2010 -0600
@@ -134,6 +134,9 @@
 /* enable NDI_DEVI_DEBUG for bus_[un]config operations */
 int	scsi_hba_bus_config_debug = 0;
 
+/* DEBUG: enable NDI_DEVI_REMOVE for bus_unconfig of dynamic node */
+int	scsi_hba_bus_unconfig_remove = 0;
+
 /* number of probe serilization messages */
 int	scsi_hba_wait_msg = 5;
 
@@ -8351,6 +8354,10 @@
 	scsi_hba_barrier_purge(self);
 	scsi_hba_devi_exit(self, circ);
 
+	/* DEBUG: for testing, allow bus_unconfig do drive removal. */
+	if (scsi_hba_bus_unconfig_remove)
+		flags |= NDI_DEVI_REMOVE;
+
 	/* Check if self is HBA-only node. */
 	if (tran->tran_hba_flags & SCSI_HBA_HBA) {
 		/* The bus_config request is to unconfigure iports below HBA. */
@@ -9821,6 +9828,11 @@
 #else
 #define	SAS_PHY_UA_LEN		SAS_PHY_NAME_LEN
 #endif
+typedef struct impl_sas_physet {	/* needed for name2phys destroy */
+	struct impl_sas_physet		*physet_next;
+	char				*physet_name;
+	bitset_t			*physet_phys;
+} impl_sas_physet_t;
 typedef struct impl_sas_phymap {
 	dev_info_t			*phymap_self;
 
@@ -9841,6 +9853,8 @@
 	sas_phymap_activate_cb_t	phymap_acp;
 	sas_phymap_deactivate_cb_t	phymap_dcp;
 	void				*phymap_private;
+
+	struct impl_sas_physet		*phymap_physets;
 } impl_sas_phymap_t;
 
 /* Detect noisy phy: max changes per stabilization period per phy. */
@@ -10062,16 +10076,9 @@
 	    ddi_driver_name(self), ddi_get_instance(self));
 	SCSI_HBA_LOG((_LOGPHY, self, NULL, "%s", context));
 
-	if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG,
-	    settle_usec, NULL, NULL, NULL,
-	    phymap, sas_phymap_config, sas_phymap_unconfig,
-	    &phymap->phymap_dam) != DAM_SUCCESS)
-		goto fail;
-
 	if (ddi_soft_state_init(&phymap->phymap_phy2name,
 	    SAS_PHY_NAME_LEN, SAS_PHY_NPHY) != 0)
 		goto fail;
-
 	if (ddi_soft_state_bystr_init(&phymap->phymap_name2phys,
 	    sizeof (bitset_t), SAS_PHY_NPHY) != 0)
 		goto fail;
@@ -10083,6 +10090,13 @@
 	    SAS_PHY_NAME_LEN, SAS_PHY_NPHY) != 0)
 		goto fail;
 
+	if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG,
+	    settle_usec, NULL, NULL, NULL,
+	    phymap, sas_phymap_config, sas_phymap_unconfig,
+	    &phymap->phymap_dam) != DAM_SUCCESS)
+		goto fail;
+
+
 	*handlep = (sas_phymap_t *)phymap;
 	return (DDI_SUCCESS);
 
@@ -10096,11 +10110,34 @@
 {
 	impl_sas_phymap_t	*phymap = (impl_sas_phymap_t *)handle;
 	char			*context;
+	struct impl_sas_physet	*physet, *nphyset;
+	bitset_t		*phys;
+	char			*name;
 
 	context = phymap->phymap_dam ?
 	    damap_name(phymap->phymap_dam) : "unknown";
 	SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, "%s", context));
 
+	if (phymap->phymap_dam)
+		damap_destroy(phymap->phymap_dam);
+
+	/* free the bitsets of allocated physets */
+	for (physet = phymap->phymap_physets; physet; physet = nphyset) {
+		nphyset = physet->physet_next;
+		phys = physet->physet_phys;
+		name = physet->physet_name;
+
+		if (phys)
+			bitset_fini(phys);
+		if (name) {
+			ddi_soft_state_bystr_free(
+			    phymap->phymap_name2phys, name);
+			strfree(name);
+		}
+		kmem_free(physet, sizeof (*physet));
+	}
+
+	/* free the maps */
 	if (phymap->phymap_ua2name)
 		ddi_soft_state_bystr_fini(&phymap->phymap_ua2name);
 	if (phymap->phymap_name2ua)
@@ -10108,12 +10145,9 @@
 
 	if (phymap->phymap_name2phys)
 		ddi_soft_state_bystr_fini(&phymap->phymap_name2phys);
-
 	if (phymap->phymap_phy2name)
 		ddi_soft_state_fini(&phymap->phymap_phy2name);
 
-	if (phymap->phymap_dam)
-		damap_destroy(phymap->phymap_dam);
 	mutex_destroy(&phymap->phymap_lock);
 	kmem_free(phymap, sizeof (*phymap));
 }
@@ -10127,9 +10161,9 @@
 	char			*context = damap_name(phymap->phymap_dam);
 	char			port[SAS_PHY_NAME_LEN];
 	char			*name;
+	int			phy2name_allocated = 0;
 	bitset_t		*phys;
-	int			phy2name_allocated = 0;
-	int			name2phys_allocated = 0;
+	struct impl_sas_physet	*physet;
 	int			rv;
 
 	/* Create the SAS port name from the local and remote addresses. */
@@ -10184,13 +10218,17 @@
 			    "%s: %s: no name2phys", context, name));
 			goto fail;
 		}
-		name2phys_allocated = 1;
-
-		/* Initialize bitset of phys */
+
+		/* Initialize bitset of phys. */
 		bitset_init(phys);
 		bitset_resize(phys, SAS_PHY_NPHY);
 
-		/* NOTE: no bitset_fini of phys needed */
+		/* Keep a list of information for destroy. */
+		physet = kmem_zalloc(sizeof (*physet), KM_SLEEP);
+		physet->physet_name = strdup(name);
+		physet->physet_phys = phys;
+		physet->physet_next = phymap->phymap_physets;
+		phymap->phymap_physets = physet;
 	}
 	ASSERT(phys);
 
@@ -10243,8 +10281,6 @@
 
 fail:	if (phy2name_allocated)
 		ddi_soft_state_free(phymap->phymap_phy2name, phy);
-	if (name2phys_allocated)
-		ddi_soft_state_bystr_free(phymap->phymap_name2phys, name);
 	mutex_exit(&phymap->phymap_lock);
 	return (DDI_FAILURE);
 }
--- a/usr/src/uts/common/os/damap.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/os/damap.c	Thu May 13 12:39:32 2010 -0600
@@ -130,9 +130,6 @@
 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
 		return (DAM_EINVAL);
 
-	DTRACE_PROBE3(damap__create, char *, name,
-	    damap_rptmode_t, mode, int, stable_usec);
-
 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
 	mapp->dam_options = map_opts;
 	mapp->dam_stable_ticks = drv_usectohz(stable_usec);
@@ -151,6 +148,11 @@
 	bitset_init(&mapp->dam_stable_set);
 	bitset_init(&mapp->dam_report_set);
 	*damapp = (damap_t *)mapp;
+
+	DTRACE_PROBE5(damap__create,
+	    char *, mapp->dam_name, damap_t *, mapp,
+	    damap_rptmode_t, mode, int, map_opts, int, stable_usec);
+
 	return (DAM_SUCCESS);
 }
 
@@ -216,7 +218,8 @@
 
 	ASSERT(mapp);
 
-	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
+	DTRACE_PROBE2(damap__destroy,
+	    char *, mapp->dam_name, damap_t *, mapp);
 
 	mutex_enter(&mapp->dam_lock);
 
@@ -287,8 +290,9 @@
 	int	rv;
 
 	ASSERT(mapp);
-	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE3(damap__map__sync__start,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    int, sync_usec);
 
 	/*
 	 * Block when waiting for
@@ -301,8 +305,8 @@
 again:	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
 	    (!bitset_is_null(&mapp->dam_report_set)) ||
 	    (mapp->dam_tid != 0)) {
-		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
-		    dam_t *, mapp);
+		DTRACE_PROBE2(damap__map__sync__waiting,
+		    char *, mapp->dam_name, dam_t *, mapp);
 
 		/* Wait for condition relayed via timeout */
 		if (sync_usec) {
@@ -330,8 +334,9 @@
 	}
 	mutex_exit(&mapp->dam_lock);
 
-	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name,
-	    int, rv, dam_t *, mapp);
+	DTRACE_PROBE3(damap__map__sync__end,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    int, rv);
 	return (rv);
 }
 
@@ -404,8 +409,9 @@
 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 		return (DAM_EINVAL);
 
-	DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name,
-	    char *, address, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__add,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, address);
 
 	mutex_enter(&mapp->dam_lock);
 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
@@ -422,8 +428,9 @@
 	 * the existing report
 	 */
 	if (DAM_IN_REPORT(mapp, addrid)) {
-		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
-		    char *, address, dam_t *, mapp);
+		DTRACE_PROBE3(damap__addr__add__jitter,
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, address);
 		DAM_INCR_STAT(mapp, dam_jitter);
 		dam_addr_report_release(mapp, addrid);
 		passp->da_jitter++;
@@ -459,8 +466,9 @@
 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 		return (DAM_EINVAL);
 
-	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
-	    char *, address, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__del,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, address);
 	mutex_enter(&mapp->dam_lock);
 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
 		mutex_exit(&mapp->dam_lock);
@@ -478,8 +486,9 @@
 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
 	ASSERT(passp);
 	if (DAM_IN_REPORT(mapp, addrid)) {
-		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
-		    char *, address, dam_t *, mapp);
+		DTRACE_PROBE3(damap__addr__del__jitter,
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, address);
 		DAM_INCR_STAT(mapp, dam_jitter);
 		dam_addr_report_release(mapp, addrid);
 		passp->da_jitter++;
@@ -501,11 +510,11 @@
 		return (DAM_EINVAL);
 	}
 
-	DTRACE_PROBE2(damap__addrset__flush__locked__enter, char *,
-	    mapp->dam_name, dam_t *, mapp);
+	DTRACE_PROBE2(damap__addrset__flush__locked__enter,
+	    char *, mapp->dam_name, dam_t *, mapp);
 	if (mapp->dam_flags & DAM_SETADD) {
-		DTRACE_PROBE2(damap__addrset__flush__locked__reset, char *,
-		    mapp->dam_name, dam_t *, mapp);
+		DTRACE_PROBE2(damap__addrset__flush__locked__reset,
+		    char *, mapp->dam_name, dam_t *, mapp);
 
 		/*
 		 * cancel stabilization timeout
@@ -548,8 +557,8 @@
 		return (DAM_EINVAL);
 	}
 
-	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
-	    mapp);
+	DTRACE_PROBE2(damap__addrset__begin,
+	    char *, mapp->dam_name, dam_t *, mapp);
 
 	mutex_enter(&mapp->dam_lock);
 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
@@ -585,8 +594,8 @@
 		return (DAM_EINVAL);
 	}
 
-	DTRACE_PROBE2(damap__addrset__flush, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE2(damap__addrset__flush,
+	    char *, mapp->dam_name, dam_t *, mapp);
 
 	mutex_enter(&mapp->dam_lock);
 	rv = damap_addrset_flush_locked(damapp);
@@ -620,8 +629,8 @@
 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 		return (DAM_EINVAL);
 
-	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
-	    char *, address, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addrset__add,
+	    char *, mapp->dam_name, dam_t *, mapp, char *, address);
 
 	mutex_enter(&mapp->dam_lock);
 	if (!(mapp->dam_flags & DAM_SETADD)) {
@@ -637,8 +646,9 @@
 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
 	ASSERT(passp);
 	if (DAM_IN_REPORT(mapp, addrid)) {
-		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
-		    mapp->dam_name, char *, address, dam_t *, mapp);
+		DTRACE_PROBE3(damap__addrset__add__jitter,
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, address);
 		dam_addr_report_release(mapp, addrid);
 		passp->da_jitter++;
 	}
@@ -671,8 +681,8 @@
 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 		return (DAM_EINVAL);
 
-	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE2(damap__addrset__end,
+	    char *, mapp->dam_name, dam_t *, mapp);
 
 	mutex_enter(&mapp->dam_lock);
 	if (!(mapp->dam_flags & DAM_SETADD)) {
@@ -681,8 +691,8 @@
 	}
 
 	if (flags & DAMAP_END_RESET) {
-		DTRACE_PROBE2(damap__addrset__end__reset, char *,
-		    mapp->dam_name, dam_t *, mapp);
+		DTRACE_PROBE2(damap__addrset__end__reset,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		dam_sched_timeout(NULL, mapp, 0);
 		for (i = 1; i < mapp->dam_high; i++)
 			if (DAM_IN_REPORT(mapp, i))
@@ -755,8 +765,9 @@
 	ASSERT(passp);
 
 	addr = damap_id2addr(damapp, addrid);
-	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
-	    dam_t *, mapp, int, passp->da_ref);
+	DTRACE_PROBE4(damap__id__rele,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addr, int, passp->da_ref);
 
 	mutex_enter(&mapp->dam_lock);
 
@@ -890,8 +901,9 @@
 	id_t addrid = 0;
 	dam_da_t *passp = NULL;
 
-	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
-	    char *, address, dam_t *, mapp);
+	DTRACE_PROBE3(damap__lookup,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, address);
 	mutex_enter(&mapp->dam_lock);
 	if (!mapp->dam_high)
 		addrid = 0;
@@ -911,8 +923,9 @@
 		}
 	}
 	mutex_exit(&mapp->dam_lock);
-	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
-	    char *, address, dam_t *, mapp, int, addrid);
+	DTRACE_PROBE4(damap__lookup__return,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, address, int, addrid);
 	return ((damap_id_t)addrid);
 }
 
@@ -935,14 +948,14 @@
 	char	 *addrp;
 	dam_da_t *passp;
 
-	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE2(damap__lookup__all,
+	    char *, mapp->dam_name, dam_t *, mapp);
 	mutex_enter(&mapp->dam_lock);
 	if (!mapp->dam_high) {
 		*id_listp = (damap_id_list_t)NULL;
 		mutex_exit(&mapp->dam_lock);
-		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
-		    mapp->dam_name, dam_t *, mapp, int, 0);
+		DTRACE_PROBE2(damap__lookup__all__nomap,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		return (0);
 	}
 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
@@ -955,9 +968,9 @@
 			ASSERT(passp);
 			if (passp) {
 				addrp = damap_id2addr(damapp, i);
-				DTRACE_PROBE3(damap__lookup__all__item, char *,
-				    mapp->dam_name, char *, addrp, dam_t *,
-				    mapp);
+				DTRACE_PROBE3(damap__lookup__all__item,
+				    char *, mapp->dam_name, dam_t *, mapp,
+				    char *, addrp);
 				passp->da_ref++;
 				n_ids++;
 			}
@@ -1020,8 +1033,9 @@
 	 * copy the reported nvlist and provider private data
 	 */
 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
-	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__activate__start,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr);
 	passp->da_nvl = passp->da_nvl_rpt;
 	passp->da_ppriv = passp->da_ppriv_rpt;
 	passp->da_ppriv_rpt = NULL;
@@ -1045,12 +1059,14 @@
 		passp->da_flags |= DA_FAILED_CONFIG;
 		mutex_exit(&mapp->dam_lock);
 		DTRACE_PROBE3(damap__addr__activate__config__failure,
-		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, addrstr);
 		dam_deact_cleanup(mapp, addrid, addrstr,
 		    DAMAP_DEACT_RSN_CFG_FAIL);
 	} else {
-		DTRACE_PROBE3(damap__addr__activate__end, char *,
-		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
+		DTRACE_PROBE3(damap__addr__activate__end,
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, addrstr);
 	}
 }
 
@@ -1063,8 +1079,9 @@
 	char *addrstr;
 
 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
-	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__deactivate__start,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr);
 
 	/*
 	 * call the unconfiguration callback
@@ -1101,8 +1118,9 @@
 		nvlist_free(passp->da_nvl_rpt);
 	passp->da_nvl_rpt = NULL;
 
-	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__deactivate__end,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr);
 
 	(void) dam_addr_release(mapp, addrid);
 	mutex_exit(&mapp->dam_lock);
@@ -1190,8 +1208,8 @@
 	cfg_tqd_t *tqd = NULL;
 	char tqn[TASKQ_NAMELEN];
 
-	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE2(damap__addrset__deactivate,
+	    char *, mapp->dam_name, dam_t *, mapp);
 
 	if (mapp->dam_options & DAMAP_MTCONFIG) {
 		/*
@@ -1240,8 +1258,9 @@
 	ASSERT(passp);
 
 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
-	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__release,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr);
 
 	/*
 	 * defer releasing the address until outstanding references
@@ -1249,8 +1268,8 @@
 	 */
 	if (passp->da_ref > 1) {
 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
-		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
-		    int, passp->da_ref);
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, addrstr, int, passp->da_ref);
 		return;
 	}
 
@@ -1259,7 +1278,8 @@
 	 */
 	if (DAM_IN_REPORT(mapp, addrid)) {
 		DTRACE_PROBE3(damap__addr__release__report__pending,
-		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
+		    char *, mapp->dam_name, dam_t *, mapp,
+		    char *, addrstr);
 		return;
 	}
 
@@ -1280,8 +1300,8 @@
 	int has_cfg, has_uncfg;
 	uint32_t i, n_active;
 
-	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
-	    dam_t *, mapp);
+	DTRACE_PROBE2(damap__stabilize__map,
+	    char *, mapp->dam_name, dam_t *, mapp);
 
 	bitset_init(&delta);
 	bitset_resize(&delta, mapp->dam_size);
@@ -1309,8 +1329,8 @@
 		bitset_fini(&uncfg);
 		bitset_fini(&cfg);
 		bitset_fini(&delta);
-		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
-		    mapp->dam_name, dam_t *, mapp);
+		DTRACE_PROBE2(damap__stabilize__map__nochange,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		return;
 	}
 
@@ -1357,8 +1377,9 @@
 			n_active++;
 	DAM_SET_STAT(mapp, dam_active, n_active);
 
-	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
-	    dam_t *, mapp, int, n_active);
+	DTRACE_PROBE3(damap__map__stable__end,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    int, n_active);
 
 	mapp->dam_flags &= ~DAM_SPEND;
 	cv_signal(&mapp->dam_sync_cv);
@@ -1384,8 +1405,8 @@
 
 	mutex_enter(&mapp->dam_lock);
 	if (mapp->dam_tid == 0) {
-		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
-		    mapp->dam_name, dam_t *, mapp);
+		DTRACE_PROBE2(damap__map__addr__stable__cancelled,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		mutex_exit(&mapp->dam_lock);
 		return;
 	}
@@ -1399,10 +1420,10 @@
 	if (mapp->dam_flags & DAM_SPEND) {
 		DAM_INCR_STAT(mapp, dam_overrun);
 		mapp->dam_stable_overrun++;
+		DTRACE_PROBE2(damap__map__addr__stable__overrun,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		dam_sched_timeout(dam_addr_stable_cb, mapp,
 		    mapp->dam_stable_ticks);
-		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
-		    mapp->dam_name, dam_t *, mapp);
 		mutex_exit(&mapp->dam_lock);
 		return;
 	}
@@ -1410,39 +1431,24 @@
 	DAM_SET_STAT(mapp, dam_overrun, 0);
 	mapp->dam_stable_overrun = 0;
 
-	/*
-	 * copy the current active set to the stable map
-	 * for each address being reported, decrement its
-	 * stabilize deadline, and if stable, add or remove the
-	 * address from the stable set
-	 */
-	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
+	/* See if any reports stabalized and compute next timeout. */
 	ts = ddi_get_lbolt64();
 	next_ticks = mapp->dam_stable_ticks;
 	for (i = 1; i < mapp->dam_high; i++) {
-		if (!bitset_in_set(&mapp->dam_report_set, i))
-			continue;
-		passp = ddi_get_soft_state(mapp->dam_da, i);
-		ASSERT(passp);
+		if (bitset_in_set(&mapp->dam_report_set, i)) {
+			passp = ddi_get_soft_state(mapp->dam_da, i);
+			ASSERT(passp);
 
-		/* report has stabilized */
-		if (passp->da_deadline <= ts) {
-			bitset_del(&mapp->dam_report_set, i);
-			if (passp->da_flags & DA_RELE)
-				bitset_del(&mapp->dam_stable_set, i);
-			else
-				bitset_add(&mapp->dam_stable_set, i);
-			spend++;
-			continue;
+			if (passp->da_deadline <= ts)
+				spend++;	/* report has stabilized */
+			else {
+				/* not stabilized, determine next map timeout */
+				tpend++;
+				delta_ticks = passp->da_deadline - ts;
+				if (delta_ticks < next_ticks)
+					next_ticks = delta_ticks;
+			}
 		}
-
-		/*
-		 * not stabilized, determine next map timeout
-		 */
-		tpend++;
-		delta_ticks = passp->da_deadline - ts;
-		if (delta_ticks < next_ticks)
-			next_ticks = delta_ticks;
 	}
 
 	/*
@@ -1451,16 +1457,52 @@
 	if (spend) {
 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
+			DTRACE_PROBE2(damap__map__addr__stable__start,
+			    char *, mapp->dam_name, dam_t *, mapp);
+
+			/*
+			 * The stable_set we compute below stays pending until
+			 * processed by dam_stabilize_map. We can't set
+			 * DAM_SPEND (or bitset_del things from the
+			 * report_set) until we *know* that we can handoff the
+			 * result to dam_stabilize_map. If dam_stabilize_map
+			 * starts executing before we are complete, it will
+			 * block on the dam_lock mutex until we are ready.
+			 */
 			mapp->dam_flags |= DAM_SPEND;
-			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
-			    mapp->dam_name, dam_t *, mapp);
+
+			/*
+			 * Copy the current active_set to the stable_set, then
+			 * add or remove stabilized report_set address from
+			 * the stable set (and delete them from the report_set).
+			 */
+			bitset_copy(&mapp->dam_active_set,
+			    &mapp->dam_stable_set);
+			for (i = 1; i < mapp->dam_high; i++) {
+				if (!bitset_in_set(&mapp->dam_report_set, i))
+					continue;
+
+				passp = ddi_get_soft_state(mapp->dam_da, i);
+				if (passp->da_deadline > ts)
+					continue; /* report not stabilized */
+
+				/* report has stabilized */
+				if (passp->da_flags & DA_RELE)
+					bitset_del(&mapp->dam_stable_set, i);
+				else
+					bitset_add(&mapp->dam_stable_set, i);
+
+				bitset_del(&mapp->dam_report_set, i);
+			}
 		} else {
-			tpend++;
+			DTRACE_PROBE2(damap__map__addr__stable__spendfail,
+			    char *, mapp->dam_name, dam_t *, mapp);
 
 			/*
 			 * Avoid waiting the entire stabalization
 			 * time again if taskq_diskpatch fails.
 			 */
+			tpend++;
 			delta_ticks = drv_usectohz(
 			    damap_taskq_dispatch_retry_usec);
 			if (delta_ticks < next_ticks)
@@ -1472,9 +1514,12 @@
 	 * reschedule the stabilization timer if there are reports
 	 * still pending
 	 */
-	if (tpend)
+	if (tpend) {
+		DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
+		    mapp->dam_name, dam_t *, mapp);
 		dam_sched_timeout(dam_addr_stable_cb, mapp,
 		    (clock_t)next_ticks);
+	}
 
 	mutex_exit(&mapp->dam_lock);
 }
@@ -1509,8 +1554,8 @@
 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
 		    drv_usectohz(damap_taskq_dispatch_retry_usec));
 
-		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
-		    mapp->dam_name, dam_t *, mapp);
+		DTRACE_PROBE2(damap__map__addrset__stable__overrun,
+		    char *, mapp->dam_name, dam_t *, mapp);
 		mutex_exit(&mapp->dam_lock);
 		return;
 	}
@@ -1523,8 +1568,8 @@
 	mapp->dam_flags &= ~DAM_SETADD;
 	/* NOTE: don't need cv_signal since DAM_SPEND is still set */
 
-	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
-	    mapp->dam_name, dam_t *, mapp);
+	DTRACE_PROBE2(damap__map__addrset__stable__start,
+	    char *, mapp->dam_name, dam_t *, mapp);
 	mutex_exit(&mapp->dam_lock);
 }
 
@@ -1537,8 +1582,9 @@
 {
 	timeout_id_t tid;
 
-	DTRACE_PROBE3(damap__sched__timeout, char *, mapp->dam_name,
-	    dam_t *, mapp, int, ticks);
+	DTRACE_PROBE4(damap__sched__timeout,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    int, ticks, timeout_id_t, mapp->dam_tid);
 
 	ASSERT(mutex_owned(&mapp->dam_lock));
 	if ((tid = mapp->dam_tid) != 0) {
@@ -1562,8 +1608,9 @@
 {
 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
 
-	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp, int, rpt_type);
+	DTRACE_PROBE4(damap__addr__report,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr, int, rpt_type);
 
 	ASSERT(mutex_owned(&mapp->dam_lock));
 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
@@ -1588,8 +1635,9 @@
 	dam_da_t *passp;
 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
 
-	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
-	    char *, addrstr, dam_t *, mapp);
+	DTRACE_PROBE3(damap__addr__report__release,
+	    char *, mapp->dam_name, dam_t *, mapp,
+	    char *, addrstr);
 
 	ASSERT(mutex_owned(&mapp->dam_lock));
 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
--- a/usr/src/uts/common/os/instance.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/os/instance.c	Thu May 13 12:39:32 2010 -0600
@@ -747,6 +747,12 @@
 		prev = dp->ind_instance;
 	}
 
+	/* Don't return anything in the preassign area. */
+	if (prev < dnp->dn_pinstance) {
+		prev = dnp->dn_pinstance - 1;
+		hole++;			/* preassign hole */
+	}
+
 	/*
 	 * If hole is zero then all holes are patched and we can resume
 	 * quick allocations.
--- a/usr/src/uts/common/os/sunmdi.c	Thu May 13 11:20:37 2010 -0700
+++ b/usr/src/uts/common/os/sunmdi.c	Thu May 13 12:39:32 2010 -0600
@@ -1828,7 +1828,7 @@
 	 * checks again.
 	 */
 	if ((MDI_CLIENT_IS_DETACHED(ct)) || (MDI_CLIENT_IS_FAILED(ct)) ||
-	    (!i_ddi_devi_attached(ct->ct_dip))) {
+	    (!i_ddi_devi_attached(cdip))) {
 		/*
 		 * Client is in failed state. Nothing more to do.
 		 */
@@ -6046,7 +6046,7 @@
 	case DDI_DETACH:
 		MDI_DEBUG(2, (MDI_NOTE, dip,
 		    "client post_detach: called %p", (void *)ct));
-		if (DEVI_IS_ATTACHING(ct->ct_dip)) {
+		if (DEVI_IS_ATTACHING(dip)) {
 			MDI_DEBUG(4, (MDI_NOTE, dip,
 			    "i_mdi_pm_rele_client\n"));
 			i_mdi_pm_rele_client(ct, ct->ct_path_count);
@@ -6912,7 +6912,7 @@
 	while (MDI_CLIENT_IS_POWER_TRANSITION(ct))
 		cv_wait(&ct->ct_powerchange_cv, &ct->ct_mutex);
 
-	if (!i_ddi_devi_attached(ct->ct_dip)) {
+	if (!i_ddi_devi_attached(child)) {
 		MDI_DEBUG(4, (MDI_NOTE, child, "node detached already\n"));
 		MDI_CLIENT_UNLOCK(ct);
 		return (MDI_SUCCESS);
@@ -7007,9 +7007,9 @@
 
 	/* another thread might have powered it down or detached it */
 	if ((MDI_CLIENT_IS_POWERED_DOWN(ct) &&
-	    !DEVI_IS_ATTACHING(ct->ct_dip)) ||
-	    (!i_ddi_devi_attached(ct->ct_dip) &&
-	    !DEVI_IS_ATTACHING(ct->ct_dip))) {
+	    !DEVI_IS_ATTACHING(child)) ||
+	    (!i_ddi_devi_attached(child) &&
+	    !DEVI_IS_ATTACHING(child))) {
 		MDI_DEBUG(4, (MDI_NOTE, child, "i_mdi_pm_reset_client\n"));
 		i_mdi_pm_reset_client(ct);
 	} else {
@@ -7080,9 +7080,9 @@
 
 	/* failure detaching or another thread just attached it */
 	if ((MDI_CLIENT_IS_POWERED_DOWN(ct) &&
-	    i_ddi_devi_attached(ct->ct_dip)) ||
-	    (!i_ddi_devi_attached(ct->ct_dip) &&
-	    !DEVI_IS_ATTACHING(ct->ct_dip))) {
+	    i_ddi_devi_attached(child)) ||
+	    (!i_ddi_devi_attached(child) &&
+	    !DEVI_IS_ATTACHING(child))) {
 		MDI_DEBUG(4, (MDI_NOTE, child, "i_mdi_pm_reset_client\n"));
 		i_mdi_pm_reset_client(ct);
 	} else {
@@ -7194,7 +7194,7 @@
 				i_mdi_pm_hold_client(ct, ct->ct_path_count);
 			}
 		} else {
-			if (DEVI_IS_ATTACHING(ct->ct_dip)) {
+			if (DEVI_IS_ATTACHING(client_dip)) {
 				MDI_DEBUG(4, (MDI_NOTE, client_dip,
 				    "i_mdi_pm_rele_client\n"));
 				i_mdi_pm_rele_client(ct, ct->ct_path_count);