xref: /onnv-gate/usr/src/uts/common/os/damap.c (revision 12000:19ca97e58197)
110696SDavid.Hollister@Sun.COM /*
210696SDavid.Hollister@Sun.COM  * CDDL HEADER START
310696SDavid.Hollister@Sun.COM  *
410696SDavid.Hollister@Sun.COM  * The contents of this file are subject to the terms of the
510696SDavid.Hollister@Sun.COM  * Common Development and Distribution License (the "License").
610696SDavid.Hollister@Sun.COM  * You may not use this file except in compliance with the License.
710696SDavid.Hollister@Sun.COM  *
810696SDavid.Hollister@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910696SDavid.Hollister@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010696SDavid.Hollister@Sun.COM  * See the License for the specific language governing permissions
1110696SDavid.Hollister@Sun.COM  * and limitations under the License.
1210696SDavid.Hollister@Sun.COM  *
1310696SDavid.Hollister@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410696SDavid.Hollister@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510696SDavid.Hollister@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610696SDavid.Hollister@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710696SDavid.Hollister@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810696SDavid.Hollister@Sun.COM  *
1910696SDavid.Hollister@Sun.COM  * CDDL HEADER END
2010696SDavid.Hollister@Sun.COM  */
2110696SDavid.Hollister@Sun.COM 
2210696SDavid.Hollister@Sun.COM /*
2311601SDavid.Hollister@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2410696SDavid.Hollister@Sun.COM  * Use is subject to license terms.
2510696SDavid.Hollister@Sun.COM  */
2610696SDavid.Hollister@Sun.COM 
2710696SDavid.Hollister@Sun.COM #include <sys/note.h>
2810696SDavid.Hollister@Sun.COM #include <sys/types.h>
2910696SDavid.Hollister@Sun.COM #include <sys/param.h>
3010696SDavid.Hollister@Sun.COM #include <sys/systm.h>
3110696SDavid.Hollister@Sun.COM #include <sys/buf.h>
3210696SDavid.Hollister@Sun.COM #include <sys/kmem.h>
3310696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h>
3410696SDavid.Hollister@Sun.COM #include <sys/debug.h>
3510696SDavid.Hollister@Sun.COM #include <sys/sunndi.h>
3610696SDavid.Hollister@Sun.COM #include <sys/kstat.h>
3710696SDavid.Hollister@Sun.COM #include <sys/conf.h>
3810696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h>
3910696SDavid.Hollister@Sun.COM #include <sys/devctl.h>
4010696SDavid.Hollister@Sun.COM #include <sys/callb.h>
4110696SDavid.Hollister@Sun.COM #include <sys/sysevent.h>
4210696SDavid.Hollister@Sun.COM #include <sys/taskq.h>
4310696SDavid.Hollister@Sun.COM #include <sys/ddi.h>
4410696SDavid.Hollister@Sun.COM #include <sys/bitset.h>
4510696SDavid.Hollister@Sun.COM #include <sys/damap.h>
4610696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h>
4710696SDavid.Hollister@Sun.COM 
4810696SDavid.Hollister@Sun.COM #ifdef DEBUG
4910696SDavid.Hollister@Sun.COM static int damap_debug = 0;
5010696SDavid.Hollister@Sun.COM #endif /* DEBUG */
5110696SDavid.Hollister@Sun.COM 
5211068SJohn.Danielson@Sun.COM extern taskq_t *system_taskq;
5311068SJohn.Danielson@Sun.COM 
5410696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *);
5511068SJohn.Danielson@Sun.COM static void dam_addrset_deactivate(dam_t *, bitset_t *);
5611068SJohn.Danielson@Sun.COM static void dam_stabilize_map(void *);
5710696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *);
5811068SJohn.Danielson@Sun.COM static void dam_addrset_stable_cb(void *);
5910696SDavid.Hollister@Sun.COM static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)());
6011068SJohn.Danielson@Sun.COM static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
6111068SJohn.Danielson@Sun.COM static void dam_addr_release(dam_t *, id_t);
6211068SJohn.Danielson@Sun.COM static void dam_addr_report_release(dam_t *, id_t);
6311068SJohn.Danielson@Sun.COM static void dam_addr_deactivate(dam_t *, id_t);
6411363SReed.Liu@Sun.COM static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
6510696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *);
6610696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *);
6711068SJohn.Danielson@Sun.COM static int dam_map_alloc(dam_t *);
6810696SDavid.Hollister@Sun.COM 
6910696SDavid.Hollister@Sun.COM #define	DAM_INCR_STAT(mapp, stat)				\
7010696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
7110696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
7210696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32++;				\
7310696SDavid.Hollister@Sun.COM 	}
7410696SDavid.Hollister@Sun.COM 
7510696SDavid.Hollister@Sun.COM #define	DAM_SET_STAT(mapp, stat, val)				\
7610696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
7710696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
7810696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32 = (val);			\
7910696SDavid.Hollister@Sun.COM 	}
8010696SDavid.Hollister@Sun.COM 
8111068SJohn.Danielson@Sun.COM 
8211068SJohn.Danielson@Sun.COM /*
8311068SJohn.Danielson@Sun.COM  * increase damap size by 64 entries at a time
8411068SJohn.Danielson@Sun.COM  */
8511068SJohn.Danielson@Sun.COM #define	DAM_SIZE_BUMP	64
8611068SJohn.Danielson@Sun.COM 
8711854SChris.Horne@Sun.COM int	damap_taskq_dispatch_retry_usec = 1000;
8811854SChris.Horne@Sun.COM 
8911068SJohn.Danielson@Sun.COM /*
9011068SJohn.Danielson@Sun.COM  * config/unconfig taskq data
9111068SJohn.Danielson@Sun.COM  */
9211068SJohn.Danielson@Sun.COM typedef struct {
9311068SJohn.Danielson@Sun.COM 	dam_t *tqd_mapp;
9411068SJohn.Danielson@Sun.COM 	id_t tqd_id;
9511068SJohn.Danielson@Sun.COM } cfg_tqd_t;
9611068SJohn.Danielson@Sun.COM 
9711068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri;
9811068SJohn.Danielson@Sun.COM 
9910696SDavid.Hollister@Sun.COM /*
10010696SDavid.Hollister@Sun.COM  * Create new device address map
10110696SDavid.Hollister@Sun.COM  *
10211068SJohn.Danielson@Sun.COM  * name:		map name (kstat unique)
10310696SDavid.Hollister@Sun.COM  * size:		max # of map entries
10411068SJohn.Danielson@Sun.COM  * mode:		style of address reports: per-address or fullset
10510696SDavid.Hollister@Sun.COM  * stable_usec:		# of quiescent microseconds before report/map is stable
10610696SDavid.Hollister@Sun.COM  *
10710696SDavid.Hollister@Sun.COM  * activate_arg:	address provider activation-callout private
10810696SDavid.Hollister@Sun.COM  * activate_cb:		address provider activation callback handler
10910696SDavid.Hollister@Sun.COM  * deactivate_cb:	address provider deactivation callback handler
11010696SDavid.Hollister@Sun.COM  *
11110696SDavid.Hollister@Sun.COM  * config_arg:		configuration-callout private
11210696SDavid.Hollister@Sun.COM  * config_cb:		class configuration callout
11310696SDavid.Hollister@Sun.COM  * unconfig_cb:		class unconfiguration callout
11410696SDavid.Hollister@Sun.COM  *
11510696SDavid.Hollister@Sun.COM  * damapp:		pointer to map handle (return)
11610696SDavid.Hollister@Sun.COM  *
11710696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
11810696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
11910696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
12010696SDavid.Hollister@Sun.COM  */
12110696SDavid.Hollister@Sun.COM int
12211068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts,
12311068SJohn.Danielson@Sun.COM     clock_t stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
12410696SDavid.Hollister@Sun.COM     damap_deactivate_cb_t deactivate_cb,
12510696SDavid.Hollister@Sun.COM     void *config_arg, damap_configure_cb_t configure_cb,
12610696SDavid.Hollister@Sun.COM     damap_unconfig_cb_t unconfig_cb,
12710696SDavid.Hollister@Sun.COM     damap_t **damapp)
12810696SDavid.Hollister@Sun.COM {
12910696SDavid.Hollister@Sun.COM 	dam_t *mapp;
13010696SDavid.Hollister@Sun.COM 
13111068SJohn.Danielson@Sun.COM 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
13210696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
13310696SDavid.Hollister@Sun.COM 
13411068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__create, char *, name,
13511068SJohn.Danielson@Sun.COM 	    damap_rptmode_t, mode, clock_t, stable_usec);
13610696SDavid.Hollister@Sun.COM 
13710696SDavid.Hollister@Sun.COM 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
13811068SJohn.Danielson@Sun.COM 	mapp->dam_options = map_opts;
13910696SDavid.Hollister@Sun.COM 	mapp->dam_stabletmo = drv_usectohz(stable_usec);
14011068SJohn.Danielson@Sun.COM 	mapp->dam_size = 0;
14111068SJohn.Danielson@Sun.COM 	mapp->dam_rptmode = mode;
14210696SDavid.Hollister@Sun.COM 	mapp->dam_activate_arg = activate_arg;
14310696SDavid.Hollister@Sun.COM 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
14410696SDavid.Hollister@Sun.COM 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
14510696SDavid.Hollister@Sun.COM 	mapp->dam_config_arg = config_arg;
14610696SDavid.Hollister@Sun.COM 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
14710696SDavid.Hollister@Sun.COM 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
14811068SJohn.Danielson@Sun.COM 	mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
14910696SDavid.Hollister@Sun.COM 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
15010696SDavid.Hollister@Sun.COM 	cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL);
15111068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_active_set);
15211068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_stable_set);
15311068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_report_set);
15410696SDavid.Hollister@Sun.COM 	*damapp = (damap_t *)mapp;
15510696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
15610696SDavid.Hollister@Sun.COM }
15710696SDavid.Hollister@Sun.COM 
15810696SDavid.Hollister@Sun.COM /*
15911068SJohn.Danielson@Sun.COM  * Allocate backing resources
16011068SJohn.Danielson@Sun.COM  *
16111068SJohn.Danielson@Sun.COM  * DAMs are lightly backed on create - major allocations occur
16211068SJohn.Danielson@Sun.COM  * at the time a report is made to the map, and are extended on
16311068SJohn.Danielson@Sun.COM  * a demand basis.
16411068SJohn.Danielson@Sun.COM  */
16511068SJohn.Danielson@Sun.COM static int
16611068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp)
16711068SJohn.Danielson@Sun.COM {
16811068SJohn.Danielson@Sun.COM 	void *softstate_p;
16911068SJohn.Danielson@Sun.COM 
17011068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
17111068SJohn.Danielson@Sun.COM 	if (mapp->dam_flags & DAM_DESTROYPEND)
17211068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
17311068SJohn.Danielson@Sun.COM 
17411068SJohn.Danielson@Sun.COM 	/*
17511068SJohn.Danielson@Sun.COM 	 * dam_high > 0 signals map allocation complete
17611068SJohn.Danielson@Sun.COM 	 */
17711068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
17811068SJohn.Danielson@Sun.COM 		return (DAM_SUCCESS);
17911068SJohn.Danielson@Sun.COM 
18011068SJohn.Danielson@Sun.COM 	mapp->dam_size = DAM_SIZE_BUMP;
18111068SJohn.Danielson@Sun.COM 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
18211068SJohn.Danielson@Sun.COM 	    mapp->dam_size) != DDI_SUCCESS)
18311068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18411068SJohn.Danielson@Sun.COM 
18511068SJohn.Danielson@Sun.COM 	if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
18611068SJohn.Danielson@Sun.COM 	    DDI_SUCCESS) {
18711068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
18811068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18911068SJohn.Danielson@Sun.COM 	}
19011068SJohn.Danielson@Sun.COM 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
19111068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
19211068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
19311068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
19411068SJohn.Danielson@Sun.COM 	}
19511068SJohn.Danielson@Sun.COM 	mapp->dam_da = softstate_p;
19611068SJohn.Danielson@Sun.COM 	mapp->dam_high = 1;
19711068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_active_set, mapp->dam_size);
19811068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
19911068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_report_set, mapp->dam_size);
20011068SJohn.Danielson@Sun.COM 	return (DAM_SUCCESS);
20111068SJohn.Danielson@Sun.COM }
20211068SJohn.Danielson@Sun.COM 
20311068SJohn.Danielson@Sun.COM /*
20411068SJohn.Danielson@Sun.COM  * Destroy address map
20510696SDavid.Hollister@Sun.COM  *
20610696SDavid.Hollister@Sun.COM  * damapp:	address map
20710696SDavid.Hollister@Sun.COM  *
20810696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
20910696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
21010696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
21110696SDavid.Hollister@Sun.COM  */
21210696SDavid.Hollister@Sun.COM void
21310696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp)
21410696SDavid.Hollister@Sun.COM {
21510696SDavid.Hollister@Sun.COM 	int i;
21610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
21710696SDavid.Hollister@Sun.COM 
21810696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
21910696SDavid.Hollister@Sun.COM 
22011068SJohn.Danielson@Sun.COM 	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
22110696SDavid.Hollister@Sun.COM 
22211068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
22310696SDavid.Hollister@Sun.COM 
22410696SDavid.Hollister@Sun.COM 	/*
22511068SJohn.Danielson@Sun.COM 	 * prevent new reports from being added to the map
22610696SDavid.Hollister@Sun.COM 	 */
22711068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_DESTROYPEND;
22811068SJohn.Danielson@Sun.COM 
22911068SJohn.Danielson@Sun.COM 	if (mapp->dam_high) {
23011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
23111068SJohn.Danielson@Sun.COM 		/*
23211068SJohn.Danielson@Sun.COM 		 * wait for outstanding reports to stabilize and cancel
23311068SJohn.Danielson@Sun.COM 		 * the timer for this map
23411068SJohn.Danielson@Sun.COM 		 */
23511068SJohn.Danielson@Sun.COM 		(void) damap_sync(damapp);
23611068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
23711068SJohn.Danielson@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
23810696SDavid.Hollister@Sun.COM 
23911068SJohn.Danielson@Sun.COM 		/*
24011068SJohn.Danielson@Sun.COM 		 * map is at full stop
24111068SJohn.Danielson@Sun.COM 		 * release the contents of the map, invoking the
24211068SJohn.Danielson@Sun.COM 		 * detactivation protocol as addresses are released
24311068SJohn.Danielson@Sun.COM 		 */
24411068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
24511068SJohn.Danielson@Sun.COM 		for (i = 1; i < mapp->dam_high; i++) {
24611068SJohn.Danielson@Sun.COM 			if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
24711068SJohn.Danielson@Sun.COM 				continue;
24811068SJohn.Danielson@Sun.COM 
24911068SJohn.Danielson@Sun.COM 			ASSERT(DAM_IN_REPORT(mapp, i) == 0);
25011068SJohn.Danielson@Sun.COM 
25111068SJohn.Danielson@Sun.COM 			if (DAM_IS_STABLE(mapp, i)) {
25211068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
25311068SJohn.Danielson@Sun.COM 			} else {
25411068SJohn.Danielson@Sun.COM 				ddi_strid_free(mapp->dam_addr_hash, i);
25511068SJohn.Danielson@Sun.COM 				ddi_soft_state_free(mapp->dam_da, i);
25611068SJohn.Danielson@Sun.COM 			}
25711068SJohn.Danielson@Sun.COM 		}
25811068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
25911068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(&mapp->dam_da);
26011068SJohn.Danielson@Sun.COM 		kstat_delete(mapp->dam_kstatsp);
26110696SDavid.Hollister@Sun.COM 	}
26210696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_active_set);
26310696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_stable_set);
26410696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_report_set);
26510696SDavid.Hollister@Sun.COM 	mutex_destroy(&mapp->dam_lock);
26610696SDavid.Hollister@Sun.COM 	cv_destroy(&mapp->dam_cv);
26710696SDavid.Hollister@Sun.COM 	if (mapp->dam_name)
26810696SDavid.Hollister@Sun.COM 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
26910696SDavid.Hollister@Sun.COM 	kmem_free(mapp, sizeof (*mapp));
27010696SDavid.Hollister@Sun.COM }
27110696SDavid.Hollister@Sun.COM 
27210696SDavid.Hollister@Sun.COM /*
27310696SDavid.Hollister@Sun.COM  * Wait for map stability.
27410696SDavid.Hollister@Sun.COM  *
27510696SDavid.Hollister@Sun.COM  * damapp:	address map
27610696SDavid.Hollister@Sun.COM  */
27710696SDavid.Hollister@Sun.COM int
27810696SDavid.Hollister@Sun.COM damap_sync(damap_t *damapp)
27910696SDavid.Hollister@Sun.COM {
28011068SJohn.Danielson@Sun.COM #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
28110696SDavid.Hollister@Sun.COM 
28210696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
28310696SDavid.Hollister@Sun.COM 	int   none_active;
28410696SDavid.Hollister@Sun.COM 
28510696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
28610696SDavid.Hollister@Sun.COM 
28711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
28811068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
28910696SDavid.Hollister@Sun.COM 
29011068SJohn.Danielson@Sun.COM 	/*
29111068SJohn.Danielson@Sun.COM 	 * block where waiting for
29211068SJohn.Danielson@Sun.COM 	 * a) stabilization pending or a fullset update pending
29311068SJohn.Danielson@Sun.COM 	 * b) any scheduled timeouts to fire
29411068SJohn.Danielson@Sun.COM 	 * c) the report set to finalize (bitset is null)
29511068SJohn.Danielson@Sun.COM 	 */
29610696SDavid.Hollister@Sun.COM 	mutex_enter(&mapp->dam_lock);
29710696SDavid.Hollister@Sun.COM 	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
29810696SDavid.Hollister@Sun.COM 	    (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) {
29911068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
30011068SJohn.Danielson@Sun.COM 		    dam_t *, mapp);
30110696SDavid.Hollister@Sun.COM 		cv_wait(&mapp->dam_cv, &mapp->dam_lock);
30210696SDavid.Hollister@Sun.COM 	}
30310696SDavid.Hollister@Sun.COM 
30410696SDavid.Hollister@Sun.COM 	none_active = bitset_is_null(&mapp->dam_active_set);
30510696SDavid.Hollister@Sun.COM 
30610696SDavid.Hollister@Sun.COM 	mutex_exit(&mapp->dam_lock);
30711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, int,
30811068SJohn.Danielson@Sun.COM 	    none_active, dam_t *, mapp);
30910696SDavid.Hollister@Sun.COM 
31010696SDavid.Hollister@Sun.COM 	return (none_active);
31110696SDavid.Hollister@Sun.COM }
31210696SDavid.Hollister@Sun.COM 
31310696SDavid.Hollister@Sun.COM /*
31410696SDavid.Hollister@Sun.COM  * Get the name of a device address map
31510696SDavid.Hollister@Sun.COM  *
31610696SDavid.Hollister@Sun.COM  * damapp:	address map
31710696SDavid.Hollister@Sun.COM  *
31810696SDavid.Hollister@Sun.COM  * Returns:	name
31910696SDavid.Hollister@Sun.COM  */
32010696SDavid.Hollister@Sun.COM char *
32110696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp)
32210696SDavid.Hollister@Sun.COM {
32310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
32410696SDavid.Hollister@Sun.COM 
32510696SDavid.Hollister@Sun.COM 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
32610696SDavid.Hollister@Sun.COM }
32710696SDavid.Hollister@Sun.COM 
32810696SDavid.Hollister@Sun.COM /*
32910696SDavid.Hollister@Sun.COM  * Report an address to per-address report
33010696SDavid.Hollister@Sun.COM  *
33110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
33210696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
33311068SJohn.Danielson@Sun.COM  * addridp:	address ID
33410696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
33510696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
33610696SDavid.Hollister@Sun.COM  *
33710696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
33810696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
33910696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
34010696SDavid.Hollister@Sun.COM  */
34110696SDavid.Hollister@Sun.COM int
34211068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
34311068SJohn.Danielson@Sun.COM     nvlist_t *nvl, void *addr_priv)
34410696SDavid.Hollister@Sun.COM {
34510696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
34610696SDavid.Hollister@Sun.COM 	id_t addrid;
34710696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
34810696SDavid.Hollister@Sun.COM 
34911068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
35010696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
35110696SDavid.Hollister@Sun.COM 
35211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name,
35311068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
35411068SJohn.Danielson@Sun.COM 
35511068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
35611068SJohn.Danielson@Sun.COM 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
35711068SJohn.Danielson@Sun.COM 	    ((addrid = dam_get_addrid(mapp, address)) == 0)) {
35811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
35910696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
36010696SDavid.Hollister@Sun.COM 	}
36110696SDavid.Hollister@Sun.COM 
36210696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
36310696SDavid.Hollister@Sun.COM 	ASSERT(passp != NULL);
36410696SDavid.Hollister@Sun.COM 
36510696SDavid.Hollister@Sun.COM 	/*
36610696SDavid.Hollister@Sun.COM 	 * If re-reporting the same address (add or remove) clear
36710696SDavid.Hollister@Sun.COM 	 * the existing report
36810696SDavid.Hollister@Sun.COM 	 */
36910696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
37011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
37111068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
37211068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
37311068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
37410696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
37510696SDavid.Hollister@Sun.COM 	}
37610696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
37710696SDavid.Hollister@Sun.COM 	if (nvl)
37810696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
37910696SDavid.Hollister@Sun.COM 
38011068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
38111068SJohn.Danielson@Sun.COM 	if (addridp != NULL)
38211068SJohn.Danielson@Sun.COM 		*addridp = (damap_id_t)addrid;
38311068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
38410696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
38510696SDavid.Hollister@Sun.COM }
38610696SDavid.Hollister@Sun.COM 
38710696SDavid.Hollister@Sun.COM /*
38810696SDavid.Hollister@Sun.COM  * Report removal of address from per-address report
38910696SDavid.Hollister@Sun.COM  *
39010696SDavid.Hollister@Sun.COM  * damapp:	address map
39110696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
39210696SDavid.Hollister@Sun.COM  *
39310696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
39410696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
39510696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
39610696SDavid.Hollister@Sun.COM  */
39710696SDavid.Hollister@Sun.COM int
39810696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address)
39910696SDavid.Hollister@Sun.COM {
40010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
40110696SDavid.Hollister@Sun.COM 	id_t addrid;
40210696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
40310696SDavid.Hollister@Sun.COM 
40411068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
40510696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
40610696SDavid.Hollister@Sun.COM 
40711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
40811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
40911068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
41011068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
41111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
41211068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
41311068SJohn.Danielson@Sun.COM 	}
41411068SJohn.Danielson@Sun.COM 
41511068SJohn.Danielson@Sun.COM 	/*
41611068SJohn.Danielson@Sun.COM 	 * if reporting the removal of an address which is not in the map
41711068SJohn.Danielson@Sun.COM 	 * return success
41811068SJohn.Danielson@Sun.COM 	 */
41910696SDavid.Hollister@Sun.COM 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
42011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
42110696SDavid.Hollister@Sun.COM 		return (DAM_SUCCESS);
42210696SDavid.Hollister@Sun.COM 	}
42310696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
42410696SDavid.Hollister@Sun.COM 	ASSERT(passp);
42510696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
42611068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
42711068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
42811068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
42911068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
43010696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
43110696SDavid.Hollister@Sun.COM 	}
43211068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
43311068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
43410696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
43510696SDavid.Hollister@Sun.COM }
43610696SDavid.Hollister@Sun.COM 
437*12000SReed.Liu@Sun.COM static int
438*12000SReed.Liu@Sun.COM damap_addrset_flush_locked(damap_t *damapp)
439*12000SReed.Liu@Sun.COM {
440*12000SReed.Liu@Sun.COM 	dam_t   *mapp = (dam_t *)damapp;
441*12000SReed.Liu@Sun.COM 	int	idx;
442*12000SReed.Liu@Sun.COM 
443*12000SReed.Liu@Sun.COM 	ASSERT(mapp);
444*12000SReed.Liu@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
445*12000SReed.Liu@Sun.COM 	if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
446*12000SReed.Liu@Sun.COM 		return (DAM_EINVAL);
447*12000SReed.Liu@Sun.COM 	}
448*12000SReed.Liu@Sun.COM 
449*12000SReed.Liu@Sun.COM 	DTRACE_PROBE2(damap__addrset__flush__locked__enter, char *,
450*12000SReed.Liu@Sun.COM 	    mapp->dam_name, dam_t *, mapp);
451*12000SReed.Liu@Sun.COM 	if (mapp->dam_flags & DAM_SETADD) {
452*12000SReed.Liu@Sun.COM 		DTRACE_PROBE2(damap__addrset__flush__locked__reset, char *,
453*12000SReed.Liu@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
454*12000SReed.Liu@Sun.COM 
455*12000SReed.Liu@Sun.COM 		/*
456*12000SReed.Liu@Sun.COM 		 * cancel stabilization timeout
457*12000SReed.Liu@Sun.COM 		 */
458*12000SReed.Liu@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
459*12000SReed.Liu@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
460*12000SReed.Liu@Sun.COM 
461*12000SReed.Liu@Sun.COM 		/*
462*12000SReed.Liu@Sun.COM 		 * clear pending reports
463*12000SReed.Liu@Sun.COM 		 */
464*12000SReed.Liu@Sun.COM 		for (idx = 1; idx < mapp->dam_high; idx++) {
465*12000SReed.Liu@Sun.COM 			if (DAM_IN_REPORT(mapp, idx)) {
466*12000SReed.Liu@Sun.COM 				dam_addr_report_release(mapp, idx);
467*12000SReed.Liu@Sun.COM 			}
468*12000SReed.Liu@Sun.COM 		}
469*12000SReed.Liu@Sun.COM 
470*12000SReed.Liu@Sun.COM 		bitset_zero(&mapp->dam_report_set);
471*12000SReed.Liu@Sun.COM 		mapp->dam_flags &= ~DAM_SETADD;
472*12000SReed.Liu@Sun.COM 	}
473*12000SReed.Liu@Sun.COM 
474*12000SReed.Liu@Sun.COM 	return (DAM_SUCCESS);
475*12000SReed.Liu@Sun.COM }
476*12000SReed.Liu@Sun.COM 
47710696SDavid.Hollister@Sun.COM /*
47810696SDavid.Hollister@Sun.COM  * Initiate full-set report
47910696SDavid.Hollister@Sun.COM  *
48010696SDavid.Hollister@Sun.COM  * damapp:	address map
48110696SDavid.Hollister@Sun.COM  *
48210696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
48310696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
48410696SDavid.Hollister@Sun.COM  */
48510696SDavid.Hollister@Sun.COM int
48610696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp)
48710696SDavid.Hollister@Sun.COM {
488*12000SReed.Liu@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
489*12000SReed.Liu@Sun.COM 	int	rv;
49010696SDavid.Hollister@Sun.COM 
491*12000SReed.Liu@Sun.COM 	if (mapp == NULL) {
49210696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
493*12000SReed.Liu@Sun.COM 	}
49410696SDavid.Hollister@Sun.COM 
49511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
49611068SJohn.Danielson@Sun.COM 	    mapp);
497*12000SReed.Liu@Sun.COM 
49811068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
49911068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
50011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
501*12000SReed.Liu@Sun.COM 
50211068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
50311068SJohn.Danielson@Sun.COM 	}
504*12000SReed.Liu@Sun.COM 
505*12000SReed.Liu@Sun.COM 	rv = damap_addrset_flush_locked(damapp);
506*12000SReed.Liu@Sun.COM 	if (rv == DAM_SUCCESS) {
507*12000SReed.Liu@Sun.COM 		mapp->dam_flags |= DAM_SETADD;
508*12000SReed.Liu@Sun.COM 	}
509*12000SReed.Liu@Sun.COM 	mutex_exit(&mapp->dam_lock);
510*12000SReed.Liu@Sun.COM 
511*12000SReed.Liu@Sun.COM 	return (rv);
512*12000SReed.Liu@Sun.COM }
51311068SJohn.Danielson@Sun.COM 
514*12000SReed.Liu@Sun.COM /*
515*12000SReed.Liu@Sun.COM  * Cancel full-set report
516*12000SReed.Liu@Sun.COM  *
517*12000SReed.Liu@Sun.COM  * damapp:      address map
518*12000SReed.Liu@Sun.COM  *
519*12000SReed.Liu@Sun.COM  * Returns:     DAM_SUCCESS
520*12000SReed.Liu@Sun.COM  *	      DAM_EINVAL      Invalid argument(s)
521*12000SReed.Liu@Sun.COM  */
522*12000SReed.Liu@Sun.COM int
523*12000SReed.Liu@Sun.COM damap_addrset_flush(damap_t *damapp)
524*12000SReed.Liu@Sun.COM {
525*12000SReed.Liu@Sun.COM 	int	rv;
526*12000SReed.Liu@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
527*12000SReed.Liu@Sun.COM 
528*12000SReed.Liu@Sun.COM 	if (mapp == NULL) {
529*12000SReed.Liu@Sun.COM 		return (DAM_EINVAL);
53010696SDavid.Hollister@Sun.COM 	}
531*12000SReed.Liu@Sun.COM 
532*12000SReed.Liu@Sun.COM 	DTRACE_PROBE2(damap__addrset__flush, char *, mapp->dam_name,
533*12000SReed.Liu@Sun.COM 	    dam_t *, mapp);
534*12000SReed.Liu@Sun.COM 
535*12000SReed.Liu@Sun.COM 	mutex_enter(&mapp->dam_lock);
536*12000SReed.Liu@Sun.COM 	rv = damap_addrset_flush_locked(damapp);
53711068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
538*12000SReed.Liu@Sun.COM 
539*12000SReed.Liu@Sun.COM 	return (rv);
54010696SDavid.Hollister@Sun.COM }
54110696SDavid.Hollister@Sun.COM 
54210696SDavid.Hollister@Sun.COM /*
54310696SDavid.Hollister@Sun.COM  * Report address to full-set report
54410696SDavid.Hollister@Sun.COM  *
54510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
54610696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
54710696SDavid.Hollister@Sun.COM  * rindx:	index if address stabilizes
54810696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
54910696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private data (passed to activate/release cb)
55010696SDavid.Hollister@Sun.COM  *
55110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
55210696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
55310696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
55410696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
55510696SDavid.Hollister@Sun.COM  */
55610696SDavid.Hollister@Sun.COM int
55710696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
55810696SDavid.Hollister@Sun.COM     nvlist_t *nvl, void *addr_priv)
55910696SDavid.Hollister@Sun.COM {
56010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
56110696SDavid.Hollister@Sun.COM 	id_t addrid;
56210696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
56310696SDavid.Hollister@Sun.COM 
56411068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
56510696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
56610696SDavid.Hollister@Sun.COM 
56711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
56811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
56910696SDavid.Hollister@Sun.COM 
57011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
57111068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
57211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
57311068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
57411068SJohn.Danielson@Sun.COM 	}
57511068SJohn.Danielson@Sun.COM 
57610696SDavid.Hollister@Sun.COM 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
57711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
57810696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
57910696SDavid.Hollister@Sun.COM 	}
58010696SDavid.Hollister@Sun.COM 
58110696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
58210696SDavid.Hollister@Sun.COM 	ASSERT(passp);
58310696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
58411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
58511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, char *, address, dam_t *, mapp);
58611068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
58710696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
58810696SDavid.Hollister@Sun.COM 	}
58910696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
59010696SDavid.Hollister@Sun.COM 	if (nvl)
59110696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
59210696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
59310696SDavid.Hollister@Sun.COM 	if (ridx)
59410696SDavid.Hollister@Sun.COM 		*ridx = (damap_id_t)addrid;
59511068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
59610696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
59710696SDavid.Hollister@Sun.COM }
59810696SDavid.Hollister@Sun.COM 
59910696SDavid.Hollister@Sun.COM /*
60010696SDavid.Hollister@Sun.COM  * Commit full-set report for stabilization
60110696SDavid.Hollister@Sun.COM  *
60210696SDavid.Hollister@Sun.COM  * damapp:	address map handle
60310696SDavid.Hollister@Sun.COM  * flags:	(currently 0)
60410696SDavid.Hollister@Sun.COM  *
60510696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
60610696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
60710696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
60810696SDavid.Hollister@Sun.COM  */
60910696SDavid.Hollister@Sun.COM int
61010696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags)
61110696SDavid.Hollister@Sun.COM {
61210696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
61310696SDavid.Hollister@Sun.COM 	int i;
61410696SDavid.Hollister@Sun.COM 
61511068SJohn.Danielson@Sun.COM 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
61610696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
61710696SDavid.Hollister@Sun.COM 
61811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
61911068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
62010696SDavid.Hollister@Sun.COM 
62111068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
62211068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
62311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
62411068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
62511068SJohn.Danielson@Sun.COM 	}
62611068SJohn.Danielson@Sun.COM 
62711068SJohn.Danielson@Sun.COM 	if (flags & DAMAP_END_RESET) {
62811068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
62911068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
63010696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
63110696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++)
63210696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
63311068SJohn.Danielson@Sun.COM 				dam_addr_report_release(mapp, i);
63410696SDavid.Hollister@Sun.COM 	} else {
63510696SDavid.Hollister@Sun.COM 		mapp->dam_last_update = gethrtime();
63611068SJohn.Danielson@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
63710696SDavid.Hollister@Sun.COM 	}
63811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
63910696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
64010696SDavid.Hollister@Sun.COM }
64110696SDavid.Hollister@Sun.COM 
64210696SDavid.Hollister@Sun.COM /*
64310696SDavid.Hollister@Sun.COM  * Return nvlist registered with reported address
64410696SDavid.Hollister@Sun.COM  *
64510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
64611068SJohn.Danielson@Sun.COM  * addrid:	address ID
64710696SDavid.Hollister@Sun.COM  *
64810696SDavid.Hollister@Sun.COM  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
64910696SDavid.Hollister@Sun.COM  *		NULL
65010696SDavid.Hollister@Sun.COM  */
65110696SDavid.Hollister@Sun.COM nvlist_t *
65210696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
65310696SDavid.Hollister@Sun.COM {
65410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
65510696SDavid.Hollister@Sun.COM 	dam_da_t *pass;
65610696SDavid.Hollister@Sun.COM 
65711068SJohn.Danielson@Sun.COM 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
65811068SJohn.Danielson@Sun.COM 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
65910696SDavid.Hollister@Sun.COM 			return (pass->da_nvl);
66010696SDavid.Hollister@Sun.COM 	}
66110696SDavid.Hollister@Sun.COM 	return (NULL);
66210696SDavid.Hollister@Sun.COM }
66310696SDavid.Hollister@Sun.COM 
66410696SDavid.Hollister@Sun.COM /*
66510696SDavid.Hollister@Sun.COM  * Return address string
66610696SDavid.Hollister@Sun.COM  *
66710696SDavid.Hollister@Sun.COM  * damapp:	address map handle
66811068SJohn.Danielson@Sun.COM  * addrid:	address ID
66910696SDavid.Hollister@Sun.COM  *
67010696SDavid.Hollister@Sun.COM  * Returns:	char *		Address string
67110696SDavid.Hollister@Sun.COM  *		NULL
67210696SDavid.Hollister@Sun.COM  */
67310696SDavid.Hollister@Sun.COM char *
67411068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid)
67510696SDavid.Hollister@Sun.COM {
67610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
67710696SDavid.Hollister@Sun.COM 
67811068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
67911068SJohn.Danielson@Sun.COM 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
68011068SJohn.Danielson@Sun.COM 	else
68111068SJohn.Danielson@Sun.COM 		return (NULL);
68210696SDavid.Hollister@Sun.COM }
68310696SDavid.Hollister@Sun.COM 
68410696SDavid.Hollister@Sun.COM /*
68510696SDavid.Hollister@Sun.COM  * Release address reference in map
68610696SDavid.Hollister@Sun.COM  *
68710696SDavid.Hollister@Sun.COM  * damapp:	address map handle
68811068SJohn.Danielson@Sun.COM  * addrid:	address ID
68910696SDavid.Hollister@Sun.COM  */
69010696SDavid.Hollister@Sun.COM void
69110696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid)
69210696SDavid.Hollister@Sun.COM {
69310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
69411068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
69511068SJohn.Danielson@Sun.COM 	char *addr;
69610696SDavid.Hollister@Sun.COM 
69711068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
69811068SJohn.Danielson@Sun.COM 	ASSERT(passp);
69911068SJohn.Danielson@Sun.COM 
70011068SJohn.Danielson@Sun.COM 	addr = damap_id2addr(damapp, addrid);
70111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
70211068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, passp->da_ref);
70311068SJohn.Danielson@Sun.COM 
70411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
70511068SJohn.Danielson@Sun.COM 
70611068SJohn.Danielson@Sun.COM 	/*
70711068SJohn.Danielson@Sun.COM 	 * teardown address if last outstanding reference
70811068SJohn.Danielson@Sun.COM 	 */
70911068SJohn.Danielson@Sun.COM 	if (--passp->da_ref == 0)
71011068SJohn.Danielson@Sun.COM 		dam_addr_release(mapp, (id_t)addrid);
71111068SJohn.Danielson@Sun.COM 
71211068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
71310696SDavid.Hollister@Sun.COM }
71410696SDavid.Hollister@Sun.COM 
71510696SDavid.Hollister@Sun.COM /*
71610696SDavid.Hollister@Sun.COM  * Return current reference count on address reference in map
71710696SDavid.Hollister@Sun.COM  *
71810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
71911068SJohn.Danielson@Sun.COM  * addrid:	address ID
72010696SDavid.Hollister@Sun.COM  *
72110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
72210696SDavid.Hollister@Sun.COM  *		DAM_FAILURE
72310696SDavid.Hollister@Sun.COM  */
72410696SDavid.Hollister@Sun.COM int
72511068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid)
72610696SDavid.Hollister@Sun.COM {
72710696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
72810696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
72910696SDavid.Hollister@Sun.COM 	int ref = -1;
73010696SDavid.Hollister@Sun.COM 
73111068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
73210696SDavid.Hollister@Sun.COM 	if (passp)
73310696SDavid.Hollister@Sun.COM 		ref = passp->da_ref;
73411068SJohn.Danielson@Sun.COM 
73510696SDavid.Hollister@Sun.COM 	return (ref);
73610696SDavid.Hollister@Sun.COM }
73710696SDavid.Hollister@Sun.COM 
73810696SDavid.Hollister@Sun.COM /*
73910696SDavid.Hollister@Sun.COM  * Return next address ID in list
74010696SDavid.Hollister@Sun.COM  *
74110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
74210696SDavid.Hollister@Sun.COM  * damap_list:	address ID list passed to config|unconfig
74310696SDavid.Hollister@Sun.COM  *		returned by look by lookup_all
74410696SDavid.Hollister@Sun.COM  * last:	last ID returned, 0 is start of list
74510696SDavid.Hollister@Sun.COM  *
74610696SDavid.Hollister@Sun.COM  * Returns:	addrid		Next ID from the list
74710696SDavid.Hollister@Sun.COM  *		0		End of the list
74810696SDavid.Hollister@Sun.COM  */
74910696SDavid.Hollister@Sun.COM damap_id_t
75010696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
75110696SDavid.Hollister@Sun.COM {
75210696SDavid.Hollister@Sun.COM 	int i, start;
75310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
75410696SDavid.Hollister@Sun.COM 	bitset_t *dam_list = (bitset_t *)damap_list;
75510696SDavid.Hollister@Sun.COM 
75610696SDavid.Hollister@Sun.COM 	if (!mapp || !dam_list)
75710696SDavid.Hollister@Sun.COM 		return ((damap_id_t)0);
75810696SDavid.Hollister@Sun.COM 
75910696SDavid.Hollister@Sun.COM 	start = (int)last + 1;
76011068SJohn.Danielson@Sun.COM 	for (i = start; i < mapp->dam_high; i++) {
76111068SJohn.Danielson@Sun.COM 		if (bitset_in_set(dam_list, i)) {
76210696SDavid.Hollister@Sun.COM 			return ((damap_id_t)i);
76311068SJohn.Danielson@Sun.COM 		}
76411068SJohn.Danielson@Sun.COM 	}
76510696SDavid.Hollister@Sun.COM 	return ((damap_id_t)0);
76610696SDavid.Hollister@Sun.COM }
76710696SDavid.Hollister@Sun.COM 
76810696SDavid.Hollister@Sun.COM /*
76910696SDavid.Hollister@Sun.COM  * Set config private data
77010696SDavid.Hollister@Sun.COM  *
77110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
77211068SJohn.Danielson@Sun.COM  * addrid:	address ID
77310696SDavid.Hollister@Sun.COM  * cfg_priv:	configuration private data
77410696SDavid.Hollister@Sun.COM  *
77510696SDavid.Hollister@Sun.COM  */
77610696SDavid.Hollister@Sun.COM void
77711068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
77810696SDavid.Hollister@Sun.COM {
77910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
78010696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
78110696SDavid.Hollister@Sun.COM 
78211068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
78311068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
78410696SDavid.Hollister@Sun.COM 	if (!passp) {
78511068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
78610696SDavid.Hollister@Sun.COM 		return;
78710696SDavid.Hollister@Sun.COM 	}
78810696SDavid.Hollister@Sun.COM 	passp->da_cfg_priv = cfg_priv;
78911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
79010696SDavid.Hollister@Sun.COM }
79110696SDavid.Hollister@Sun.COM 
79210696SDavid.Hollister@Sun.COM /*
79310696SDavid.Hollister@Sun.COM  * Get config private data
79410696SDavid.Hollister@Sun.COM  *
79510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
79611068SJohn.Danielson@Sun.COM  * addrid:	address ID
79710696SDavid.Hollister@Sun.COM  *
79810696SDavid.Hollister@Sun.COM  * Returns:	configuration private data
79910696SDavid.Hollister@Sun.COM  */
80010696SDavid.Hollister@Sun.COM void *
80111068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
80210696SDavid.Hollister@Sun.COM {
80310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
80410696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
80510696SDavid.Hollister@Sun.COM 	void *rv;
80610696SDavid.Hollister@Sun.COM 
80711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
80811068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
80910696SDavid.Hollister@Sun.COM 	if (!passp) {
81011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
81110696SDavid.Hollister@Sun.COM 		return (NULL);
81210696SDavid.Hollister@Sun.COM 	}
81310696SDavid.Hollister@Sun.COM 	rv = passp->da_cfg_priv;
81411068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
81510696SDavid.Hollister@Sun.COM 	return (rv);
81610696SDavid.Hollister@Sun.COM }
81710696SDavid.Hollister@Sun.COM 
81810696SDavid.Hollister@Sun.COM /*
81910696SDavid.Hollister@Sun.COM  * Lookup a single address in the active address map
82010696SDavid.Hollister@Sun.COM  *
82110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
82210696SDavid.Hollister@Sun.COM  * address:	address string
82310696SDavid.Hollister@Sun.COM  *
82410696SDavid.Hollister@Sun.COM  * Returns:	ID of active/stable address
82510696SDavid.Hollister@Sun.COM  *		0	Address not in stable set
82610696SDavid.Hollister@Sun.COM  *
82710696SDavid.Hollister@Sun.COM  * Future: Allow the caller to wait for stabilize before returning not found.
82810696SDavid.Hollister@Sun.COM  */
82910696SDavid.Hollister@Sun.COM damap_id_t
83010696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address)
83110696SDavid.Hollister@Sun.COM {
83210696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
83310696SDavid.Hollister@Sun.COM 	id_t addrid = 0;
83410696SDavid.Hollister@Sun.COM 	dam_da_t *passp = NULL;
83510696SDavid.Hollister@Sun.COM 
83611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
83711068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
83811068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
83911068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high)
84011068SJohn.Danielson@Sun.COM 		addrid = 0;
84111068SJohn.Danielson@Sun.COM 	else
84211068SJohn.Danielson@Sun.COM 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
84310696SDavid.Hollister@Sun.COM 	if (addrid) {
84410696SDavid.Hollister@Sun.COM 		if (DAM_IS_STABLE(mapp, addrid)) {
84510696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
84610696SDavid.Hollister@Sun.COM 			ASSERT(passp);
84710696SDavid.Hollister@Sun.COM 			if (passp) {
84810696SDavid.Hollister@Sun.COM 				passp->da_ref++;
84910696SDavid.Hollister@Sun.COM 			} else {
85010696SDavid.Hollister@Sun.COM 				addrid = 0;
85110696SDavid.Hollister@Sun.COM 			}
85210696SDavid.Hollister@Sun.COM 		} else {
85310696SDavid.Hollister@Sun.COM 			addrid = 0;
85410696SDavid.Hollister@Sun.COM 		}
85510696SDavid.Hollister@Sun.COM 	}
85611068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
85711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
85811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp, int, addrid);
85910696SDavid.Hollister@Sun.COM 	return ((damap_id_t)addrid);
86010696SDavid.Hollister@Sun.COM }
86110696SDavid.Hollister@Sun.COM 
86210696SDavid.Hollister@Sun.COM 
86310696SDavid.Hollister@Sun.COM /*
86410696SDavid.Hollister@Sun.COM  * Return the list of stable addresses in the map
86510696SDavid.Hollister@Sun.COM  *
86610696SDavid.Hollister@Sun.COM  * damapp:	address map handle
86710696SDavid.Hollister@Sun.COM  * id_listp:	pointer to list of address IDs in stable map (returned)
86810696SDavid.Hollister@Sun.COM  *
86910696SDavid.Hollister@Sun.COM  * Returns:	# of entries returned in alist
87010696SDavid.Hollister@Sun.COM  */
87110696SDavid.Hollister@Sun.COM int
87210696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
87310696SDavid.Hollister@Sun.COM {
87410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
87510696SDavid.Hollister@Sun.COM 	int mapsz = mapp->dam_size;
87610696SDavid.Hollister@Sun.COM 	int n_ids, i;
87710696SDavid.Hollister@Sun.COM 	bitset_t *bsp;
87811068SJohn.Danielson@Sun.COM 	char	 *addrp;
87910696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
88010696SDavid.Hollister@Sun.COM 
88111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
88211068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
88311068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
88411068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high) {
88511068SJohn.Danielson@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
88611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
88711068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
88811068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp, int, 0);
88911068SJohn.Danielson@Sun.COM 		return (0);
89011068SJohn.Danielson@Sun.COM 	}
89110696SDavid.Hollister@Sun.COM 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
89210696SDavid.Hollister@Sun.COM 	bitset_init(bsp);
89310696SDavid.Hollister@Sun.COM 	bitset_resize(bsp, mapsz);
89410696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, bsp);
89510696SDavid.Hollister@Sun.COM 	for (n_ids = 0, i = 1; i < mapsz; i++) {
89610696SDavid.Hollister@Sun.COM 		if (bitset_in_set(bsp, i)) {
89710696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, i);
89810696SDavid.Hollister@Sun.COM 			ASSERT(passp);
89910696SDavid.Hollister@Sun.COM 			if (passp) {
90011068SJohn.Danielson@Sun.COM 				addrp = damap_id2addr(damapp, i);
90111068SJohn.Danielson@Sun.COM 				DTRACE_PROBE3(damap__lookup__all__item, char *,
90211068SJohn.Danielson@Sun.COM 				    mapp->dam_name, char *, addrp, dam_t *,
90311068SJohn.Danielson@Sun.COM 				    mapp);
90410696SDavid.Hollister@Sun.COM 				passp->da_ref++;
90510696SDavid.Hollister@Sun.COM 				n_ids++;
90610696SDavid.Hollister@Sun.COM 			}
90710696SDavid.Hollister@Sun.COM 		}
90810696SDavid.Hollister@Sun.COM 	}
90910696SDavid.Hollister@Sun.COM 	if (n_ids) {
91010696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)bsp;
91111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
91210696SDavid.Hollister@Sun.COM 		return (n_ids);
91310696SDavid.Hollister@Sun.COM 	} else {
91410696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
91510696SDavid.Hollister@Sun.COM 		bitset_fini(bsp);
91610696SDavid.Hollister@Sun.COM 		kmem_free(bsp, sizeof (*bsp));
91711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
91810696SDavid.Hollister@Sun.COM 		return (0);
91910696SDavid.Hollister@Sun.COM 	}
92010696SDavid.Hollister@Sun.COM }
92110696SDavid.Hollister@Sun.COM 
92210696SDavid.Hollister@Sun.COM /*
92310696SDavid.Hollister@Sun.COM  * Release the address list returned by damap_lookup_all()
92410696SDavid.Hollister@Sun.COM  *
92510696SDavid.Hollister@Sun.COM  * mapp:	address map handle
92610696SDavid.Hollister@Sun.COM  * id_list:	list of address IDs returned in damap_lookup_all()
92710696SDavid.Hollister@Sun.COM  */
92810696SDavid.Hollister@Sun.COM void
92910696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
93010696SDavid.Hollister@Sun.COM {
93110696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
93210696SDavid.Hollister@Sun.COM 	int i;
93310696SDavid.Hollister@Sun.COM 
93410696SDavid.Hollister@Sun.COM 	if (id_list == NULL)
93510696SDavid.Hollister@Sun.COM 		return;
93610696SDavid.Hollister@Sun.COM 
93711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
93810696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
93910696SDavid.Hollister@Sun.COM 		if (bitset_in_set((bitset_t *)id_list, i))
94011068SJohn.Danielson@Sun.COM 			(void) dam_addr_release(mapp, i);
94110696SDavid.Hollister@Sun.COM 	}
94211068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
94310696SDavid.Hollister@Sun.COM 	bitset_fini((bitset_t *)id_list);
94410696SDavid.Hollister@Sun.COM 	kmem_free((void *)id_list, sizeof (bitset_t));
94510696SDavid.Hollister@Sun.COM }
94610696SDavid.Hollister@Sun.COM 
94710696SDavid.Hollister@Sun.COM /*
94811068SJohn.Danielson@Sun.COM  * activate an address that has passed the stabilization interval
94911068SJohn.Danielson@Sun.COM  */
95011068SJohn.Danielson@Sun.COM static void
95111068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid)
95211068SJohn.Danielson@Sun.COM {
95311068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
95411068SJohn.Danielson@Sun.COM 	int config_rv;
95511068SJohn.Danielson@Sun.COM 	char *addrstr;
95611068SJohn.Danielson@Sun.COM 
95711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
95811068SJohn.Danielson@Sun.COM 	bitset_add(&mapp->dam_active_set, addrid);
95911068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
96011068SJohn.Danielson@Sun.COM 	ASSERT(passp);
96111068SJohn.Danielson@Sun.COM 
96211068SJohn.Danielson@Sun.COM 	/*
96311068SJohn.Danielson@Sun.COM 	 * copy the reported nvlist and provider private data
96411068SJohn.Danielson@Sun.COM 	 */
96511068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
96611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
96711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
96811068SJohn.Danielson@Sun.COM 	passp->da_nvl = passp->da_nvl_rpt;
96911068SJohn.Danielson@Sun.COM 	passp->da_ppriv = passp->da_ppriv_rpt;
97011068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
97111068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
97211068SJohn.Danielson@Sun.COM 	passp->da_last_stable = gethrtime();
97311068SJohn.Danielson@Sun.COM 	passp->da_stable_cnt++;
97411068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
97511068SJohn.Danielson@Sun.COM 	if (mapp->dam_activate_cb) {
97611068SJohn.Danielson@Sun.COM 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
97711068SJohn.Danielson@Sun.COM 		    addrid, &passp->da_ppriv_rpt);
97811068SJohn.Danielson@Sun.COM 	}
97911068SJohn.Danielson@Sun.COM 
98011068SJohn.Danielson@Sun.COM 	/*
98111068SJohn.Danielson@Sun.COM 	 * call the address-specific configuration action as part of
98211068SJohn.Danielson@Sun.COM 	 * activation.
98311068SJohn.Danielson@Sun.COM 	 */
98411068SJohn.Danielson@Sun.COM 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
98511068SJohn.Danielson@Sun.COM 	    addrid);
98611068SJohn.Danielson@Sun.COM 	if (config_rv != DAM_SUCCESS) {
98711068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
98811068SJohn.Danielson@Sun.COM 		passp->da_flags |= DA_FAILED_CONFIG;
98911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
99011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__config__failure,
99111068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
99211363SReed.Liu@Sun.COM 		dam_deact_cleanup(mapp, addrid, addrstr,
99311363SReed.Liu@Sun.COM 		    DAMAP_DEACT_RSN_CFG_FAIL);
99411363SReed.Liu@Sun.COM 	} else {
99511363SReed.Liu@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__end, char *,
99611363SReed.Liu@Sun.COM 		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
99711068SJohn.Danielson@Sun.COM 	}
99811068SJohn.Danielson@Sun.COM }
99911068SJohn.Danielson@Sun.COM 
100011068SJohn.Danielson@Sun.COM /*
100111068SJohn.Danielson@Sun.COM  * deactivate a previously stable address
100211068SJohn.Danielson@Sun.COM  */
100311068SJohn.Danielson@Sun.COM static void
100411068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid)
100511068SJohn.Danielson@Sun.COM {
100611068SJohn.Danielson@Sun.COM 	char *addrstr;
100711068SJohn.Danielson@Sun.COM 
100811068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
100911068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
101011068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
101111068SJohn.Danielson@Sun.COM 
101211068SJohn.Danielson@Sun.COM 	/*
101311068SJohn.Danielson@Sun.COM 	 * call the unconfiguration callback
101411068SJohn.Danielson@Sun.COM 	 */
101511068SJohn.Danielson@Sun.COM 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
101611363SReed.Liu@Sun.COM 	dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
101711363SReed.Liu@Sun.COM }
101811363SReed.Liu@Sun.COM 
101911363SReed.Liu@Sun.COM static void
102011363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
102111363SReed.Liu@Sun.COM     damap_deact_rsn_t deact_rsn)
102211363SReed.Liu@Sun.COM {
102311363SReed.Liu@Sun.COM 	dam_da_t *passp;
102411363SReed.Liu@Sun.COM 
102511068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
102611068SJohn.Danielson@Sun.COM 	ASSERT(passp);
102711068SJohn.Danielson@Sun.COM 	if (mapp->dam_deactivate_cb)
102811068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
102911068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
103011363SReed.Liu@Sun.COM 		    addrid, passp->da_ppriv, deact_rsn);
103111068SJohn.Danielson@Sun.COM 
103211068SJohn.Danielson@Sun.COM 	/*
103311068SJohn.Danielson@Sun.COM 	 * clear the active bit and free the backing info for
103411068SJohn.Danielson@Sun.COM 	 * this address
103511068SJohn.Danielson@Sun.COM 	 */
103611068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
103711068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_active_set, addrid);
103811068SJohn.Danielson@Sun.COM 	passp->da_ppriv = NULL;
103911068SJohn.Danielson@Sun.COM 	if (passp->da_nvl)
104011068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl);
104111068SJohn.Danielson@Sun.COM 	passp->da_nvl = NULL;
104211068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
104311068SJohn.Danielson@Sun.COM 	if (passp->da_nvl_rpt)
104411068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
104511068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
104611068SJohn.Danielson@Sun.COM 
104711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
104811068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
104911068SJohn.Danielson@Sun.COM 
105011068SJohn.Danielson@Sun.COM 	(void) dam_addr_release(mapp, addrid);
105111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
105211068SJohn.Danielson@Sun.COM }
105311068SJohn.Danielson@Sun.COM 
105411068SJohn.Danielson@Sun.COM /*
105511068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread activation
105611068SJohn.Danielson@Sun.COM  */
105711068SJohn.Danielson@Sun.COM static void
105811068SJohn.Danielson@Sun.COM dam_tq_config(void *arg)
105911068SJohn.Danielson@Sun.COM {
106011068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
106111068SJohn.Danielson@Sun.COM 
106211068SJohn.Danielson@Sun.COM 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
106311068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
106411068SJohn.Danielson@Sun.COM }
106511068SJohn.Danielson@Sun.COM 
106611068SJohn.Danielson@Sun.COM /*
106711068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread deactivation
106811068SJohn.Danielson@Sun.COM  */
106911068SJohn.Danielson@Sun.COM static void
107011068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg)
107111068SJohn.Danielson@Sun.COM {
107211068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
107311068SJohn.Danielson@Sun.COM 
107411068SJohn.Danielson@Sun.COM 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
107511068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
107611068SJohn.Danielson@Sun.COM }
107711068SJohn.Danielson@Sun.COM 
107811068SJohn.Danielson@Sun.COM /*
107910696SDavid.Hollister@Sun.COM  * Activate a set of stabilized addresses
108010696SDavid.Hollister@Sun.COM  */
108110696SDavid.Hollister@Sun.COM static void
108211068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate)
108310696SDavid.Hollister@Sun.COM {
108411068SJohn.Danielson@Sun.COM 
108511068SJohn.Danielson@Sun.COM 	int i, nset;
108611068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
108711068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
108811068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
108911068SJohn.Danielson@Sun.COM 	extern pri_t maxclsyspri;
109010696SDavid.Hollister@Sun.COM 
109111068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
109211068SJohn.Danielson@Sun.COM 		/*
109311068SJohn.Danielson@Sun.COM 		 * calculate the # of taskq threads to create
109411068SJohn.Danielson@Sun.COM 		 */
109511068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
109611068SJohn.Danielson@Sun.COM 			if (bitset_in_set(activate, i))
109711068SJohn.Danielson@Sun.COM 				nset++;
109811068SJohn.Danielson@Sun.COM 		ASSERT(nset);
109911068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
110011068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
110111068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
110211068SJohn.Danielson@Sun.COM 	}
110310696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
110411068SJohn.Danielson@Sun.COM 		if (bitset_in_set(activate, i)) {
110511068SJohn.Danielson@Sun.COM 			if (!tqp)
110611068SJohn.Danielson@Sun.COM 				dam_addr_activate(mapp, i);
110711068SJohn.Danielson@Sun.COM 			else {
110811068SJohn.Danielson@Sun.COM 				/*
110911068SJohn.Danielson@Sun.COM 				 * multi-threaded activation
111011068SJohn.Danielson@Sun.COM 				 */
111111068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
111211068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
111311068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
111411068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp, dam_tq_config,
111511854SChris.Horne@Sun.COM 				    tqd, TQ_SLEEP);
111611068SJohn.Danielson@Sun.COM 			}
111710696SDavid.Hollister@Sun.COM 		}
111811068SJohn.Danielson@Sun.COM 	}
111911068SJohn.Danielson@Sun.COM 	if (tqp) {
112011068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
112111068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
112210696SDavid.Hollister@Sun.COM 	}
112310696SDavid.Hollister@Sun.COM }
112410696SDavid.Hollister@Sun.COM 
112510696SDavid.Hollister@Sun.COM /*
112611068SJohn.Danielson@Sun.COM  * Deactivate a set of stabilized addresses
112710696SDavid.Hollister@Sun.COM  */
112810696SDavid.Hollister@Sun.COM static void
112911068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
113010696SDavid.Hollister@Sun.COM {
113111068SJohn.Danielson@Sun.COM 	int i, nset;
113211068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
113311068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
113411068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
113511068SJohn.Danielson@Sun.COM 
113611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
113711068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
113810696SDavid.Hollister@Sun.COM 
113911068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
114011068SJohn.Danielson@Sun.COM 		/*
114111068SJohn.Danielson@Sun.COM 		 * compute the # of taskq threads to dispatch
114211068SJohn.Danielson@Sun.COM 		 */
114311068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
114411068SJohn.Danielson@Sun.COM 			if (bitset_in_set(deactivate, i))
114511068SJohn.Danielson@Sun.COM 				nset++;
114611068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
114711068SJohn.Danielson@Sun.COM 		    mapp->dam_name);
114811068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
114911068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
115011068SJohn.Danielson@Sun.COM 	}
115110696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
115211068SJohn.Danielson@Sun.COM 		if (bitset_in_set(deactivate, i)) {
115311068SJohn.Danielson@Sun.COM 			if (!tqp) {
115411068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
115511068SJohn.Danielson@Sun.COM 			} else {
115611068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
115711068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
115811068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
115911068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp,
116011854SChris.Horne@Sun.COM 				    dam_tq_unconfig, tqd, TQ_SLEEP);
116111068SJohn.Danielson@Sun.COM 			}
116210696SDavid.Hollister@Sun.COM 		}
116310696SDavid.Hollister@Sun.COM 	}
116411068SJohn.Danielson@Sun.COM 
116511068SJohn.Danielson@Sun.COM 	if (tqp) {
116611068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
116711068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
116811068SJohn.Danielson@Sun.COM 	}
116910696SDavid.Hollister@Sun.COM }
117010696SDavid.Hollister@Sun.COM 
117110696SDavid.Hollister@Sun.COM /*
117211068SJohn.Danielson@Sun.COM  * Release a previously activated address
117310696SDavid.Hollister@Sun.COM  */
117410696SDavid.Hollister@Sun.COM static void
117511068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid)
117610696SDavid.Hollister@Sun.COM {
117710696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
117811068SJohn.Danielson@Sun.COM 	char	 *addrstr;
117910696SDavid.Hollister@Sun.COM 
118011068SJohn.Danielson@Sun.COM 
118111068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
118210696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
118310696SDavid.Hollister@Sun.COM 	ASSERT(passp);
118410696SDavid.Hollister@Sun.COM 
118511068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
118611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
118711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
118810696SDavid.Hollister@Sun.COM 
118910696SDavid.Hollister@Sun.COM 	/*
119011068SJohn.Danielson@Sun.COM 	 * defer releasing the address until outstanding references
119111068SJohn.Danielson@Sun.COM 	 * are released
119210696SDavid.Hollister@Sun.COM 	 */
119311068SJohn.Danielson@Sun.COM 	if (passp->da_ref > 1) {
119411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
119511068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
119611068SJohn.Danielson@Sun.COM 		    int, passp->da_ref);
119710696SDavid.Hollister@Sun.COM 		return;
119811068SJohn.Danielson@Sun.COM 	}
119910696SDavid.Hollister@Sun.COM 
120010696SDavid.Hollister@Sun.COM 	/*
120111068SJohn.Danielson@Sun.COM 	 * allow pending reports to stabilize
120210696SDavid.Hollister@Sun.COM 	 */
120311068SJohn.Danielson@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
120411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__release__report__pending,
120511068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
120610696SDavid.Hollister@Sun.COM 		return;
120710696SDavid.Hollister@Sun.COM 	}
120811068SJohn.Danielson@Sun.COM 
120910696SDavid.Hollister@Sun.COM 	ddi_strid_free(mapp->dam_addr_hash, addrid);
121010696SDavid.Hollister@Sun.COM 	ddi_soft_state_free(mapp->dam_da, addrid);
121110696SDavid.Hollister@Sun.COM }
121210696SDavid.Hollister@Sun.COM 
121310696SDavid.Hollister@Sun.COM /*
121410696SDavid.Hollister@Sun.COM  * process stabilized address reports
121510696SDavid.Hollister@Sun.COM  */
121610696SDavid.Hollister@Sun.COM static void
121711068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg)
121810696SDavid.Hollister@Sun.COM {
121910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
122010696SDavid.Hollister@Sun.COM 	bitset_t delta;
122110696SDavid.Hollister@Sun.COM 	bitset_t cfg;
122210696SDavid.Hollister@Sun.COM 	bitset_t uncfg;
122310696SDavid.Hollister@Sun.COM 	int has_cfg, has_uncfg;
122411068SJohn.Danielson@Sun.COM 	uint32_t i, n_active;
122511068SJohn.Danielson@Sun.COM 
122611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
122711068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
122810696SDavid.Hollister@Sun.COM 
122910696SDavid.Hollister@Sun.COM 	bitset_init(&delta);
123010696SDavid.Hollister@Sun.COM 	bitset_resize(&delta, mapp->dam_size);
123110696SDavid.Hollister@Sun.COM 	bitset_init(&cfg);
123210696SDavid.Hollister@Sun.COM 	bitset_resize(&cfg, mapp->dam_size);
123310696SDavid.Hollister@Sun.COM 	bitset_init(&uncfg);
123410696SDavid.Hollister@Sun.COM 	bitset_resize(&uncfg, mapp->dam_size);
123510696SDavid.Hollister@Sun.COM 
123611068SJohn.Danielson@Sun.COM 	/*
123711068SJohn.Danielson@Sun.COM 	 * determine which addresses have changed during
123811068SJohn.Danielson@Sun.COM 	 * this stabilization cycle
123911068SJohn.Danielson@Sun.COM 	 */
124011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
124111068SJohn.Danielson@Sun.COM 	ASSERT(mapp->dam_flags & DAM_SPEND);
124210696SDavid.Hollister@Sun.COM 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
124310696SDavid.Hollister@Sun.COM 	    &delta)) {
124411068SJohn.Danielson@Sun.COM 		/*
124511068SJohn.Danielson@Sun.COM 		 * no difference
124611068SJohn.Danielson@Sun.COM 		 */
124710696SDavid.Hollister@Sun.COM 		bitset_zero(&mapp->dam_stable_set);
124811068SJohn.Danielson@Sun.COM 		mapp->dam_flags  &= ~DAM_SPEND;
124911068SJohn.Danielson@Sun.COM 		cv_signal(&mapp->dam_cv);
125011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
125110696SDavid.Hollister@Sun.COM 		bitset_fini(&uncfg);
125210696SDavid.Hollister@Sun.COM 		bitset_fini(&cfg);
125310696SDavid.Hollister@Sun.COM 		bitset_fini(&delta);
125411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
125511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
125610696SDavid.Hollister@Sun.COM 		return;
125710696SDavid.Hollister@Sun.COM 	}
125811068SJohn.Danielson@Sun.COM 
125911068SJohn.Danielson@Sun.COM 	/*
126011068SJohn.Danielson@Sun.COM 	 * compute the sets of addresses to be activated and deactivated
126111068SJohn.Danielson@Sun.COM 	 */
126210696SDavid.Hollister@Sun.COM 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
126310696SDavid.Hollister@Sun.COM 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
126411068SJohn.Danielson@Sun.COM 
126511068SJohn.Danielson@Sun.COM 	/*
126611068SJohn.Danielson@Sun.COM 	 * drop map lock while invoking callouts
126711068SJohn.Danielson@Sun.COM 	 */
126811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
126911068SJohn.Danielson@Sun.COM 
127011068SJohn.Danielson@Sun.COM 	/*
127111068SJohn.Danielson@Sun.COM 	 * activate all newly stable addresss
127211068SJohn.Danielson@Sun.COM 	 */
127311068SJohn.Danielson@Sun.COM 	if (has_cfg)
127410696SDavid.Hollister@Sun.COM 		dam_addrset_activate(mapp, &cfg);
127511068SJohn.Danielson@Sun.COM 
127611068SJohn.Danielson@Sun.COM 	/*
127711068SJohn.Danielson@Sun.COM 	 * deactivate addresss which are no longer in the map
127811068SJohn.Danielson@Sun.COM 	 */
127911068SJohn.Danielson@Sun.COM 	if (has_uncfg)
128011068SJohn.Danielson@Sun.COM 		dam_addrset_deactivate(mapp, &uncfg);
128111068SJohn.Danielson@Sun.COM 
128211068SJohn.Danielson@Sun.COM 
128311068SJohn.Danielson@Sun.COM 	/*
128411068SJohn.Danielson@Sun.COM 	 * timestamp the last stable time and increment the kstat keeping
128511068SJohn.Danielson@Sun.COM 	 * the # of of stable cycles for the map
128611068SJohn.Danielson@Sun.COM 	 */
128711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
128810696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_stable_set);
128910696SDavid.Hollister@Sun.COM 	mapp->dam_last_stable = gethrtime();
129010696SDavid.Hollister@Sun.COM 	mapp->dam_stable_cnt++;
129111068SJohn.Danielson@Sun.COM 	DAM_INCR_STAT(mapp, dam_cycles);
129211068SJohn.Danielson@Sun.COM 
129311068SJohn.Danielson@Sun.COM 	/*
129411068SJohn.Danielson@Sun.COM 	 * determine the number of stable addresses
129511068SJohn.Danielson@Sun.COM 	 * and update the n_active kstat for this map
129611068SJohn.Danielson@Sun.COM 	 */
129711068SJohn.Danielson@Sun.COM 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
129811068SJohn.Danielson@Sun.COM 		if (bitset_in_set(&mapp->dam_active_set, i))
129911068SJohn.Danielson@Sun.COM 			n_active++;
130011068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_active, n_active);
130111068SJohn.Danielson@Sun.COM 
130211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
130311068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, n_active);
130411068SJohn.Danielson@Sun.COM 
130511068SJohn.Danielson@Sun.COM 	mapp->dam_flags  &= ~DAM_SPEND;
130611068SJohn.Danielson@Sun.COM 	cv_signal(&mapp->dam_cv);
130711068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
130810696SDavid.Hollister@Sun.COM 	bitset_fini(&uncfg);
130910696SDavid.Hollister@Sun.COM 	bitset_fini(&cfg);
131010696SDavid.Hollister@Sun.COM 	bitset_fini(&delta);
131110696SDavid.Hollister@Sun.COM }
131210696SDavid.Hollister@Sun.COM 
131310696SDavid.Hollister@Sun.COM /*
131410696SDavid.Hollister@Sun.COM  * per-address stabilization timeout
131510696SDavid.Hollister@Sun.COM  */
131610696SDavid.Hollister@Sun.COM static void
131710696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg)
131810696SDavid.Hollister@Sun.COM {
131910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
132010696SDavid.Hollister@Sun.COM 	int i;
132110696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
132210696SDavid.Hollister@Sun.COM 	int spend = 0;
132310696SDavid.Hollister@Sun.COM 	int tpend = 0;
132410696SDavid.Hollister@Sun.COM 	int64_t	next_tmov = mapp->dam_stabletmo;
132510696SDavid.Hollister@Sun.COM 	int64_t tmo_delta;
132611066Srafael.vanoni@sun.com 	int64_t ts = ddi_get_lbolt64();
132710696SDavid.Hollister@Sun.COM 
132811068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
132910696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
133011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
133111068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
133211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
133310696SDavid.Hollister@Sun.COM 		return;
133410696SDavid.Hollister@Sun.COM 	}
133510696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
133611068SJohn.Danielson@Sun.COM 
133710696SDavid.Hollister@Sun.COM 	/*
133810696SDavid.Hollister@Sun.COM 	 * If still under stabilization, reschedule timeout,
133911068SJohn.Danielson@Sun.COM 	 * otherwise dispatch the task to activate and deactivate the
134011068SJohn.Danielson@Sun.COM 	 * new stable address
134110696SDavid.Hollister@Sun.COM 	 */
134210696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SPEND) {
134311068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
134410696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
134510696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
134611068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
134711068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
134811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
134910696SDavid.Hollister@Sun.COM 		return;
135010696SDavid.Hollister@Sun.COM 	}
135110696SDavid.Hollister@Sun.COM 
135211068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
135311068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
135411068SJohn.Danielson@Sun.COM 
135511068SJohn.Danielson@Sun.COM 	/*
135611068SJohn.Danielson@Sun.COM 	 * copy the current active set to the stable map
135711068SJohn.Danielson@Sun.COM 	 * for each address being reported, decrement its
135811068SJohn.Danielson@Sun.COM 	 * stabilize deadline, and if stable, add or remove the
135911068SJohn.Danielson@Sun.COM 	 * address from the stable set
136011068SJohn.Danielson@Sun.COM 	 */
136110696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
136210696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
136310696SDavid.Hollister@Sun.COM 		if (!bitset_in_set(&mapp->dam_report_set, i))
136410696SDavid.Hollister@Sun.COM 			continue;
136510696SDavid.Hollister@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, i);
136610696SDavid.Hollister@Sun.COM 		ASSERT(passp);
136710696SDavid.Hollister@Sun.COM 
136810696SDavid.Hollister@Sun.COM 		/* report has stabilized */
136910696SDavid.Hollister@Sun.COM 		if (passp->da_deadline <= ts) {
137010696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_report_set, i);
137111068SJohn.Danielson@Sun.COM 			if (passp->da_flags & DA_RELE)
137210696SDavid.Hollister@Sun.COM 				bitset_del(&mapp->dam_stable_set, i);
137311068SJohn.Danielson@Sun.COM 			else
137410696SDavid.Hollister@Sun.COM 				bitset_add(&mapp->dam_stable_set, i);
137510696SDavid.Hollister@Sun.COM 			spend++;
137610696SDavid.Hollister@Sun.COM 			continue;
137710696SDavid.Hollister@Sun.COM 		}
137810696SDavid.Hollister@Sun.COM 
137910696SDavid.Hollister@Sun.COM 		/*
138011068SJohn.Danielson@Sun.COM 		 * not stabilized, determine next map timeout
138110696SDavid.Hollister@Sun.COM 		 */
138210696SDavid.Hollister@Sun.COM 		tpend++;
138310696SDavid.Hollister@Sun.COM 		tmo_delta = passp->da_deadline - ts;
138410696SDavid.Hollister@Sun.COM 		if (tmo_delta < next_tmov)
138510696SDavid.Hollister@Sun.COM 			next_tmov = tmo_delta;
138610696SDavid.Hollister@Sun.COM 	}
138710696SDavid.Hollister@Sun.COM 
138810696SDavid.Hollister@Sun.COM 	/*
138911068SJohn.Danielson@Sun.COM 	 * schedule system_taskq activation of stabilized reports
139010696SDavid.Hollister@Sun.COM 	 */
139110696SDavid.Hollister@Sun.COM 	if (spend) {
139211068SJohn.Danielson@Sun.COM 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
139311854SChris.Horne@Sun.COM 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
139411068SJohn.Danielson@Sun.COM 			mapp->dam_flags  |= DAM_SPEND;
139511068SJohn.Danielson@Sun.COM 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
139611068SJohn.Danielson@Sun.COM 			    mapp->dam_name, dam_t *, mapp);
139711068SJohn.Danielson@Sun.COM 		} else {
139810696SDavid.Hollister@Sun.COM 			tpend++;
139911854SChris.Horne@Sun.COM 
140011854SChris.Horne@Sun.COM 			/*
140111854SChris.Horne@Sun.COM 			 * Avoid waiting the entire stabalization
140211854SChris.Horne@Sun.COM 			 * time again if taskq_diskpatch fails.
140311854SChris.Horne@Sun.COM 			 */
140411854SChris.Horne@Sun.COM 			tmo_delta = drv_usectohz(
140511854SChris.Horne@Sun.COM 			    damap_taskq_dispatch_retry_usec);
140611854SChris.Horne@Sun.COM 			if (tmo_delta < next_tmov)
140711854SChris.Horne@Sun.COM 				next_tmov = tmo_delta;
140811068SJohn.Danielson@Sun.COM 		}
140910696SDavid.Hollister@Sun.COM 	}
141010696SDavid.Hollister@Sun.COM 
141110696SDavid.Hollister@Sun.COM 	/*
141211068SJohn.Danielson@Sun.COM 	 * reschedule the stabilization timer if there are reports
141311068SJohn.Danielson@Sun.COM 	 * still pending
141410696SDavid.Hollister@Sun.COM 	 */
141510696SDavid.Hollister@Sun.COM 	if (tpend)
141610696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
141711068SJohn.Danielson@Sun.COM 
141811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
141910696SDavid.Hollister@Sun.COM }
142010696SDavid.Hollister@Sun.COM 
142110696SDavid.Hollister@Sun.COM /*
142211068SJohn.Danielson@Sun.COM  * fullset stabilization timeout callback
142310696SDavid.Hollister@Sun.COM  */
142410696SDavid.Hollister@Sun.COM static void
142511068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg)
142610696SDavid.Hollister@Sun.COM {
142710696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
142810696SDavid.Hollister@Sun.COM 
142911068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
143010696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
143111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
143211068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
143311068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, dam_t *, mapp);
143410696SDavid.Hollister@Sun.COM 		return;
143510696SDavid.Hollister@Sun.COM 	}
143610696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
143710696SDavid.Hollister@Sun.COM 
143810696SDavid.Hollister@Sun.COM 	/*
143911068SJohn.Danielson@Sun.COM 	 * If map still underoing stabilization reschedule timeout,
144011068SJohn.Danielson@Sun.COM 	 * else dispatch the task to configure the new stable set of
144111068SJohn.Danielson@Sun.COM 	 * addresses.
144210696SDavid.Hollister@Sun.COM 	 */
144311854SChris.Horne@Sun.COM 	if ((mapp->dam_flags & DAM_SPEND) ||
144411854SChris.Horne@Sun.COM 	    (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
144511854SChris.Horne@Sun.COM 	    TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
144611068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
144710696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
144811854SChris.Horne@Sun.COM 		dam_sched_tmo(mapp,
144911854SChris.Horne@Sun.COM 		    drv_usectohz(damap_taskq_dispatch_retry_usec),
145011854SChris.Horne@Sun.COM 		    dam_addrset_stable_cb);
145111854SChris.Horne@Sun.COM 
145211068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
145311068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
145411068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
145511068SJohn.Danielson@Sun.COM 		return;
145610696SDavid.Hollister@Sun.COM 	}
145711068SJohn.Danielson@Sun.COM 
145811068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
145911068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
146011068SJohn.Danielson@Sun.COM 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
146111068SJohn.Danielson@Sun.COM 	bitset_zero(&mapp->dam_report_set);
146211068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_SPEND;
146311068SJohn.Danielson@Sun.COM 	mapp->dam_flags &= ~DAM_SETADD;
146411068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
146511068SJohn.Danielson@Sun.COM 	    mapp->dam_name, dam_t *, mapp);
146611068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
146710696SDavid.Hollister@Sun.COM }
146810696SDavid.Hollister@Sun.COM 
146910696SDavid.Hollister@Sun.COM /*
147011068SJohn.Danielson@Sun.COM  * schedule map timeout 'tmo_ms' ticks
147111068SJohn.Danielson@Sun.COM  * if map timer is currently running, cancel if tmo_ms == 0
147210696SDavid.Hollister@Sun.COM  */
147310696SDavid.Hollister@Sun.COM static void
147410696SDavid.Hollister@Sun.COM dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
147510696SDavid.Hollister@Sun.COM {
147610696SDavid.Hollister@Sun.COM 	timeout_id_t tid;
147710696SDavid.Hollister@Sun.COM 
147811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp,
147911068SJohn.Danielson@Sun.COM 	    clock_t, tmo_ms);
148011068SJohn.Danielson@Sun.COM 
148111068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
148210696SDavid.Hollister@Sun.COM 	if ((tid = mapp->dam_tid) != 0) {
148311068SJohn.Danielson@Sun.COM 		if (tmo_ms == 0) {
148411068SJohn.Danielson@Sun.COM 			mapp->dam_tid = 0;
148511068SJohn.Danielson@Sun.COM 			mutex_exit(&mapp->dam_lock);
148611068SJohn.Danielson@Sun.COM 			(void) untimeout(tid);
148711068SJohn.Danielson@Sun.COM 			mutex_enter(&mapp->dam_lock);
148811068SJohn.Danielson@Sun.COM 		}
148911068SJohn.Danielson@Sun.COM 	} else {
149011068SJohn.Danielson@Sun.COM 		if (tmo_cb && (tmo_ms != 0))
149111068SJohn.Danielson@Sun.COM 			mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
149210696SDavid.Hollister@Sun.COM 	}
149310696SDavid.Hollister@Sun.COM }
149410696SDavid.Hollister@Sun.COM 
149510696SDavid.Hollister@Sun.COM /*
149611068SJohn.Danielson@Sun.COM  * report addition or removal of an address
149710696SDavid.Hollister@Sun.COM  */
149810696SDavid.Hollister@Sun.COM static void
149911068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
150010696SDavid.Hollister@Sun.COM {
150111068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
150211068SJohn.Danielson@Sun.COM 
150311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
150411068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
150511068SJohn.Danielson@Sun.COM 
150611068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
150710696SDavid.Hollister@Sun.COM 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
150810696SDavid.Hollister@Sun.COM 	passp->da_last_report = gethrtime();
150910696SDavid.Hollister@Sun.COM 	mapp->dam_last_update = gethrtime();
151010696SDavid.Hollister@Sun.COM 	passp->da_report_cnt++;
151111066Srafael.vanoni@sun.com 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo;
151211068SJohn.Danielson@Sun.COM 	if (rpt_type == RPT_ADDR_DEL)
151310696SDavid.Hollister@Sun.COM 		passp->da_flags |= DA_RELE;
151411068SJohn.Danielson@Sun.COM 	else if (rpt_type == RPT_ADDR_ADD)
151510696SDavid.Hollister@Sun.COM 		passp->da_flags &= ~DA_RELE;
151610696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
151710696SDavid.Hollister@Sun.COM 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
151810696SDavid.Hollister@Sun.COM }
151910696SDavid.Hollister@Sun.COM 
152010696SDavid.Hollister@Sun.COM /*
152110696SDavid.Hollister@Sun.COM  * release an address report
152210696SDavid.Hollister@Sun.COM  */
152310696SDavid.Hollister@Sun.COM static void
152411068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid)
152510696SDavid.Hollister@Sun.COM {
152610696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
152711068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
152810696SDavid.Hollister@Sun.COM 
152911068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
153011068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
153111068SJohn.Danielson@Sun.COM 
153211068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
153310696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
153410696SDavid.Hollister@Sun.COM 	ASSERT(passp);
153511068SJohn.Danielson@Sun.COM 	/*
153611068SJohn.Danielson@Sun.COM 	 * clear the report bit
153711068SJohn.Danielson@Sun.COM 	 * if the address has a registered deactivation handler and
153811601SDavid.Hollister@Sun.COM 	 * we are holding a private data pointer and the address has not
153911601SDavid.Hollister@Sun.COM 	 * stabilized, deactivate the address (private data).
154011068SJohn.Danielson@Sun.COM 	 */
154111068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_report_set, addrid);
154211601SDavid.Hollister@Sun.COM 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
154311601SDavid.Hollister@Sun.COM 	    passp->da_ppriv_rpt) {
154411068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
154511068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
154611068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
154711601SDavid.Hollister@Sun.COM 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
154811068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
154911068SJohn.Danielson@Sun.COM 	}
155010696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = NULL;
155110696SDavid.Hollister@Sun.COM 	if (passp->da_nvl_rpt)
155210696SDavid.Hollister@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
155310696SDavid.Hollister@Sun.COM }
155410696SDavid.Hollister@Sun.COM 
155510696SDavid.Hollister@Sun.COM /*
155610696SDavid.Hollister@Sun.COM  * return the map ID of an address
155710696SDavid.Hollister@Sun.COM  */
155810696SDavid.Hollister@Sun.COM static id_t
155910696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address)
156010696SDavid.Hollister@Sun.COM {
156110696SDavid.Hollister@Sun.COM 	damap_id_t addrid;
156210696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
156310696SDavid.Hollister@Sun.COM 
156411068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
156510696SDavid.Hollister@Sun.COM 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
156611068SJohn.Danielson@Sun.COM 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
156710696SDavid.Hollister@Sun.COM 		    address)) == (damap_id_t)0) {
156810696SDavid.Hollister@Sun.COM 			return (0);
156910696SDavid.Hollister@Sun.COM 		}
157010696SDavid.Hollister@Sun.COM 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
157110696SDavid.Hollister@Sun.COM 		    DDI_SUCCESS) {
157210696SDavid.Hollister@Sun.COM 			ddi_strid_free(mapp->dam_addr_hash, addrid);
157310696SDavid.Hollister@Sun.COM 			return (0);
157410696SDavid.Hollister@Sun.COM 		}
157511068SJohn.Danielson@Sun.COM 
157610696SDavid.Hollister@Sun.COM 		if (addrid >= mapp->dam_high)
157710696SDavid.Hollister@Sun.COM 			mapp->dam_high = addrid + 1;
157811068SJohn.Danielson@Sun.COM 
157911068SJohn.Danielson@Sun.COM 		/*
158011068SJohn.Danielson@Sun.COM 		 * expand bitmaps if ID has outgrown old map size
158111068SJohn.Danielson@Sun.COM 		 */
158211068SJohn.Danielson@Sun.COM 		if (mapp->dam_high > mapp->dam_size) {
158311068SJohn.Danielson@Sun.COM 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
158411068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
158511068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
158611068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
158711068SJohn.Danielson@Sun.COM 		}
158811068SJohn.Danielson@Sun.COM 
158911068SJohn.Danielson@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
159011068SJohn.Danielson@Sun.COM 		passp->da_ref = 1;
159111068SJohn.Danielson@Sun.COM 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
159211068SJohn.Danielson@Sun.COM 		    addrid); /* for mdb */
159310696SDavid.Hollister@Sun.COM 	}
159410696SDavid.Hollister@Sun.COM 	return (addrid);
159510696SDavid.Hollister@Sun.COM }
159610696SDavid.Hollister@Sun.COM 
159710696SDavid.Hollister@Sun.COM /*
159810696SDavid.Hollister@Sun.COM  * create and install map statistics
159910696SDavid.Hollister@Sun.COM  */
160010696SDavid.Hollister@Sun.COM static int
160110696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp)
160210696SDavid.Hollister@Sun.COM {
160310696SDavid.Hollister@Sun.COM 	kstat_t			*mapsp;
160410696SDavid.Hollister@Sun.COM 	struct dam_kstats	*statsp;
160510696SDavid.Hollister@Sun.COM 
160610696SDavid.Hollister@Sun.COM 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
160710696SDavid.Hollister@Sun.COM 	    KSTAT_TYPE_NAMED,
160810696SDavid.Hollister@Sun.COM 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
160911068SJohn.Danielson@Sun.COM 
161011068SJohn.Danielson@Sun.COM 	if (mapsp == NULL)
161110696SDavid.Hollister@Sun.COM 		return (DDI_FAILURE);
161210696SDavid.Hollister@Sun.COM 
161310696SDavid.Hollister@Sun.COM 	statsp = (struct dam_kstats *)mapsp->ks_data;
161411068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
161511068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
161611068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
161711068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
161810696SDavid.Hollister@Sun.COM 	kstat_install(mapsp);
161910696SDavid.Hollister@Sun.COM 	mapp->dam_kstatsp = mapsp;
162010696SDavid.Hollister@Sun.COM 	return (DDI_SUCCESS);
162110696SDavid.Hollister@Sun.COM }
1622