xref: /onnv-gate/usr/src/uts/common/os/damap.c (revision 11601:5a8b35d191ab)
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 /*
23*11601SDavid.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 
8711068SJohn.Danielson@Sun.COM /*
8811068SJohn.Danielson@Sun.COM  * config/unconfig taskq data
8911068SJohn.Danielson@Sun.COM  */
9011068SJohn.Danielson@Sun.COM typedef struct {
9111068SJohn.Danielson@Sun.COM 	dam_t *tqd_mapp;
9211068SJohn.Danielson@Sun.COM 	id_t tqd_id;
9311068SJohn.Danielson@Sun.COM } cfg_tqd_t;
9411068SJohn.Danielson@Sun.COM 
9511068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri;
9611068SJohn.Danielson@Sun.COM 
9710696SDavid.Hollister@Sun.COM /*
9810696SDavid.Hollister@Sun.COM  * Create new device address map
9910696SDavid.Hollister@Sun.COM  *
10011068SJohn.Danielson@Sun.COM  * name:		map name (kstat unique)
10110696SDavid.Hollister@Sun.COM  * size:		max # of map entries
10211068SJohn.Danielson@Sun.COM  * mode:		style of address reports: per-address or fullset
10310696SDavid.Hollister@Sun.COM  * stable_usec:		# of quiescent microseconds before report/map is stable
10410696SDavid.Hollister@Sun.COM  *
10510696SDavid.Hollister@Sun.COM  * activate_arg:	address provider activation-callout private
10610696SDavid.Hollister@Sun.COM  * activate_cb:		address provider activation callback handler
10710696SDavid.Hollister@Sun.COM  * deactivate_cb:	address provider deactivation callback handler
10810696SDavid.Hollister@Sun.COM  *
10910696SDavid.Hollister@Sun.COM  * config_arg:		configuration-callout private
11010696SDavid.Hollister@Sun.COM  * config_cb:		class configuration callout
11110696SDavid.Hollister@Sun.COM  * unconfig_cb:		class unconfiguration callout
11210696SDavid.Hollister@Sun.COM  *
11310696SDavid.Hollister@Sun.COM  * damapp:		pointer to map handle (return)
11410696SDavid.Hollister@Sun.COM  *
11510696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
11610696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
11710696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
11810696SDavid.Hollister@Sun.COM  */
11910696SDavid.Hollister@Sun.COM int
12011068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts,
12111068SJohn.Danielson@Sun.COM     clock_t stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
12210696SDavid.Hollister@Sun.COM     damap_deactivate_cb_t deactivate_cb,
12310696SDavid.Hollister@Sun.COM     void *config_arg, damap_configure_cb_t configure_cb,
12410696SDavid.Hollister@Sun.COM     damap_unconfig_cb_t unconfig_cb,
12510696SDavid.Hollister@Sun.COM     damap_t **damapp)
12610696SDavid.Hollister@Sun.COM {
12710696SDavid.Hollister@Sun.COM 	dam_t *mapp;
12810696SDavid.Hollister@Sun.COM 
12911068SJohn.Danielson@Sun.COM 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
13010696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
13110696SDavid.Hollister@Sun.COM 
13211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__create, char *, name,
13311068SJohn.Danielson@Sun.COM 	    damap_rptmode_t, mode, clock_t, stable_usec);
13410696SDavid.Hollister@Sun.COM 
13510696SDavid.Hollister@Sun.COM 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
13611068SJohn.Danielson@Sun.COM 	mapp->dam_options = map_opts;
13710696SDavid.Hollister@Sun.COM 	mapp->dam_stabletmo = drv_usectohz(stable_usec);
13811068SJohn.Danielson@Sun.COM 	mapp->dam_size = 0;
13911068SJohn.Danielson@Sun.COM 	mapp->dam_rptmode = mode;
14010696SDavid.Hollister@Sun.COM 	mapp->dam_activate_arg = activate_arg;
14110696SDavid.Hollister@Sun.COM 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
14210696SDavid.Hollister@Sun.COM 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
14310696SDavid.Hollister@Sun.COM 	mapp->dam_config_arg = config_arg;
14410696SDavid.Hollister@Sun.COM 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
14510696SDavid.Hollister@Sun.COM 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
14611068SJohn.Danielson@Sun.COM 	mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
14710696SDavid.Hollister@Sun.COM 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
14810696SDavid.Hollister@Sun.COM 	cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL);
14911068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_active_set);
15011068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_stable_set);
15111068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_report_set);
15210696SDavid.Hollister@Sun.COM 	*damapp = (damap_t *)mapp;
15310696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
15410696SDavid.Hollister@Sun.COM }
15510696SDavid.Hollister@Sun.COM 
15610696SDavid.Hollister@Sun.COM /*
15711068SJohn.Danielson@Sun.COM  * Allocate backing resources
15811068SJohn.Danielson@Sun.COM  *
15911068SJohn.Danielson@Sun.COM  * DAMs are lightly backed on create - major allocations occur
16011068SJohn.Danielson@Sun.COM  * at the time a report is made to the map, and are extended on
16111068SJohn.Danielson@Sun.COM  * a demand basis.
16211068SJohn.Danielson@Sun.COM  */
16311068SJohn.Danielson@Sun.COM static int
16411068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp)
16511068SJohn.Danielson@Sun.COM {
16611068SJohn.Danielson@Sun.COM 	void *softstate_p;
16711068SJohn.Danielson@Sun.COM 
16811068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
16911068SJohn.Danielson@Sun.COM 	if (mapp->dam_flags & DAM_DESTROYPEND)
17011068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
17111068SJohn.Danielson@Sun.COM 
17211068SJohn.Danielson@Sun.COM 	/*
17311068SJohn.Danielson@Sun.COM 	 * dam_high > 0 signals map allocation complete
17411068SJohn.Danielson@Sun.COM 	 */
17511068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
17611068SJohn.Danielson@Sun.COM 		return (DAM_SUCCESS);
17711068SJohn.Danielson@Sun.COM 
17811068SJohn.Danielson@Sun.COM 	mapp->dam_size = DAM_SIZE_BUMP;
17911068SJohn.Danielson@Sun.COM 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
18011068SJohn.Danielson@Sun.COM 	    mapp->dam_size) != DDI_SUCCESS)
18111068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18211068SJohn.Danielson@Sun.COM 
18311068SJohn.Danielson@Sun.COM 	if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
18411068SJohn.Danielson@Sun.COM 	    DDI_SUCCESS) {
18511068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
18611068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18711068SJohn.Danielson@Sun.COM 	}
18811068SJohn.Danielson@Sun.COM 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
18911068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
19011068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
19111068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
19211068SJohn.Danielson@Sun.COM 	}
19311068SJohn.Danielson@Sun.COM 	mapp->dam_da = softstate_p;
19411068SJohn.Danielson@Sun.COM 	mapp->dam_high = 1;
19511068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_active_set, mapp->dam_size);
19611068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
19711068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_report_set, mapp->dam_size);
19811068SJohn.Danielson@Sun.COM 	return (DAM_SUCCESS);
19911068SJohn.Danielson@Sun.COM }
20011068SJohn.Danielson@Sun.COM 
20111068SJohn.Danielson@Sun.COM /*
20211068SJohn.Danielson@Sun.COM  * Destroy address map
20310696SDavid.Hollister@Sun.COM  *
20410696SDavid.Hollister@Sun.COM  * damapp:	address map
20510696SDavid.Hollister@Sun.COM  *
20610696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
20710696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
20810696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
20910696SDavid.Hollister@Sun.COM  */
21010696SDavid.Hollister@Sun.COM void
21110696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp)
21210696SDavid.Hollister@Sun.COM {
21310696SDavid.Hollister@Sun.COM 	int i;
21410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
21510696SDavid.Hollister@Sun.COM 
21610696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
21710696SDavid.Hollister@Sun.COM 
21811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
21910696SDavid.Hollister@Sun.COM 
22011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
22110696SDavid.Hollister@Sun.COM 
22210696SDavid.Hollister@Sun.COM 	/*
22311068SJohn.Danielson@Sun.COM 	 * prevent new reports from being added to the map
22410696SDavid.Hollister@Sun.COM 	 */
22511068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_DESTROYPEND;
22611068SJohn.Danielson@Sun.COM 
22711068SJohn.Danielson@Sun.COM 	if (mapp->dam_high) {
22811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
22911068SJohn.Danielson@Sun.COM 		/*
23011068SJohn.Danielson@Sun.COM 		 * wait for outstanding reports to stabilize and cancel
23111068SJohn.Danielson@Sun.COM 		 * the timer for this map
23211068SJohn.Danielson@Sun.COM 		 */
23311068SJohn.Danielson@Sun.COM 		(void) damap_sync(damapp);
23411068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
23511068SJohn.Danielson@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
23610696SDavid.Hollister@Sun.COM 
23711068SJohn.Danielson@Sun.COM 		/*
23811068SJohn.Danielson@Sun.COM 		 * map is at full stop
23911068SJohn.Danielson@Sun.COM 		 * release the contents of the map, invoking the
24011068SJohn.Danielson@Sun.COM 		 * detactivation protocol as addresses are released
24111068SJohn.Danielson@Sun.COM 		 */
24211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
24311068SJohn.Danielson@Sun.COM 		for (i = 1; i < mapp->dam_high; i++) {
24411068SJohn.Danielson@Sun.COM 			if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
24511068SJohn.Danielson@Sun.COM 				continue;
24611068SJohn.Danielson@Sun.COM 
24711068SJohn.Danielson@Sun.COM 			ASSERT(DAM_IN_REPORT(mapp, i) == 0);
24811068SJohn.Danielson@Sun.COM 
24911068SJohn.Danielson@Sun.COM 			if (DAM_IS_STABLE(mapp, i)) {
25011068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
25111068SJohn.Danielson@Sun.COM 			} else {
25211068SJohn.Danielson@Sun.COM 				ddi_strid_free(mapp->dam_addr_hash, i);
25311068SJohn.Danielson@Sun.COM 				ddi_soft_state_free(mapp->dam_da, i);
25411068SJohn.Danielson@Sun.COM 			}
25511068SJohn.Danielson@Sun.COM 		}
25611068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
25711068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(&mapp->dam_da);
25811068SJohn.Danielson@Sun.COM 		kstat_delete(mapp->dam_kstatsp);
25910696SDavid.Hollister@Sun.COM 	}
26010696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_active_set);
26110696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_stable_set);
26210696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_report_set);
26310696SDavid.Hollister@Sun.COM 	mutex_destroy(&mapp->dam_lock);
26410696SDavid.Hollister@Sun.COM 	cv_destroy(&mapp->dam_cv);
26510696SDavid.Hollister@Sun.COM 	if (mapp->dam_name)
26610696SDavid.Hollister@Sun.COM 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
26710696SDavid.Hollister@Sun.COM 	kmem_free(mapp, sizeof (*mapp));
26810696SDavid.Hollister@Sun.COM }
26910696SDavid.Hollister@Sun.COM 
27010696SDavid.Hollister@Sun.COM /*
27110696SDavid.Hollister@Sun.COM  * Wait for map stability.
27210696SDavid.Hollister@Sun.COM  *
27310696SDavid.Hollister@Sun.COM  * damapp:	address map
27410696SDavid.Hollister@Sun.COM  */
27510696SDavid.Hollister@Sun.COM int
27610696SDavid.Hollister@Sun.COM damap_sync(damap_t *damapp)
27710696SDavid.Hollister@Sun.COM {
27811068SJohn.Danielson@Sun.COM #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
27910696SDavid.Hollister@Sun.COM 
28010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
28110696SDavid.Hollister@Sun.COM 	int   none_active;
28210696SDavid.Hollister@Sun.COM 
28310696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
28410696SDavid.Hollister@Sun.COM 
28511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
28611068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
28710696SDavid.Hollister@Sun.COM 
28811068SJohn.Danielson@Sun.COM 	/*
28911068SJohn.Danielson@Sun.COM 	 * block where waiting for
29011068SJohn.Danielson@Sun.COM 	 * a) stabilization pending or a fullset update pending
29111068SJohn.Danielson@Sun.COM 	 * b) any scheduled timeouts to fire
29211068SJohn.Danielson@Sun.COM 	 * c) the report set to finalize (bitset is null)
29311068SJohn.Danielson@Sun.COM 	 */
29410696SDavid.Hollister@Sun.COM 	mutex_enter(&mapp->dam_lock);
29510696SDavid.Hollister@Sun.COM 	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
29610696SDavid.Hollister@Sun.COM 	    (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) {
29711068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
29811068SJohn.Danielson@Sun.COM 		    dam_t *, mapp);
29910696SDavid.Hollister@Sun.COM 		cv_wait(&mapp->dam_cv, &mapp->dam_lock);
30010696SDavid.Hollister@Sun.COM 	}
30110696SDavid.Hollister@Sun.COM 
30210696SDavid.Hollister@Sun.COM 	none_active = bitset_is_null(&mapp->dam_active_set);
30310696SDavid.Hollister@Sun.COM 
30410696SDavid.Hollister@Sun.COM 	mutex_exit(&mapp->dam_lock);
30511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, int,
30611068SJohn.Danielson@Sun.COM 	    none_active, dam_t *, mapp);
30710696SDavid.Hollister@Sun.COM 
30810696SDavid.Hollister@Sun.COM 	return (none_active);
30910696SDavid.Hollister@Sun.COM }
31010696SDavid.Hollister@Sun.COM 
31110696SDavid.Hollister@Sun.COM /*
31210696SDavid.Hollister@Sun.COM  * Get the name of a device address map
31310696SDavid.Hollister@Sun.COM  *
31410696SDavid.Hollister@Sun.COM  * damapp:	address map
31510696SDavid.Hollister@Sun.COM  *
31610696SDavid.Hollister@Sun.COM  * Returns:	name
31710696SDavid.Hollister@Sun.COM  */
31810696SDavid.Hollister@Sun.COM char *
31910696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp)
32010696SDavid.Hollister@Sun.COM {
32110696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
32210696SDavid.Hollister@Sun.COM 
32310696SDavid.Hollister@Sun.COM 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
32410696SDavid.Hollister@Sun.COM }
32510696SDavid.Hollister@Sun.COM 
32610696SDavid.Hollister@Sun.COM /*
32710696SDavid.Hollister@Sun.COM  * Report an address to per-address report
32810696SDavid.Hollister@Sun.COM  *
32910696SDavid.Hollister@Sun.COM  * damapp:	address map handle
33010696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
33111068SJohn.Danielson@Sun.COM  * addridp:	address ID
33210696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
33310696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
33410696SDavid.Hollister@Sun.COM  *
33510696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
33610696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
33710696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
33810696SDavid.Hollister@Sun.COM  */
33910696SDavid.Hollister@Sun.COM int
34011068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
34111068SJohn.Danielson@Sun.COM     nvlist_t *nvl, void *addr_priv)
34210696SDavid.Hollister@Sun.COM {
34310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
34410696SDavid.Hollister@Sun.COM 	id_t addrid;
34510696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
34610696SDavid.Hollister@Sun.COM 
34711068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
34810696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
34910696SDavid.Hollister@Sun.COM 
35011068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name,
35111068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
35211068SJohn.Danielson@Sun.COM 
35311068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
35411068SJohn.Danielson@Sun.COM 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
35511068SJohn.Danielson@Sun.COM 	    ((addrid = dam_get_addrid(mapp, address)) == 0)) {
35611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
35710696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
35810696SDavid.Hollister@Sun.COM 	}
35910696SDavid.Hollister@Sun.COM 
36010696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
36110696SDavid.Hollister@Sun.COM 	ASSERT(passp != NULL);
36210696SDavid.Hollister@Sun.COM 
36310696SDavid.Hollister@Sun.COM 	/*
36410696SDavid.Hollister@Sun.COM 	 * If re-reporting the same address (add or remove) clear
36510696SDavid.Hollister@Sun.COM 	 * the existing report
36610696SDavid.Hollister@Sun.COM 	 */
36710696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
36811068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
36911068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
37011068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
37111068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
37210696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
37310696SDavid.Hollister@Sun.COM 	}
37410696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
37510696SDavid.Hollister@Sun.COM 	if (nvl)
37610696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
37710696SDavid.Hollister@Sun.COM 
37811068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
37911068SJohn.Danielson@Sun.COM 	if (addridp != NULL)
38011068SJohn.Danielson@Sun.COM 		*addridp = (damap_id_t)addrid;
38111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
38210696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
38310696SDavid.Hollister@Sun.COM }
38410696SDavid.Hollister@Sun.COM 
38510696SDavid.Hollister@Sun.COM /*
38610696SDavid.Hollister@Sun.COM  * Report removal of address from per-address report
38710696SDavid.Hollister@Sun.COM  *
38810696SDavid.Hollister@Sun.COM  * damapp:	address map
38910696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
39010696SDavid.Hollister@Sun.COM  *
39110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
39210696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
39310696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
39410696SDavid.Hollister@Sun.COM  */
39510696SDavid.Hollister@Sun.COM int
39610696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address)
39710696SDavid.Hollister@Sun.COM {
39810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
39910696SDavid.Hollister@Sun.COM 	id_t addrid;
40010696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
40110696SDavid.Hollister@Sun.COM 
40211068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
40310696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
40410696SDavid.Hollister@Sun.COM 
40511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
40611068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
40711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
40811068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
40911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
41011068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
41111068SJohn.Danielson@Sun.COM 	}
41211068SJohn.Danielson@Sun.COM 
41311068SJohn.Danielson@Sun.COM 	/*
41411068SJohn.Danielson@Sun.COM 	 * if reporting the removal of an address which is not in the map
41511068SJohn.Danielson@Sun.COM 	 * return success
41611068SJohn.Danielson@Sun.COM 	 */
41710696SDavid.Hollister@Sun.COM 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
41811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
41910696SDavid.Hollister@Sun.COM 		return (DAM_SUCCESS);
42010696SDavid.Hollister@Sun.COM 	}
42110696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
42210696SDavid.Hollister@Sun.COM 	ASSERT(passp);
42310696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
42411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
42511068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
42611068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
42711068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
42810696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
42910696SDavid.Hollister@Sun.COM 	}
43011068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
43111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
43210696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
43310696SDavid.Hollister@Sun.COM }
43410696SDavid.Hollister@Sun.COM 
43510696SDavid.Hollister@Sun.COM /*
43610696SDavid.Hollister@Sun.COM  * Initiate full-set report
43710696SDavid.Hollister@Sun.COM  *
43810696SDavid.Hollister@Sun.COM  * damapp:	address map
43910696SDavid.Hollister@Sun.COM  *
44010696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
44110696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
44210696SDavid.Hollister@Sun.COM  */
44310696SDavid.Hollister@Sun.COM int
44410696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp)
44510696SDavid.Hollister@Sun.COM {
44610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
44710696SDavid.Hollister@Sun.COM 	int i;
44810696SDavid.Hollister@Sun.COM 
44911068SJohn.Danielson@Sun.COM 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
45010696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
45110696SDavid.Hollister@Sun.COM 
45211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
45311068SJohn.Danielson@Sun.COM 	    mapp);
45411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
45511068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
45611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
45711068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
45811068SJohn.Danielson@Sun.COM 	}
45910696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SETADD) {
46011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__addrset__begin__reset, char *,
46111068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
46210696SDavid.Hollister@Sun.COM 		/*
46310696SDavid.Hollister@Sun.COM 		 * cancel stabilization timeout
46410696SDavid.Hollister@Sun.COM 		 */
46510696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
46611068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
46711068SJohn.Danielson@Sun.COM 
46811068SJohn.Danielson@Sun.COM 		/*
46911068SJohn.Danielson@Sun.COM 		 * clear pending reports
47011068SJohn.Danielson@Sun.COM 		 */
47110696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++) {
47210696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
47311068SJohn.Danielson@Sun.COM 				dam_addr_report_release(mapp, i);
47410696SDavid.Hollister@Sun.COM 		}
47510696SDavid.Hollister@Sun.COM 	}
47610696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_report_set);
47711068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_SETADD;
47811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
47910696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
48010696SDavid.Hollister@Sun.COM }
48110696SDavid.Hollister@Sun.COM 
48210696SDavid.Hollister@Sun.COM /*
48310696SDavid.Hollister@Sun.COM  * Report address to full-set report
48410696SDavid.Hollister@Sun.COM  *
48510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
48610696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
48710696SDavid.Hollister@Sun.COM  * rindx:	index if address stabilizes
48810696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
48910696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private data (passed to activate/release cb)
49010696SDavid.Hollister@Sun.COM  *
49110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
49210696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
49310696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
49410696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
49510696SDavid.Hollister@Sun.COM  */
49610696SDavid.Hollister@Sun.COM int
49710696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
49810696SDavid.Hollister@Sun.COM     nvlist_t *nvl, void *addr_priv)
49910696SDavid.Hollister@Sun.COM {
50010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
50110696SDavid.Hollister@Sun.COM 	id_t addrid;
50210696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
50310696SDavid.Hollister@Sun.COM 
50411068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
50510696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
50610696SDavid.Hollister@Sun.COM 
50711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
50811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
50910696SDavid.Hollister@Sun.COM 
51011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
51111068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
51211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
51311068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
51411068SJohn.Danielson@Sun.COM 	}
51511068SJohn.Danielson@Sun.COM 
51610696SDavid.Hollister@Sun.COM 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
51711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
51810696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
51910696SDavid.Hollister@Sun.COM 	}
52010696SDavid.Hollister@Sun.COM 
52110696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
52210696SDavid.Hollister@Sun.COM 	ASSERT(passp);
52310696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
52411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
52511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, char *, address, dam_t *, mapp);
52611068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
52710696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
52810696SDavid.Hollister@Sun.COM 	}
52910696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
53010696SDavid.Hollister@Sun.COM 	if (nvl)
53110696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
53210696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
53310696SDavid.Hollister@Sun.COM 	if (ridx)
53410696SDavid.Hollister@Sun.COM 		*ridx = (damap_id_t)addrid;
53511068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
53610696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
53710696SDavid.Hollister@Sun.COM }
53810696SDavid.Hollister@Sun.COM 
53910696SDavid.Hollister@Sun.COM /*
54010696SDavid.Hollister@Sun.COM  * Commit full-set report for stabilization
54110696SDavid.Hollister@Sun.COM  *
54210696SDavid.Hollister@Sun.COM  * damapp:	address map handle
54310696SDavid.Hollister@Sun.COM  * flags:	(currently 0)
54410696SDavid.Hollister@Sun.COM  *
54510696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
54610696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
54710696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
54810696SDavid.Hollister@Sun.COM  */
54910696SDavid.Hollister@Sun.COM int
55010696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags)
55110696SDavid.Hollister@Sun.COM {
55210696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
55310696SDavid.Hollister@Sun.COM 	int i;
55410696SDavid.Hollister@Sun.COM 
55511068SJohn.Danielson@Sun.COM 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
55610696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
55710696SDavid.Hollister@Sun.COM 
55811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
55911068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
56010696SDavid.Hollister@Sun.COM 
56111068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
56211068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
56311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
56411068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
56511068SJohn.Danielson@Sun.COM 	}
56611068SJohn.Danielson@Sun.COM 
56711068SJohn.Danielson@Sun.COM 	if (flags & DAMAP_END_RESET) {
56811068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
56911068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
57010696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
57110696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++)
57210696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
57311068SJohn.Danielson@Sun.COM 				dam_addr_report_release(mapp, i);
57410696SDavid.Hollister@Sun.COM 	} else {
57510696SDavid.Hollister@Sun.COM 		mapp->dam_last_update = gethrtime();
57611068SJohn.Danielson@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
57710696SDavid.Hollister@Sun.COM 	}
57811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
57910696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
58010696SDavid.Hollister@Sun.COM }
58110696SDavid.Hollister@Sun.COM 
58210696SDavid.Hollister@Sun.COM /*
58310696SDavid.Hollister@Sun.COM  * Return nvlist registered with reported address
58410696SDavid.Hollister@Sun.COM  *
58510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
58611068SJohn.Danielson@Sun.COM  * addrid:	address ID
58710696SDavid.Hollister@Sun.COM  *
58810696SDavid.Hollister@Sun.COM  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
58910696SDavid.Hollister@Sun.COM  *		NULL
59010696SDavid.Hollister@Sun.COM  */
59110696SDavid.Hollister@Sun.COM nvlist_t *
59210696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
59310696SDavid.Hollister@Sun.COM {
59410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
59510696SDavid.Hollister@Sun.COM 	dam_da_t *pass;
59610696SDavid.Hollister@Sun.COM 
59711068SJohn.Danielson@Sun.COM 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
59811068SJohn.Danielson@Sun.COM 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
59910696SDavid.Hollister@Sun.COM 			return (pass->da_nvl);
60010696SDavid.Hollister@Sun.COM 	}
60110696SDavid.Hollister@Sun.COM 	return (NULL);
60210696SDavid.Hollister@Sun.COM }
60310696SDavid.Hollister@Sun.COM 
60410696SDavid.Hollister@Sun.COM /*
60510696SDavid.Hollister@Sun.COM  * Return address string
60610696SDavid.Hollister@Sun.COM  *
60710696SDavid.Hollister@Sun.COM  * damapp:	address map handle
60811068SJohn.Danielson@Sun.COM  * addrid:	address ID
60910696SDavid.Hollister@Sun.COM  *
61010696SDavid.Hollister@Sun.COM  * Returns:	char *		Address string
61110696SDavid.Hollister@Sun.COM  *		NULL
61210696SDavid.Hollister@Sun.COM  */
61310696SDavid.Hollister@Sun.COM char *
61411068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid)
61510696SDavid.Hollister@Sun.COM {
61610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
61710696SDavid.Hollister@Sun.COM 
61811068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
61911068SJohn.Danielson@Sun.COM 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
62011068SJohn.Danielson@Sun.COM 	else
62111068SJohn.Danielson@Sun.COM 		return (NULL);
62210696SDavid.Hollister@Sun.COM }
62310696SDavid.Hollister@Sun.COM 
62410696SDavid.Hollister@Sun.COM /*
62510696SDavid.Hollister@Sun.COM  * Release address reference in map
62610696SDavid.Hollister@Sun.COM  *
62710696SDavid.Hollister@Sun.COM  * damapp:	address map handle
62811068SJohn.Danielson@Sun.COM  * addrid:	address ID
62910696SDavid.Hollister@Sun.COM  */
63010696SDavid.Hollister@Sun.COM void
63110696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid)
63210696SDavid.Hollister@Sun.COM {
63310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
63411068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
63511068SJohn.Danielson@Sun.COM 	char *addr;
63610696SDavid.Hollister@Sun.COM 
63711068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
63811068SJohn.Danielson@Sun.COM 	ASSERT(passp);
63911068SJohn.Danielson@Sun.COM 
64011068SJohn.Danielson@Sun.COM 	addr = damap_id2addr(damapp, addrid);
64111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
64211068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, passp->da_ref);
64311068SJohn.Danielson@Sun.COM 
64411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
64511068SJohn.Danielson@Sun.COM 
64611068SJohn.Danielson@Sun.COM 	/*
64711068SJohn.Danielson@Sun.COM 	 * teardown address if last outstanding reference
64811068SJohn.Danielson@Sun.COM 	 */
64911068SJohn.Danielson@Sun.COM 	if (--passp->da_ref == 0)
65011068SJohn.Danielson@Sun.COM 		dam_addr_release(mapp, (id_t)addrid);
65111068SJohn.Danielson@Sun.COM 
65211068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
65310696SDavid.Hollister@Sun.COM }
65410696SDavid.Hollister@Sun.COM 
65510696SDavid.Hollister@Sun.COM /*
65610696SDavid.Hollister@Sun.COM  * Return current reference count on address reference in map
65710696SDavid.Hollister@Sun.COM  *
65810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
65911068SJohn.Danielson@Sun.COM  * addrid:	address ID
66010696SDavid.Hollister@Sun.COM  *
66110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
66210696SDavid.Hollister@Sun.COM  *		DAM_FAILURE
66310696SDavid.Hollister@Sun.COM  */
66410696SDavid.Hollister@Sun.COM int
66511068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid)
66610696SDavid.Hollister@Sun.COM {
66710696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
66810696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
66910696SDavid.Hollister@Sun.COM 	int ref = -1;
67010696SDavid.Hollister@Sun.COM 
67111068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
67210696SDavid.Hollister@Sun.COM 	if (passp)
67310696SDavid.Hollister@Sun.COM 		ref = passp->da_ref;
67411068SJohn.Danielson@Sun.COM 
67510696SDavid.Hollister@Sun.COM 	return (ref);
67610696SDavid.Hollister@Sun.COM }
67710696SDavid.Hollister@Sun.COM 
67810696SDavid.Hollister@Sun.COM /*
67910696SDavid.Hollister@Sun.COM  * Return next address ID in list
68010696SDavid.Hollister@Sun.COM  *
68110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
68210696SDavid.Hollister@Sun.COM  * damap_list:	address ID list passed to config|unconfig
68310696SDavid.Hollister@Sun.COM  *		returned by look by lookup_all
68410696SDavid.Hollister@Sun.COM  * last:	last ID returned, 0 is start of list
68510696SDavid.Hollister@Sun.COM  *
68610696SDavid.Hollister@Sun.COM  * Returns:	addrid		Next ID from the list
68710696SDavid.Hollister@Sun.COM  *		0		End of the list
68810696SDavid.Hollister@Sun.COM  */
68910696SDavid.Hollister@Sun.COM damap_id_t
69010696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
69110696SDavid.Hollister@Sun.COM {
69210696SDavid.Hollister@Sun.COM 	int i, start;
69310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
69410696SDavid.Hollister@Sun.COM 	bitset_t *dam_list = (bitset_t *)damap_list;
69510696SDavid.Hollister@Sun.COM 
69610696SDavid.Hollister@Sun.COM 	if (!mapp || !dam_list)
69710696SDavid.Hollister@Sun.COM 		return ((damap_id_t)0);
69810696SDavid.Hollister@Sun.COM 
69910696SDavid.Hollister@Sun.COM 	start = (int)last + 1;
70011068SJohn.Danielson@Sun.COM 	for (i = start; i < mapp->dam_high; i++) {
70111068SJohn.Danielson@Sun.COM 		if (bitset_in_set(dam_list, i)) {
70210696SDavid.Hollister@Sun.COM 			return ((damap_id_t)i);
70311068SJohn.Danielson@Sun.COM 		}
70411068SJohn.Danielson@Sun.COM 	}
70510696SDavid.Hollister@Sun.COM 	return ((damap_id_t)0);
70610696SDavid.Hollister@Sun.COM }
70710696SDavid.Hollister@Sun.COM 
70810696SDavid.Hollister@Sun.COM /*
70910696SDavid.Hollister@Sun.COM  * Set config private data
71010696SDavid.Hollister@Sun.COM  *
71110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
71211068SJohn.Danielson@Sun.COM  * addrid:	address ID
71310696SDavid.Hollister@Sun.COM  * cfg_priv:	configuration private data
71410696SDavid.Hollister@Sun.COM  *
71510696SDavid.Hollister@Sun.COM  */
71610696SDavid.Hollister@Sun.COM void
71711068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
71810696SDavid.Hollister@Sun.COM {
71910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
72010696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
72110696SDavid.Hollister@Sun.COM 
72211068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
72311068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
72410696SDavid.Hollister@Sun.COM 	if (!passp) {
72511068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
72610696SDavid.Hollister@Sun.COM 		return;
72710696SDavid.Hollister@Sun.COM 	}
72810696SDavid.Hollister@Sun.COM 	passp->da_cfg_priv = cfg_priv;
72911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
73010696SDavid.Hollister@Sun.COM }
73110696SDavid.Hollister@Sun.COM 
73210696SDavid.Hollister@Sun.COM /*
73310696SDavid.Hollister@Sun.COM  * Get config private data
73410696SDavid.Hollister@Sun.COM  *
73510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
73611068SJohn.Danielson@Sun.COM  * addrid:	address ID
73710696SDavid.Hollister@Sun.COM  *
73810696SDavid.Hollister@Sun.COM  * Returns:	configuration private data
73910696SDavid.Hollister@Sun.COM  */
74010696SDavid.Hollister@Sun.COM void *
74111068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
74210696SDavid.Hollister@Sun.COM {
74310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
74410696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
74510696SDavid.Hollister@Sun.COM 	void *rv;
74610696SDavid.Hollister@Sun.COM 
74711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
74811068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
74910696SDavid.Hollister@Sun.COM 	if (!passp) {
75011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
75110696SDavid.Hollister@Sun.COM 		return (NULL);
75210696SDavid.Hollister@Sun.COM 	}
75310696SDavid.Hollister@Sun.COM 	rv = passp->da_cfg_priv;
75411068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
75510696SDavid.Hollister@Sun.COM 	return (rv);
75610696SDavid.Hollister@Sun.COM }
75710696SDavid.Hollister@Sun.COM 
75810696SDavid.Hollister@Sun.COM /*
75910696SDavid.Hollister@Sun.COM  * Lookup a single address in the active address map
76010696SDavid.Hollister@Sun.COM  *
76110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
76210696SDavid.Hollister@Sun.COM  * address:	address string
76310696SDavid.Hollister@Sun.COM  *
76410696SDavid.Hollister@Sun.COM  * Returns:	ID of active/stable address
76510696SDavid.Hollister@Sun.COM  *		0	Address not in stable set
76610696SDavid.Hollister@Sun.COM  *
76710696SDavid.Hollister@Sun.COM  * Future: Allow the caller to wait for stabilize before returning not found.
76810696SDavid.Hollister@Sun.COM  */
76910696SDavid.Hollister@Sun.COM damap_id_t
77010696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address)
77110696SDavid.Hollister@Sun.COM {
77210696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
77310696SDavid.Hollister@Sun.COM 	id_t addrid = 0;
77410696SDavid.Hollister@Sun.COM 	dam_da_t *passp = NULL;
77510696SDavid.Hollister@Sun.COM 
77611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
77711068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
77811068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
77911068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high)
78011068SJohn.Danielson@Sun.COM 		addrid = 0;
78111068SJohn.Danielson@Sun.COM 	else
78211068SJohn.Danielson@Sun.COM 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
78310696SDavid.Hollister@Sun.COM 	if (addrid) {
78410696SDavid.Hollister@Sun.COM 		if (DAM_IS_STABLE(mapp, addrid)) {
78510696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
78610696SDavid.Hollister@Sun.COM 			ASSERT(passp);
78710696SDavid.Hollister@Sun.COM 			if (passp) {
78810696SDavid.Hollister@Sun.COM 				passp->da_ref++;
78910696SDavid.Hollister@Sun.COM 			} else {
79010696SDavid.Hollister@Sun.COM 				addrid = 0;
79110696SDavid.Hollister@Sun.COM 			}
79210696SDavid.Hollister@Sun.COM 		} else {
79310696SDavid.Hollister@Sun.COM 			addrid = 0;
79410696SDavid.Hollister@Sun.COM 		}
79510696SDavid.Hollister@Sun.COM 	}
79611068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
79711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
79811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp, int, addrid);
79910696SDavid.Hollister@Sun.COM 	return ((damap_id_t)addrid);
80010696SDavid.Hollister@Sun.COM }
80110696SDavid.Hollister@Sun.COM 
80210696SDavid.Hollister@Sun.COM 
80310696SDavid.Hollister@Sun.COM /*
80410696SDavid.Hollister@Sun.COM  * Return the list of stable addresses in the map
80510696SDavid.Hollister@Sun.COM  *
80610696SDavid.Hollister@Sun.COM  * damapp:	address map handle
80710696SDavid.Hollister@Sun.COM  * id_listp:	pointer to list of address IDs in stable map (returned)
80810696SDavid.Hollister@Sun.COM  *
80910696SDavid.Hollister@Sun.COM  * Returns:	# of entries returned in alist
81010696SDavid.Hollister@Sun.COM  */
81110696SDavid.Hollister@Sun.COM int
81210696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
81310696SDavid.Hollister@Sun.COM {
81410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
81510696SDavid.Hollister@Sun.COM 	int mapsz = mapp->dam_size;
81610696SDavid.Hollister@Sun.COM 	int n_ids, i;
81710696SDavid.Hollister@Sun.COM 	bitset_t *bsp;
81811068SJohn.Danielson@Sun.COM 	char	 *addrp;
81910696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
82010696SDavid.Hollister@Sun.COM 
82111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
82211068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
82311068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
82411068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high) {
82511068SJohn.Danielson@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
82611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
82711068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
82811068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp, int, 0);
82911068SJohn.Danielson@Sun.COM 		return (0);
83011068SJohn.Danielson@Sun.COM 	}
83110696SDavid.Hollister@Sun.COM 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
83210696SDavid.Hollister@Sun.COM 	bitset_init(bsp);
83310696SDavid.Hollister@Sun.COM 	bitset_resize(bsp, mapsz);
83410696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, bsp);
83510696SDavid.Hollister@Sun.COM 	for (n_ids = 0, i = 1; i < mapsz; i++) {
83610696SDavid.Hollister@Sun.COM 		if (bitset_in_set(bsp, i)) {
83710696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, i);
83810696SDavid.Hollister@Sun.COM 			ASSERT(passp);
83910696SDavid.Hollister@Sun.COM 			if (passp) {
84011068SJohn.Danielson@Sun.COM 				addrp = damap_id2addr(damapp, i);
84111068SJohn.Danielson@Sun.COM 				DTRACE_PROBE3(damap__lookup__all__item, char *,
84211068SJohn.Danielson@Sun.COM 				    mapp->dam_name, char *, addrp, dam_t *,
84311068SJohn.Danielson@Sun.COM 				    mapp);
84410696SDavid.Hollister@Sun.COM 				passp->da_ref++;
84510696SDavid.Hollister@Sun.COM 				n_ids++;
84610696SDavid.Hollister@Sun.COM 			}
84710696SDavid.Hollister@Sun.COM 		}
84810696SDavid.Hollister@Sun.COM 	}
84910696SDavid.Hollister@Sun.COM 	if (n_ids) {
85010696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)bsp;
85111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
85210696SDavid.Hollister@Sun.COM 		return (n_ids);
85310696SDavid.Hollister@Sun.COM 	} else {
85410696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
85510696SDavid.Hollister@Sun.COM 		bitset_fini(bsp);
85610696SDavid.Hollister@Sun.COM 		kmem_free(bsp, sizeof (*bsp));
85711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
85810696SDavid.Hollister@Sun.COM 		return (0);
85910696SDavid.Hollister@Sun.COM 	}
86010696SDavid.Hollister@Sun.COM }
86110696SDavid.Hollister@Sun.COM 
86210696SDavid.Hollister@Sun.COM /*
86310696SDavid.Hollister@Sun.COM  * Release the address list returned by damap_lookup_all()
86410696SDavid.Hollister@Sun.COM  *
86510696SDavid.Hollister@Sun.COM  * mapp:	address map handle
86610696SDavid.Hollister@Sun.COM  * id_list:	list of address IDs returned in damap_lookup_all()
86710696SDavid.Hollister@Sun.COM  */
86810696SDavid.Hollister@Sun.COM void
86910696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
87010696SDavid.Hollister@Sun.COM {
87110696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
87210696SDavid.Hollister@Sun.COM 	int i;
87310696SDavid.Hollister@Sun.COM 
87410696SDavid.Hollister@Sun.COM 	if (id_list == NULL)
87510696SDavid.Hollister@Sun.COM 		return;
87610696SDavid.Hollister@Sun.COM 
87711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
87810696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
87910696SDavid.Hollister@Sun.COM 		if (bitset_in_set((bitset_t *)id_list, i))
88011068SJohn.Danielson@Sun.COM 			(void) dam_addr_release(mapp, i);
88110696SDavid.Hollister@Sun.COM 	}
88211068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
88310696SDavid.Hollister@Sun.COM 	bitset_fini((bitset_t *)id_list);
88410696SDavid.Hollister@Sun.COM 	kmem_free((void *)id_list, sizeof (bitset_t));
88510696SDavid.Hollister@Sun.COM }
88610696SDavid.Hollister@Sun.COM 
88710696SDavid.Hollister@Sun.COM /*
88811068SJohn.Danielson@Sun.COM  * activate an address that has passed the stabilization interval
88911068SJohn.Danielson@Sun.COM  */
89011068SJohn.Danielson@Sun.COM static void
89111068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid)
89211068SJohn.Danielson@Sun.COM {
89311068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
89411068SJohn.Danielson@Sun.COM 	int config_rv;
89511068SJohn.Danielson@Sun.COM 	char *addrstr;
89611068SJohn.Danielson@Sun.COM 
89711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
89811068SJohn.Danielson@Sun.COM 	bitset_add(&mapp->dam_active_set, addrid);
89911068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
90011068SJohn.Danielson@Sun.COM 	ASSERT(passp);
90111068SJohn.Danielson@Sun.COM 
90211068SJohn.Danielson@Sun.COM 	/*
90311068SJohn.Danielson@Sun.COM 	 * copy the reported nvlist and provider private data
90411068SJohn.Danielson@Sun.COM 	 */
90511068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
90611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
90711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
90811068SJohn.Danielson@Sun.COM 	passp->da_nvl = passp->da_nvl_rpt;
90911068SJohn.Danielson@Sun.COM 	passp->da_ppriv = passp->da_ppriv_rpt;
91011068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
91111068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
91211068SJohn.Danielson@Sun.COM 	passp->da_last_stable = gethrtime();
91311068SJohn.Danielson@Sun.COM 	passp->da_stable_cnt++;
91411068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
91511068SJohn.Danielson@Sun.COM 	if (mapp->dam_activate_cb) {
91611068SJohn.Danielson@Sun.COM 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
91711068SJohn.Danielson@Sun.COM 		    addrid, &passp->da_ppriv_rpt);
91811068SJohn.Danielson@Sun.COM 	}
91911068SJohn.Danielson@Sun.COM 
92011068SJohn.Danielson@Sun.COM 	/*
92111068SJohn.Danielson@Sun.COM 	 * call the address-specific configuration action as part of
92211068SJohn.Danielson@Sun.COM 	 * activation.
92311068SJohn.Danielson@Sun.COM 	 */
92411068SJohn.Danielson@Sun.COM 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
92511068SJohn.Danielson@Sun.COM 	    addrid);
92611068SJohn.Danielson@Sun.COM 	if (config_rv != DAM_SUCCESS) {
92711068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
92811068SJohn.Danielson@Sun.COM 		passp->da_flags |= DA_FAILED_CONFIG;
92911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
93011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__config__failure,
93111068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
93211363SReed.Liu@Sun.COM 		dam_deact_cleanup(mapp, addrid, addrstr,
93311363SReed.Liu@Sun.COM 		    DAMAP_DEACT_RSN_CFG_FAIL);
93411363SReed.Liu@Sun.COM 	} else {
93511363SReed.Liu@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__end, char *,
93611363SReed.Liu@Sun.COM 		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
93711068SJohn.Danielson@Sun.COM 	}
93811068SJohn.Danielson@Sun.COM }
93911068SJohn.Danielson@Sun.COM 
94011068SJohn.Danielson@Sun.COM /*
94111068SJohn.Danielson@Sun.COM  * deactivate a previously stable address
94211068SJohn.Danielson@Sun.COM  */
94311068SJohn.Danielson@Sun.COM static void
94411068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid)
94511068SJohn.Danielson@Sun.COM {
94611068SJohn.Danielson@Sun.COM 	char *addrstr;
94711068SJohn.Danielson@Sun.COM 
94811068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
94911068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
95011068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
95111068SJohn.Danielson@Sun.COM 
95211068SJohn.Danielson@Sun.COM 	/*
95311068SJohn.Danielson@Sun.COM 	 * call the unconfiguration callback
95411068SJohn.Danielson@Sun.COM 	 */
95511068SJohn.Danielson@Sun.COM 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
95611363SReed.Liu@Sun.COM 	dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
95711363SReed.Liu@Sun.COM }
95811363SReed.Liu@Sun.COM 
95911363SReed.Liu@Sun.COM static void
96011363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
96111363SReed.Liu@Sun.COM     damap_deact_rsn_t deact_rsn)
96211363SReed.Liu@Sun.COM {
96311363SReed.Liu@Sun.COM 	dam_da_t *passp;
96411363SReed.Liu@Sun.COM 
96511068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
96611068SJohn.Danielson@Sun.COM 	ASSERT(passp);
96711068SJohn.Danielson@Sun.COM 	if (mapp->dam_deactivate_cb)
96811068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
96911068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
97011363SReed.Liu@Sun.COM 		    addrid, passp->da_ppriv, deact_rsn);
97111068SJohn.Danielson@Sun.COM 
97211068SJohn.Danielson@Sun.COM 	/*
97311068SJohn.Danielson@Sun.COM 	 * clear the active bit and free the backing info for
97411068SJohn.Danielson@Sun.COM 	 * this address
97511068SJohn.Danielson@Sun.COM 	 */
97611068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
97711068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_active_set, addrid);
97811068SJohn.Danielson@Sun.COM 	passp->da_ppriv = NULL;
97911068SJohn.Danielson@Sun.COM 	if (passp->da_nvl)
98011068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl);
98111068SJohn.Danielson@Sun.COM 	passp->da_nvl = NULL;
98211068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
98311068SJohn.Danielson@Sun.COM 	if (passp->da_nvl_rpt)
98411068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
98511068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
98611068SJohn.Danielson@Sun.COM 
98711068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
98811068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
98911068SJohn.Danielson@Sun.COM 
99011068SJohn.Danielson@Sun.COM 	(void) dam_addr_release(mapp, addrid);
99111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
99211068SJohn.Danielson@Sun.COM }
99311068SJohn.Danielson@Sun.COM 
99411068SJohn.Danielson@Sun.COM /*
99511068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread activation
99611068SJohn.Danielson@Sun.COM  */
99711068SJohn.Danielson@Sun.COM static void
99811068SJohn.Danielson@Sun.COM dam_tq_config(void *arg)
99911068SJohn.Danielson@Sun.COM {
100011068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
100111068SJohn.Danielson@Sun.COM 
100211068SJohn.Danielson@Sun.COM 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
100311068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
100411068SJohn.Danielson@Sun.COM }
100511068SJohn.Danielson@Sun.COM 
100611068SJohn.Danielson@Sun.COM /*
100711068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread deactivation
100811068SJohn.Danielson@Sun.COM  */
100911068SJohn.Danielson@Sun.COM static void
101011068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg)
101111068SJohn.Danielson@Sun.COM {
101211068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
101311068SJohn.Danielson@Sun.COM 
101411068SJohn.Danielson@Sun.COM 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
101511068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
101611068SJohn.Danielson@Sun.COM }
101711068SJohn.Danielson@Sun.COM 
101811068SJohn.Danielson@Sun.COM /*
101910696SDavid.Hollister@Sun.COM  * Activate a set of stabilized addresses
102010696SDavid.Hollister@Sun.COM  */
102110696SDavid.Hollister@Sun.COM static void
102211068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate)
102310696SDavid.Hollister@Sun.COM {
102411068SJohn.Danielson@Sun.COM 
102511068SJohn.Danielson@Sun.COM 	int i, nset;
102611068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
102711068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
102811068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
102911068SJohn.Danielson@Sun.COM 	extern pri_t maxclsyspri;
103010696SDavid.Hollister@Sun.COM 
103111068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
103211068SJohn.Danielson@Sun.COM 		/*
103311068SJohn.Danielson@Sun.COM 		 * calculate the # of taskq threads to create
103411068SJohn.Danielson@Sun.COM 		 */
103511068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
103611068SJohn.Danielson@Sun.COM 			if (bitset_in_set(activate, i))
103711068SJohn.Danielson@Sun.COM 				nset++;
103811068SJohn.Danielson@Sun.COM 		ASSERT(nset);
103911068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
104011068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
104111068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
104211068SJohn.Danielson@Sun.COM 	}
104310696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
104411068SJohn.Danielson@Sun.COM 		if (bitset_in_set(activate, i)) {
104511068SJohn.Danielson@Sun.COM 			if (!tqp)
104611068SJohn.Danielson@Sun.COM 				dam_addr_activate(mapp, i);
104711068SJohn.Danielson@Sun.COM 			else {
104811068SJohn.Danielson@Sun.COM 				/*
104911068SJohn.Danielson@Sun.COM 				 * multi-threaded activation
105011068SJohn.Danielson@Sun.COM 				 */
105111068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
105211068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
105311068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
105411068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp, dam_tq_config,
105511068SJohn.Danielson@Sun.COM 				    tqd, KM_SLEEP);
105611068SJohn.Danielson@Sun.COM 			}
105710696SDavid.Hollister@Sun.COM 		}
105811068SJohn.Danielson@Sun.COM 	}
105911068SJohn.Danielson@Sun.COM 	if (tqp) {
106011068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
106111068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
106210696SDavid.Hollister@Sun.COM 	}
106310696SDavid.Hollister@Sun.COM }
106410696SDavid.Hollister@Sun.COM 
106510696SDavid.Hollister@Sun.COM /*
106611068SJohn.Danielson@Sun.COM  * Deactivate a set of stabilized addresses
106710696SDavid.Hollister@Sun.COM  */
106810696SDavid.Hollister@Sun.COM static void
106911068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
107010696SDavid.Hollister@Sun.COM {
107111068SJohn.Danielson@Sun.COM 	int i, nset;
107211068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
107311068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
107411068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
107511068SJohn.Danielson@Sun.COM 
107611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
107711068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
107810696SDavid.Hollister@Sun.COM 
107911068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
108011068SJohn.Danielson@Sun.COM 		/*
108111068SJohn.Danielson@Sun.COM 		 * compute the # of taskq threads to dispatch
108211068SJohn.Danielson@Sun.COM 		 */
108311068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
108411068SJohn.Danielson@Sun.COM 			if (bitset_in_set(deactivate, i))
108511068SJohn.Danielson@Sun.COM 				nset++;
108611068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
108711068SJohn.Danielson@Sun.COM 		    mapp->dam_name);
108811068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
108911068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
109011068SJohn.Danielson@Sun.COM 	}
109110696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
109211068SJohn.Danielson@Sun.COM 		if (bitset_in_set(deactivate, i)) {
109311068SJohn.Danielson@Sun.COM 			if (!tqp) {
109411068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
109511068SJohn.Danielson@Sun.COM 			} else {
109611068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
109711068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
109811068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
109911068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp,
110011068SJohn.Danielson@Sun.COM 				    dam_tq_unconfig, tqd, KM_SLEEP);
110111068SJohn.Danielson@Sun.COM 			}
110210696SDavid.Hollister@Sun.COM 		}
110310696SDavid.Hollister@Sun.COM 	}
110411068SJohn.Danielson@Sun.COM 
110511068SJohn.Danielson@Sun.COM 	if (tqp) {
110611068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
110711068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
110811068SJohn.Danielson@Sun.COM 	}
110910696SDavid.Hollister@Sun.COM }
111010696SDavid.Hollister@Sun.COM 
111110696SDavid.Hollister@Sun.COM /*
111211068SJohn.Danielson@Sun.COM  * Release a previously activated address
111310696SDavid.Hollister@Sun.COM  */
111410696SDavid.Hollister@Sun.COM static void
111511068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid)
111610696SDavid.Hollister@Sun.COM {
111710696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
111811068SJohn.Danielson@Sun.COM 	char	 *addrstr;
111910696SDavid.Hollister@Sun.COM 
112011068SJohn.Danielson@Sun.COM 
112111068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
112210696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
112310696SDavid.Hollister@Sun.COM 	ASSERT(passp);
112410696SDavid.Hollister@Sun.COM 
112511068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
112611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
112711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
112810696SDavid.Hollister@Sun.COM 
112910696SDavid.Hollister@Sun.COM 	/*
113011068SJohn.Danielson@Sun.COM 	 * defer releasing the address until outstanding references
113111068SJohn.Danielson@Sun.COM 	 * are released
113210696SDavid.Hollister@Sun.COM 	 */
113311068SJohn.Danielson@Sun.COM 	if (passp->da_ref > 1) {
113411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
113511068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
113611068SJohn.Danielson@Sun.COM 		    int, passp->da_ref);
113710696SDavid.Hollister@Sun.COM 		return;
113811068SJohn.Danielson@Sun.COM 	}
113910696SDavid.Hollister@Sun.COM 
114010696SDavid.Hollister@Sun.COM 	/*
114111068SJohn.Danielson@Sun.COM 	 * allow pending reports to stabilize
114210696SDavid.Hollister@Sun.COM 	 */
114311068SJohn.Danielson@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
114411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__release__report__pending,
114511068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
114610696SDavid.Hollister@Sun.COM 		return;
114710696SDavid.Hollister@Sun.COM 	}
114811068SJohn.Danielson@Sun.COM 
114910696SDavid.Hollister@Sun.COM 	ddi_strid_free(mapp->dam_addr_hash, addrid);
115010696SDavid.Hollister@Sun.COM 	ddi_soft_state_free(mapp->dam_da, addrid);
115110696SDavid.Hollister@Sun.COM }
115210696SDavid.Hollister@Sun.COM 
115310696SDavid.Hollister@Sun.COM /*
115410696SDavid.Hollister@Sun.COM  * process stabilized address reports
115510696SDavid.Hollister@Sun.COM  */
115610696SDavid.Hollister@Sun.COM static void
115711068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg)
115810696SDavid.Hollister@Sun.COM {
115910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
116010696SDavid.Hollister@Sun.COM 	bitset_t delta;
116110696SDavid.Hollister@Sun.COM 	bitset_t cfg;
116210696SDavid.Hollister@Sun.COM 	bitset_t uncfg;
116310696SDavid.Hollister@Sun.COM 	int has_cfg, has_uncfg;
116411068SJohn.Danielson@Sun.COM 	uint32_t i, n_active;
116511068SJohn.Danielson@Sun.COM 
116611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
116711068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
116810696SDavid.Hollister@Sun.COM 
116910696SDavid.Hollister@Sun.COM 	bitset_init(&delta);
117010696SDavid.Hollister@Sun.COM 	bitset_resize(&delta, mapp->dam_size);
117110696SDavid.Hollister@Sun.COM 	bitset_init(&cfg);
117210696SDavid.Hollister@Sun.COM 	bitset_resize(&cfg, mapp->dam_size);
117310696SDavid.Hollister@Sun.COM 	bitset_init(&uncfg);
117410696SDavid.Hollister@Sun.COM 	bitset_resize(&uncfg, mapp->dam_size);
117510696SDavid.Hollister@Sun.COM 
117611068SJohn.Danielson@Sun.COM 	/*
117711068SJohn.Danielson@Sun.COM 	 * determine which addresses have changed during
117811068SJohn.Danielson@Sun.COM 	 * this stabilization cycle
117911068SJohn.Danielson@Sun.COM 	 */
118011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
118111068SJohn.Danielson@Sun.COM 	ASSERT(mapp->dam_flags & DAM_SPEND);
118210696SDavid.Hollister@Sun.COM 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
118310696SDavid.Hollister@Sun.COM 	    &delta)) {
118411068SJohn.Danielson@Sun.COM 		/*
118511068SJohn.Danielson@Sun.COM 		 * no difference
118611068SJohn.Danielson@Sun.COM 		 */
118710696SDavid.Hollister@Sun.COM 		bitset_zero(&mapp->dam_stable_set);
118811068SJohn.Danielson@Sun.COM 		mapp->dam_flags  &= ~DAM_SPEND;
118911068SJohn.Danielson@Sun.COM 		cv_signal(&mapp->dam_cv);
119011068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
119110696SDavid.Hollister@Sun.COM 		bitset_fini(&uncfg);
119210696SDavid.Hollister@Sun.COM 		bitset_fini(&cfg);
119310696SDavid.Hollister@Sun.COM 		bitset_fini(&delta);
119411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
119511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
119610696SDavid.Hollister@Sun.COM 		return;
119710696SDavid.Hollister@Sun.COM 	}
119811068SJohn.Danielson@Sun.COM 
119911068SJohn.Danielson@Sun.COM 	/*
120011068SJohn.Danielson@Sun.COM 	 * compute the sets of addresses to be activated and deactivated
120111068SJohn.Danielson@Sun.COM 	 */
120210696SDavid.Hollister@Sun.COM 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
120310696SDavid.Hollister@Sun.COM 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
120411068SJohn.Danielson@Sun.COM 
120511068SJohn.Danielson@Sun.COM 	/*
120611068SJohn.Danielson@Sun.COM 	 * drop map lock while invoking callouts
120711068SJohn.Danielson@Sun.COM 	 */
120811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
120911068SJohn.Danielson@Sun.COM 
121011068SJohn.Danielson@Sun.COM 	/*
121111068SJohn.Danielson@Sun.COM 	 * activate all newly stable addresss
121211068SJohn.Danielson@Sun.COM 	 */
121311068SJohn.Danielson@Sun.COM 	if (has_cfg)
121410696SDavid.Hollister@Sun.COM 		dam_addrset_activate(mapp, &cfg);
121511068SJohn.Danielson@Sun.COM 
121611068SJohn.Danielson@Sun.COM 	/*
121711068SJohn.Danielson@Sun.COM 	 * deactivate addresss which are no longer in the map
121811068SJohn.Danielson@Sun.COM 	 */
121911068SJohn.Danielson@Sun.COM 	if (has_uncfg)
122011068SJohn.Danielson@Sun.COM 		dam_addrset_deactivate(mapp, &uncfg);
122111068SJohn.Danielson@Sun.COM 
122211068SJohn.Danielson@Sun.COM 
122311068SJohn.Danielson@Sun.COM 	/*
122411068SJohn.Danielson@Sun.COM 	 * timestamp the last stable time and increment the kstat keeping
122511068SJohn.Danielson@Sun.COM 	 * the # of of stable cycles for the map
122611068SJohn.Danielson@Sun.COM 	 */
122711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
122810696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_stable_set);
122910696SDavid.Hollister@Sun.COM 	mapp->dam_last_stable = gethrtime();
123010696SDavid.Hollister@Sun.COM 	mapp->dam_stable_cnt++;
123111068SJohn.Danielson@Sun.COM 	DAM_INCR_STAT(mapp, dam_cycles);
123211068SJohn.Danielson@Sun.COM 
123311068SJohn.Danielson@Sun.COM 	/*
123411068SJohn.Danielson@Sun.COM 	 * determine the number of stable addresses
123511068SJohn.Danielson@Sun.COM 	 * and update the n_active kstat for this map
123611068SJohn.Danielson@Sun.COM 	 */
123711068SJohn.Danielson@Sun.COM 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
123811068SJohn.Danielson@Sun.COM 		if (bitset_in_set(&mapp->dam_active_set, i))
123911068SJohn.Danielson@Sun.COM 			n_active++;
124011068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_active, n_active);
124111068SJohn.Danielson@Sun.COM 
124211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
124311068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, n_active);
124411068SJohn.Danielson@Sun.COM 
124511068SJohn.Danielson@Sun.COM 	mapp->dam_flags  &= ~DAM_SPEND;
124611068SJohn.Danielson@Sun.COM 	cv_signal(&mapp->dam_cv);
124711068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
124810696SDavid.Hollister@Sun.COM 	bitset_fini(&uncfg);
124910696SDavid.Hollister@Sun.COM 	bitset_fini(&cfg);
125010696SDavid.Hollister@Sun.COM 	bitset_fini(&delta);
125110696SDavid.Hollister@Sun.COM }
125210696SDavid.Hollister@Sun.COM 
125310696SDavid.Hollister@Sun.COM /*
125410696SDavid.Hollister@Sun.COM  * per-address stabilization timeout
125510696SDavid.Hollister@Sun.COM  */
125610696SDavid.Hollister@Sun.COM static void
125710696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg)
125810696SDavid.Hollister@Sun.COM {
125910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
126010696SDavid.Hollister@Sun.COM 	int i;
126110696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
126210696SDavid.Hollister@Sun.COM 	int spend = 0;
126310696SDavid.Hollister@Sun.COM 	int tpend = 0;
126410696SDavid.Hollister@Sun.COM 	int64_t	next_tmov = mapp->dam_stabletmo;
126510696SDavid.Hollister@Sun.COM 	int64_t tmo_delta;
126611066Srafael.vanoni@sun.com 	int64_t ts = ddi_get_lbolt64();
126710696SDavid.Hollister@Sun.COM 
126811068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
126910696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
127011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
127111068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
127211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
127310696SDavid.Hollister@Sun.COM 		return;
127410696SDavid.Hollister@Sun.COM 	}
127510696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
127611068SJohn.Danielson@Sun.COM 
127710696SDavid.Hollister@Sun.COM 	/*
127810696SDavid.Hollister@Sun.COM 	 * If still under stabilization, reschedule timeout,
127911068SJohn.Danielson@Sun.COM 	 * otherwise dispatch the task to activate and deactivate the
128011068SJohn.Danielson@Sun.COM 	 * new stable address
128110696SDavid.Hollister@Sun.COM 	 */
128210696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SPEND) {
128311068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
128410696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
128510696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
128611068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
128711068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
128811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
128910696SDavid.Hollister@Sun.COM 		return;
129010696SDavid.Hollister@Sun.COM 	}
129110696SDavid.Hollister@Sun.COM 
129211068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
129311068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
129411068SJohn.Danielson@Sun.COM 
129511068SJohn.Danielson@Sun.COM 	/*
129611068SJohn.Danielson@Sun.COM 	 * copy the current active set to the stable map
129711068SJohn.Danielson@Sun.COM 	 * for each address being reported, decrement its
129811068SJohn.Danielson@Sun.COM 	 * stabilize deadline, and if stable, add or remove the
129911068SJohn.Danielson@Sun.COM 	 * address from the stable set
130011068SJohn.Danielson@Sun.COM 	 */
130110696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
130210696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
130310696SDavid.Hollister@Sun.COM 		if (!bitset_in_set(&mapp->dam_report_set, i))
130410696SDavid.Hollister@Sun.COM 			continue;
130510696SDavid.Hollister@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, i);
130610696SDavid.Hollister@Sun.COM 		ASSERT(passp);
130710696SDavid.Hollister@Sun.COM 
130810696SDavid.Hollister@Sun.COM 		/* report has stabilized */
130910696SDavid.Hollister@Sun.COM 		if (passp->da_deadline <= ts) {
131010696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_report_set, i);
131111068SJohn.Danielson@Sun.COM 			if (passp->da_flags & DA_RELE)
131210696SDavid.Hollister@Sun.COM 				bitset_del(&mapp->dam_stable_set, i);
131311068SJohn.Danielson@Sun.COM 			else
131410696SDavid.Hollister@Sun.COM 				bitset_add(&mapp->dam_stable_set, i);
131510696SDavid.Hollister@Sun.COM 			spend++;
131610696SDavid.Hollister@Sun.COM 			continue;
131710696SDavid.Hollister@Sun.COM 		}
131810696SDavid.Hollister@Sun.COM 
131910696SDavid.Hollister@Sun.COM 		/*
132011068SJohn.Danielson@Sun.COM 		 * not stabilized, determine next map timeout
132110696SDavid.Hollister@Sun.COM 		 */
132210696SDavid.Hollister@Sun.COM 		tpend++;
132310696SDavid.Hollister@Sun.COM 		tmo_delta = passp->da_deadline - ts;
132410696SDavid.Hollister@Sun.COM 		if (tmo_delta < next_tmov)
132510696SDavid.Hollister@Sun.COM 			next_tmov = tmo_delta;
132610696SDavid.Hollister@Sun.COM 	}
132710696SDavid.Hollister@Sun.COM 
132810696SDavid.Hollister@Sun.COM 	/*
132911068SJohn.Danielson@Sun.COM 	 * schedule system_taskq activation of stabilized reports
133010696SDavid.Hollister@Sun.COM 	 */
133110696SDavid.Hollister@Sun.COM 	if (spend) {
133211068SJohn.Danielson@Sun.COM 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
133311068SJohn.Danielson@Sun.COM 		    mapp, TQ_NOSLEEP)) {
133411068SJohn.Danielson@Sun.COM 			mapp->dam_flags  |= DAM_SPEND;
133511068SJohn.Danielson@Sun.COM 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
133611068SJohn.Danielson@Sun.COM 			    mapp->dam_name, dam_t *, mapp);
133711068SJohn.Danielson@Sun.COM 		} else {
133810696SDavid.Hollister@Sun.COM 			tpend++;
133911068SJohn.Danielson@Sun.COM 		}
134010696SDavid.Hollister@Sun.COM 	}
134110696SDavid.Hollister@Sun.COM 
134210696SDavid.Hollister@Sun.COM 	/*
134311068SJohn.Danielson@Sun.COM 	 * reschedule the stabilization timer if there are reports
134411068SJohn.Danielson@Sun.COM 	 * still pending
134510696SDavid.Hollister@Sun.COM 	 */
134610696SDavid.Hollister@Sun.COM 	if (tpend)
134710696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
134811068SJohn.Danielson@Sun.COM 
134911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
135010696SDavid.Hollister@Sun.COM }
135110696SDavid.Hollister@Sun.COM 
135210696SDavid.Hollister@Sun.COM /*
135311068SJohn.Danielson@Sun.COM  * fullset stabilization timeout callback
135410696SDavid.Hollister@Sun.COM  */
135510696SDavid.Hollister@Sun.COM static void
135611068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg)
135710696SDavid.Hollister@Sun.COM {
135810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
135910696SDavid.Hollister@Sun.COM 
136011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
136110696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
136211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
136311068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
136411068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, dam_t *, mapp);
136510696SDavid.Hollister@Sun.COM 		return;
136610696SDavid.Hollister@Sun.COM 	}
136710696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
136810696SDavid.Hollister@Sun.COM 
136910696SDavid.Hollister@Sun.COM 	/*
137011068SJohn.Danielson@Sun.COM 	 * If map still underoing stabilization reschedule timeout,
137111068SJohn.Danielson@Sun.COM 	 * else dispatch the task to configure the new stable set of
137211068SJohn.Danielson@Sun.COM 	 * addresses.
137310696SDavid.Hollister@Sun.COM 	 */
137411068SJohn.Danielson@Sun.COM 	if ((mapp->dam_flags & DAM_SPEND) || (taskq_dispatch(system_taskq,
137511068SJohn.Danielson@Sun.COM 	    dam_stabilize_map, mapp, TQ_NOSLEEP) == NULL)) {
137611068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
137710696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
137811068SJohn.Danielson@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
137911068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
138011068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
138111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
138211068SJohn.Danielson@Sun.COM 		return;
138310696SDavid.Hollister@Sun.COM 	}
138411068SJohn.Danielson@Sun.COM 
138511068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
138611068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
138711068SJohn.Danielson@Sun.COM 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
138811068SJohn.Danielson@Sun.COM 	bitset_zero(&mapp->dam_report_set);
138911068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_SPEND;
139011068SJohn.Danielson@Sun.COM 	mapp->dam_flags &= ~DAM_SETADD;
139111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
139211068SJohn.Danielson@Sun.COM 	    mapp->dam_name, dam_t *, mapp);
139311068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
139410696SDavid.Hollister@Sun.COM }
139510696SDavid.Hollister@Sun.COM 
139610696SDavid.Hollister@Sun.COM /*
139711068SJohn.Danielson@Sun.COM  * schedule map timeout 'tmo_ms' ticks
139811068SJohn.Danielson@Sun.COM  * if map timer is currently running, cancel if tmo_ms == 0
139910696SDavid.Hollister@Sun.COM  */
140010696SDavid.Hollister@Sun.COM static void
140110696SDavid.Hollister@Sun.COM dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
140210696SDavid.Hollister@Sun.COM {
140310696SDavid.Hollister@Sun.COM 	timeout_id_t tid;
140410696SDavid.Hollister@Sun.COM 
140511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp,
140611068SJohn.Danielson@Sun.COM 	    clock_t, tmo_ms);
140711068SJohn.Danielson@Sun.COM 
140811068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
140910696SDavid.Hollister@Sun.COM 	if ((tid = mapp->dam_tid) != 0) {
141011068SJohn.Danielson@Sun.COM 		if (tmo_ms == 0) {
141111068SJohn.Danielson@Sun.COM 			mapp->dam_tid = 0;
141211068SJohn.Danielson@Sun.COM 			mutex_exit(&mapp->dam_lock);
141311068SJohn.Danielson@Sun.COM 			(void) untimeout(tid);
141411068SJohn.Danielson@Sun.COM 			mutex_enter(&mapp->dam_lock);
141511068SJohn.Danielson@Sun.COM 		}
141611068SJohn.Danielson@Sun.COM 	} else {
141711068SJohn.Danielson@Sun.COM 		if (tmo_cb && (tmo_ms != 0))
141811068SJohn.Danielson@Sun.COM 			mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
141910696SDavid.Hollister@Sun.COM 	}
142010696SDavid.Hollister@Sun.COM }
142110696SDavid.Hollister@Sun.COM 
142210696SDavid.Hollister@Sun.COM /*
142311068SJohn.Danielson@Sun.COM  * report addition or removal of an address
142410696SDavid.Hollister@Sun.COM  */
142510696SDavid.Hollister@Sun.COM static void
142611068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
142710696SDavid.Hollister@Sun.COM {
142811068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
142911068SJohn.Danielson@Sun.COM 
143011068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
143111068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
143211068SJohn.Danielson@Sun.COM 
143311068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
143410696SDavid.Hollister@Sun.COM 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
143510696SDavid.Hollister@Sun.COM 	passp->da_last_report = gethrtime();
143610696SDavid.Hollister@Sun.COM 	mapp->dam_last_update = gethrtime();
143710696SDavid.Hollister@Sun.COM 	passp->da_report_cnt++;
143811066Srafael.vanoni@sun.com 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo;
143911068SJohn.Danielson@Sun.COM 	if (rpt_type == RPT_ADDR_DEL)
144010696SDavid.Hollister@Sun.COM 		passp->da_flags |= DA_RELE;
144111068SJohn.Danielson@Sun.COM 	else if (rpt_type == RPT_ADDR_ADD)
144210696SDavid.Hollister@Sun.COM 		passp->da_flags &= ~DA_RELE;
144310696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
144410696SDavid.Hollister@Sun.COM 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
144510696SDavid.Hollister@Sun.COM }
144610696SDavid.Hollister@Sun.COM 
144710696SDavid.Hollister@Sun.COM /*
144810696SDavid.Hollister@Sun.COM  * release an address report
144910696SDavid.Hollister@Sun.COM  */
145010696SDavid.Hollister@Sun.COM static void
145111068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid)
145210696SDavid.Hollister@Sun.COM {
145310696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
145411068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
145510696SDavid.Hollister@Sun.COM 
145611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
145711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
145811068SJohn.Danielson@Sun.COM 
145911068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
146010696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
146110696SDavid.Hollister@Sun.COM 	ASSERT(passp);
146211068SJohn.Danielson@Sun.COM 	/*
146311068SJohn.Danielson@Sun.COM 	 * clear the report bit
146411068SJohn.Danielson@Sun.COM 	 * if the address has a registered deactivation handler and
1465*11601SDavid.Hollister@Sun.COM 	 * we are holding a private data pointer and the address has not
1466*11601SDavid.Hollister@Sun.COM 	 * stabilized, deactivate the address (private data).
146711068SJohn.Danielson@Sun.COM 	 */
146811068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_report_set, addrid);
1469*11601SDavid.Hollister@Sun.COM 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1470*11601SDavid.Hollister@Sun.COM 	    passp->da_ppriv_rpt) {
147111068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
147211068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
147311068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1474*11601SDavid.Hollister@Sun.COM 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
147511068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
147611068SJohn.Danielson@Sun.COM 	}
147710696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = NULL;
147810696SDavid.Hollister@Sun.COM 	if (passp->da_nvl_rpt)
147910696SDavid.Hollister@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
148010696SDavid.Hollister@Sun.COM }
148110696SDavid.Hollister@Sun.COM 
148210696SDavid.Hollister@Sun.COM /*
148310696SDavid.Hollister@Sun.COM  * return the map ID of an address
148410696SDavid.Hollister@Sun.COM  */
148510696SDavid.Hollister@Sun.COM static id_t
148610696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address)
148710696SDavid.Hollister@Sun.COM {
148810696SDavid.Hollister@Sun.COM 	damap_id_t addrid;
148910696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
149010696SDavid.Hollister@Sun.COM 
149111068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
149210696SDavid.Hollister@Sun.COM 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
149311068SJohn.Danielson@Sun.COM 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
149410696SDavid.Hollister@Sun.COM 		    address)) == (damap_id_t)0) {
149510696SDavid.Hollister@Sun.COM 			return (0);
149610696SDavid.Hollister@Sun.COM 		}
149710696SDavid.Hollister@Sun.COM 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
149810696SDavid.Hollister@Sun.COM 		    DDI_SUCCESS) {
149910696SDavid.Hollister@Sun.COM 			ddi_strid_free(mapp->dam_addr_hash, addrid);
150010696SDavid.Hollister@Sun.COM 			return (0);
150110696SDavid.Hollister@Sun.COM 		}
150211068SJohn.Danielson@Sun.COM 
150310696SDavid.Hollister@Sun.COM 		if (addrid >= mapp->dam_high)
150410696SDavid.Hollister@Sun.COM 			mapp->dam_high = addrid + 1;
150511068SJohn.Danielson@Sun.COM 
150611068SJohn.Danielson@Sun.COM 		/*
150711068SJohn.Danielson@Sun.COM 		 * expand bitmaps if ID has outgrown old map size
150811068SJohn.Danielson@Sun.COM 		 */
150911068SJohn.Danielson@Sun.COM 		if (mapp->dam_high > mapp->dam_size) {
151011068SJohn.Danielson@Sun.COM 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
151111068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
151211068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
151311068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
151411068SJohn.Danielson@Sun.COM 		}
151511068SJohn.Danielson@Sun.COM 
151611068SJohn.Danielson@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
151711068SJohn.Danielson@Sun.COM 		passp->da_ref = 1;
151811068SJohn.Danielson@Sun.COM 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
151911068SJohn.Danielson@Sun.COM 		    addrid); /* for mdb */
152010696SDavid.Hollister@Sun.COM 	}
152110696SDavid.Hollister@Sun.COM 	return (addrid);
152210696SDavid.Hollister@Sun.COM }
152310696SDavid.Hollister@Sun.COM 
152410696SDavid.Hollister@Sun.COM /*
152510696SDavid.Hollister@Sun.COM  * create and install map statistics
152610696SDavid.Hollister@Sun.COM  */
152710696SDavid.Hollister@Sun.COM static int
152810696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp)
152910696SDavid.Hollister@Sun.COM {
153010696SDavid.Hollister@Sun.COM 	kstat_t			*mapsp;
153110696SDavid.Hollister@Sun.COM 	struct dam_kstats	*statsp;
153210696SDavid.Hollister@Sun.COM 
153310696SDavid.Hollister@Sun.COM 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
153410696SDavid.Hollister@Sun.COM 	    KSTAT_TYPE_NAMED,
153510696SDavid.Hollister@Sun.COM 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
153611068SJohn.Danielson@Sun.COM 
153711068SJohn.Danielson@Sun.COM 	if (mapsp == NULL)
153810696SDavid.Hollister@Sun.COM 		return (DDI_FAILURE);
153910696SDavid.Hollister@Sun.COM 
154010696SDavid.Hollister@Sun.COM 	statsp = (struct dam_kstats *)mapsp->ks_data;
154111068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
154211068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
154311068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
154411068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
154510696SDavid.Hollister@Sun.COM 	kstat_install(mapsp);
154610696SDavid.Hollister@Sun.COM 	mapp->dam_kstatsp = mapsp;
154710696SDavid.Hollister@Sun.COM 	return (DDI_SUCCESS);
154810696SDavid.Hollister@Sun.COM }
1549