xref: /titanic_53/usr/src/uts/common/os/damap.c (revision d3d50737e566cade9a08d73d2af95105ac7cd960)
14c06356bSdh142964 /*
24c06356bSdh142964  * CDDL HEADER START
34c06356bSdh142964  *
44c06356bSdh142964  * The contents of this file are subject to the terms of the
54c06356bSdh142964  * Common Development and Distribution License (the "License").
64c06356bSdh142964  * You may not use this file except in compliance with the License.
74c06356bSdh142964  *
84c06356bSdh142964  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94c06356bSdh142964  * or http://www.opensolaris.org/os/licensing.
104c06356bSdh142964  * See the License for the specific language governing permissions
114c06356bSdh142964  * and limitations under the License.
124c06356bSdh142964  *
134c06356bSdh142964  * When distributing Covered Code, include this CDDL HEADER in each
144c06356bSdh142964  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154c06356bSdh142964  * If applicable, add the following below this CDDL HEADER, with the
164c06356bSdh142964  * fields enclosed by brackets "[]" replaced with your own identifying
174c06356bSdh142964  * information: Portions Copyright [yyyy] [name of copyright owner]
184c06356bSdh142964  *
194c06356bSdh142964  * CDDL HEADER END
204c06356bSdh142964  */
214c06356bSdh142964 
224c06356bSdh142964 /*
234c06356bSdh142964  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
244c06356bSdh142964  * Use is subject to license terms.
254c06356bSdh142964  */
264c06356bSdh142964 
274c06356bSdh142964 #include <sys/note.h>
284c06356bSdh142964 #include <sys/types.h>
294c06356bSdh142964 #include <sys/param.h>
304c06356bSdh142964 #include <sys/systm.h>
314c06356bSdh142964 #include <sys/buf.h>
324c06356bSdh142964 #include <sys/kmem.h>
334c06356bSdh142964 #include <sys/cmn_err.h>
344c06356bSdh142964 #include <sys/debug.h>
354c06356bSdh142964 #include <sys/sunndi.h>
364c06356bSdh142964 #include <sys/kstat.h>
374c06356bSdh142964 #include <sys/conf.h>
384c06356bSdh142964 #include <sys/ddi_timer.h>
394c06356bSdh142964 #include <sys/devctl.h>
404c06356bSdh142964 #include <sys/callb.h>
414c06356bSdh142964 #include <sys/sysevent.h>
424c06356bSdh142964 #include <sys/taskq.h>
434c06356bSdh142964 #include <sys/ddi.h>
444c06356bSdh142964 #include <sys/bitset.h>
454c06356bSdh142964 #include <sys/damap.h>
464c06356bSdh142964 #include <sys/damap_impl.h>
474c06356bSdh142964 
484c06356bSdh142964 #ifdef DEBUG
494c06356bSdh142964 static int damap_debug = 0;
504c06356bSdh142964 #endif /* DEBUG */
514c06356bSdh142964 
524c06356bSdh142964 static void dam_addrset_activate(dam_t *, bitset_t *);
534c06356bSdh142964 static void dam_addrset_release(dam_t *, bitset_t *);
544c06356bSdh142964 static void dam_activate_taskq(void *);
554c06356bSdh142964 static void dam_addr_stable_cb(void *);
564c06356bSdh142964 static void dam_set_stable_cb(void *);
574c06356bSdh142964 static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)());
584c06356bSdh142964 static void dam_add_report(dam_t *, dam_da_t *, id_t, int);
594c06356bSdh142964 static void dam_release(dam_t *, id_t);
604c06356bSdh142964 static void dam_release_report(dam_t *, id_t);
614c06356bSdh142964 static void dam_deactivate_addr(dam_t *, id_t);
624c06356bSdh142964 static id_t dam_get_addrid(dam_t *, char *);
634c06356bSdh142964 static int dam_kstat_create(dam_t *);
644c06356bSdh142964 static void dam_kstat_destroy(dam_t *);
654c06356bSdh142964 
664c06356bSdh142964 #define	DAM_INCR_STAT(mapp, stat)				\
674c06356bSdh142964 	if ((mapp)->dam_kstatsp) {				\
684c06356bSdh142964 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
694c06356bSdh142964 		stp->stat.value.ui32++;				\
704c06356bSdh142964 	}
714c06356bSdh142964 
724c06356bSdh142964 #define	DAM_SET_STAT(mapp, stat, val)				\
734c06356bSdh142964 	if ((mapp)->dam_kstatsp) {				\
744c06356bSdh142964 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
754c06356bSdh142964 		stp->stat.value.ui32 = (val);			\
764c06356bSdh142964 	}
774c06356bSdh142964 
784c06356bSdh142964 /*
794c06356bSdh142964  * Create new device address map
804c06356bSdh142964  *
814c06356bSdh142964  * ident:		map name (kstat)
824c06356bSdh142964  * size:		max # of map entries
834c06356bSdh142964  * rptmode:		type or mode of reporting
844c06356bSdh142964  * stable_usec:		# of quiescent microseconds before report/map is stable
854c06356bSdh142964  *
864c06356bSdh142964  * activate_arg:	address provider activation-callout private
874c06356bSdh142964  * activate_cb:		address provider activation callback handler
884c06356bSdh142964  * deactivate_cb:	address provider deactivation callback handler
894c06356bSdh142964  *
904c06356bSdh142964  * config_arg:		configuration-callout private
914c06356bSdh142964  * config_cb:		class configuration callout
924c06356bSdh142964  * unconfig_cb:		class unconfiguration callout
934c06356bSdh142964  *
944c06356bSdh142964  * damapp:		pointer to map handle (return)
954c06356bSdh142964  *
964c06356bSdh142964  * Returns:	DAM_SUCCESS
974c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
984c06356bSdh142964  *		DAM_FAILURE	General failure
994c06356bSdh142964  */
1004c06356bSdh142964 int
1014c06356bSdh142964 damap_create(char *ident, size_t size, damap_rptmode_t rptmode,
1024c06356bSdh142964     clock_t stable_usec,
1034c06356bSdh142964     void *activate_arg, damap_activate_cb_t activate_cb,
1044c06356bSdh142964     damap_deactivate_cb_t deactivate_cb,
1054c06356bSdh142964     void *config_arg, damap_configure_cb_t configure_cb,
1064c06356bSdh142964     damap_unconfig_cb_t unconfig_cb,
1074c06356bSdh142964     damap_t **damapp)
1084c06356bSdh142964 {
1094c06356bSdh142964 	dam_t *mapp;
1104c06356bSdh142964 	void *softstate_p;
1114c06356bSdh142964 
1124c06356bSdh142964 	DTRACE_PROBE1(damap__create__entry, char *, ident);
1134c06356bSdh142964 	if ((configure_cb == NULL) || (unconfig_cb == NULL))
1144c06356bSdh142964 		return (DAM_EINVAL);
1154c06356bSdh142964 
1164c06356bSdh142964 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) !=
1174c06356bSdh142964 	    DDI_SUCCESS)
1184c06356bSdh142964 		return (DAM_FAILURE);
1194c06356bSdh142964 
1204c06356bSdh142964 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
1214c06356bSdh142964 	if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) {
1224c06356bSdh142964 		ddi_soft_state_fini(&softstate_p);
1234c06356bSdh142964 		kmem_free(mapp, sizeof (*mapp));
1244c06356bSdh142964 		return (DAM_FAILURE);
1254c06356bSdh142964 	}
1264c06356bSdh142964 
1274c06356bSdh142964 	mapp->dam_da = softstate_p;
1284c06356bSdh142964 	mapp->dam_stabletmo = drv_usectohz(stable_usec);
1294c06356bSdh142964 	mapp->dam_size = size;
1304c06356bSdh142964 	mapp->dam_high = 1;
1314c06356bSdh142964 	mapp->dam_rptmode = rptmode;
1324c06356bSdh142964 
1334c06356bSdh142964 	mapp->dam_activate_arg = activate_arg;
1344c06356bSdh142964 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
1354c06356bSdh142964 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
1364c06356bSdh142964 
1374c06356bSdh142964 	mapp->dam_config_arg = config_arg;
1384c06356bSdh142964 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
1394c06356bSdh142964 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
1404c06356bSdh142964 
1414c06356bSdh142964 	if (ident)
1424c06356bSdh142964 		mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP);
1434c06356bSdh142964 
1444c06356bSdh142964 	bitset_init(&mapp->dam_active_set);
1454c06356bSdh142964 	bitset_resize(&mapp->dam_active_set, size);
1464c06356bSdh142964 	bitset_init(&mapp->dam_stable_set);
1474c06356bSdh142964 	bitset_resize(&mapp->dam_stable_set, size);
1484c06356bSdh142964 	bitset_init(&mapp->dam_report_set);
1494c06356bSdh142964 	bitset_resize(&mapp->dam_report_set, size);
1504c06356bSdh142964 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
1514c06356bSdh142964 	cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL);
1524c06356bSdh142964 	mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI,
1534c06356bSdh142964 	    0);
1544c06356bSdh142964 	*damapp = (damap_t *)mapp;
1554c06356bSdh142964 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
1564c06356bSdh142964 		damap_destroy((damap_t *)mapp);
1574c06356bSdh142964 		return (DAM_FAILURE);
1584c06356bSdh142964 	}
1594c06356bSdh142964 
1604c06356bSdh142964 	DTRACE_PROBE1(damap__create__exit, dam_t *, mapp);
1614c06356bSdh142964 	return (DAM_SUCCESS);
1624c06356bSdh142964 }
1634c06356bSdh142964 
1644c06356bSdh142964 /*
1654c06356bSdh142964  * Destroy device address map
1664c06356bSdh142964  *
1674c06356bSdh142964  * damapp:	address map
1684c06356bSdh142964  *
1694c06356bSdh142964  * Returns:	DAM_SUCCESS
1704c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
1714c06356bSdh142964  *		DAM_FAILURE	General failure
1724c06356bSdh142964  */
1734c06356bSdh142964 void
1744c06356bSdh142964 damap_destroy(damap_t *damapp)
1754c06356bSdh142964 {
1764c06356bSdh142964 	int i;
1774c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
1784c06356bSdh142964 
1794c06356bSdh142964 	ASSERT(mapp);
1804c06356bSdh142964 
1814c06356bSdh142964 	DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *,
1824c06356bSdh142964 	    mapp->dam_name);
1834c06356bSdh142964 
1844c06356bSdh142964 	DAM_FLAG_SET(mapp, DAM_DESTROYPEND);
1854c06356bSdh142964 	(void) damap_sync(damapp);
1864c06356bSdh142964 
1874c06356bSdh142964 	/*
1884c06356bSdh142964 	 * cancel pending timeouts and kill off the taskq
1894c06356bSdh142964 	 */
1904c06356bSdh142964 	dam_sched_tmo(mapp, 0, NULL);
1914c06356bSdh142964 	ddi_taskq_wait(mapp->dam_taskqp);
1924c06356bSdh142964 	ddi_taskq_destroy(mapp->dam_taskqp);
1934c06356bSdh142964 
1944c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
1954c06356bSdh142964 		if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
1964c06356bSdh142964 			continue;
1974c06356bSdh142964 		if (DAM_IN_REPORT(mapp, i))
1984c06356bSdh142964 			dam_release_report(mapp, i);
1994c06356bSdh142964 		if (DAM_IS_STABLE(mapp, i))
2004c06356bSdh142964 			dam_deactivate_addr(mapp, i);
2014c06356bSdh142964 		ddi_strid_free(mapp->dam_addr_hash, i);
2024c06356bSdh142964 		ddi_soft_state_free(mapp->dam_da, i);
2034c06356bSdh142964 	}
2044c06356bSdh142964 	ddi_strid_fini(&mapp->dam_addr_hash);
2054c06356bSdh142964 	ddi_soft_state_fini(&mapp->dam_da);
2064c06356bSdh142964 	bitset_fini(&mapp->dam_active_set);
2074c06356bSdh142964 	bitset_fini(&mapp->dam_stable_set);
2084c06356bSdh142964 	bitset_fini(&mapp->dam_report_set);
2094c06356bSdh142964 	dam_kstat_destroy(mapp);
2104c06356bSdh142964 	mutex_destroy(&mapp->dam_lock);
2114c06356bSdh142964 	cv_destroy(&mapp->dam_cv);
2124c06356bSdh142964 	if (mapp->dam_name)
2134c06356bSdh142964 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
2144c06356bSdh142964 	kmem_free(mapp, sizeof (*mapp));
2154c06356bSdh142964 	DTRACE_PROBE(damap__destroy__exit);
2164c06356bSdh142964 }
2174c06356bSdh142964 
2184c06356bSdh142964 /*
2194c06356bSdh142964  * Wait for map stability.
2204c06356bSdh142964  *
2214c06356bSdh142964  * damapp:	address map
2224c06356bSdh142964  */
2234c06356bSdh142964 int
2244c06356bSdh142964 damap_sync(damap_t *damapp)
2254c06356bSdh142964 {
2264c06356bSdh142964 
2274c06356bSdh142964 #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK)
2284c06356bSdh142964 
2294c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
2304c06356bSdh142964 	int   none_active;
2314c06356bSdh142964 
2324c06356bSdh142964 	ASSERT(mapp);
2334c06356bSdh142964 
2344c06356bSdh142964 	DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp);
2354c06356bSdh142964 
2364c06356bSdh142964 	mutex_enter(&mapp->dam_lock);
2374c06356bSdh142964 	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
2384c06356bSdh142964 	    (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) {
2394c06356bSdh142964 		cv_wait(&mapp->dam_cv, &mapp->dam_lock);
2404c06356bSdh142964 	}
2414c06356bSdh142964 
2424c06356bSdh142964 	none_active = bitset_is_null(&mapp->dam_active_set);
2434c06356bSdh142964 
2444c06356bSdh142964 	mutex_exit(&mapp->dam_lock);
2454c06356bSdh142964 	DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active);
2464c06356bSdh142964 
2474c06356bSdh142964 	return (none_active);
2484c06356bSdh142964 }
2494c06356bSdh142964 
2504c06356bSdh142964 /*
2514c06356bSdh142964  * Get the name of a device address map
2524c06356bSdh142964  *
2534c06356bSdh142964  * damapp:	address map
2544c06356bSdh142964  *
2554c06356bSdh142964  * Returns:	name
2564c06356bSdh142964  */
2574c06356bSdh142964 char *
2584c06356bSdh142964 damap_name(damap_t *damapp)
2594c06356bSdh142964 {
2604c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
2614c06356bSdh142964 
2624c06356bSdh142964 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
2634c06356bSdh142964 }
2644c06356bSdh142964 
2654c06356bSdh142964 /*
2664c06356bSdh142964  * Report an address to per-address report
2674c06356bSdh142964  *
2684c06356bSdh142964  * damapp:	address map handle
2694c06356bSdh142964  * address:	address in ascii string representation
2704c06356bSdh142964  * rindx:	index if address stabilizes
2714c06356bSdh142964  * nvl:		optional nvlist of configuration-private data
2724c06356bSdh142964  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
2734c06356bSdh142964  *
2744c06356bSdh142964  * Returns:	DAM_SUCCESS
2754c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
2764c06356bSdh142964  *		DAM_MAPFULL	address map exhausted
2774c06356bSdh142964  */
2784c06356bSdh142964 int
2794c06356bSdh142964 damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl,
2804c06356bSdh142964     void *addr_priv)
2814c06356bSdh142964 {
2824c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
2834c06356bSdh142964 	id_t addrid;
2844c06356bSdh142964 	dam_da_t *passp;
2854c06356bSdh142964 
2864c06356bSdh142964 	DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp,
2874c06356bSdh142964 	    char *, address);
2884c06356bSdh142964 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) ||
2894c06356bSdh142964 	    (mapp->dam_flags & DAM_DESTROYPEND))
2904c06356bSdh142964 		return (DAM_EINVAL);
2914c06356bSdh142964 
2924c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
2934c06356bSdh142964 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
2944c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
2954c06356bSdh142964 		return (DAM_MAPFULL);
2964c06356bSdh142964 	}
2974c06356bSdh142964 
2984c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
2994c06356bSdh142964 	ASSERT(passp != NULL);
3004c06356bSdh142964 
3014c06356bSdh142964 	/*
3024c06356bSdh142964 	 * If re-reporting the same address (add or remove) clear
3034c06356bSdh142964 	 * the existing report
3044c06356bSdh142964 	 */
3054c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
3064c06356bSdh142964 		DAM_INCR_STAT(mapp, dam_rereport);
3074c06356bSdh142964 		dam_release_report(mapp, addrid);
3084c06356bSdh142964 		passp->da_jitter++;
3094c06356bSdh142964 	}
3104c06356bSdh142964 	passp->da_ppriv_rpt = addr_priv;
3114c06356bSdh142964 	if (nvl)
3124c06356bSdh142964 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
3134c06356bSdh142964 
3144c06356bSdh142964 	dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD);
3154c06356bSdh142964 	if (ridx != NULL)
3164c06356bSdh142964 		*ridx = (damap_id_t)addrid;
3174c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
3184c06356bSdh142964 	DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *,
3194c06356bSdh142964 	    address, int, addrid);
3204c06356bSdh142964 	return (DAM_SUCCESS);
3214c06356bSdh142964 }
3224c06356bSdh142964 
3234c06356bSdh142964 /*
3244c06356bSdh142964  * Report removal of address from per-address report
3254c06356bSdh142964  *
3264c06356bSdh142964  * damapp:	address map
3274c06356bSdh142964  * address:	address in ascii string representation
3284c06356bSdh142964  *
3294c06356bSdh142964  * Returns:	DAM_SUCCESS
3304c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
3314c06356bSdh142964  *		DAM_FAILURE	General failure
3324c06356bSdh142964  */
3334c06356bSdh142964 int
3344c06356bSdh142964 damap_addr_del(damap_t *damapp, char *address)
3354c06356bSdh142964 {
3364c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
3374c06356bSdh142964 	id_t addrid;
3384c06356bSdh142964 	dam_da_t *passp;
3394c06356bSdh142964 
3404c06356bSdh142964 	DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp,
3414c06356bSdh142964 	    char *, address);
3424c06356bSdh142964 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) ||
3434c06356bSdh142964 	    (mapp->dam_flags & DAM_DESTROYPEND))
3444c06356bSdh142964 		return (DAM_EINVAL);
3454c06356bSdh142964 
3464c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
3474c06356bSdh142964 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
3484c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
3494c06356bSdh142964 		return (DAM_SUCCESS);
3504c06356bSdh142964 	}
3514c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
3524c06356bSdh142964 	ASSERT(passp);
3534c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
3544c06356bSdh142964 		DAM_INCR_STAT(mapp, dam_rereport);
3554c06356bSdh142964 		dam_release_report(mapp, addrid);
3564c06356bSdh142964 		passp->da_jitter++;
3574c06356bSdh142964 	}
3584c06356bSdh142964 	dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL);
3594c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
3604c06356bSdh142964 	DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp,
3614c06356bSdh142964 	    char *, address, int, addrid);
3624c06356bSdh142964 	return (DAM_SUCCESS);
3634c06356bSdh142964 }
3644c06356bSdh142964 
3654c06356bSdh142964 /*
3664c06356bSdh142964  * Initiate full-set report
3674c06356bSdh142964  *
3684c06356bSdh142964  * damapp:	address map
3694c06356bSdh142964  *
3704c06356bSdh142964  * Returns:	DAM_SUCCESS
3714c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
3724c06356bSdh142964  */
3734c06356bSdh142964 int
3744c06356bSdh142964 damap_addrset_begin(damap_t *damapp)
3754c06356bSdh142964 {
3764c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
3774c06356bSdh142964 	int i;
3784c06356bSdh142964 
3794c06356bSdh142964 	DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp);
3804c06356bSdh142964 
3814c06356bSdh142964 	if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
3824c06356bSdh142964 	    (mapp->dam_flags & DAM_DESTROYPEND))
3834c06356bSdh142964 		return (DAM_EINVAL);
3844c06356bSdh142964 
3854c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
3864c06356bSdh142964 	/*
3874c06356bSdh142964 	 * reset any pending reports
3884c06356bSdh142964 	 */
3894c06356bSdh142964 	if (mapp->dam_flags & DAM_SETADD) {
3904c06356bSdh142964 		/*
3914c06356bSdh142964 		 * cancel stabilization timeout
3924c06356bSdh142964 		 */
3934c06356bSdh142964 		dam_sched_tmo(mapp, 0, NULL);
3944c06356bSdh142964 		DAM_INCR_STAT(mapp, dam_rereport);
3954c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
3964c06356bSdh142964 		DAM_LOCK(mapp, ADDR_LOCK);
3974c06356bSdh142964 		for (i = 1; i < mapp->dam_high; i++) {
3984c06356bSdh142964 			if (DAM_IN_REPORT(mapp, i))
3994c06356bSdh142964 				dam_release_report(mapp, i);
4004c06356bSdh142964 		}
4014c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
4024c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
4034c06356bSdh142964 	}
4044c06356bSdh142964 	DAM_FLAG_SET(mapp, DAM_SETADD);
4054c06356bSdh142964 	bitset_zero(&mapp->dam_report_set);
4064c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
4074c06356bSdh142964 	DTRACE_PROBE(damap__addrset__begin__exit);
4084c06356bSdh142964 	return (DAM_SUCCESS);
4094c06356bSdh142964 }
4104c06356bSdh142964 
4114c06356bSdh142964 /*
4124c06356bSdh142964  * Report address to full-set report
4134c06356bSdh142964  *
4144c06356bSdh142964  * damapp:	address map handle
4154c06356bSdh142964  * address:	address in ascii string representation
4164c06356bSdh142964  * rindx:	index if address stabilizes
4174c06356bSdh142964  * nvl:		optional nvlist of configuration-private data
4184c06356bSdh142964  * addr_priv:	optional provider-private data (passed to activate/release cb)
4194c06356bSdh142964  *
4204c06356bSdh142964  * Returns:	DAM_SUCCESS
4214c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
4224c06356bSdh142964  *		DAM_MAPFULL	address map exhausted
4234c06356bSdh142964  *		DAM_FAILURE	General failure
4244c06356bSdh142964  */
4254c06356bSdh142964 int
4264c06356bSdh142964 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
4274c06356bSdh142964     nvlist_t *nvl, void *addr_priv)
4284c06356bSdh142964 {
4294c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
4304c06356bSdh142964 	id_t addrid;
4314c06356bSdh142964 	dam_da_t *passp;
4324c06356bSdh142964 
4334c06356bSdh142964 	DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp,
4344c06356bSdh142964 	    char *, address);
4354c06356bSdh142964 
4364c06356bSdh142964 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
4374c06356bSdh142964 	    (mapp->dam_flags & DAM_DESTROYPEND))
4384c06356bSdh142964 		return (DAM_EINVAL);
4394c06356bSdh142964 
4404c06356bSdh142964 	if (!(mapp->dam_flags & DAM_SETADD))
4414c06356bSdh142964 		return (DAM_FAILURE);
4424c06356bSdh142964 
4434c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
4444c06356bSdh142964 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
4454c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
4464c06356bSdh142964 		return (DAM_MAPFULL);
4474c06356bSdh142964 	}
4484c06356bSdh142964 
4494c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
4504c06356bSdh142964 	ASSERT(passp);
4514c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
4524c06356bSdh142964 		dam_release_report(mapp, addrid);
4534c06356bSdh142964 		passp->da_jitter++;
4544c06356bSdh142964 	}
4554c06356bSdh142964 	passp->da_ppriv_rpt = addr_priv;
4564c06356bSdh142964 	if (nvl)
4574c06356bSdh142964 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
4584c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
4594c06356bSdh142964 	bitset_add(&mapp->dam_report_set, addrid);
4604c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
4614c06356bSdh142964 	if (ridx)
4624c06356bSdh142964 		*ridx = (damap_id_t)addrid;
4634c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
4644c06356bSdh142964 	DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *,
4654c06356bSdh142964 	    address, int, addrid);
4664c06356bSdh142964 	return (DAM_SUCCESS);
4674c06356bSdh142964 }
4684c06356bSdh142964 
4694c06356bSdh142964 /*
4704c06356bSdh142964  * Commit full-set report for stabilization
4714c06356bSdh142964  *
4724c06356bSdh142964  * damapp:	address map handle
4734c06356bSdh142964  * flags:	(currently 0)
4744c06356bSdh142964  *
4754c06356bSdh142964  * Returns:	DAM_SUCCESS
4764c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
4774c06356bSdh142964  *		DAM_FAILURE	General failure
4784c06356bSdh142964  */
4794c06356bSdh142964 int
4804c06356bSdh142964 damap_addrset_end(damap_t *damapp, int flags)
4814c06356bSdh142964 {
4824c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
4834c06356bSdh142964 	int i;
4844c06356bSdh142964 
4854c06356bSdh142964 	DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp);
4864c06356bSdh142964 
4874c06356bSdh142964 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
4884c06356bSdh142964 	    (mapp->dam_flags & DAM_DESTROYPEND))
4894c06356bSdh142964 		return (DAM_EINVAL);
4904c06356bSdh142964 
4914c06356bSdh142964 	if (!(mapp->dam_flags & DAM_SETADD))
4924c06356bSdh142964 		return (DAM_FAILURE);
4934c06356bSdh142964 
4944c06356bSdh142964 	if (flags & DAMAP_RESET) {
4954c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
4964c06356bSdh142964 		dam_sched_tmo(mapp, 0, NULL);
4974c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
4984c06356bSdh142964 		DAM_LOCK(mapp, ADDR_LOCK);
4994c06356bSdh142964 		for (i = 1; i < mapp->dam_high; i++)
5004c06356bSdh142964 			if (DAM_IN_REPORT(mapp, i))
5014c06356bSdh142964 				dam_release_report(mapp, i);
5024c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
5034c06356bSdh142964 	} else {
5044c06356bSdh142964 		mapp->dam_last_update = gethrtime();
5054c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
5064c06356bSdh142964 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
5074c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
5084c06356bSdh142964 	}
5094c06356bSdh142964 	DTRACE_PROBE(damap__addrset__end__exit);
5104c06356bSdh142964 	return (DAM_SUCCESS);
5114c06356bSdh142964 }
5124c06356bSdh142964 
5134c06356bSdh142964 /*
5144c06356bSdh142964  * Return nvlist registered with reported address
5154c06356bSdh142964  *
5164c06356bSdh142964  * damapp:	address map handle
5174c06356bSdh142964  * aid:		address ID
5184c06356bSdh142964  *
5194c06356bSdh142964  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
5204c06356bSdh142964  *		NULL
5214c06356bSdh142964  */
5224c06356bSdh142964 nvlist_t *
5234c06356bSdh142964 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
5244c06356bSdh142964 {
5254c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5264c06356bSdh142964 	id_t aid = (id_t)addrid;
5274c06356bSdh142964 	dam_da_t *pass;
5284c06356bSdh142964 
5294c06356bSdh142964 	if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) {
5304c06356bSdh142964 		if (pass = ddi_get_soft_state(mapp->dam_da, aid))
5314c06356bSdh142964 			return (pass->da_nvl);
5324c06356bSdh142964 	}
5334c06356bSdh142964 	return (NULL);
5344c06356bSdh142964 }
5354c06356bSdh142964 
5364c06356bSdh142964 /*
5374c06356bSdh142964  * Return address string
5384c06356bSdh142964  *
5394c06356bSdh142964  * damapp:	address map handle
5404c06356bSdh142964  * aid:		address ID
5414c06356bSdh142964  *
5424c06356bSdh142964  * Returns:	char *		Address string
5434c06356bSdh142964  *		NULL
5444c06356bSdh142964  */
5454c06356bSdh142964 char *
5464c06356bSdh142964 damap_id2addr(damap_t *damapp, damap_id_t aid)
5474c06356bSdh142964 {
5484c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5494c06356bSdh142964 
5504c06356bSdh142964 	return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid));
5514c06356bSdh142964 }
5524c06356bSdh142964 
5534c06356bSdh142964 /*
5544c06356bSdh142964  * Hold address reference in map
5554c06356bSdh142964  *
5564c06356bSdh142964  * damapp:	address map handle
5574c06356bSdh142964  * aid:		address ID
5584c06356bSdh142964  *
5594c06356bSdh142964  * Returns:	DAM_SUCCESS
5604c06356bSdh142964  *		DAM_FAILURE
5614c06356bSdh142964  */
5624c06356bSdh142964 int
5634c06356bSdh142964 damap_id_hold(damap_t *damapp, damap_id_t aid)
5644c06356bSdh142964 {
5654c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5664c06356bSdh142964 	dam_da_t *passp;
5674c06356bSdh142964 
5684c06356bSdh142964 
5694c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
5704c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
5714c06356bSdh142964 	if (!passp) {
5724c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
5734c06356bSdh142964 		return (DAM_FAILURE);
5744c06356bSdh142964 	}
5754c06356bSdh142964 	passp->da_ref++;
5764c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
5774c06356bSdh142964 	return (DAM_SUCCESS);
5784c06356bSdh142964 }
5794c06356bSdh142964 
5804c06356bSdh142964 /*
5814c06356bSdh142964  * Release address reference in map
5824c06356bSdh142964  *
5834c06356bSdh142964  * damapp:	address map handle
5844c06356bSdh142964  * aid:		address ID
5854c06356bSdh142964  */
5864c06356bSdh142964 void
5874c06356bSdh142964 damap_id_rele(damap_t *damapp, damap_id_t addrid)
5884c06356bSdh142964 {
5894c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5904c06356bSdh142964 
5914c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
5924c06356bSdh142964 	dam_release(mapp, (id_t)addrid);
5934c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
5944c06356bSdh142964 }
5954c06356bSdh142964 
5964c06356bSdh142964 /*
5974c06356bSdh142964  * Return current reference count on address reference in map
5984c06356bSdh142964  *
5994c06356bSdh142964  * damapp:	address map handle
6004c06356bSdh142964  * aid:		address ID
6014c06356bSdh142964  *
6024c06356bSdh142964  * Returns:	DAM_SUCCESS
6034c06356bSdh142964  *		DAM_FAILURE
6044c06356bSdh142964  */
6054c06356bSdh142964 int
6064c06356bSdh142964 damap_id_ref(damap_t *damapp, damap_id_t aid)
6074c06356bSdh142964 {
6084c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6094c06356bSdh142964 	dam_da_t *passp;
6104c06356bSdh142964 	int ref = -1;
6114c06356bSdh142964 
6124c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
6134c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
6144c06356bSdh142964 	if (passp)
6154c06356bSdh142964 		ref = passp->da_ref;
6164c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
6174c06356bSdh142964 	return (ref);
6184c06356bSdh142964 }
6194c06356bSdh142964 
6204c06356bSdh142964 /*
6214c06356bSdh142964  * Return next address ID in list
6224c06356bSdh142964  *
6234c06356bSdh142964  * damapp:	address map handle
6244c06356bSdh142964  * damap_list:	address ID list passed to config|unconfig
6254c06356bSdh142964  *		returned by look by lookup_all
6264c06356bSdh142964  * last:	last ID returned, 0 is start of list
6274c06356bSdh142964  *
6284c06356bSdh142964  * Returns:	addrid		Next ID from the list
6294c06356bSdh142964  *		0		End of the list
6304c06356bSdh142964  */
6314c06356bSdh142964 damap_id_t
6324c06356bSdh142964 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
6334c06356bSdh142964 {
6344c06356bSdh142964 	int i, start;
6354c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6364c06356bSdh142964 	bitset_t *dam_list = (bitset_t *)damap_list;
6374c06356bSdh142964 
6384c06356bSdh142964 	if (!mapp || !dam_list)
6394c06356bSdh142964 		return ((damap_id_t)0);
6404c06356bSdh142964 
6414c06356bSdh142964 	start = (int)last + 1;
6424c06356bSdh142964 	for (i = start; i < mapp->dam_high; i++)
6434c06356bSdh142964 		if (bitset_in_set(dam_list, i))
6444c06356bSdh142964 			return ((damap_id_t)i);
6454c06356bSdh142964 	return ((damap_id_t)0);
6464c06356bSdh142964 }
6474c06356bSdh142964 
6484c06356bSdh142964 /*
6494c06356bSdh142964  * Set config private data
6504c06356bSdh142964  *
6514c06356bSdh142964  * damapp:	address map handle
6524c06356bSdh142964  * aid:		address ID
6534c06356bSdh142964  * cfg_priv:	configuration private data
6544c06356bSdh142964  *
6554c06356bSdh142964  */
6564c06356bSdh142964 void
6574c06356bSdh142964 damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv)
6584c06356bSdh142964 {
6594c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6604c06356bSdh142964 	dam_da_t *passp;
6614c06356bSdh142964 
6624c06356bSdh142964 
6634c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
6644c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
6654c06356bSdh142964 	if (!passp) {
6664c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
6674c06356bSdh142964 		return;
6684c06356bSdh142964 	}
6694c06356bSdh142964 	passp->da_cfg_priv = cfg_priv;
6704c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
6714c06356bSdh142964 }
6724c06356bSdh142964 
6734c06356bSdh142964 /*
6744c06356bSdh142964  * Get config private data
6754c06356bSdh142964  *
6764c06356bSdh142964  * damapp:	address map handle
6774c06356bSdh142964  * aid:		address ID
6784c06356bSdh142964  *
6794c06356bSdh142964  * Returns:	configuration private data
6804c06356bSdh142964  */
6814c06356bSdh142964 void *
6824c06356bSdh142964 damap_id_priv_get(damap_t *damapp, damap_id_t aid)
6834c06356bSdh142964 {
6844c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6854c06356bSdh142964 	dam_da_t *passp;
6864c06356bSdh142964 	void *rv;
6874c06356bSdh142964 
6884c06356bSdh142964 
6894c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
6904c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
6914c06356bSdh142964 	if (!passp) {
6924c06356bSdh142964 		DAM_UNLOCK(mapp, ADDR_LOCK);
6934c06356bSdh142964 		return (NULL);
6944c06356bSdh142964 	}
6954c06356bSdh142964 	rv = passp->da_cfg_priv;
6964c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
6974c06356bSdh142964 	return (rv);
6984c06356bSdh142964 }
6994c06356bSdh142964 
7004c06356bSdh142964 /*
7014c06356bSdh142964  * Lookup a single address in the active address map
7024c06356bSdh142964  *
7034c06356bSdh142964  * damapp:	address map handle
7044c06356bSdh142964  * address:	address string
7054c06356bSdh142964  *
7064c06356bSdh142964  * Returns:	ID of active/stable address
7074c06356bSdh142964  *		0	Address not in stable set
7084c06356bSdh142964  *
7094c06356bSdh142964  * Future: Allow the caller to wait for stabilize before returning not found.
7104c06356bSdh142964  */
7114c06356bSdh142964 damap_id_t
7124c06356bSdh142964 damap_lookup(damap_t *damapp, char *address)
7134c06356bSdh142964 {
7144c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7154c06356bSdh142964 	id_t addrid = 0;
7164c06356bSdh142964 	dam_da_t *passp = NULL;
7174c06356bSdh142964 
7184c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
7194c06356bSdh142964 	addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
7204c06356bSdh142964 	if (addrid) {
7214c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
7224c06356bSdh142964 		if (DAM_IS_STABLE(mapp, addrid)) {
7234c06356bSdh142964 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
7244c06356bSdh142964 			ASSERT(passp);
7254c06356bSdh142964 			if (passp) {
7264c06356bSdh142964 				passp->da_ref++;
7274c06356bSdh142964 			} else {
7284c06356bSdh142964 				addrid = 0;
7294c06356bSdh142964 			}
7304c06356bSdh142964 		} else {
7314c06356bSdh142964 			addrid = 0;
7324c06356bSdh142964 		}
7334c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
7344c06356bSdh142964 	}
7354c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
7364c06356bSdh142964 	return ((damap_id_t)addrid);
7374c06356bSdh142964 }
7384c06356bSdh142964 
7394c06356bSdh142964 
7404c06356bSdh142964 /*
7414c06356bSdh142964  * Return the list of stable addresses in the map
7424c06356bSdh142964  *
7434c06356bSdh142964  * damapp:	address map handle
7444c06356bSdh142964  * id_listp:	pointer to list of address IDs in stable map (returned)
7454c06356bSdh142964  *
7464c06356bSdh142964  * Returns:	# of entries returned in alist
7474c06356bSdh142964  */
7484c06356bSdh142964 int
7494c06356bSdh142964 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
7504c06356bSdh142964 {
7514c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7524c06356bSdh142964 	int mapsz = mapp->dam_size;
7534c06356bSdh142964 	int n_ids, i;
7544c06356bSdh142964 	bitset_t *bsp;
7554c06356bSdh142964 	dam_da_t *passp;
7564c06356bSdh142964 
7574c06356bSdh142964 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
7584c06356bSdh142964 	bitset_init(bsp);
7594c06356bSdh142964 	bitset_resize(bsp, mapsz);
7604c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
7614c06356bSdh142964 	bitset_copy(&mapp->dam_active_set, bsp);
7624c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
7634c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
7644c06356bSdh142964 	for (n_ids = 0, i = 1; i < mapsz; i++) {
7654c06356bSdh142964 		if (bitset_in_set(bsp, i)) {
7664c06356bSdh142964 			passp = ddi_get_soft_state(mapp->dam_da, i);
7674c06356bSdh142964 			ASSERT(passp);
7684c06356bSdh142964 			if (passp) {
7694c06356bSdh142964 				passp->da_ref++;
7704c06356bSdh142964 				n_ids++;
7714c06356bSdh142964 			}
7724c06356bSdh142964 		}
7734c06356bSdh142964 	}
7744c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
7754c06356bSdh142964 	if (n_ids) {
7764c06356bSdh142964 		*id_listp = (damap_id_list_t)bsp;
7774c06356bSdh142964 		return (n_ids);
7784c06356bSdh142964 	} else {
7794c06356bSdh142964 		*id_listp = (damap_id_list_t)NULL;
7804c06356bSdh142964 		bitset_fini(bsp);
7814c06356bSdh142964 		kmem_free(bsp, sizeof (*bsp));
7824c06356bSdh142964 		return (0);
7834c06356bSdh142964 	}
7844c06356bSdh142964 }
7854c06356bSdh142964 
7864c06356bSdh142964 /*
7874c06356bSdh142964  * Release the address list returned by damap_lookup_all()
7884c06356bSdh142964  *
7894c06356bSdh142964  * mapp:	address map handle
7904c06356bSdh142964  * id_list:	list of address IDs returned in damap_lookup_all()
7914c06356bSdh142964  */
7924c06356bSdh142964 void
7934c06356bSdh142964 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
7944c06356bSdh142964 {
7954c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7964c06356bSdh142964 	int i;
7974c06356bSdh142964 
7984c06356bSdh142964 	if (id_list == NULL)
7994c06356bSdh142964 		return;
8004c06356bSdh142964 
8014c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
8024c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
8034c06356bSdh142964 		if (bitset_in_set((bitset_t *)id_list, i))
8044c06356bSdh142964 			(void) dam_release(mapp, i);
8054c06356bSdh142964 	}
8064c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
8074c06356bSdh142964 	bitset_fini((bitset_t *)id_list);
8084c06356bSdh142964 	kmem_free((void *)id_list, sizeof (bitset_t));
8094c06356bSdh142964 }
8104c06356bSdh142964 
8114c06356bSdh142964 /*
8124c06356bSdh142964  * Activate a set of stabilized addresses
8134c06356bSdh142964  */
8144c06356bSdh142964 static void
8154c06356bSdh142964 dam_addrset_activate(dam_t *mapp, bitset_t *active_set)
8164c06356bSdh142964 {
8174c06356bSdh142964 	dam_da_t *passp;
8184c06356bSdh142964 	char *addrstr;
8194c06356bSdh142964 	int i;
8204c06356bSdh142964 	uint32_t n_active = 0;
8214c06356bSdh142964 
8224c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
8234c06356bSdh142964 		if (bitset_in_set(&mapp->dam_active_set, i))
8244c06356bSdh142964 			n_active++;
8254c06356bSdh142964 		if (!bitset_in_set(active_set, i))
8264c06356bSdh142964 			continue;
8274c06356bSdh142964 		n_active++;
8284c06356bSdh142964 		passp = ddi_get_soft_state(mapp->dam_da, i);
8294c06356bSdh142964 		ASSERT(passp);
8304c06356bSdh142964 		if (mapp->dam_activate_cb) {
8314c06356bSdh142964 			addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i);
8324c06356bSdh142964 			(*mapp->dam_activate_cb)(
8334c06356bSdh142964 			    mapp->dam_activate_arg, addrstr, i,
8344c06356bSdh142964 			    &passp->da_ppriv_rpt);
8354c06356bSdh142964 		}
8364c06356bSdh142964 		DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i);
8374c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
8384c06356bSdh142964 		bitset_add(&mapp->dam_active_set, i);
8394c06356bSdh142964 		/*
8404c06356bSdh142964 		 * copy the reported nvlist and provider private data
8414c06356bSdh142964 		 */
8424c06356bSdh142964 		passp->da_nvl = passp->da_nvl_rpt;
8434c06356bSdh142964 		passp->da_ppriv = passp->da_ppriv_rpt;
8444c06356bSdh142964 		passp->da_ppriv_rpt = NULL;
8454c06356bSdh142964 		passp->da_nvl_rpt = NULL;
8464c06356bSdh142964 		passp->da_last_stable = gethrtime();
8474c06356bSdh142964 		passp->da_stable_cnt++;
8484c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
8494c06356bSdh142964 		DAM_SET_STAT(mapp, dam_numstable, n_active);
8504c06356bSdh142964 	}
8514c06356bSdh142964 }
8524c06356bSdh142964 
8534c06356bSdh142964 /*
8544c06356bSdh142964  * Release a set of stabilized addresses
8554c06356bSdh142964  */
8564c06356bSdh142964 static void
8574c06356bSdh142964 dam_addrset_release(dam_t *mapp, bitset_t *release_set)
8584c06356bSdh142964 {
8594c06356bSdh142964 	int i;
8604c06356bSdh142964 
8614c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
8624c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
8634c06356bSdh142964 		if (bitset_in_set(release_set, i)) {
8644c06356bSdh142964 			DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp,
8654c06356bSdh142964 			    int, i);
8664c06356bSdh142964 			DAM_LOCK(mapp, MAP_LOCK);
8674c06356bSdh142964 			bitset_del(&mapp->dam_active_set, i);
8684c06356bSdh142964 			DAM_UNLOCK(mapp, MAP_LOCK);
8694c06356bSdh142964 			(void) dam_release(mapp, i);
8704c06356bSdh142964 		}
8714c06356bSdh142964 	}
8724c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
8734c06356bSdh142964 }
8744c06356bSdh142964 
8754c06356bSdh142964 /*
8764c06356bSdh142964  * release a previously activated address
8774c06356bSdh142964  */
8784c06356bSdh142964 static void
8794c06356bSdh142964 dam_release(dam_t *mapp, id_t addrid)
8804c06356bSdh142964 {
8814c06356bSdh142964 	dam_da_t *passp;
8824c06356bSdh142964 
8834c06356bSdh142964 	DAM_ASSERT_LOCKED(mapp, ADDR_LOCK);
8844c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
8854c06356bSdh142964 	ASSERT(passp);
8864c06356bSdh142964 
8874c06356bSdh142964 	/*
8884c06356bSdh142964 	 * invoke the deactivation callback to notify
8894c06356bSdh142964 	 * this address is no longer active
8904c06356bSdh142964 	 */
8914c06356bSdh142964 	dam_deactivate_addr(mapp, addrid);
8924c06356bSdh142964 
8934c06356bSdh142964 	/*
8944c06356bSdh142964 	 * allow pending reports for this address to stabilize
8954c06356bSdh142964 	 */
8964c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid))
8974c06356bSdh142964 		return;
8984c06356bSdh142964 
8994c06356bSdh142964 	/*
9004c06356bSdh142964 	 * defer teardown until outstanding references are released
9014c06356bSdh142964 	 */
9024c06356bSdh142964 	if (--passp->da_ref) {
9034c06356bSdh142964 		passp->da_flags |= DA_RELE;
9044c06356bSdh142964 		return;
9054c06356bSdh142964 	}
9064c06356bSdh142964 	ddi_strid_free(mapp->dam_addr_hash, addrid);
9074c06356bSdh142964 	ddi_soft_state_free(mapp->dam_da, addrid);
9084c06356bSdh142964 }
9094c06356bSdh142964 
9104c06356bSdh142964 /*
9114c06356bSdh142964  * process stabilized address reports
9124c06356bSdh142964  */
9134c06356bSdh142964 static void
9144c06356bSdh142964 dam_activate_taskq(void *arg)
9154c06356bSdh142964 {
9164c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
9174c06356bSdh142964 	bitset_t delta;
9184c06356bSdh142964 	bitset_t cfg;
9194c06356bSdh142964 	bitset_t uncfg;
9204c06356bSdh142964 	int has_cfg, has_uncfg;
9214c06356bSdh142964 
9224c06356bSdh142964 	bitset_init(&delta);
9234c06356bSdh142964 	bitset_resize(&delta, mapp->dam_size);
9244c06356bSdh142964 	bitset_init(&cfg);
9254c06356bSdh142964 	bitset_resize(&cfg, mapp->dam_size);
9264c06356bSdh142964 	bitset_init(&uncfg);
9274c06356bSdh142964 	bitset_resize(&uncfg, mapp->dam_size);
9284c06356bSdh142964 
9294c06356bSdh142964 	DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp);
9304c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
9314c06356bSdh142964 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
9324c06356bSdh142964 	    &delta)) {
9334c06356bSdh142964 		bitset_zero(&mapp->dam_stable_set);
9344c06356bSdh142964 		DAM_FLAG_CLR(mapp, DAM_SPEND);
9354c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
9364c06356bSdh142964 		bitset_fini(&uncfg);
9374c06356bSdh142964 		bitset_fini(&cfg);
9384c06356bSdh142964 		bitset_fini(&delta);
9394c06356bSdh142964 		return;
9404c06356bSdh142964 	}
9414c06356bSdh142964 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
9424c06356bSdh142964 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
9434c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
9444c06356bSdh142964 	if (has_cfg) {
9454c06356bSdh142964 		dam_addrset_activate(mapp, &cfg);
9464c06356bSdh142964 		(*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg);
9474c06356bSdh142964 	}
9484c06356bSdh142964 	if (has_uncfg) {
9494c06356bSdh142964 		(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg);
9504c06356bSdh142964 		dam_addrset_release(mapp, &uncfg);
9514c06356bSdh142964 	}
9524c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
9534c06356bSdh142964 	bitset_zero(&mapp->dam_stable_set);
9544c06356bSdh142964 	DAM_FLAG_CLR(mapp, DAM_SPEND);
9554c06356bSdh142964 	mapp->dam_last_stable = gethrtime();
9564c06356bSdh142964 	mapp->dam_stable_cnt++;
9574c06356bSdh142964 	DAM_INCR_STAT(mapp, dam_stable);
9584c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
9594c06356bSdh142964 	bitset_fini(&uncfg);
9604c06356bSdh142964 	bitset_fini(&cfg);
9614c06356bSdh142964 	bitset_fini(&delta);
9624c06356bSdh142964 	DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp);
9634c06356bSdh142964 }
9644c06356bSdh142964 
9654c06356bSdh142964 /*
9664c06356bSdh142964  * per-address stabilization timeout
9674c06356bSdh142964  */
9684c06356bSdh142964 static void
9694c06356bSdh142964 dam_addr_stable_cb(void *arg)
9704c06356bSdh142964 {
9714c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
9724c06356bSdh142964 	int i;
9734c06356bSdh142964 	dam_da_t *passp;
9744c06356bSdh142964 	int spend = 0;
9754c06356bSdh142964 	int tpend = 0;
9764c06356bSdh142964 	int64_t	next_tmov = mapp->dam_stabletmo;
9774c06356bSdh142964 	int64_t tmo_delta;
978*d3d50737SRafael Vanoni 	int64_t ts = ddi_get_lbolt64();
9794c06356bSdh142964 
9804c06356bSdh142964 	DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp);
9814c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
9824c06356bSdh142964 	if (mapp->dam_tid == 0) {
9834c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
9844c06356bSdh142964 		return;
9854c06356bSdh142964 	}
9864c06356bSdh142964 	mapp->dam_tid = 0;
9874c06356bSdh142964 	/*
9884c06356bSdh142964 	 * If still under stabilization, reschedule timeout,
9894c06356bSdh142964 	 * else dispatch the task to activate & deactivate the stable
9904c06356bSdh142964 	 * set.
9914c06356bSdh142964 	 */
9924c06356bSdh142964 	if (mapp->dam_flags & DAM_SPEND) {
9934c06356bSdh142964 		DAM_INCR_STAT(mapp, dam_stable_blocked);
9944c06356bSdh142964 		mapp->dam_stable_overrun++;
9954c06356bSdh142964 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
9964c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
9974c06356bSdh142964 		DTRACE_PROBE1(damap__addr__stable__cb__overrun,
9984c06356bSdh142964 		    dam_t *, mapp);
9994c06356bSdh142964 		return;
10004c06356bSdh142964 	}
10014c06356bSdh142964 
10024c06356bSdh142964 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
10034c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
10044c06356bSdh142964 		if (!bitset_in_set(&mapp->dam_report_set, i))
10054c06356bSdh142964 			continue;
10064c06356bSdh142964 		/*
10074c06356bSdh142964 		 * Stabilize each address
10084c06356bSdh142964 		 */
10094c06356bSdh142964 		passp = ddi_get_soft_state(mapp->dam_da, i);
10104c06356bSdh142964 		ASSERT(passp);
10114c06356bSdh142964 		if (!passp) {
10124c06356bSdh142964 			cmn_err(CE_WARN, "Clearing report no softstate %d", i);
10134c06356bSdh142964 			bitset_del(&mapp->dam_report_set, i);
10144c06356bSdh142964 			continue;
10154c06356bSdh142964 		}
10164c06356bSdh142964 
10174c06356bSdh142964 		/* report has stabilized */
10184c06356bSdh142964 		if (passp->da_deadline <= ts) {
10194c06356bSdh142964 			bitset_del(&mapp->dam_report_set, i);
10204c06356bSdh142964 			if (passp->da_flags & DA_RELE) {
10214c06356bSdh142964 				DTRACE_PROBE2(damap__addr__stable__del,
10224c06356bSdh142964 				    dam_t *, mapp, int, i);
10234c06356bSdh142964 				bitset_del(&mapp->dam_stable_set, i);
10244c06356bSdh142964 			} else {
10254c06356bSdh142964 				DTRACE_PROBE2(damap__addr__stable__add,
10264c06356bSdh142964 				    dam_t *, mapp, int, i);
10274c06356bSdh142964 				bitset_add(&mapp->dam_stable_set, i);
10284c06356bSdh142964 			}
10294c06356bSdh142964 			spend++;
10304c06356bSdh142964 			continue;
10314c06356bSdh142964 		}
10324c06356bSdh142964 
10334c06356bSdh142964 		/*
10344c06356bSdh142964 		 * not stabilized, determine next (future) map timeout
10354c06356bSdh142964 		 */
10364c06356bSdh142964 		tpend++;
10374c06356bSdh142964 		tmo_delta = passp->da_deadline - ts;
10384c06356bSdh142964 		if (tmo_delta < next_tmov)
10394c06356bSdh142964 			next_tmov = tmo_delta;
10404c06356bSdh142964 	}
10414c06356bSdh142964 
10424c06356bSdh142964 	/*
10434c06356bSdh142964 	 * schedule taskq activation of stabilized reports
10444c06356bSdh142964 	 */
10454c06356bSdh142964 	if (spend) {
10464c06356bSdh142964 		if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq,
10474c06356bSdh142964 		    mapp, DDI_NOSLEEP) == DDI_SUCCESS) {
10484c06356bSdh142964 			DAM_FLAG_SET(mapp, DAM_SPEND);
10494c06356bSdh142964 		} else
10504c06356bSdh142964 			tpend++;
10514c06356bSdh142964 	}
10524c06356bSdh142964 
10534c06356bSdh142964 	/*
10544c06356bSdh142964 	 * schedule timeout to handle future stabalization of active reports
10554c06356bSdh142964 	 */
10564c06356bSdh142964 	if (tpend)
10574c06356bSdh142964 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
10584c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
10594c06356bSdh142964 	DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp);
10604c06356bSdh142964 }
10614c06356bSdh142964 
10624c06356bSdh142964 /*
10634c06356bSdh142964  * fullset stabilization timeout
10644c06356bSdh142964  */
10654c06356bSdh142964 static void
10664c06356bSdh142964 dam_set_stable_cb(void *arg)
10674c06356bSdh142964 {
10684c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
10694c06356bSdh142964 
10704c06356bSdh142964 	DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp);
10714c06356bSdh142964 
10724c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
10734c06356bSdh142964 	if (mapp->dam_tid == 0) {
10744c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
10754c06356bSdh142964 		return;
10764c06356bSdh142964 	}
10774c06356bSdh142964 	mapp->dam_tid = 0;
10784c06356bSdh142964 
10794c06356bSdh142964 	/*
10804c06356bSdh142964 	 * If still under stabilization, reschedule timeout,
10814c06356bSdh142964 	 * else dispatch the task to activate & deactivate the stable
10824c06356bSdh142964 	 * set.
10834c06356bSdh142964 	 */
10844c06356bSdh142964 	if (mapp->dam_flags & DAM_SPEND) {
10854c06356bSdh142964 		DAM_INCR_STAT(mapp, dam_stable_blocked);
10864c06356bSdh142964 		mapp->dam_stable_overrun++;
10874c06356bSdh142964 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
10884c06356bSdh142964 		DTRACE_PROBE1(damap__set__stable__cb__overrun,
10894c06356bSdh142964 		    dam_t *, mapp);
10904c06356bSdh142964 	} else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq,
10914c06356bSdh142964 	    mapp, DDI_NOSLEEP) == DDI_FAILURE) {
10924c06356bSdh142964 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
10934c06356bSdh142964 	} else {
10944c06356bSdh142964 		bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
10954c06356bSdh142964 		bitset_zero(&mapp->dam_report_set);
10964c06356bSdh142964 		DAM_FLAG_CLR(mapp, DAM_SETADD);
10974c06356bSdh142964 		DAM_FLAG_SET(mapp, DAM_SPEND);
10984c06356bSdh142964 	}
10994c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
11004c06356bSdh142964 	DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp);
11014c06356bSdh142964 }
11024c06356bSdh142964 
11034c06356bSdh142964 /*
11044c06356bSdh142964  * reschedule map timeout 'tmo_ms' ticks
11054c06356bSdh142964  */
11064c06356bSdh142964 static void
11074c06356bSdh142964 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
11084c06356bSdh142964 {
11094c06356bSdh142964 	timeout_id_t tid;
11104c06356bSdh142964 
11114c06356bSdh142964 	if ((tid = mapp->dam_tid) != 0) {
11124c06356bSdh142964 		mapp->dam_tid = 0;
11134c06356bSdh142964 		DAM_UNLOCK(mapp, MAP_LOCK);
11144c06356bSdh142964 		(void) untimeout(tid);
11154c06356bSdh142964 		DAM_LOCK(mapp, MAP_LOCK);
11164c06356bSdh142964 	}
11174c06356bSdh142964 
11184c06356bSdh142964 	if (tmo_cb && (tmo_ms != 0))
11194c06356bSdh142964 		mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
11204c06356bSdh142964 }
11214c06356bSdh142964 
11224c06356bSdh142964 /*
11234c06356bSdh142964  * record report addition or removal of an address
11244c06356bSdh142964  */
11254c06356bSdh142964 static void
11264c06356bSdh142964 dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report)
11274c06356bSdh142964 {
11284c06356bSdh142964 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
11294c06356bSdh142964 	passp->da_last_report = gethrtime();
11304c06356bSdh142964 	mapp->dam_last_update = gethrtime();
11314c06356bSdh142964 	passp->da_report_cnt++;
1132*d3d50737SRafael Vanoni 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo;
11334c06356bSdh142964 	if (report == RPT_ADDR_DEL)
11344c06356bSdh142964 		passp->da_flags |= DA_RELE;
11354c06356bSdh142964 	else if (report == RPT_ADDR_ADD)
11364c06356bSdh142964 		passp->da_flags &= ~DA_RELE;
11374c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
11384c06356bSdh142964 	bitset_add(&mapp->dam_report_set, addrid);
11394c06356bSdh142964 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
11404c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
11414c06356bSdh142964 
11424c06356bSdh142964 }
11434c06356bSdh142964 
11444c06356bSdh142964 /*
11454c06356bSdh142964  * release an address report
11464c06356bSdh142964  */
11474c06356bSdh142964 static void
11484c06356bSdh142964 dam_release_report(dam_t *mapp, id_t addrid)
11494c06356bSdh142964 {
11504c06356bSdh142964 	dam_da_t *passp;
11514c06356bSdh142964 
11524c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
11534c06356bSdh142964 	ASSERT(passp);
11544c06356bSdh142964 	passp->da_ppriv_rpt = NULL;
11554c06356bSdh142964 	if (passp->da_nvl_rpt)
11564c06356bSdh142964 		nvlist_free(passp->da_nvl_rpt);
11574c06356bSdh142964 	passp->da_nvl_rpt = NULL;
11584c06356bSdh142964 	DAM_LOCK(mapp, MAP_LOCK);
11594c06356bSdh142964 	bitset_del(&mapp->dam_report_set, addrid);
11604c06356bSdh142964 	DAM_UNLOCK(mapp, MAP_LOCK);
11614c06356bSdh142964 }
11624c06356bSdh142964 
11634c06356bSdh142964 /*
11644c06356bSdh142964  * deactivate a previously stable address
11654c06356bSdh142964  */
11664c06356bSdh142964 static void
11674c06356bSdh142964 dam_deactivate_addr(dam_t *mapp, id_t addrid)
11684c06356bSdh142964 {
11694c06356bSdh142964 	dam_da_t *passp;
11704c06356bSdh142964 
11714c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
11724c06356bSdh142964 	ASSERT(passp);
11734c06356bSdh142964 	if (passp == NULL)
11744c06356bSdh142964 		return;
11754c06356bSdh142964 	DAM_UNLOCK(mapp, ADDR_LOCK);
11764c06356bSdh142964 	if (mapp->dam_deactivate_cb)
11774c06356bSdh142964 		(*mapp->dam_deactivate_cb)(
11784c06356bSdh142964 		    mapp->dam_activate_arg,
11794c06356bSdh142964 		    ddi_strid_id2str(mapp->dam_addr_hash,
11804c06356bSdh142964 		    addrid), addrid, passp->da_ppriv);
11814c06356bSdh142964 	DAM_LOCK(mapp, ADDR_LOCK);
11824c06356bSdh142964 	passp->da_ppriv = NULL;
11834c06356bSdh142964 	if (passp->da_nvl)
11844c06356bSdh142964 		nvlist_free(passp->da_nvl);
11854c06356bSdh142964 	passp->da_nvl = NULL;
11864c06356bSdh142964 }
11874c06356bSdh142964 
11884c06356bSdh142964 /*
11894c06356bSdh142964  * return the map ID of an address
11904c06356bSdh142964  */
11914c06356bSdh142964 static id_t
11924c06356bSdh142964 dam_get_addrid(dam_t *mapp, char *address)
11934c06356bSdh142964 {
11944c06356bSdh142964 	damap_id_t addrid;
11954c06356bSdh142964 	dam_da_t *passp;
11964c06356bSdh142964 
11974c06356bSdh142964 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
11984c06356bSdh142964 		if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash,
11994c06356bSdh142964 		    address)) == (damap_id_t)0) {
12004c06356bSdh142964 			return (0);
12014c06356bSdh142964 		}
12024c06356bSdh142964 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
12034c06356bSdh142964 		    DDI_SUCCESS) {
12044c06356bSdh142964 			ddi_strid_free(mapp->dam_addr_hash, addrid);
12054c06356bSdh142964 			return (0);
12064c06356bSdh142964 		}
12074c06356bSdh142964 		if (addrid >= mapp->dam_high)
12084c06356bSdh142964 			mapp->dam_high = addrid + 1;
12094c06356bSdh142964 	}
12104c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
12114c06356bSdh142964 	if (passp == NULL)
12124c06356bSdh142964 		return (0);
12134c06356bSdh142964 	passp->da_ref++;
12144c06356bSdh142964 	if (passp->da_addr == NULL)
12154c06356bSdh142964 		passp->da_addr = ddi_strid_id2str(
12164c06356bSdh142964 		    mapp->dam_addr_hash, addrid); /* for mdb */
12174c06356bSdh142964 	return (addrid);
12184c06356bSdh142964 }
12194c06356bSdh142964 
12204c06356bSdh142964 /*
12214c06356bSdh142964  * create and install map statistics
12224c06356bSdh142964  */
12234c06356bSdh142964 static int
12244c06356bSdh142964 dam_kstat_create(dam_t *mapp)
12254c06356bSdh142964 {
12264c06356bSdh142964 	kstat_t			*mapsp;
12274c06356bSdh142964 	struct dam_kstats	*statsp;
12284c06356bSdh142964 
12294c06356bSdh142964 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
12304c06356bSdh142964 	    KSTAT_TYPE_NAMED,
12314c06356bSdh142964 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
12324c06356bSdh142964 	if (mapsp == NULL) {
12334c06356bSdh142964 		return (DDI_FAILURE);
12344c06356bSdh142964 	}
12354c06356bSdh142964 
12364c06356bSdh142964 	statsp = (struct dam_kstats *)mapsp->ks_data;
12374c06356bSdh142964 	kstat_named_init(&statsp->dam_stable, "stable cycles",
12384c06356bSdh142964 	    KSTAT_DATA_UINT32);
12394c06356bSdh142964 	kstat_named_init(&statsp->dam_stable_blocked,
12404c06356bSdh142964 	    "stable cycle overrun", KSTAT_DATA_UINT32);
12414c06356bSdh142964 	kstat_named_init(&statsp->dam_rereport,
12424c06356bSdh142964 	    "restarted reports", KSTAT_DATA_UINT32);
12434c06356bSdh142964 	kstat_named_init(&statsp->dam_numstable,
12444c06356bSdh142964 	    "# of stable map entries", KSTAT_DATA_UINT32);
12454c06356bSdh142964 	kstat_install(mapsp);
12464c06356bSdh142964 	mapp->dam_kstatsp = mapsp;
12474c06356bSdh142964 	return (DDI_SUCCESS);
12484c06356bSdh142964 }
12494c06356bSdh142964 
12504c06356bSdh142964 /*
12514c06356bSdh142964  * destroy map stats
12524c06356bSdh142964  */
12534c06356bSdh142964 static void
12544c06356bSdh142964 dam_kstat_destroy(dam_t *mapp)
12554c06356bSdh142964 {
12564c06356bSdh142964 
12574c06356bSdh142964 	kstat_delete(mapp->dam_kstatsp);
12584c06356bSdh142964 }
1259