xref: /onnv-gate/usr/src/uts/common/os/damap.c (revision 12207:877b2956883c)
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*12207SChris.Horne@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410696SDavid.Hollister@Sun.COM  */
2510696SDavid.Hollister@Sun.COM 
2610696SDavid.Hollister@Sun.COM #include <sys/note.h>
2710696SDavid.Hollister@Sun.COM #include <sys/types.h>
2810696SDavid.Hollister@Sun.COM #include <sys/param.h>
2910696SDavid.Hollister@Sun.COM #include <sys/systm.h>
3010696SDavid.Hollister@Sun.COM #include <sys/buf.h>
3110696SDavid.Hollister@Sun.COM #include <sys/kmem.h>
3210696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h>
3310696SDavid.Hollister@Sun.COM #include <sys/debug.h>
3410696SDavid.Hollister@Sun.COM #include <sys/sunndi.h>
3510696SDavid.Hollister@Sun.COM #include <sys/kstat.h>
3610696SDavid.Hollister@Sun.COM #include <sys/conf.h>
3710696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h>
3810696SDavid.Hollister@Sun.COM #include <sys/devctl.h>
3910696SDavid.Hollister@Sun.COM #include <sys/callb.h>
4010696SDavid.Hollister@Sun.COM #include <sys/sysevent.h>
4110696SDavid.Hollister@Sun.COM #include <sys/taskq.h>
4210696SDavid.Hollister@Sun.COM #include <sys/ddi.h>
4310696SDavid.Hollister@Sun.COM #include <sys/bitset.h>
4410696SDavid.Hollister@Sun.COM #include <sys/damap.h>
4510696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h>
4610696SDavid.Hollister@Sun.COM 
4710696SDavid.Hollister@Sun.COM #ifdef DEBUG
4810696SDavid.Hollister@Sun.COM static int damap_debug = 0;
4910696SDavid.Hollister@Sun.COM #endif /* DEBUG */
5010696SDavid.Hollister@Sun.COM 
5111068SJohn.Danielson@Sun.COM extern taskq_t *system_taskq;
5211068SJohn.Danielson@Sun.COM 
5310696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *);
5411068SJohn.Danielson@Sun.COM static void dam_addrset_deactivate(dam_t *, bitset_t *);
5511068SJohn.Danielson@Sun.COM static void dam_stabilize_map(void *);
5610696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *);
5711068SJohn.Danielson@Sun.COM static void dam_addrset_stable_cb(void *);
58*12207SChris.Horne@Sun.COM static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
5911068SJohn.Danielson@Sun.COM static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
6011068SJohn.Danielson@Sun.COM static void dam_addr_release(dam_t *, id_t);
6111068SJohn.Danielson@Sun.COM static void dam_addr_report_release(dam_t *, id_t);
6211068SJohn.Danielson@Sun.COM static void dam_addr_deactivate(dam_t *, id_t);
6311363SReed.Liu@Sun.COM static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
6410696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *);
6510696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *);
6611068SJohn.Danielson@Sun.COM static int dam_map_alloc(dam_t *);
6710696SDavid.Hollister@Sun.COM 
6810696SDavid.Hollister@Sun.COM #define	DAM_INCR_STAT(mapp, stat)				\
6910696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
7010696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
7110696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32++;				\
7210696SDavid.Hollister@Sun.COM 	}
7310696SDavid.Hollister@Sun.COM 
7410696SDavid.Hollister@Sun.COM #define	DAM_SET_STAT(mapp, stat, val)				\
7510696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
7610696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
7710696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32 = (val);			\
7810696SDavid.Hollister@Sun.COM 	}
7910696SDavid.Hollister@Sun.COM 
8011068SJohn.Danielson@Sun.COM 
8111068SJohn.Danielson@Sun.COM /*
8211068SJohn.Danielson@Sun.COM  * increase damap size by 64 entries at a time
8311068SJohn.Danielson@Sun.COM  */
8411068SJohn.Danielson@Sun.COM #define	DAM_SIZE_BUMP	64
8511068SJohn.Danielson@Sun.COM 
8611854SChris.Horne@Sun.COM int	damap_taskq_dispatch_retry_usec = 1000;
8711854SChris.Horne@Sun.COM 
8811068SJohn.Danielson@Sun.COM /*
8911068SJohn.Danielson@Sun.COM  * config/unconfig taskq data
9011068SJohn.Danielson@Sun.COM  */
9111068SJohn.Danielson@Sun.COM typedef struct {
9211068SJohn.Danielson@Sun.COM 	dam_t *tqd_mapp;
9311068SJohn.Danielson@Sun.COM 	id_t tqd_id;
9411068SJohn.Danielson@Sun.COM } cfg_tqd_t;
9511068SJohn.Danielson@Sun.COM 
9611068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri;
9711068SJohn.Danielson@Sun.COM 
9810696SDavid.Hollister@Sun.COM /*
9910696SDavid.Hollister@Sun.COM  * Create new device address map
10010696SDavid.Hollister@Sun.COM  *
10111068SJohn.Danielson@Sun.COM  * name:		map name (kstat unique)
10210696SDavid.Hollister@Sun.COM  * size:		max # of map entries
10311068SJohn.Danielson@Sun.COM  * mode:		style of address reports: per-address or fullset
10410696SDavid.Hollister@Sun.COM  * stable_usec:		# of quiescent microseconds before report/map is stable
10510696SDavid.Hollister@Sun.COM  *
10610696SDavid.Hollister@Sun.COM  * activate_arg:	address provider activation-callout private
10710696SDavid.Hollister@Sun.COM  * activate_cb:		address provider activation callback handler
10810696SDavid.Hollister@Sun.COM  * deactivate_cb:	address provider deactivation callback handler
10910696SDavid.Hollister@Sun.COM  *
11010696SDavid.Hollister@Sun.COM  * config_arg:		configuration-callout private
11110696SDavid.Hollister@Sun.COM  * config_cb:		class configuration callout
11210696SDavid.Hollister@Sun.COM  * unconfig_cb:		class unconfiguration callout
11310696SDavid.Hollister@Sun.COM  *
11410696SDavid.Hollister@Sun.COM  * damapp:		pointer to map handle (return)
11510696SDavid.Hollister@Sun.COM  *
11610696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
11710696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
11810696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
11910696SDavid.Hollister@Sun.COM  */
12010696SDavid.Hollister@Sun.COM int
12111068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts,
122*12207SChris.Horne@Sun.COM     int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
12310696SDavid.Hollister@Sun.COM     damap_deactivate_cb_t deactivate_cb,
12410696SDavid.Hollister@Sun.COM     void *config_arg, damap_configure_cb_t configure_cb,
12510696SDavid.Hollister@Sun.COM     damap_unconfig_cb_t unconfig_cb,
12610696SDavid.Hollister@Sun.COM     damap_t **damapp)
12710696SDavid.Hollister@Sun.COM {
12810696SDavid.Hollister@Sun.COM 	dam_t *mapp;
12910696SDavid.Hollister@Sun.COM 
13011068SJohn.Danielson@Sun.COM 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
13110696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
13210696SDavid.Hollister@Sun.COM 
13311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__create, char *, name,
134*12207SChris.Horne@Sun.COM 	    damap_rptmode_t, mode, int, stable_usec);
13510696SDavid.Hollister@Sun.COM 
13610696SDavid.Hollister@Sun.COM 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
13711068SJohn.Danielson@Sun.COM 	mapp->dam_options = map_opts;
138*12207SChris.Horne@Sun.COM 	mapp->dam_stable_ticks = drv_usectohz(stable_usec);
13911068SJohn.Danielson@Sun.COM 	mapp->dam_size = 0;
14011068SJohn.Danielson@Sun.COM 	mapp->dam_rptmode = mode;
14110696SDavid.Hollister@Sun.COM 	mapp->dam_activate_arg = activate_arg;
14210696SDavid.Hollister@Sun.COM 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
14310696SDavid.Hollister@Sun.COM 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
14410696SDavid.Hollister@Sun.COM 	mapp->dam_config_arg = config_arg;
14510696SDavid.Hollister@Sun.COM 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
14610696SDavid.Hollister@Sun.COM 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
14711068SJohn.Danielson@Sun.COM 	mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
14810696SDavid.Hollister@Sun.COM 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
149*12207SChris.Horne@Sun.COM 	cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
15011068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_active_set);
15111068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_stable_set);
15211068SJohn.Danielson@Sun.COM 	bitset_init(&mapp->dam_report_set);
15310696SDavid.Hollister@Sun.COM 	*damapp = (damap_t *)mapp;
15410696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
15510696SDavid.Hollister@Sun.COM }
15610696SDavid.Hollister@Sun.COM 
15710696SDavid.Hollister@Sun.COM /*
15811068SJohn.Danielson@Sun.COM  * Allocate backing resources
15911068SJohn.Danielson@Sun.COM  *
16011068SJohn.Danielson@Sun.COM  * DAMs are lightly backed on create - major allocations occur
16111068SJohn.Danielson@Sun.COM  * at the time a report is made to the map, and are extended on
16211068SJohn.Danielson@Sun.COM  * a demand basis.
16311068SJohn.Danielson@Sun.COM  */
16411068SJohn.Danielson@Sun.COM static int
16511068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp)
16611068SJohn.Danielson@Sun.COM {
16711068SJohn.Danielson@Sun.COM 	void *softstate_p;
16811068SJohn.Danielson@Sun.COM 
16911068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
17011068SJohn.Danielson@Sun.COM 	if (mapp->dam_flags & DAM_DESTROYPEND)
17111068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
17211068SJohn.Danielson@Sun.COM 
17311068SJohn.Danielson@Sun.COM 	/*
17411068SJohn.Danielson@Sun.COM 	 * dam_high > 0 signals map allocation complete
17511068SJohn.Danielson@Sun.COM 	 */
17611068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
17711068SJohn.Danielson@Sun.COM 		return (DAM_SUCCESS);
17811068SJohn.Danielson@Sun.COM 
17911068SJohn.Danielson@Sun.COM 	mapp->dam_size = DAM_SIZE_BUMP;
18011068SJohn.Danielson@Sun.COM 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
18111068SJohn.Danielson@Sun.COM 	    mapp->dam_size) != DDI_SUCCESS)
18211068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18311068SJohn.Danielson@Sun.COM 
18411068SJohn.Danielson@Sun.COM 	if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
18511068SJohn.Danielson@Sun.COM 	    DDI_SUCCESS) {
18611068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
18711068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
18811068SJohn.Danielson@Sun.COM 	}
18911068SJohn.Danielson@Sun.COM 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
19011068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(softstate_p);
19111068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
19211068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
19311068SJohn.Danielson@Sun.COM 	}
19411068SJohn.Danielson@Sun.COM 	mapp->dam_da = softstate_p;
19511068SJohn.Danielson@Sun.COM 	mapp->dam_high = 1;
19611068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_active_set, mapp->dam_size);
19711068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
19811068SJohn.Danielson@Sun.COM 	bitset_resize(&mapp->dam_report_set, mapp->dam_size);
19911068SJohn.Danielson@Sun.COM 	return (DAM_SUCCESS);
20011068SJohn.Danielson@Sun.COM }
20111068SJohn.Danielson@Sun.COM 
20211068SJohn.Danielson@Sun.COM /*
20311068SJohn.Danielson@Sun.COM  * Destroy address map
20410696SDavid.Hollister@Sun.COM  *
20510696SDavid.Hollister@Sun.COM  * damapp:	address map
20610696SDavid.Hollister@Sun.COM  *
20710696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
20810696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
20910696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
21010696SDavid.Hollister@Sun.COM  */
21110696SDavid.Hollister@Sun.COM void
21210696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp)
21310696SDavid.Hollister@Sun.COM {
21410696SDavid.Hollister@Sun.COM 	int i;
21510696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
21610696SDavid.Hollister@Sun.COM 
21710696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
21810696SDavid.Hollister@Sun.COM 
21911068SJohn.Danielson@Sun.COM 	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
22010696SDavid.Hollister@Sun.COM 
22111068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
22210696SDavid.Hollister@Sun.COM 
22310696SDavid.Hollister@Sun.COM 	/*
22411068SJohn.Danielson@Sun.COM 	 * prevent new reports from being added to the map
22510696SDavid.Hollister@Sun.COM 	 */
22611068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_DESTROYPEND;
22711068SJohn.Danielson@Sun.COM 
22811068SJohn.Danielson@Sun.COM 	if (mapp->dam_high) {
22911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
23011068SJohn.Danielson@Sun.COM 		/*
23111068SJohn.Danielson@Sun.COM 		 * wait for outstanding reports to stabilize and cancel
23211068SJohn.Danielson@Sun.COM 		 * the timer for this map
23311068SJohn.Danielson@Sun.COM 		 */
234*12207SChris.Horne@Sun.COM 		(void) damap_sync(damapp, 0);
23511068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
236*12207SChris.Horne@Sun.COM 		dam_sched_timeout(NULL, mapp, 0);
23710696SDavid.Hollister@Sun.COM 
23811068SJohn.Danielson@Sun.COM 		/*
23911068SJohn.Danielson@Sun.COM 		 * map is at full stop
24011068SJohn.Danielson@Sun.COM 		 * release the contents of the map, invoking the
24111068SJohn.Danielson@Sun.COM 		 * detactivation protocol as addresses are released
24211068SJohn.Danielson@Sun.COM 		 */
24311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
24411068SJohn.Danielson@Sun.COM 		for (i = 1; i < mapp->dam_high; i++) {
24511068SJohn.Danielson@Sun.COM 			if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
24611068SJohn.Danielson@Sun.COM 				continue;
24711068SJohn.Danielson@Sun.COM 
24811068SJohn.Danielson@Sun.COM 			ASSERT(DAM_IN_REPORT(mapp, i) == 0);
24911068SJohn.Danielson@Sun.COM 
25011068SJohn.Danielson@Sun.COM 			if (DAM_IS_STABLE(mapp, i)) {
25111068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
25211068SJohn.Danielson@Sun.COM 			} else {
25311068SJohn.Danielson@Sun.COM 				ddi_strid_free(mapp->dam_addr_hash, i);
25411068SJohn.Danielson@Sun.COM 				ddi_soft_state_free(mapp->dam_da, i);
25511068SJohn.Danielson@Sun.COM 			}
25611068SJohn.Danielson@Sun.COM 		}
25711068SJohn.Danielson@Sun.COM 		ddi_strid_fini(&mapp->dam_addr_hash);
25811068SJohn.Danielson@Sun.COM 		ddi_soft_state_fini(&mapp->dam_da);
25911068SJohn.Danielson@Sun.COM 		kstat_delete(mapp->dam_kstatsp);
260*12207SChris.Horne@Sun.COM 	} else
261*12207SChris.Horne@Sun.COM 		mutex_exit(&mapp->dam_lock);
262*12207SChris.Horne@Sun.COM 
26310696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_active_set);
26410696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_stable_set);
26510696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_report_set);
26610696SDavid.Hollister@Sun.COM 	mutex_destroy(&mapp->dam_lock);
267*12207SChris.Horne@Sun.COM 	cv_destroy(&mapp->dam_sync_cv);
26810696SDavid.Hollister@Sun.COM 	if (mapp->dam_name)
26910696SDavid.Hollister@Sun.COM 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
27010696SDavid.Hollister@Sun.COM 	kmem_free(mapp, sizeof (*mapp));
27110696SDavid.Hollister@Sun.COM }
27210696SDavid.Hollister@Sun.COM 
27310696SDavid.Hollister@Sun.COM /*
274*12207SChris.Horne@Sun.COM  * Wait for map stability.  If sync was successfull then return 1.
275*12207SChris.Horne@Sun.COM  * If called with a non-zero sync_usec, then a return value of 0 means a
276*12207SChris.Horne@Sun.COM  * timeout occurred prior to sync completion. NOTE: if sync_usec is
277*12207SChris.Horne@Sun.COM  * non-zero, it should be much longer than dam_stable_ticks.
27810696SDavid.Hollister@Sun.COM  *
27910696SDavid.Hollister@Sun.COM  * damapp:	address map
280*12207SChris.Horne@Sun.COM  * sync_usec:	micorseconds until we give up on sync completion.
28110696SDavid.Hollister@Sun.COM  */
282*12207SChris.Horne@Sun.COM #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
28310696SDavid.Hollister@Sun.COM int
284*12207SChris.Horne@Sun.COM damap_sync(damap_t *damapp, int sync_usec)
28510696SDavid.Hollister@Sun.COM {
286*12207SChris.Horne@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
287*12207SChris.Horne@Sun.COM 	int	rv;
28810696SDavid.Hollister@Sun.COM 
28910696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
29011068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
29111068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
29210696SDavid.Hollister@Sun.COM 
29311068SJohn.Danielson@Sun.COM 	/*
294*12207SChris.Horne@Sun.COM 	 * Block when waiting for
295*12207SChris.Horne@Sun.COM 	 *	a) stabilization pending or a fullset update pending
296*12207SChris.Horne@Sun.COM 	 *	b) the report set to finalize (bitset is null)
297*12207SChris.Horne@Sun.COM 	 *	c) any scheduled timeouts to fire
29811068SJohn.Danielson@Sun.COM 	 */
299*12207SChris.Horne@Sun.COM 	rv = 1;					/* return synced */
30010696SDavid.Hollister@Sun.COM 	mutex_enter(&mapp->dam_lock);
301*12207SChris.Horne@Sun.COM again:	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
302*12207SChris.Horne@Sun.COM 	    (!bitset_is_null(&mapp->dam_report_set)) ||
303*12207SChris.Horne@Sun.COM 	    (mapp->dam_tid != 0)) {
30411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
30511068SJohn.Danielson@Sun.COM 		    dam_t *, mapp);
306*12207SChris.Horne@Sun.COM 
307*12207SChris.Horne@Sun.COM 		/* Wait for condition relayed via timeout */
308*12207SChris.Horne@Sun.COM 		if (sync_usec) {
309*12207SChris.Horne@Sun.COM 			if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
310*12207SChris.Horne@Sun.COM 			    drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
311*12207SChris.Horne@Sun.COM 				mapp->dam_sync_to_cnt++;
312*12207SChris.Horne@Sun.COM 				rv = 0;		/* return timeout */
313*12207SChris.Horne@Sun.COM 				break;
314*12207SChris.Horne@Sun.COM 			}
315*12207SChris.Horne@Sun.COM 		} else
316*12207SChris.Horne@Sun.COM 			cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
31710696SDavid.Hollister@Sun.COM 	}
31810696SDavid.Hollister@Sun.COM 
319*12207SChris.Horne@Sun.COM 	if (rv) {
320*12207SChris.Horne@Sun.COM 		/*
321*12207SChris.Horne@Sun.COM 		 * Delay one stabilization time after the apparent sync above
322*12207SChris.Horne@Sun.COM 		 * and verify accuracy - resync if not accurate.
323*12207SChris.Horne@Sun.COM 		 */
324*12207SChris.Horne@Sun.COM 		(void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
325*12207SChris.Horne@Sun.COM 		    mapp->dam_stable_ticks, TR_MICROSEC);
326*12207SChris.Horne@Sun.COM 		if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
327*12207SChris.Horne@Sun.COM 		    (!bitset_is_null(&mapp->dam_report_set)) ||
328*12207SChris.Horne@Sun.COM 		    (mapp->dam_tid != 0)))
329*12207SChris.Horne@Sun.COM 			goto again;
330*12207SChris.Horne@Sun.COM 	}
33110696SDavid.Hollister@Sun.COM 	mutex_exit(&mapp->dam_lock);
332*12207SChris.Horne@Sun.COM 
333*12207SChris.Horne@Sun.COM 	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name,
334*12207SChris.Horne@Sun.COM 	    int, rv, dam_t *, mapp);
335*12207SChris.Horne@Sun.COM 	return (rv);
336*12207SChris.Horne@Sun.COM }
33710696SDavid.Hollister@Sun.COM 
338*12207SChris.Horne@Sun.COM /*
339*12207SChris.Horne@Sun.COM  * Return 1 if active set is empty
340*12207SChris.Horne@Sun.COM  */
341*12207SChris.Horne@Sun.COM int
342*12207SChris.Horne@Sun.COM damap_is_empty(damap_t *damapp)
343*12207SChris.Horne@Sun.COM {
344*12207SChris.Horne@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
345*12207SChris.Horne@Sun.COM 	int	rv;
346*12207SChris.Horne@Sun.COM 
347*12207SChris.Horne@Sun.COM 	mutex_enter(&mapp->dam_lock);
348*12207SChris.Horne@Sun.COM 	rv = bitset_is_null(&mapp->dam_active_set);
349*12207SChris.Horne@Sun.COM 	mutex_exit(&mapp->dam_lock);
350*12207SChris.Horne@Sun.COM 	return (rv);
35110696SDavid.Hollister@Sun.COM }
35210696SDavid.Hollister@Sun.COM 
35310696SDavid.Hollister@Sun.COM /*
35410696SDavid.Hollister@Sun.COM  * Get the name of a device address map
35510696SDavid.Hollister@Sun.COM  *
35610696SDavid.Hollister@Sun.COM  * damapp:	address map
35710696SDavid.Hollister@Sun.COM  *
35810696SDavid.Hollister@Sun.COM  * Returns:	name
35910696SDavid.Hollister@Sun.COM  */
36010696SDavid.Hollister@Sun.COM char *
36110696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp)
36210696SDavid.Hollister@Sun.COM {
36310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
36410696SDavid.Hollister@Sun.COM 
36510696SDavid.Hollister@Sun.COM 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
36610696SDavid.Hollister@Sun.COM }
36710696SDavid.Hollister@Sun.COM 
36810696SDavid.Hollister@Sun.COM /*
369*12207SChris.Horne@Sun.COM  * Get the current size of the device address map
370*12207SChris.Horne@Sun.COM  *
371*12207SChris.Horne@Sun.COM  * damapp:	address map
372*12207SChris.Horne@Sun.COM  *
373*12207SChris.Horne@Sun.COM  * Returns:	size
374*12207SChris.Horne@Sun.COM  */
375*12207SChris.Horne@Sun.COM int
376*12207SChris.Horne@Sun.COM damap_size(damap_t *damapp)
377*12207SChris.Horne@Sun.COM {
378*12207SChris.Horne@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
379*12207SChris.Horne@Sun.COM 
380*12207SChris.Horne@Sun.COM 	return (mapp->dam_size);
381*12207SChris.Horne@Sun.COM }
382*12207SChris.Horne@Sun.COM 
383*12207SChris.Horne@Sun.COM /*
38410696SDavid.Hollister@Sun.COM  * Report an address to per-address report
38510696SDavid.Hollister@Sun.COM  *
38610696SDavid.Hollister@Sun.COM  * damapp:	address map handle
38710696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
38811068SJohn.Danielson@Sun.COM  * addridp:	address ID
38910696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
39010696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
39110696SDavid.Hollister@Sun.COM  *
39210696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
39310696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
39410696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
39510696SDavid.Hollister@Sun.COM  */
39610696SDavid.Hollister@Sun.COM int
39711068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
39811068SJohn.Danielson@Sun.COM     nvlist_t *nvl, void *addr_priv)
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__add, char *, mapp->dam_name,
40811068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
40911068SJohn.Danielson@Sun.COM 
41011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
41111068SJohn.Danielson@Sun.COM 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
41211068SJohn.Danielson@Sun.COM 	    ((addrid = dam_get_addrid(mapp, address)) == 0)) {
41311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
41410696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
41510696SDavid.Hollister@Sun.COM 	}
41610696SDavid.Hollister@Sun.COM 
41710696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
41810696SDavid.Hollister@Sun.COM 	ASSERT(passp != NULL);
41910696SDavid.Hollister@Sun.COM 
42010696SDavid.Hollister@Sun.COM 	/*
42110696SDavid.Hollister@Sun.COM 	 * If re-reporting the same address (add or remove) clear
42210696SDavid.Hollister@Sun.COM 	 * the existing report
42310696SDavid.Hollister@Sun.COM 	 */
42410696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
42511068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
42611068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
42711068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
42811068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
42910696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
43010696SDavid.Hollister@Sun.COM 	}
43110696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
43210696SDavid.Hollister@Sun.COM 	if (nvl)
43310696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
43410696SDavid.Hollister@Sun.COM 
43511068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
43611068SJohn.Danielson@Sun.COM 	if (addridp != NULL)
43711068SJohn.Danielson@Sun.COM 		*addridp = (damap_id_t)addrid;
43811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
43910696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
44010696SDavid.Hollister@Sun.COM }
44110696SDavid.Hollister@Sun.COM 
44210696SDavid.Hollister@Sun.COM /*
44310696SDavid.Hollister@Sun.COM  * Report removal of address from per-address report
44410696SDavid.Hollister@Sun.COM  *
44510696SDavid.Hollister@Sun.COM  * damapp:	address map
44610696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
44710696SDavid.Hollister@Sun.COM  *
44810696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
44910696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
45010696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
45110696SDavid.Hollister@Sun.COM  */
45210696SDavid.Hollister@Sun.COM int
45310696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address)
45410696SDavid.Hollister@Sun.COM {
45510696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
45610696SDavid.Hollister@Sun.COM 	id_t addrid;
45710696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
45810696SDavid.Hollister@Sun.COM 
45911068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
46010696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
46110696SDavid.Hollister@Sun.COM 
46211068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
46311068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
46411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
46511068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
46611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
46711068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
46811068SJohn.Danielson@Sun.COM 	}
46911068SJohn.Danielson@Sun.COM 
47011068SJohn.Danielson@Sun.COM 	/*
47111068SJohn.Danielson@Sun.COM 	 * if reporting the removal of an address which is not in the map
47211068SJohn.Danielson@Sun.COM 	 * return success
47311068SJohn.Danielson@Sun.COM 	 */
47410696SDavid.Hollister@Sun.COM 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
47511068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
47610696SDavid.Hollister@Sun.COM 		return (DAM_SUCCESS);
47710696SDavid.Hollister@Sun.COM 	}
47810696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
47910696SDavid.Hollister@Sun.COM 	ASSERT(passp);
48010696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
48111068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
48211068SJohn.Danielson@Sun.COM 		    char *, address, dam_t *, mapp);
48311068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
48411068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
48510696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
48610696SDavid.Hollister@Sun.COM 	}
48711068SJohn.Danielson@Sun.COM 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
48811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
48910696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
49010696SDavid.Hollister@Sun.COM }
49110696SDavid.Hollister@Sun.COM 
49212000SReed.Liu@Sun.COM static int
49312000SReed.Liu@Sun.COM damap_addrset_flush_locked(damap_t *damapp)
49412000SReed.Liu@Sun.COM {
495*12207SChris.Horne@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
49612000SReed.Liu@Sun.COM 	int	idx;
49712000SReed.Liu@Sun.COM 
49812000SReed.Liu@Sun.COM 	ASSERT(mapp);
49912000SReed.Liu@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
50012000SReed.Liu@Sun.COM 	if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
50112000SReed.Liu@Sun.COM 		return (DAM_EINVAL);
50212000SReed.Liu@Sun.COM 	}
50312000SReed.Liu@Sun.COM 
50412000SReed.Liu@Sun.COM 	DTRACE_PROBE2(damap__addrset__flush__locked__enter, char *,
50512000SReed.Liu@Sun.COM 	    mapp->dam_name, dam_t *, mapp);
50612000SReed.Liu@Sun.COM 	if (mapp->dam_flags & DAM_SETADD) {
50712000SReed.Liu@Sun.COM 		DTRACE_PROBE2(damap__addrset__flush__locked__reset, char *,
50812000SReed.Liu@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
50912000SReed.Liu@Sun.COM 
51012000SReed.Liu@Sun.COM 		/*
51112000SReed.Liu@Sun.COM 		 * cancel stabilization timeout
51212000SReed.Liu@Sun.COM 		 */
513*12207SChris.Horne@Sun.COM 		dam_sched_timeout(NULL, mapp, 0);
51412000SReed.Liu@Sun.COM 		DAM_INCR_STAT(mapp, dam_jitter);
51512000SReed.Liu@Sun.COM 
51612000SReed.Liu@Sun.COM 		/*
51712000SReed.Liu@Sun.COM 		 * clear pending reports
51812000SReed.Liu@Sun.COM 		 */
51912000SReed.Liu@Sun.COM 		for (idx = 1; idx < mapp->dam_high; idx++) {
52012000SReed.Liu@Sun.COM 			if (DAM_IN_REPORT(mapp, idx)) {
52112000SReed.Liu@Sun.COM 				dam_addr_report_release(mapp, idx);
52212000SReed.Liu@Sun.COM 			}
52312000SReed.Liu@Sun.COM 		}
52412000SReed.Liu@Sun.COM 
52512000SReed.Liu@Sun.COM 		bitset_zero(&mapp->dam_report_set);
52612000SReed.Liu@Sun.COM 		mapp->dam_flags &= ~DAM_SETADD;
527*12207SChris.Horne@Sun.COM 		cv_signal(&mapp->dam_sync_cv);
52812000SReed.Liu@Sun.COM 	}
52912000SReed.Liu@Sun.COM 
53012000SReed.Liu@Sun.COM 	return (DAM_SUCCESS);
53112000SReed.Liu@Sun.COM }
53212000SReed.Liu@Sun.COM 
53310696SDavid.Hollister@Sun.COM /*
53410696SDavid.Hollister@Sun.COM  * Initiate full-set report
53510696SDavid.Hollister@Sun.COM  *
53610696SDavid.Hollister@Sun.COM  * damapp:	address map
53710696SDavid.Hollister@Sun.COM  *
53810696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
53910696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
54010696SDavid.Hollister@Sun.COM  */
54110696SDavid.Hollister@Sun.COM int
54210696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp)
54310696SDavid.Hollister@Sun.COM {
54412000SReed.Liu@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
54512000SReed.Liu@Sun.COM 	int	rv;
54610696SDavid.Hollister@Sun.COM 
54712000SReed.Liu@Sun.COM 	if (mapp == NULL) {
54810696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
54912000SReed.Liu@Sun.COM 	}
55010696SDavid.Hollister@Sun.COM 
55111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
55211068SJohn.Danielson@Sun.COM 	    mapp);
55312000SReed.Liu@Sun.COM 
55411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
55511068SJohn.Danielson@Sun.COM 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
55611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
55712000SReed.Liu@Sun.COM 
55811068SJohn.Danielson@Sun.COM 		return (DAM_MAPFULL);
55911068SJohn.Danielson@Sun.COM 	}
56012000SReed.Liu@Sun.COM 
56112000SReed.Liu@Sun.COM 	rv = damap_addrset_flush_locked(damapp);
56212000SReed.Liu@Sun.COM 	if (rv == DAM_SUCCESS) {
56312000SReed.Liu@Sun.COM 		mapp->dam_flags |= DAM_SETADD;
56412000SReed.Liu@Sun.COM 	}
56512000SReed.Liu@Sun.COM 	mutex_exit(&mapp->dam_lock);
56612000SReed.Liu@Sun.COM 
56712000SReed.Liu@Sun.COM 	return (rv);
56812000SReed.Liu@Sun.COM }
56911068SJohn.Danielson@Sun.COM 
57012000SReed.Liu@Sun.COM /*
57112000SReed.Liu@Sun.COM  * Cancel full-set report
57212000SReed.Liu@Sun.COM  *
573*12207SChris.Horne@Sun.COM  * damapp:	address map
57412000SReed.Liu@Sun.COM  *
575*12207SChris.Horne@Sun.COM  * Returns:	DAM_SUCCESS
576*12207SChris.Horne@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
57712000SReed.Liu@Sun.COM  */
57812000SReed.Liu@Sun.COM int
57912000SReed.Liu@Sun.COM damap_addrset_flush(damap_t *damapp)
58012000SReed.Liu@Sun.COM {
58112000SReed.Liu@Sun.COM 	int	rv;
58212000SReed.Liu@Sun.COM 	dam_t	*mapp = (dam_t *)damapp;
58312000SReed.Liu@Sun.COM 
58412000SReed.Liu@Sun.COM 	if (mapp == NULL) {
58512000SReed.Liu@Sun.COM 		return (DAM_EINVAL);
58610696SDavid.Hollister@Sun.COM 	}
58712000SReed.Liu@Sun.COM 
58812000SReed.Liu@Sun.COM 	DTRACE_PROBE2(damap__addrset__flush, char *, mapp->dam_name,
58912000SReed.Liu@Sun.COM 	    dam_t *, mapp);
59012000SReed.Liu@Sun.COM 
59112000SReed.Liu@Sun.COM 	mutex_enter(&mapp->dam_lock);
59212000SReed.Liu@Sun.COM 	rv = damap_addrset_flush_locked(damapp);
59311068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
59412000SReed.Liu@Sun.COM 
59512000SReed.Liu@Sun.COM 	return (rv);
59610696SDavid.Hollister@Sun.COM }
59710696SDavid.Hollister@Sun.COM 
59810696SDavid.Hollister@Sun.COM /*
59910696SDavid.Hollister@Sun.COM  * Report address to full-set report
60010696SDavid.Hollister@Sun.COM  *
60110696SDavid.Hollister@Sun.COM  * damapp:	address map handle
60210696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
60310696SDavid.Hollister@Sun.COM  * rindx:	index if address stabilizes
60410696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
60510696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private data (passed to activate/release cb)
60610696SDavid.Hollister@Sun.COM  *
60710696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
60810696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
60910696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
61010696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
61110696SDavid.Hollister@Sun.COM  */
61210696SDavid.Hollister@Sun.COM int
61310696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
61410696SDavid.Hollister@Sun.COM     nvlist_t *nvl, void *addr_priv)
61510696SDavid.Hollister@Sun.COM {
61610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
61710696SDavid.Hollister@Sun.COM 	id_t addrid;
61810696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
61910696SDavid.Hollister@Sun.COM 
62011068SJohn.Danielson@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
62110696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
62210696SDavid.Hollister@Sun.COM 
62311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
62411068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
62510696SDavid.Hollister@Sun.COM 
62611068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
62711068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
62811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
62911068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
63011068SJohn.Danielson@Sun.COM 	}
63111068SJohn.Danielson@Sun.COM 
63210696SDavid.Hollister@Sun.COM 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
63311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
63410696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
63510696SDavid.Hollister@Sun.COM 	}
63610696SDavid.Hollister@Sun.COM 
63710696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
63810696SDavid.Hollister@Sun.COM 	ASSERT(passp);
63910696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
64011068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
64111068SJohn.Danielson@Sun.COM 		    mapp->dam_name, char *, address, dam_t *, mapp);
64211068SJohn.Danielson@Sun.COM 		dam_addr_report_release(mapp, addrid);
64310696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
64410696SDavid.Hollister@Sun.COM 	}
64510696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
64610696SDavid.Hollister@Sun.COM 	if (nvl)
64710696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
64810696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
64910696SDavid.Hollister@Sun.COM 	if (ridx)
65010696SDavid.Hollister@Sun.COM 		*ridx = (damap_id_t)addrid;
65111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
65210696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
65310696SDavid.Hollister@Sun.COM }
65410696SDavid.Hollister@Sun.COM 
65510696SDavid.Hollister@Sun.COM /*
65610696SDavid.Hollister@Sun.COM  * Commit full-set report for stabilization
65710696SDavid.Hollister@Sun.COM  *
65810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
65910696SDavid.Hollister@Sun.COM  * flags:	(currently 0)
66010696SDavid.Hollister@Sun.COM  *
66110696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
66210696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
66310696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
66410696SDavid.Hollister@Sun.COM  */
66510696SDavid.Hollister@Sun.COM int
66610696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags)
66710696SDavid.Hollister@Sun.COM {
66810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
66910696SDavid.Hollister@Sun.COM 	int i;
67010696SDavid.Hollister@Sun.COM 
67111068SJohn.Danielson@Sun.COM 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
67210696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
67310696SDavid.Hollister@Sun.COM 
67411068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
67511068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
67610696SDavid.Hollister@Sun.COM 
67711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
67811068SJohn.Danielson@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD)) {
67911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
68011068SJohn.Danielson@Sun.COM 		return (DAM_FAILURE);
68111068SJohn.Danielson@Sun.COM 	}
68211068SJohn.Danielson@Sun.COM 
68311068SJohn.Danielson@Sun.COM 	if (flags & DAMAP_END_RESET) {
68411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
68511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
686*12207SChris.Horne@Sun.COM 		dam_sched_timeout(NULL, mapp, 0);
68710696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++)
68810696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
68911068SJohn.Danielson@Sun.COM 				dam_addr_report_release(mapp, i);
69010696SDavid.Hollister@Sun.COM 	} else {
69110696SDavid.Hollister@Sun.COM 		mapp->dam_last_update = gethrtime();
692*12207SChris.Horne@Sun.COM 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
693*12207SChris.Horne@Sun.COM 		    mapp->dam_stable_ticks);
69410696SDavid.Hollister@Sun.COM 	}
69511068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
69610696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
69710696SDavid.Hollister@Sun.COM }
69810696SDavid.Hollister@Sun.COM 
69910696SDavid.Hollister@Sun.COM /*
70010696SDavid.Hollister@Sun.COM  * Return nvlist registered with reported address
70110696SDavid.Hollister@Sun.COM  *
70210696SDavid.Hollister@Sun.COM  * damapp:	address map handle
70311068SJohn.Danielson@Sun.COM  * addrid:	address ID
70410696SDavid.Hollister@Sun.COM  *
70510696SDavid.Hollister@Sun.COM  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
70610696SDavid.Hollister@Sun.COM  *		NULL
70710696SDavid.Hollister@Sun.COM  */
70810696SDavid.Hollister@Sun.COM nvlist_t *
70910696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
71010696SDavid.Hollister@Sun.COM {
71110696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
71210696SDavid.Hollister@Sun.COM 	dam_da_t *pass;
71310696SDavid.Hollister@Sun.COM 
71411068SJohn.Danielson@Sun.COM 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
71511068SJohn.Danielson@Sun.COM 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
71610696SDavid.Hollister@Sun.COM 			return (pass->da_nvl);
71710696SDavid.Hollister@Sun.COM 	}
71810696SDavid.Hollister@Sun.COM 	return (NULL);
71910696SDavid.Hollister@Sun.COM }
72010696SDavid.Hollister@Sun.COM 
72110696SDavid.Hollister@Sun.COM /*
72210696SDavid.Hollister@Sun.COM  * Return address string
72310696SDavid.Hollister@Sun.COM  *
72410696SDavid.Hollister@Sun.COM  * damapp:	address map handle
72511068SJohn.Danielson@Sun.COM  * addrid:	address ID
72610696SDavid.Hollister@Sun.COM  *
72710696SDavid.Hollister@Sun.COM  * Returns:	char *		Address string
72810696SDavid.Hollister@Sun.COM  *		NULL
72910696SDavid.Hollister@Sun.COM  */
73010696SDavid.Hollister@Sun.COM char *
73111068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid)
73210696SDavid.Hollister@Sun.COM {
73310696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
73410696SDavid.Hollister@Sun.COM 
73511068SJohn.Danielson@Sun.COM 	if (mapp->dam_high)
73611068SJohn.Danielson@Sun.COM 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
73711068SJohn.Danielson@Sun.COM 	else
73811068SJohn.Danielson@Sun.COM 		return (NULL);
73910696SDavid.Hollister@Sun.COM }
74010696SDavid.Hollister@Sun.COM 
74110696SDavid.Hollister@Sun.COM /*
74210696SDavid.Hollister@Sun.COM  * Release address reference in map
74310696SDavid.Hollister@Sun.COM  *
74410696SDavid.Hollister@Sun.COM  * damapp:	address map handle
74511068SJohn.Danielson@Sun.COM  * addrid:	address ID
74610696SDavid.Hollister@Sun.COM  */
74710696SDavid.Hollister@Sun.COM void
74810696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid)
74910696SDavid.Hollister@Sun.COM {
75010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
75111068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
75211068SJohn.Danielson@Sun.COM 	char *addr;
75310696SDavid.Hollister@Sun.COM 
75411068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
75511068SJohn.Danielson@Sun.COM 	ASSERT(passp);
75611068SJohn.Danielson@Sun.COM 
75711068SJohn.Danielson@Sun.COM 	addr = damap_id2addr(damapp, addrid);
75811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
75911068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, passp->da_ref);
76011068SJohn.Danielson@Sun.COM 
76111068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
76211068SJohn.Danielson@Sun.COM 
76311068SJohn.Danielson@Sun.COM 	/*
76411068SJohn.Danielson@Sun.COM 	 * teardown address if last outstanding reference
76511068SJohn.Danielson@Sun.COM 	 */
76611068SJohn.Danielson@Sun.COM 	if (--passp->da_ref == 0)
76711068SJohn.Danielson@Sun.COM 		dam_addr_release(mapp, (id_t)addrid);
76811068SJohn.Danielson@Sun.COM 
76911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
77010696SDavid.Hollister@Sun.COM }
77110696SDavid.Hollister@Sun.COM 
77210696SDavid.Hollister@Sun.COM /*
77310696SDavid.Hollister@Sun.COM  * Return current reference count on address reference in map
77410696SDavid.Hollister@Sun.COM  *
77510696SDavid.Hollister@Sun.COM  * damapp:	address map handle
77611068SJohn.Danielson@Sun.COM  * addrid:	address ID
77710696SDavid.Hollister@Sun.COM  *
77810696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
77910696SDavid.Hollister@Sun.COM  *		DAM_FAILURE
78010696SDavid.Hollister@Sun.COM  */
78110696SDavid.Hollister@Sun.COM int
78211068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid)
78310696SDavid.Hollister@Sun.COM {
78410696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
78510696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
78610696SDavid.Hollister@Sun.COM 	int ref = -1;
78710696SDavid.Hollister@Sun.COM 
78811068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
78910696SDavid.Hollister@Sun.COM 	if (passp)
79010696SDavid.Hollister@Sun.COM 		ref = passp->da_ref;
79111068SJohn.Danielson@Sun.COM 
79210696SDavid.Hollister@Sun.COM 	return (ref);
79310696SDavid.Hollister@Sun.COM }
79410696SDavid.Hollister@Sun.COM 
79510696SDavid.Hollister@Sun.COM /*
79610696SDavid.Hollister@Sun.COM  * Return next address ID in list
79710696SDavid.Hollister@Sun.COM  *
79810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
79910696SDavid.Hollister@Sun.COM  * damap_list:	address ID list passed to config|unconfig
80010696SDavid.Hollister@Sun.COM  *		returned by look by lookup_all
80110696SDavid.Hollister@Sun.COM  * last:	last ID returned, 0 is start of list
80210696SDavid.Hollister@Sun.COM  *
80310696SDavid.Hollister@Sun.COM  * Returns:	addrid		Next ID from the list
80410696SDavid.Hollister@Sun.COM  *		0		End of the list
80510696SDavid.Hollister@Sun.COM  */
80610696SDavid.Hollister@Sun.COM damap_id_t
80710696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
80810696SDavid.Hollister@Sun.COM {
80910696SDavid.Hollister@Sun.COM 	int i, start;
81010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
81110696SDavid.Hollister@Sun.COM 	bitset_t *dam_list = (bitset_t *)damap_list;
81210696SDavid.Hollister@Sun.COM 
81310696SDavid.Hollister@Sun.COM 	if (!mapp || !dam_list)
81410696SDavid.Hollister@Sun.COM 		return ((damap_id_t)0);
81510696SDavid.Hollister@Sun.COM 
81610696SDavid.Hollister@Sun.COM 	start = (int)last + 1;
81711068SJohn.Danielson@Sun.COM 	for (i = start; i < mapp->dam_high; i++) {
81811068SJohn.Danielson@Sun.COM 		if (bitset_in_set(dam_list, i)) {
81910696SDavid.Hollister@Sun.COM 			return ((damap_id_t)i);
82011068SJohn.Danielson@Sun.COM 		}
82111068SJohn.Danielson@Sun.COM 	}
82210696SDavid.Hollister@Sun.COM 	return ((damap_id_t)0);
82310696SDavid.Hollister@Sun.COM }
82410696SDavid.Hollister@Sun.COM 
82510696SDavid.Hollister@Sun.COM /*
82610696SDavid.Hollister@Sun.COM  * Set config private data
82710696SDavid.Hollister@Sun.COM  *
82810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
82911068SJohn.Danielson@Sun.COM  * addrid:	address ID
83010696SDavid.Hollister@Sun.COM  * cfg_priv:	configuration private data
83110696SDavid.Hollister@Sun.COM  *
83210696SDavid.Hollister@Sun.COM  */
83310696SDavid.Hollister@Sun.COM void
83411068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
83510696SDavid.Hollister@Sun.COM {
83610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
83710696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
83810696SDavid.Hollister@Sun.COM 
83911068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
84011068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
84110696SDavid.Hollister@Sun.COM 	if (!passp) {
84211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
84310696SDavid.Hollister@Sun.COM 		return;
84410696SDavid.Hollister@Sun.COM 	}
84510696SDavid.Hollister@Sun.COM 	passp->da_cfg_priv = cfg_priv;
84611068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
84710696SDavid.Hollister@Sun.COM }
84810696SDavid.Hollister@Sun.COM 
84910696SDavid.Hollister@Sun.COM /*
85010696SDavid.Hollister@Sun.COM  * Get config private data
85110696SDavid.Hollister@Sun.COM  *
85210696SDavid.Hollister@Sun.COM  * damapp:	address map handle
85311068SJohn.Danielson@Sun.COM  * addrid:	address ID
85410696SDavid.Hollister@Sun.COM  *
85510696SDavid.Hollister@Sun.COM  * Returns:	configuration private data
85610696SDavid.Hollister@Sun.COM  */
85710696SDavid.Hollister@Sun.COM void *
85811068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
85910696SDavid.Hollister@Sun.COM {
86010696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
86110696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
86210696SDavid.Hollister@Sun.COM 	void *rv;
86310696SDavid.Hollister@Sun.COM 
86411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
86511068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
86610696SDavid.Hollister@Sun.COM 	if (!passp) {
86711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
86810696SDavid.Hollister@Sun.COM 		return (NULL);
86910696SDavid.Hollister@Sun.COM 	}
87010696SDavid.Hollister@Sun.COM 	rv = passp->da_cfg_priv;
87111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
87210696SDavid.Hollister@Sun.COM 	return (rv);
87310696SDavid.Hollister@Sun.COM }
87410696SDavid.Hollister@Sun.COM 
87510696SDavid.Hollister@Sun.COM /*
87610696SDavid.Hollister@Sun.COM  * Lookup a single address in the active address map
87710696SDavid.Hollister@Sun.COM  *
87810696SDavid.Hollister@Sun.COM  * damapp:	address map handle
87910696SDavid.Hollister@Sun.COM  * address:	address string
88010696SDavid.Hollister@Sun.COM  *
88110696SDavid.Hollister@Sun.COM  * Returns:	ID of active/stable address
88210696SDavid.Hollister@Sun.COM  *		0	Address not in stable set
88310696SDavid.Hollister@Sun.COM  *
88410696SDavid.Hollister@Sun.COM  * Future: Allow the caller to wait for stabilize before returning not found.
88510696SDavid.Hollister@Sun.COM  */
88610696SDavid.Hollister@Sun.COM damap_id_t
88710696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address)
88810696SDavid.Hollister@Sun.COM {
88910696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
89010696SDavid.Hollister@Sun.COM 	id_t addrid = 0;
89110696SDavid.Hollister@Sun.COM 	dam_da_t *passp = NULL;
89210696SDavid.Hollister@Sun.COM 
89311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
89411068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp);
89511068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
89611068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high)
89711068SJohn.Danielson@Sun.COM 		addrid = 0;
89811068SJohn.Danielson@Sun.COM 	else
89911068SJohn.Danielson@Sun.COM 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
90010696SDavid.Hollister@Sun.COM 	if (addrid) {
90110696SDavid.Hollister@Sun.COM 		if (DAM_IS_STABLE(mapp, addrid)) {
90210696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
90310696SDavid.Hollister@Sun.COM 			ASSERT(passp);
90410696SDavid.Hollister@Sun.COM 			if (passp) {
90510696SDavid.Hollister@Sun.COM 				passp->da_ref++;
90610696SDavid.Hollister@Sun.COM 			} else {
90710696SDavid.Hollister@Sun.COM 				addrid = 0;
90810696SDavid.Hollister@Sun.COM 			}
90910696SDavid.Hollister@Sun.COM 		} else {
91010696SDavid.Hollister@Sun.COM 			addrid = 0;
91110696SDavid.Hollister@Sun.COM 		}
91210696SDavid.Hollister@Sun.COM 	}
91311068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
91411068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
91511068SJohn.Danielson@Sun.COM 	    char *, address, dam_t *, mapp, int, addrid);
91610696SDavid.Hollister@Sun.COM 	return ((damap_id_t)addrid);
91710696SDavid.Hollister@Sun.COM }
91810696SDavid.Hollister@Sun.COM 
91910696SDavid.Hollister@Sun.COM 
92010696SDavid.Hollister@Sun.COM /*
92110696SDavid.Hollister@Sun.COM  * Return the list of stable addresses in the map
92210696SDavid.Hollister@Sun.COM  *
92310696SDavid.Hollister@Sun.COM  * damapp:	address map handle
92410696SDavid.Hollister@Sun.COM  * id_listp:	pointer to list of address IDs in stable map (returned)
92510696SDavid.Hollister@Sun.COM  *
92610696SDavid.Hollister@Sun.COM  * Returns:	# of entries returned in alist
92710696SDavid.Hollister@Sun.COM  */
92810696SDavid.Hollister@Sun.COM int
92910696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
93010696SDavid.Hollister@Sun.COM {
93110696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
93210696SDavid.Hollister@Sun.COM 	int mapsz = mapp->dam_size;
93310696SDavid.Hollister@Sun.COM 	int n_ids, i;
93410696SDavid.Hollister@Sun.COM 	bitset_t *bsp;
93511068SJohn.Danielson@Sun.COM 	char	 *addrp;
93610696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
93710696SDavid.Hollister@Sun.COM 
93811068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
93911068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
94011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
94111068SJohn.Danielson@Sun.COM 	if (!mapp->dam_high) {
94211068SJohn.Danielson@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
94311068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
94411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
94511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp, int, 0);
94611068SJohn.Danielson@Sun.COM 		return (0);
94711068SJohn.Danielson@Sun.COM 	}
94810696SDavid.Hollister@Sun.COM 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
94910696SDavid.Hollister@Sun.COM 	bitset_init(bsp);
95010696SDavid.Hollister@Sun.COM 	bitset_resize(bsp, mapsz);
95110696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, bsp);
95210696SDavid.Hollister@Sun.COM 	for (n_ids = 0, i = 1; i < mapsz; i++) {
95310696SDavid.Hollister@Sun.COM 		if (bitset_in_set(bsp, i)) {
95410696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, i);
95510696SDavid.Hollister@Sun.COM 			ASSERT(passp);
95610696SDavid.Hollister@Sun.COM 			if (passp) {
95711068SJohn.Danielson@Sun.COM 				addrp = damap_id2addr(damapp, i);
95811068SJohn.Danielson@Sun.COM 				DTRACE_PROBE3(damap__lookup__all__item, char *,
95911068SJohn.Danielson@Sun.COM 				    mapp->dam_name, char *, addrp, dam_t *,
96011068SJohn.Danielson@Sun.COM 				    mapp);
96110696SDavid.Hollister@Sun.COM 				passp->da_ref++;
96210696SDavid.Hollister@Sun.COM 				n_ids++;
96310696SDavid.Hollister@Sun.COM 			}
96410696SDavid.Hollister@Sun.COM 		}
96510696SDavid.Hollister@Sun.COM 	}
96610696SDavid.Hollister@Sun.COM 	if (n_ids) {
96710696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)bsp;
96811068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
96910696SDavid.Hollister@Sun.COM 		return (n_ids);
97010696SDavid.Hollister@Sun.COM 	} else {
97110696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
97210696SDavid.Hollister@Sun.COM 		bitset_fini(bsp);
97310696SDavid.Hollister@Sun.COM 		kmem_free(bsp, sizeof (*bsp));
97411068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
97510696SDavid.Hollister@Sun.COM 		return (0);
97610696SDavid.Hollister@Sun.COM 	}
97710696SDavid.Hollister@Sun.COM }
97810696SDavid.Hollister@Sun.COM 
97910696SDavid.Hollister@Sun.COM /*
98010696SDavid.Hollister@Sun.COM  * Release the address list returned by damap_lookup_all()
98110696SDavid.Hollister@Sun.COM  *
98210696SDavid.Hollister@Sun.COM  * mapp:	address map handle
98310696SDavid.Hollister@Sun.COM  * id_list:	list of address IDs returned in damap_lookup_all()
98410696SDavid.Hollister@Sun.COM  */
98510696SDavid.Hollister@Sun.COM void
98610696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
98710696SDavid.Hollister@Sun.COM {
98810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
98910696SDavid.Hollister@Sun.COM 	int i;
99010696SDavid.Hollister@Sun.COM 
99110696SDavid.Hollister@Sun.COM 	if (id_list == NULL)
99210696SDavid.Hollister@Sun.COM 		return;
99310696SDavid.Hollister@Sun.COM 
99411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
99510696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
99610696SDavid.Hollister@Sun.COM 		if (bitset_in_set((bitset_t *)id_list, i))
99711068SJohn.Danielson@Sun.COM 			(void) dam_addr_release(mapp, i);
99810696SDavid.Hollister@Sun.COM 	}
99911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
100010696SDavid.Hollister@Sun.COM 	bitset_fini((bitset_t *)id_list);
100110696SDavid.Hollister@Sun.COM 	kmem_free((void *)id_list, sizeof (bitset_t));
100210696SDavid.Hollister@Sun.COM }
100310696SDavid.Hollister@Sun.COM 
100410696SDavid.Hollister@Sun.COM /*
100511068SJohn.Danielson@Sun.COM  * activate an address that has passed the stabilization interval
100611068SJohn.Danielson@Sun.COM  */
100711068SJohn.Danielson@Sun.COM static void
100811068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid)
100911068SJohn.Danielson@Sun.COM {
101011068SJohn.Danielson@Sun.COM 	dam_da_t *passp;
101111068SJohn.Danielson@Sun.COM 	int config_rv;
101211068SJohn.Danielson@Sun.COM 	char *addrstr;
101311068SJohn.Danielson@Sun.COM 
101411068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
101511068SJohn.Danielson@Sun.COM 	bitset_add(&mapp->dam_active_set, addrid);
101611068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
101711068SJohn.Danielson@Sun.COM 	ASSERT(passp);
101811068SJohn.Danielson@Sun.COM 
101911068SJohn.Danielson@Sun.COM 	/*
102011068SJohn.Danielson@Sun.COM 	 * copy the reported nvlist and provider private data
102111068SJohn.Danielson@Sun.COM 	 */
102211068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
102311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
102411068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
102511068SJohn.Danielson@Sun.COM 	passp->da_nvl = passp->da_nvl_rpt;
102611068SJohn.Danielson@Sun.COM 	passp->da_ppriv = passp->da_ppriv_rpt;
102711068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
102811068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
102911068SJohn.Danielson@Sun.COM 	passp->da_last_stable = gethrtime();
103011068SJohn.Danielson@Sun.COM 	passp->da_stable_cnt++;
103111068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
103211068SJohn.Danielson@Sun.COM 	if (mapp->dam_activate_cb) {
103311068SJohn.Danielson@Sun.COM 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
103411068SJohn.Danielson@Sun.COM 		    addrid, &passp->da_ppriv_rpt);
103511068SJohn.Danielson@Sun.COM 	}
103611068SJohn.Danielson@Sun.COM 
103711068SJohn.Danielson@Sun.COM 	/*
103811068SJohn.Danielson@Sun.COM 	 * call the address-specific configuration action as part of
103911068SJohn.Danielson@Sun.COM 	 * activation.
104011068SJohn.Danielson@Sun.COM 	 */
104111068SJohn.Danielson@Sun.COM 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
104211068SJohn.Danielson@Sun.COM 	    addrid);
104311068SJohn.Danielson@Sun.COM 	if (config_rv != DAM_SUCCESS) {
104411068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
104511068SJohn.Danielson@Sun.COM 		passp->da_flags |= DA_FAILED_CONFIG;
104611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
104711068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__config__failure,
104811068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
104911363SReed.Liu@Sun.COM 		dam_deact_cleanup(mapp, addrid, addrstr,
105011363SReed.Liu@Sun.COM 		    DAMAP_DEACT_RSN_CFG_FAIL);
105111363SReed.Liu@Sun.COM 	} else {
105211363SReed.Liu@Sun.COM 		DTRACE_PROBE3(damap__addr__activate__end, char *,
105311363SReed.Liu@Sun.COM 		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
105411068SJohn.Danielson@Sun.COM 	}
105511068SJohn.Danielson@Sun.COM }
105611068SJohn.Danielson@Sun.COM 
105711068SJohn.Danielson@Sun.COM /*
105811068SJohn.Danielson@Sun.COM  * deactivate a previously stable address
105911068SJohn.Danielson@Sun.COM  */
106011068SJohn.Danielson@Sun.COM static void
106111068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid)
106211068SJohn.Danielson@Sun.COM {
106311068SJohn.Danielson@Sun.COM 	char *addrstr;
106411068SJohn.Danielson@Sun.COM 
106511068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
106611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
106711068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
106811068SJohn.Danielson@Sun.COM 
106911068SJohn.Danielson@Sun.COM 	/*
107011068SJohn.Danielson@Sun.COM 	 * call the unconfiguration callback
107111068SJohn.Danielson@Sun.COM 	 */
107211068SJohn.Danielson@Sun.COM 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
107311363SReed.Liu@Sun.COM 	dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
107411363SReed.Liu@Sun.COM }
107511363SReed.Liu@Sun.COM 
107611363SReed.Liu@Sun.COM static void
107711363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
107811363SReed.Liu@Sun.COM     damap_deact_rsn_t deact_rsn)
107911363SReed.Liu@Sun.COM {
108011363SReed.Liu@Sun.COM 	dam_da_t *passp;
108111363SReed.Liu@Sun.COM 
108211068SJohn.Danielson@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
108311068SJohn.Danielson@Sun.COM 	ASSERT(passp);
108411068SJohn.Danielson@Sun.COM 	if (mapp->dam_deactivate_cb)
108511068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
108611068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
108711363SReed.Liu@Sun.COM 		    addrid, passp->da_ppriv, deact_rsn);
108811068SJohn.Danielson@Sun.COM 
108911068SJohn.Danielson@Sun.COM 	/*
109011068SJohn.Danielson@Sun.COM 	 * clear the active bit and free the backing info for
109111068SJohn.Danielson@Sun.COM 	 * this address
109211068SJohn.Danielson@Sun.COM 	 */
109311068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
109411068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_active_set, addrid);
109511068SJohn.Danielson@Sun.COM 	passp->da_ppriv = NULL;
109611068SJohn.Danielson@Sun.COM 	if (passp->da_nvl)
109711068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl);
109811068SJohn.Danielson@Sun.COM 	passp->da_nvl = NULL;
109911068SJohn.Danielson@Sun.COM 	passp->da_ppriv_rpt = NULL;
110011068SJohn.Danielson@Sun.COM 	if (passp->da_nvl_rpt)
110111068SJohn.Danielson@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
110211068SJohn.Danielson@Sun.COM 	passp->da_nvl_rpt = NULL;
110311068SJohn.Danielson@Sun.COM 
110411068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
110511068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
110611068SJohn.Danielson@Sun.COM 
110711068SJohn.Danielson@Sun.COM 	(void) dam_addr_release(mapp, addrid);
110811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
110911068SJohn.Danielson@Sun.COM }
111011068SJohn.Danielson@Sun.COM 
111111068SJohn.Danielson@Sun.COM /*
111211068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread activation
111311068SJohn.Danielson@Sun.COM  */
111411068SJohn.Danielson@Sun.COM static void
111511068SJohn.Danielson@Sun.COM dam_tq_config(void *arg)
111611068SJohn.Danielson@Sun.COM {
111711068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
111811068SJohn.Danielson@Sun.COM 
111911068SJohn.Danielson@Sun.COM 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
112011068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
112111068SJohn.Danielson@Sun.COM }
112211068SJohn.Danielson@Sun.COM 
112311068SJohn.Danielson@Sun.COM /*
112411068SJohn.Danielson@Sun.COM  * taskq callback for multi-thread deactivation
112511068SJohn.Danielson@Sun.COM  */
112611068SJohn.Danielson@Sun.COM static void
112711068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg)
112811068SJohn.Danielson@Sun.COM {
112911068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
113011068SJohn.Danielson@Sun.COM 
113111068SJohn.Danielson@Sun.COM 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
113211068SJohn.Danielson@Sun.COM 	kmem_free(tqd, sizeof (*tqd));
113311068SJohn.Danielson@Sun.COM }
113411068SJohn.Danielson@Sun.COM 
113511068SJohn.Danielson@Sun.COM /*
113610696SDavid.Hollister@Sun.COM  * Activate a set of stabilized addresses
113710696SDavid.Hollister@Sun.COM  */
113810696SDavid.Hollister@Sun.COM static void
113911068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate)
114010696SDavid.Hollister@Sun.COM {
114111068SJohn.Danielson@Sun.COM 
114211068SJohn.Danielson@Sun.COM 	int i, nset;
114311068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
114411068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
114511068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
114611068SJohn.Danielson@Sun.COM 	extern pri_t maxclsyspri;
114710696SDavid.Hollister@Sun.COM 
114811068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
114911068SJohn.Danielson@Sun.COM 		/*
115011068SJohn.Danielson@Sun.COM 		 * calculate the # of taskq threads to create
115111068SJohn.Danielson@Sun.COM 		 */
115211068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
115311068SJohn.Danielson@Sun.COM 			if (bitset_in_set(activate, i))
115411068SJohn.Danielson@Sun.COM 				nset++;
115511068SJohn.Danielson@Sun.COM 		ASSERT(nset);
115611068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
115711068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
115811068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
115911068SJohn.Danielson@Sun.COM 	}
116010696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
116111068SJohn.Danielson@Sun.COM 		if (bitset_in_set(activate, i)) {
116211068SJohn.Danielson@Sun.COM 			if (!tqp)
116311068SJohn.Danielson@Sun.COM 				dam_addr_activate(mapp, i);
116411068SJohn.Danielson@Sun.COM 			else {
116511068SJohn.Danielson@Sun.COM 				/*
116611068SJohn.Danielson@Sun.COM 				 * multi-threaded activation
116711068SJohn.Danielson@Sun.COM 				 */
116811068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
116911068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
117011068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
117111068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp, dam_tq_config,
117211854SChris.Horne@Sun.COM 				    tqd, TQ_SLEEP);
117311068SJohn.Danielson@Sun.COM 			}
117410696SDavid.Hollister@Sun.COM 		}
117511068SJohn.Danielson@Sun.COM 	}
117611068SJohn.Danielson@Sun.COM 	if (tqp) {
117711068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
117811068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
117910696SDavid.Hollister@Sun.COM 	}
118010696SDavid.Hollister@Sun.COM }
118110696SDavid.Hollister@Sun.COM 
118210696SDavid.Hollister@Sun.COM /*
118311068SJohn.Danielson@Sun.COM  * Deactivate a set of stabilized addresses
118410696SDavid.Hollister@Sun.COM  */
118510696SDavid.Hollister@Sun.COM static void
118611068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
118710696SDavid.Hollister@Sun.COM {
118811068SJohn.Danielson@Sun.COM 	int i, nset;
118911068SJohn.Danielson@Sun.COM 	taskq_t *tqp = NULL;
119011068SJohn.Danielson@Sun.COM 	cfg_tqd_t *tqd = NULL;
119111068SJohn.Danielson@Sun.COM 	char tqn[TASKQ_NAMELEN];
119211068SJohn.Danielson@Sun.COM 
119311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
119411068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
119510696SDavid.Hollister@Sun.COM 
119611068SJohn.Danielson@Sun.COM 	if (mapp->dam_options & DAMAP_MTCONFIG) {
119711068SJohn.Danielson@Sun.COM 		/*
119811068SJohn.Danielson@Sun.COM 		 * compute the # of taskq threads to dispatch
119911068SJohn.Danielson@Sun.COM 		 */
120011068SJohn.Danielson@Sun.COM 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
120111068SJohn.Danielson@Sun.COM 			if (bitset_in_set(deactivate, i))
120211068SJohn.Danielson@Sun.COM 				nset++;
120311068SJohn.Danielson@Sun.COM 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
120411068SJohn.Danielson@Sun.COM 		    mapp->dam_name);
120511068SJohn.Danielson@Sun.COM 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
120611068SJohn.Danielson@Sun.COM 		    INT_MAX, TASKQ_PREPOPULATE);
120711068SJohn.Danielson@Sun.COM 	}
120810696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
120911068SJohn.Danielson@Sun.COM 		if (bitset_in_set(deactivate, i)) {
121011068SJohn.Danielson@Sun.COM 			if (!tqp) {
121111068SJohn.Danielson@Sun.COM 				dam_addr_deactivate(mapp, i);
121211068SJohn.Danielson@Sun.COM 			} else {
121311068SJohn.Danielson@Sun.COM 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
121411068SJohn.Danielson@Sun.COM 				tqd->tqd_mapp = mapp;
121511068SJohn.Danielson@Sun.COM 				tqd->tqd_id = i;
121611068SJohn.Danielson@Sun.COM 				(void) taskq_dispatch(tqp,
121711854SChris.Horne@Sun.COM 				    dam_tq_unconfig, tqd, TQ_SLEEP);
121811068SJohn.Danielson@Sun.COM 			}
121910696SDavid.Hollister@Sun.COM 		}
122010696SDavid.Hollister@Sun.COM 	}
122111068SJohn.Danielson@Sun.COM 
122211068SJohn.Danielson@Sun.COM 	if (tqp) {
122311068SJohn.Danielson@Sun.COM 		taskq_wait(tqp);
122411068SJohn.Danielson@Sun.COM 		taskq_destroy(tqp);
122511068SJohn.Danielson@Sun.COM 	}
122610696SDavid.Hollister@Sun.COM }
122710696SDavid.Hollister@Sun.COM 
122810696SDavid.Hollister@Sun.COM /*
122911068SJohn.Danielson@Sun.COM  * Release a previously activated address
123010696SDavid.Hollister@Sun.COM  */
123110696SDavid.Hollister@Sun.COM static void
123211068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid)
123310696SDavid.Hollister@Sun.COM {
123410696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
123511068SJohn.Danielson@Sun.COM 	char	 *addrstr;
123610696SDavid.Hollister@Sun.COM 
123711068SJohn.Danielson@Sun.COM 
123811068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
123910696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
124010696SDavid.Hollister@Sun.COM 	ASSERT(passp);
124110696SDavid.Hollister@Sun.COM 
124211068SJohn.Danielson@Sun.COM 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
124311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
124411068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
124510696SDavid.Hollister@Sun.COM 
124610696SDavid.Hollister@Sun.COM 	/*
124711068SJohn.Danielson@Sun.COM 	 * defer releasing the address until outstanding references
124811068SJohn.Danielson@Sun.COM 	 * are released
124910696SDavid.Hollister@Sun.COM 	 */
125011068SJohn.Danielson@Sun.COM 	if (passp->da_ref > 1) {
125111068SJohn.Danielson@Sun.COM 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
125211068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
125311068SJohn.Danielson@Sun.COM 		    int, passp->da_ref);
125410696SDavid.Hollister@Sun.COM 		return;
125511068SJohn.Danielson@Sun.COM 	}
125610696SDavid.Hollister@Sun.COM 
125710696SDavid.Hollister@Sun.COM 	/*
125811068SJohn.Danielson@Sun.COM 	 * allow pending reports to stabilize
125910696SDavid.Hollister@Sun.COM 	 */
126011068SJohn.Danielson@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
126111068SJohn.Danielson@Sun.COM 		DTRACE_PROBE3(damap__addr__release__report__pending,
126211068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
126310696SDavid.Hollister@Sun.COM 		return;
126410696SDavid.Hollister@Sun.COM 	}
126511068SJohn.Danielson@Sun.COM 
126610696SDavid.Hollister@Sun.COM 	ddi_strid_free(mapp->dam_addr_hash, addrid);
126710696SDavid.Hollister@Sun.COM 	ddi_soft_state_free(mapp->dam_da, addrid);
126810696SDavid.Hollister@Sun.COM }
126910696SDavid.Hollister@Sun.COM 
127010696SDavid.Hollister@Sun.COM /*
127110696SDavid.Hollister@Sun.COM  * process stabilized address reports
127210696SDavid.Hollister@Sun.COM  */
127310696SDavid.Hollister@Sun.COM static void
127411068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg)
127510696SDavid.Hollister@Sun.COM {
127610696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
127710696SDavid.Hollister@Sun.COM 	bitset_t delta;
127810696SDavid.Hollister@Sun.COM 	bitset_t cfg;
127910696SDavid.Hollister@Sun.COM 	bitset_t uncfg;
128010696SDavid.Hollister@Sun.COM 	int has_cfg, has_uncfg;
128111068SJohn.Danielson@Sun.COM 	uint32_t i, n_active;
128211068SJohn.Danielson@Sun.COM 
128311068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
128411068SJohn.Danielson@Sun.COM 	    dam_t *, mapp);
128510696SDavid.Hollister@Sun.COM 
128610696SDavid.Hollister@Sun.COM 	bitset_init(&delta);
128710696SDavid.Hollister@Sun.COM 	bitset_resize(&delta, mapp->dam_size);
128810696SDavid.Hollister@Sun.COM 	bitset_init(&cfg);
128910696SDavid.Hollister@Sun.COM 	bitset_resize(&cfg, mapp->dam_size);
129010696SDavid.Hollister@Sun.COM 	bitset_init(&uncfg);
129110696SDavid.Hollister@Sun.COM 	bitset_resize(&uncfg, mapp->dam_size);
129210696SDavid.Hollister@Sun.COM 
129311068SJohn.Danielson@Sun.COM 	/*
129411068SJohn.Danielson@Sun.COM 	 * determine which addresses have changed during
129511068SJohn.Danielson@Sun.COM 	 * this stabilization cycle
129611068SJohn.Danielson@Sun.COM 	 */
129711068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
129811068SJohn.Danielson@Sun.COM 	ASSERT(mapp->dam_flags & DAM_SPEND);
129910696SDavid.Hollister@Sun.COM 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
130010696SDavid.Hollister@Sun.COM 	    &delta)) {
130111068SJohn.Danielson@Sun.COM 		/*
130211068SJohn.Danielson@Sun.COM 		 * no difference
130311068SJohn.Danielson@Sun.COM 		 */
130410696SDavid.Hollister@Sun.COM 		bitset_zero(&mapp->dam_stable_set);
1305*12207SChris.Horne@Sun.COM 		mapp->dam_flags &= ~DAM_SPEND;
1306*12207SChris.Horne@Sun.COM 		cv_signal(&mapp->dam_sync_cv);
130711068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
1308*12207SChris.Horne@Sun.COM 
130910696SDavid.Hollister@Sun.COM 		bitset_fini(&uncfg);
131010696SDavid.Hollister@Sun.COM 		bitset_fini(&cfg);
131110696SDavid.Hollister@Sun.COM 		bitset_fini(&delta);
131211068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
131311068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
131410696SDavid.Hollister@Sun.COM 		return;
131510696SDavid.Hollister@Sun.COM 	}
131611068SJohn.Danielson@Sun.COM 
131711068SJohn.Danielson@Sun.COM 	/*
131811068SJohn.Danielson@Sun.COM 	 * compute the sets of addresses to be activated and deactivated
131911068SJohn.Danielson@Sun.COM 	 */
132010696SDavid.Hollister@Sun.COM 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
132110696SDavid.Hollister@Sun.COM 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
132211068SJohn.Danielson@Sun.COM 
132311068SJohn.Danielson@Sun.COM 	/*
132411068SJohn.Danielson@Sun.COM 	 * drop map lock while invoking callouts
132511068SJohn.Danielson@Sun.COM 	 */
132611068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
132711068SJohn.Danielson@Sun.COM 
132811068SJohn.Danielson@Sun.COM 	/*
132911068SJohn.Danielson@Sun.COM 	 * activate all newly stable addresss
133011068SJohn.Danielson@Sun.COM 	 */
133111068SJohn.Danielson@Sun.COM 	if (has_cfg)
133210696SDavid.Hollister@Sun.COM 		dam_addrset_activate(mapp, &cfg);
133311068SJohn.Danielson@Sun.COM 
133411068SJohn.Danielson@Sun.COM 	/*
133511068SJohn.Danielson@Sun.COM 	 * deactivate addresss which are no longer in the map
133611068SJohn.Danielson@Sun.COM 	 */
133711068SJohn.Danielson@Sun.COM 	if (has_uncfg)
133811068SJohn.Danielson@Sun.COM 		dam_addrset_deactivate(mapp, &uncfg);
133911068SJohn.Danielson@Sun.COM 
134011068SJohn.Danielson@Sun.COM 
134111068SJohn.Danielson@Sun.COM 	/*
134211068SJohn.Danielson@Sun.COM 	 * timestamp the last stable time and increment the kstat keeping
134311068SJohn.Danielson@Sun.COM 	 * the # of of stable cycles for the map
134411068SJohn.Danielson@Sun.COM 	 */
134511068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
134610696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_stable_set);
134710696SDavid.Hollister@Sun.COM 	mapp->dam_last_stable = gethrtime();
134810696SDavid.Hollister@Sun.COM 	mapp->dam_stable_cnt++;
134911068SJohn.Danielson@Sun.COM 	DAM_INCR_STAT(mapp, dam_cycles);
135011068SJohn.Danielson@Sun.COM 
135111068SJohn.Danielson@Sun.COM 	/*
135211068SJohn.Danielson@Sun.COM 	 * determine the number of stable addresses
135311068SJohn.Danielson@Sun.COM 	 * and update the n_active kstat for this map
135411068SJohn.Danielson@Sun.COM 	 */
135511068SJohn.Danielson@Sun.COM 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
135611068SJohn.Danielson@Sun.COM 		if (bitset_in_set(&mapp->dam_active_set, i))
135711068SJohn.Danielson@Sun.COM 			n_active++;
135811068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_active, n_active);
135911068SJohn.Danielson@Sun.COM 
136011068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
136111068SJohn.Danielson@Sun.COM 	    dam_t *, mapp, int, n_active);
136211068SJohn.Danielson@Sun.COM 
1363*12207SChris.Horne@Sun.COM 	mapp->dam_flags &= ~DAM_SPEND;
1364*12207SChris.Horne@Sun.COM 	cv_signal(&mapp->dam_sync_cv);
136511068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
1366*12207SChris.Horne@Sun.COM 
136710696SDavid.Hollister@Sun.COM 	bitset_fini(&uncfg);
136810696SDavid.Hollister@Sun.COM 	bitset_fini(&cfg);
136910696SDavid.Hollister@Sun.COM 	bitset_fini(&delta);
137010696SDavid.Hollister@Sun.COM }
137110696SDavid.Hollister@Sun.COM 
137210696SDavid.Hollister@Sun.COM /*
137310696SDavid.Hollister@Sun.COM  * per-address stabilization timeout
137410696SDavid.Hollister@Sun.COM  */
137510696SDavid.Hollister@Sun.COM static void
137610696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg)
137710696SDavid.Hollister@Sun.COM {
137810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
137910696SDavid.Hollister@Sun.COM 	int i;
138010696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
138110696SDavid.Hollister@Sun.COM 	int spend = 0;
138210696SDavid.Hollister@Sun.COM 	int tpend = 0;
1383*12207SChris.Horne@Sun.COM 	int64_t ts, next_ticks, delta_ticks;
138410696SDavid.Hollister@Sun.COM 
138511068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
138610696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
138711068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
138811068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
138911068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
139010696SDavid.Hollister@Sun.COM 		return;
139110696SDavid.Hollister@Sun.COM 	}
139210696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
139311068SJohn.Danielson@Sun.COM 
139410696SDavid.Hollister@Sun.COM 	/*
139510696SDavid.Hollister@Sun.COM 	 * If still under stabilization, reschedule timeout,
139611068SJohn.Danielson@Sun.COM 	 * otherwise dispatch the task to activate and deactivate the
139711068SJohn.Danielson@Sun.COM 	 * new stable address
139810696SDavid.Hollister@Sun.COM 	 */
139910696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SPEND) {
140011068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
140110696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
1402*12207SChris.Horne@Sun.COM 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1403*12207SChris.Horne@Sun.COM 		    mapp->dam_stable_ticks);
140411068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
140511068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
140611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
140710696SDavid.Hollister@Sun.COM 		return;
140810696SDavid.Hollister@Sun.COM 	}
140910696SDavid.Hollister@Sun.COM 
141011068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
141111068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
141211068SJohn.Danielson@Sun.COM 
141311068SJohn.Danielson@Sun.COM 	/*
141411068SJohn.Danielson@Sun.COM 	 * copy the current active set to the stable map
141511068SJohn.Danielson@Sun.COM 	 * for each address being reported, decrement its
141611068SJohn.Danielson@Sun.COM 	 * stabilize deadline, and if stable, add or remove the
141711068SJohn.Danielson@Sun.COM 	 * address from the stable set
141811068SJohn.Danielson@Sun.COM 	 */
141910696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
1420*12207SChris.Horne@Sun.COM 	ts = ddi_get_lbolt64();
1421*12207SChris.Horne@Sun.COM 	next_ticks = mapp->dam_stable_ticks;
142210696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
142310696SDavid.Hollister@Sun.COM 		if (!bitset_in_set(&mapp->dam_report_set, i))
142410696SDavid.Hollister@Sun.COM 			continue;
142510696SDavid.Hollister@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, i);
142610696SDavid.Hollister@Sun.COM 		ASSERT(passp);
142710696SDavid.Hollister@Sun.COM 
142810696SDavid.Hollister@Sun.COM 		/* report has stabilized */
142910696SDavid.Hollister@Sun.COM 		if (passp->da_deadline <= ts) {
143010696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_report_set, i);
143111068SJohn.Danielson@Sun.COM 			if (passp->da_flags & DA_RELE)
143210696SDavid.Hollister@Sun.COM 				bitset_del(&mapp->dam_stable_set, i);
143311068SJohn.Danielson@Sun.COM 			else
143410696SDavid.Hollister@Sun.COM 				bitset_add(&mapp->dam_stable_set, i);
143510696SDavid.Hollister@Sun.COM 			spend++;
143610696SDavid.Hollister@Sun.COM 			continue;
143710696SDavid.Hollister@Sun.COM 		}
143810696SDavid.Hollister@Sun.COM 
143910696SDavid.Hollister@Sun.COM 		/*
144011068SJohn.Danielson@Sun.COM 		 * not stabilized, determine next map timeout
144110696SDavid.Hollister@Sun.COM 		 */
144210696SDavid.Hollister@Sun.COM 		tpend++;
1443*12207SChris.Horne@Sun.COM 		delta_ticks = passp->da_deadline - ts;
1444*12207SChris.Horne@Sun.COM 		if (delta_ticks < next_ticks)
1445*12207SChris.Horne@Sun.COM 			next_ticks = delta_ticks;
144610696SDavid.Hollister@Sun.COM 	}
144710696SDavid.Hollister@Sun.COM 
144810696SDavid.Hollister@Sun.COM 	/*
144911068SJohn.Danielson@Sun.COM 	 * schedule system_taskq activation of stabilized reports
145010696SDavid.Hollister@Sun.COM 	 */
145110696SDavid.Hollister@Sun.COM 	if (spend) {
145211068SJohn.Danielson@Sun.COM 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
145311854SChris.Horne@Sun.COM 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1454*12207SChris.Horne@Sun.COM 			mapp->dam_flags |= DAM_SPEND;
145511068SJohn.Danielson@Sun.COM 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
145611068SJohn.Danielson@Sun.COM 			    mapp->dam_name, dam_t *, mapp);
145711068SJohn.Danielson@Sun.COM 		} else {
145810696SDavid.Hollister@Sun.COM 			tpend++;
145911854SChris.Horne@Sun.COM 
146011854SChris.Horne@Sun.COM 			/*
146111854SChris.Horne@Sun.COM 			 * Avoid waiting the entire stabalization
146211854SChris.Horne@Sun.COM 			 * time again if taskq_diskpatch fails.
146311854SChris.Horne@Sun.COM 			 */
1464*12207SChris.Horne@Sun.COM 			delta_ticks = drv_usectohz(
146511854SChris.Horne@Sun.COM 			    damap_taskq_dispatch_retry_usec);
1466*12207SChris.Horne@Sun.COM 			if (delta_ticks < next_ticks)
1467*12207SChris.Horne@Sun.COM 				next_ticks = delta_ticks;
146811068SJohn.Danielson@Sun.COM 		}
146910696SDavid.Hollister@Sun.COM 	}
147010696SDavid.Hollister@Sun.COM 
147110696SDavid.Hollister@Sun.COM 	/*
147211068SJohn.Danielson@Sun.COM 	 * reschedule the stabilization timer if there are reports
147311068SJohn.Danielson@Sun.COM 	 * still pending
147410696SDavid.Hollister@Sun.COM 	 */
147510696SDavid.Hollister@Sun.COM 	if (tpend)
1476*12207SChris.Horne@Sun.COM 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1477*12207SChris.Horne@Sun.COM 		    (clock_t)next_ticks);
147811068SJohn.Danielson@Sun.COM 
147911068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
148010696SDavid.Hollister@Sun.COM }
148110696SDavid.Hollister@Sun.COM 
148210696SDavid.Hollister@Sun.COM /*
148311068SJohn.Danielson@Sun.COM  * fullset stabilization timeout callback
148410696SDavid.Hollister@Sun.COM  */
148510696SDavid.Hollister@Sun.COM static void
148611068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg)
148710696SDavid.Hollister@Sun.COM {
148810696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
148910696SDavid.Hollister@Sun.COM 
149011068SJohn.Danielson@Sun.COM 	mutex_enter(&mapp->dam_lock);
149110696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
149211068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
149311068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
149411068SJohn.Danielson@Sun.COM 		    char *, mapp->dam_name, dam_t *, mapp);
149510696SDavid.Hollister@Sun.COM 		return;
149610696SDavid.Hollister@Sun.COM 	}
149710696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
149810696SDavid.Hollister@Sun.COM 
149910696SDavid.Hollister@Sun.COM 	/*
150011068SJohn.Danielson@Sun.COM 	 * If map still underoing stabilization reschedule timeout,
150111068SJohn.Danielson@Sun.COM 	 * else dispatch the task to configure the new stable set of
150211068SJohn.Danielson@Sun.COM 	 * addresses.
150310696SDavid.Hollister@Sun.COM 	 */
150411854SChris.Horne@Sun.COM 	if ((mapp->dam_flags & DAM_SPEND) ||
150511854SChris.Horne@Sun.COM 	    (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
150611854SChris.Horne@Sun.COM 	    TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
150711068SJohn.Danielson@Sun.COM 		DAM_INCR_STAT(mapp, dam_overrun);
150810696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
1509*12207SChris.Horne@Sun.COM 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
1510*12207SChris.Horne@Sun.COM 		    drv_usectohz(damap_taskq_dispatch_retry_usec));
151111854SChris.Horne@Sun.COM 
151211068SJohn.Danielson@Sun.COM 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
151311068SJohn.Danielson@Sun.COM 		    mapp->dam_name, dam_t *, mapp);
151411068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
151511068SJohn.Danielson@Sun.COM 		return;
151610696SDavid.Hollister@Sun.COM 	}
151711068SJohn.Danielson@Sun.COM 
151811068SJohn.Danielson@Sun.COM 	DAM_SET_STAT(mapp, dam_overrun, 0);
151911068SJohn.Danielson@Sun.COM 	mapp->dam_stable_overrun = 0;
152011068SJohn.Danielson@Sun.COM 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
152111068SJohn.Danielson@Sun.COM 	bitset_zero(&mapp->dam_report_set);
152211068SJohn.Danielson@Sun.COM 	mapp->dam_flags |= DAM_SPEND;
152311068SJohn.Danielson@Sun.COM 	mapp->dam_flags &= ~DAM_SETADD;
1524*12207SChris.Horne@Sun.COM 	/* NOTE: don't need cv_signal since DAM_SPEND is still set */
1525*12207SChris.Horne@Sun.COM 
152611068SJohn.Danielson@Sun.COM 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
152711068SJohn.Danielson@Sun.COM 	    mapp->dam_name, dam_t *, mapp);
152811068SJohn.Danielson@Sun.COM 	mutex_exit(&mapp->dam_lock);
152910696SDavid.Hollister@Sun.COM }
153010696SDavid.Hollister@Sun.COM 
153110696SDavid.Hollister@Sun.COM /*
1532*12207SChris.Horne@Sun.COM  * schedule map timeout in 'ticks' ticks
1533*12207SChris.Horne@Sun.COM  * if map timer is currently running, cancel if ticks == 0
153410696SDavid.Hollister@Sun.COM  */
153510696SDavid.Hollister@Sun.COM static void
1536*12207SChris.Horne@Sun.COM dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
153710696SDavid.Hollister@Sun.COM {
153810696SDavid.Hollister@Sun.COM 	timeout_id_t tid;
153910696SDavid.Hollister@Sun.COM 
1540*12207SChris.Horne@Sun.COM 	DTRACE_PROBE3(damap__sched__timeout, char *, mapp->dam_name,
1541*12207SChris.Horne@Sun.COM 	    dam_t *, mapp, int, ticks);
154211068SJohn.Danielson@Sun.COM 
154311068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
154410696SDavid.Hollister@Sun.COM 	if ((tid = mapp->dam_tid) != 0) {
1545*12207SChris.Horne@Sun.COM 		if (ticks == 0) {
154611068SJohn.Danielson@Sun.COM 			mapp->dam_tid = 0;
154711068SJohn.Danielson@Sun.COM 			mutex_exit(&mapp->dam_lock);
154811068SJohn.Danielson@Sun.COM 			(void) untimeout(tid);
154911068SJohn.Danielson@Sun.COM 			mutex_enter(&mapp->dam_lock);
155011068SJohn.Danielson@Sun.COM 		}
155111068SJohn.Danielson@Sun.COM 	} else {
1552*12207SChris.Horne@Sun.COM 		if (timeout_cb && (ticks != 0))
1553*12207SChris.Horne@Sun.COM 			mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
155410696SDavid.Hollister@Sun.COM 	}
155510696SDavid.Hollister@Sun.COM }
155610696SDavid.Hollister@Sun.COM 
155710696SDavid.Hollister@Sun.COM /*
155811068SJohn.Danielson@Sun.COM  * report addition or removal of an address
155910696SDavid.Hollister@Sun.COM  */
156010696SDavid.Hollister@Sun.COM static void
156111068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
156210696SDavid.Hollister@Sun.COM {
156311068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
156411068SJohn.Danielson@Sun.COM 
156511068SJohn.Danielson@Sun.COM 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
156611068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
156711068SJohn.Danielson@Sun.COM 
156811068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
156910696SDavid.Hollister@Sun.COM 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
157010696SDavid.Hollister@Sun.COM 	passp->da_last_report = gethrtime();
157110696SDavid.Hollister@Sun.COM 	mapp->dam_last_update = gethrtime();
157210696SDavid.Hollister@Sun.COM 	passp->da_report_cnt++;
1573*12207SChris.Horne@Sun.COM 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
157411068SJohn.Danielson@Sun.COM 	if (rpt_type == RPT_ADDR_DEL)
157510696SDavid.Hollister@Sun.COM 		passp->da_flags |= DA_RELE;
157611068SJohn.Danielson@Sun.COM 	else if (rpt_type == RPT_ADDR_ADD)
157710696SDavid.Hollister@Sun.COM 		passp->da_flags &= ~DA_RELE;
157810696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
1579*12207SChris.Horne@Sun.COM 	dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
158010696SDavid.Hollister@Sun.COM }
158110696SDavid.Hollister@Sun.COM 
158210696SDavid.Hollister@Sun.COM /*
158310696SDavid.Hollister@Sun.COM  * release an address report
158410696SDavid.Hollister@Sun.COM  */
158510696SDavid.Hollister@Sun.COM static void
158611068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid)
158710696SDavid.Hollister@Sun.COM {
158810696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
158911068SJohn.Danielson@Sun.COM 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
159010696SDavid.Hollister@Sun.COM 
159111068SJohn.Danielson@Sun.COM 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
159211068SJohn.Danielson@Sun.COM 	    char *, addrstr, dam_t *, mapp);
159311068SJohn.Danielson@Sun.COM 
159411068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
159510696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
159610696SDavid.Hollister@Sun.COM 	ASSERT(passp);
159711068SJohn.Danielson@Sun.COM 	/*
159811068SJohn.Danielson@Sun.COM 	 * clear the report bit
159911068SJohn.Danielson@Sun.COM 	 * if the address has a registered deactivation handler and
160011601SDavid.Hollister@Sun.COM 	 * we are holding a private data pointer and the address has not
160111601SDavid.Hollister@Sun.COM 	 * stabilized, deactivate the address (private data).
160211068SJohn.Danielson@Sun.COM 	 */
160311068SJohn.Danielson@Sun.COM 	bitset_del(&mapp->dam_report_set, addrid);
160411601SDavid.Hollister@Sun.COM 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
160511601SDavid.Hollister@Sun.COM 	    passp->da_ppriv_rpt) {
160611068SJohn.Danielson@Sun.COM 		mutex_exit(&mapp->dam_lock);
160711068SJohn.Danielson@Sun.COM 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
160811068SJohn.Danielson@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
160911601SDavid.Hollister@Sun.COM 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
161011068SJohn.Danielson@Sun.COM 		mutex_enter(&mapp->dam_lock);
161111068SJohn.Danielson@Sun.COM 	}
161210696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = NULL;
161310696SDavid.Hollister@Sun.COM 	if (passp->da_nvl_rpt)
161410696SDavid.Hollister@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
161510696SDavid.Hollister@Sun.COM }
161610696SDavid.Hollister@Sun.COM 
161710696SDavid.Hollister@Sun.COM /*
161810696SDavid.Hollister@Sun.COM  * return the map ID of an address
161910696SDavid.Hollister@Sun.COM  */
162010696SDavid.Hollister@Sun.COM static id_t
162110696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address)
162210696SDavid.Hollister@Sun.COM {
162310696SDavid.Hollister@Sun.COM 	damap_id_t addrid;
162410696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
162510696SDavid.Hollister@Sun.COM 
162611068SJohn.Danielson@Sun.COM 	ASSERT(mutex_owned(&mapp->dam_lock));
162710696SDavid.Hollister@Sun.COM 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
162811068SJohn.Danielson@Sun.COM 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
162910696SDavid.Hollister@Sun.COM 		    address)) == (damap_id_t)0) {
163010696SDavid.Hollister@Sun.COM 			return (0);
163110696SDavid.Hollister@Sun.COM 		}
163210696SDavid.Hollister@Sun.COM 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
163310696SDavid.Hollister@Sun.COM 		    DDI_SUCCESS) {
163410696SDavid.Hollister@Sun.COM 			ddi_strid_free(mapp->dam_addr_hash, addrid);
163510696SDavid.Hollister@Sun.COM 			return (0);
163610696SDavid.Hollister@Sun.COM 		}
163711068SJohn.Danielson@Sun.COM 
163810696SDavid.Hollister@Sun.COM 		if (addrid >= mapp->dam_high)
163910696SDavid.Hollister@Sun.COM 			mapp->dam_high = addrid + 1;
164011068SJohn.Danielson@Sun.COM 
164111068SJohn.Danielson@Sun.COM 		/*
164211068SJohn.Danielson@Sun.COM 		 * expand bitmaps if ID has outgrown old map size
164311068SJohn.Danielson@Sun.COM 		 */
164411068SJohn.Danielson@Sun.COM 		if (mapp->dam_high > mapp->dam_size) {
164511068SJohn.Danielson@Sun.COM 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
164611068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
164711068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
164811068SJohn.Danielson@Sun.COM 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
164911068SJohn.Danielson@Sun.COM 		}
165011068SJohn.Danielson@Sun.COM 
165111068SJohn.Danielson@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
165211068SJohn.Danielson@Sun.COM 		passp->da_ref = 1;
165311068SJohn.Danielson@Sun.COM 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
165411068SJohn.Danielson@Sun.COM 		    addrid); /* for mdb */
165510696SDavid.Hollister@Sun.COM 	}
165610696SDavid.Hollister@Sun.COM 	return (addrid);
165710696SDavid.Hollister@Sun.COM }
165810696SDavid.Hollister@Sun.COM 
165910696SDavid.Hollister@Sun.COM /*
166010696SDavid.Hollister@Sun.COM  * create and install map statistics
166110696SDavid.Hollister@Sun.COM  */
166210696SDavid.Hollister@Sun.COM static int
166310696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp)
166410696SDavid.Hollister@Sun.COM {
166510696SDavid.Hollister@Sun.COM 	kstat_t			*mapsp;
166610696SDavid.Hollister@Sun.COM 	struct dam_kstats	*statsp;
166710696SDavid.Hollister@Sun.COM 
166810696SDavid.Hollister@Sun.COM 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
166910696SDavid.Hollister@Sun.COM 	    KSTAT_TYPE_NAMED,
167010696SDavid.Hollister@Sun.COM 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
167111068SJohn.Danielson@Sun.COM 
167211068SJohn.Danielson@Sun.COM 	if (mapsp == NULL)
167310696SDavid.Hollister@Sun.COM 		return (DDI_FAILURE);
167410696SDavid.Hollister@Sun.COM 
167510696SDavid.Hollister@Sun.COM 	statsp = (struct dam_kstats *)mapsp->ks_data;
167611068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
167711068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
167811068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
167911068SJohn.Danielson@Sun.COM 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
168010696SDavid.Hollister@Sun.COM 	kstat_install(mapsp);
168110696SDavid.Hollister@Sun.COM 	mapp->dam_kstatsp = mapsp;
168210696SDavid.Hollister@Sun.COM 	return (DDI_SUCCESS);
168310696SDavid.Hollister@Sun.COM }
1684