xref: /titanic_51/usr/src/uts/common/os/damap.c (revision 1b115575fbf0d7a1e3876e6886eaeffbeb8d2e61)
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 
52*1b115575SJohn Danielson extern taskq_t *system_taskq;
53*1b115575SJohn Danielson 
544c06356bSdh142964 static void dam_addrset_activate(dam_t *, bitset_t *);
55*1b115575SJohn Danielson static void dam_addrset_deactivate(dam_t *, bitset_t *);
56*1b115575SJohn Danielson static void dam_stabilize_map(void *);
574c06356bSdh142964 static void dam_addr_stable_cb(void *);
58*1b115575SJohn Danielson static void dam_addrset_stable_cb(void *);
594c06356bSdh142964 static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)());
60*1b115575SJohn Danielson static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
61*1b115575SJohn Danielson static void dam_addr_release(dam_t *, id_t);
62*1b115575SJohn Danielson static void dam_addr_report_release(dam_t *, id_t);
63*1b115575SJohn Danielson static void dam_addr_deactivate(dam_t *, id_t);
644c06356bSdh142964 static id_t dam_get_addrid(dam_t *, char *);
654c06356bSdh142964 static int dam_kstat_create(dam_t *);
66*1b115575SJohn Danielson static int dam_map_alloc(dam_t *);
674c06356bSdh142964 
684c06356bSdh142964 #define	DAM_INCR_STAT(mapp, stat)				\
694c06356bSdh142964 	if ((mapp)->dam_kstatsp) {				\
704c06356bSdh142964 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
714c06356bSdh142964 		stp->stat.value.ui32++;				\
724c06356bSdh142964 	}
734c06356bSdh142964 
744c06356bSdh142964 #define	DAM_SET_STAT(mapp, stat, val)				\
754c06356bSdh142964 	if ((mapp)->dam_kstatsp) {				\
764c06356bSdh142964 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
774c06356bSdh142964 		stp->stat.value.ui32 = (val);			\
784c06356bSdh142964 	}
794c06356bSdh142964 
80*1b115575SJohn Danielson 
81*1b115575SJohn Danielson /*
82*1b115575SJohn Danielson  * increase damap size by 64 entries at a time
83*1b115575SJohn Danielson  */
84*1b115575SJohn Danielson #define	DAM_SIZE_BUMP	64
85*1b115575SJohn Danielson 
86*1b115575SJohn Danielson /*
87*1b115575SJohn Danielson  * config/unconfig taskq data
88*1b115575SJohn Danielson  */
89*1b115575SJohn Danielson typedef struct {
90*1b115575SJohn Danielson 	dam_t *tqd_mapp;
91*1b115575SJohn Danielson 	id_t tqd_id;
92*1b115575SJohn Danielson } cfg_tqd_t;
93*1b115575SJohn Danielson 
94*1b115575SJohn Danielson extern pri_t maxclsyspri;
95*1b115575SJohn Danielson 
964c06356bSdh142964 /*
974c06356bSdh142964  * Create new device address map
984c06356bSdh142964  *
99*1b115575SJohn Danielson  * name:		map name (kstat unique)
1004c06356bSdh142964  * size:		max # of map entries
101*1b115575SJohn Danielson  * mode:		style of address reports: per-address or fullset
1024c06356bSdh142964  * stable_usec:		# of quiescent microseconds before report/map is stable
1034c06356bSdh142964  *
1044c06356bSdh142964  * activate_arg:	address provider activation-callout private
1054c06356bSdh142964  * activate_cb:		address provider activation callback handler
1064c06356bSdh142964  * deactivate_cb:	address provider deactivation callback handler
1074c06356bSdh142964  *
1084c06356bSdh142964  * config_arg:		configuration-callout private
1094c06356bSdh142964  * config_cb:		class configuration callout
1104c06356bSdh142964  * unconfig_cb:		class unconfiguration callout
1114c06356bSdh142964  *
1124c06356bSdh142964  * damapp:		pointer to map handle (return)
1134c06356bSdh142964  *
1144c06356bSdh142964  * Returns:	DAM_SUCCESS
1154c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
1164c06356bSdh142964  *		DAM_FAILURE	General failure
1174c06356bSdh142964  */
1184c06356bSdh142964 int
119*1b115575SJohn Danielson damap_create(char *name, damap_rptmode_t mode, int map_opts,
120*1b115575SJohn Danielson     clock_t stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
1214c06356bSdh142964     damap_deactivate_cb_t deactivate_cb,
1224c06356bSdh142964     void *config_arg, damap_configure_cb_t configure_cb,
1234c06356bSdh142964     damap_unconfig_cb_t unconfig_cb,
1244c06356bSdh142964     damap_t **damapp)
1254c06356bSdh142964 {
1264c06356bSdh142964 	dam_t *mapp;
1274c06356bSdh142964 
128*1b115575SJohn Danielson 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
1294c06356bSdh142964 		return (DAM_EINVAL);
1304c06356bSdh142964 
131*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__create, char *, name,
132*1b115575SJohn Danielson 	    damap_rptmode_t, mode, clock_t, stable_usec);
1334c06356bSdh142964 
1344c06356bSdh142964 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
135*1b115575SJohn Danielson 	mapp->dam_options = map_opts;
1364c06356bSdh142964 	mapp->dam_stabletmo = drv_usectohz(stable_usec);
137*1b115575SJohn Danielson 	mapp->dam_size = 0;
138*1b115575SJohn Danielson 	mapp->dam_rptmode = mode;
1394c06356bSdh142964 	mapp->dam_activate_arg = activate_arg;
1404c06356bSdh142964 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
1414c06356bSdh142964 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
1424c06356bSdh142964 	mapp->dam_config_arg = config_arg;
1434c06356bSdh142964 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
1444c06356bSdh142964 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
145*1b115575SJohn Danielson 	mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
1464c06356bSdh142964 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
1474c06356bSdh142964 	cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL);
148*1b115575SJohn Danielson 	bitset_init(&mapp->dam_active_set);
149*1b115575SJohn Danielson 	bitset_init(&mapp->dam_stable_set);
150*1b115575SJohn Danielson 	bitset_init(&mapp->dam_report_set);
1514c06356bSdh142964 	*damapp = (damap_t *)mapp;
1524c06356bSdh142964 	return (DAM_SUCCESS);
1534c06356bSdh142964 }
1544c06356bSdh142964 
1554c06356bSdh142964 /*
156*1b115575SJohn Danielson  * Allocate backing resources
157*1b115575SJohn Danielson  *
158*1b115575SJohn Danielson  * DAMs are lightly backed on create - major allocations occur
159*1b115575SJohn Danielson  * at the time a report is made to the map, and are extended on
160*1b115575SJohn Danielson  * a demand basis.
161*1b115575SJohn Danielson  */
162*1b115575SJohn Danielson static int
163*1b115575SJohn Danielson dam_map_alloc(dam_t *mapp)
164*1b115575SJohn Danielson {
165*1b115575SJohn Danielson 	void *softstate_p;
166*1b115575SJohn Danielson 
167*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
168*1b115575SJohn Danielson 	if (mapp->dam_flags & DAM_DESTROYPEND)
169*1b115575SJohn Danielson 		return (DAM_FAILURE);
170*1b115575SJohn Danielson 
171*1b115575SJohn Danielson 	/*
172*1b115575SJohn Danielson 	 * dam_high > 0 signals map allocation complete
173*1b115575SJohn Danielson 	 */
174*1b115575SJohn Danielson 	if (mapp->dam_high)
175*1b115575SJohn Danielson 		return (DAM_SUCCESS);
176*1b115575SJohn Danielson 
177*1b115575SJohn Danielson 	mapp->dam_size = DAM_SIZE_BUMP;
178*1b115575SJohn Danielson 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
179*1b115575SJohn Danielson 	    mapp->dam_size) != DDI_SUCCESS)
180*1b115575SJohn Danielson 		return (DAM_FAILURE);
181*1b115575SJohn Danielson 
182*1b115575SJohn Danielson 	if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
183*1b115575SJohn Danielson 	    DDI_SUCCESS) {
184*1b115575SJohn Danielson 		ddi_soft_state_fini(softstate_p);
185*1b115575SJohn Danielson 		return (DAM_FAILURE);
186*1b115575SJohn Danielson 	}
187*1b115575SJohn Danielson 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
188*1b115575SJohn Danielson 		ddi_soft_state_fini(softstate_p);
189*1b115575SJohn Danielson 		ddi_strid_fini(&mapp->dam_addr_hash);
190*1b115575SJohn Danielson 		return (DAM_FAILURE);
191*1b115575SJohn Danielson 	}
192*1b115575SJohn Danielson 	mapp->dam_da = softstate_p;
193*1b115575SJohn Danielson 	mapp->dam_high = 1;
194*1b115575SJohn Danielson 	bitset_resize(&mapp->dam_active_set, mapp->dam_size);
195*1b115575SJohn Danielson 	bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
196*1b115575SJohn Danielson 	bitset_resize(&mapp->dam_report_set, mapp->dam_size);
197*1b115575SJohn Danielson 	return (DAM_SUCCESS);
198*1b115575SJohn Danielson }
199*1b115575SJohn Danielson 
200*1b115575SJohn Danielson /*
201*1b115575SJohn Danielson  * Destroy address map
2024c06356bSdh142964  *
2034c06356bSdh142964  * damapp:	address map
2044c06356bSdh142964  *
2054c06356bSdh142964  * Returns:	DAM_SUCCESS
2064c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
2074c06356bSdh142964  *		DAM_FAILURE	General failure
2084c06356bSdh142964  */
2094c06356bSdh142964 void
2104c06356bSdh142964 damap_destroy(damap_t *damapp)
2114c06356bSdh142964 {
2124c06356bSdh142964 	int i;
2134c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
2144c06356bSdh142964 
2154c06356bSdh142964 	ASSERT(mapp);
2164c06356bSdh142964 
217*1b115575SJohn Danielson 	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
2184c06356bSdh142964 
219*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
2204c06356bSdh142964 
2214c06356bSdh142964 	/*
222*1b115575SJohn Danielson 	 * prevent new reports from being added to the map
2234c06356bSdh142964 	 */
224*1b115575SJohn Danielson 	mapp->dam_flags |= DAM_DESTROYPEND;
2254c06356bSdh142964 
226*1b115575SJohn Danielson 	if (mapp->dam_high) {
227*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
228*1b115575SJohn Danielson 		/*
229*1b115575SJohn Danielson 		 * wait for outstanding reports to stabilize and cancel
230*1b115575SJohn Danielson 		 * the timer for this map
231*1b115575SJohn Danielson 		 */
232*1b115575SJohn Danielson 		(void) damap_sync(damapp);
233*1b115575SJohn Danielson 		mutex_enter(&mapp->dam_lock);
234*1b115575SJohn Danielson 		dam_sched_tmo(mapp, 0, NULL);
235*1b115575SJohn Danielson 
236*1b115575SJohn Danielson 		/*
237*1b115575SJohn Danielson 		 * map is at full stop
238*1b115575SJohn Danielson 		 * release the contents of the map, invoking the
239*1b115575SJohn Danielson 		 * detactivation protocol as addresses are released
240*1b115575SJohn Danielson 		 */
241*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
2424c06356bSdh142964 		for (i = 1; i < mapp->dam_high; i++) {
2434c06356bSdh142964 			if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
2444c06356bSdh142964 				continue;
245*1b115575SJohn Danielson 
246*1b115575SJohn Danielson 			ASSERT(DAM_IN_REPORT(mapp, i) == 0);
247*1b115575SJohn Danielson 
248*1b115575SJohn Danielson 			if (DAM_IS_STABLE(mapp, i)) {
249*1b115575SJohn Danielson 				dam_addr_deactivate(mapp, i);
250*1b115575SJohn Danielson 			} else {
2514c06356bSdh142964 				ddi_strid_free(mapp->dam_addr_hash, i);
2524c06356bSdh142964 				ddi_soft_state_free(mapp->dam_da, i);
2534c06356bSdh142964 			}
254*1b115575SJohn Danielson 		}
2554c06356bSdh142964 		ddi_strid_fini(&mapp->dam_addr_hash);
2564c06356bSdh142964 		ddi_soft_state_fini(&mapp->dam_da);
257*1b115575SJohn Danielson 		kstat_delete(mapp->dam_kstatsp);
258*1b115575SJohn Danielson 	}
2594c06356bSdh142964 	bitset_fini(&mapp->dam_active_set);
2604c06356bSdh142964 	bitset_fini(&mapp->dam_stable_set);
2614c06356bSdh142964 	bitset_fini(&mapp->dam_report_set);
2624c06356bSdh142964 	mutex_destroy(&mapp->dam_lock);
2634c06356bSdh142964 	cv_destroy(&mapp->dam_cv);
2644c06356bSdh142964 	if (mapp->dam_name)
2654c06356bSdh142964 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
2664c06356bSdh142964 	kmem_free(mapp, sizeof (*mapp));
2674c06356bSdh142964 }
2684c06356bSdh142964 
2694c06356bSdh142964 /*
2704c06356bSdh142964  * Wait for map stability.
2714c06356bSdh142964  *
2724c06356bSdh142964  * damapp:	address map
2734c06356bSdh142964  */
2744c06356bSdh142964 int
2754c06356bSdh142964 damap_sync(damap_t *damapp)
2764c06356bSdh142964 {
277*1b115575SJohn Danielson #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
2784c06356bSdh142964 
2794c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
2804c06356bSdh142964 	int   none_active;
2814c06356bSdh142964 
2824c06356bSdh142964 	ASSERT(mapp);
2834c06356bSdh142964 
284*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
285*1b115575SJohn Danielson 	    dam_t *, mapp);
2864c06356bSdh142964 
287*1b115575SJohn Danielson 	/*
288*1b115575SJohn Danielson 	 * block where waiting for
289*1b115575SJohn Danielson 	 * a) stabilization pending or a fullset update pending
290*1b115575SJohn Danielson 	 * b) any scheduled timeouts to fire
291*1b115575SJohn Danielson 	 * c) the report set to finalize (bitset is null)
292*1b115575SJohn Danielson 	 */
2934c06356bSdh142964 	mutex_enter(&mapp->dam_lock);
2944c06356bSdh142964 	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
2954c06356bSdh142964 	    (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) {
296*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
297*1b115575SJohn Danielson 		    dam_t *, mapp);
2984c06356bSdh142964 		cv_wait(&mapp->dam_cv, &mapp->dam_lock);
2994c06356bSdh142964 	}
3004c06356bSdh142964 
3014c06356bSdh142964 	none_active = bitset_is_null(&mapp->dam_active_set);
3024c06356bSdh142964 
3034c06356bSdh142964 	mutex_exit(&mapp->dam_lock);
304*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, int,
305*1b115575SJohn Danielson 	    none_active, dam_t *, mapp);
3064c06356bSdh142964 
3074c06356bSdh142964 	return (none_active);
3084c06356bSdh142964 }
3094c06356bSdh142964 
3104c06356bSdh142964 /*
3114c06356bSdh142964  * Get the name of a device address map
3124c06356bSdh142964  *
3134c06356bSdh142964  * damapp:	address map
3144c06356bSdh142964  *
3154c06356bSdh142964  * Returns:	name
3164c06356bSdh142964  */
3174c06356bSdh142964 char *
3184c06356bSdh142964 damap_name(damap_t *damapp)
3194c06356bSdh142964 {
3204c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
3214c06356bSdh142964 
3224c06356bSdh142964 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
3234c06356bSdh142964 }
3244c06356bSdh142964 
3254c06356bSdh142964 /*
3264c06356bSdh142964  * Report an address to per-address report
3274c06356bSdh142964  *
3284c06356bSdh142964  * damapp:	address map handle
3294c06356bSdh142964  * address:	address in ascii string representation
330*1b115575SJohn Danielson  * addridp:	address ID
3314c06356bSdh142964  * nvl:		optional nvlist of configuration-private data
3324c06356bSdh142964  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
3334c06356bSdh142964  *
3344c06356bSdh142964  * Returns:	DAM_SUCCESS
3354c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
3364c06356bSdh142964  *		DAM_MAPFULL	address map exhausted
3374c06356bSdh142964  */
3384c06356bSdh142964 int
339*1b115575SJohn Danielson damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
340*1b115575SJohn Danielson     nvlist_t *nvl, void *addr_priv)
3414c06356bSdh142964 {
3424c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
3434c06356bSdh142964 	id_t addrid;
3444c06356bSdh142964 	dam_da_t *passp;
3454c06356bSdh142964 
346*1b115575SJohn Danielson 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
3474c06356bSdh142964 		return (DAM_EINVAL);
3484c06356bSdh142964 
349*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name,
350*1b115575SJohn Danielson 	    char *, address, dam_t *, mapp);
351*1b115575SJohn Danielson 
352*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
353*1b115575SJohn Danielson 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
354*1b115575SJohn Danielson 	    ((addrid = dam_get_addrid(mapp, address)) == 0)) {
355*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
3564c06356bSdh142964 		return (DAM_MAPFULL);
3574c06356bSdh142964 	}
3584c06356bSdh142964 
3594c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
3604c06356bSdh142964 	ASSERT(passp != NULL);
3614c06356bSdh142964 
3624c06356bSdh142964 	/*
3634c06356bSdh142964 	 * If re-reporting the same address (add or remove) clear
3644c06356bSdh142964 	 * the existing report
3654c06356bSdh142964 	 */
3664c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
367*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
368*1b115575SJohn Danielson 		    char *, address, dam_t *, mapp);
369*1b115575SJohn Danielson 		DAM_INCR_STAT(mapp, dam_jitter);
370*1b115575SJohn Danielson 		dam_addr_report_release(mapp, addrid);
3714c06356bSdh142964 		passp->da_jitter++;
3724c06356bSdh142964 	}
3734c06356bSdh142964 	passp->da_ppriv_rpt = addr_priv;
3744c06356bSdh142964 	if (nvl)
3754c06356bSdh142964 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
3764c06356bSdh142964 
377*1b115575SJohn Danielson 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
378*1b115575SJohn Danielson 	if (addridp != NULL)
379*1b115575SJohn Danielson 		*addridp = (damap_id_t)addrid;
380*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
3814c06356bSdh142964 	return (DAM_SUCCESS);
3824c06356bSdh142964 }
3834c06356bSdh142964 
3844c06356bSdh142964 /*
3854c06356bSdh142964  * Report removal of address from per-address report
3864c06356bSdh142964  *
3874c06356bSdh142964  * damapp:	address map
3884c06356bSdh142964  * address:	address in ascii string representation
3894c06356bSdh142964  *
3904c06356bSdh142964  * Returns:	DAM_SUCCESS
3914c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
3924c06356bSdh142964  *		DAM_FAILURE	General failure
3934c06356bSdh142964  */
3944c06356bSdh142964 int
3954c06356bSdh142964 damap_addr_del(damap_t *damapp, char *address)
3964c06356bSdh142964 {
3974c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
3984c06356bSdh142964 	id_t addrid;
3994c06356bSdh142964 	dam_da_t *passp;
4004c06356bSdh142964 
401*1b115575SJohn Danielson 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
4024c06356bSdh142964 		return (DAM_EINVAL);
4034c06356bSdh142964 
404*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
405*1b115575SJohn Danielson 	    char *, address, dam_t *, mapp);
406*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
407*1b115575SJohn Danielson 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
408*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
409*1b115575SJohn Danielson 		return (DAM_MAPFULL);
410*1b115575SJohn Danielson 	}
411*1b115575SJohn Danielson 
412*1b115575SJohn Danielson 	/*
413*1b115575SJohn Danielson 	 * if reporting the removal of an address which is not in the map
414*1b115575SJohn Danielson 	 * return success
415*1b115575SJohn Danielson 	 */
4164c06356bSdh142964 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
417*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
4184c06356bSdh142964 		return (DAM_SUCCESS);
4194c06356bSdh142964 	}
4204c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
4214c06356bSdh142964 	ASSERT(passp);
4224c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
423*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
424*1b115575SJohn Danielson 		    char *, address, dam_t *, mapp);
425*1b115575SJohn Danielson 		DAM_INCR_STAT(mapp, dam_jitter);
426*1b115575SJohn Danielson 		dam_addr_report_release(mapp, addrid);
4274c06356bSdh142964 		passp->da_jitter++;
4284c06356bSdh142964 	}
429*1b115575SJohn Danielson 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
430*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
4314c06356bSdh142964 	return (DAM_SUCCESS);
4324c06356bSdh142964 }
4334c06356bSdh142964 
4344c06356bSdh142964 /*
4354c06356bSdh142964  * Initiate full-set report
4364c06356bSdh142964  *
4374c06356bSdh142964  * damapp:	address map
4384c06356bSdh142964  *
4394c06356bSdh142964  * Returns:	DAM_SUCCESS
4404c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
4414c06356bSdh142964  */
4424c06356bSdh142964 int
4434c06356bSdh142964 damap_addrset_begin(damap_t *damapp)
4444c06356bSdh142964 {
4454c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
4464c06356bSdh142964 	int i;
4474c06356bSdh142964 
448*1b115575SJohn Danielson 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
4494c06356bSdh142964 		return (DAM_EINVAL);
4504c06356bSdh142964 
451*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
452*1b115575SJohn Danielson 	    mapp);
453*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
454*1b115575SJohn Danielson 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
455*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
456*1b115575SJohn Danielson 		return (DAM_MAPFULL);
457*1b115575SJohn Danielson 	}
4584c06356bSdh142964 	if (mapp->dam_flags & DAM_SETADD) {
459*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__addrset__begin__reset, char *,
460*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
4614c06356bSdh142964 		/*
4624c06356bSdh142964 		 * cancel stabilization timeout
4634c06356bSdh142964 		 */
4644c06356bSdh142964 		dam_sched_tmo(mapp, 0, NULL);
465*1b115575SJohn Danielson 		DAM_INCR_STAT(mapp, dam_jitter);
466*1b115575SJohn Danielson 
467*1b115575SJohn Danielson 		/*
468*1b115575SJohn Danielson 		 * clear pending reports
469*1b115575SJohn Danielson 		 */
4704c06356bSdh142964 		for (i = 1; i < mapp->dam_high; i++) {
4714c06356bSdh142964 			if (DAM_IN_REPORT(mapp, i))
472*1b115575SJohn Danielson 				dam_addr_report_release(mapp, i);
4734c06356bSdh142964 		}
4744c06356bSdh142964 	}
4754c06356bSdh142964 	bitset_zero(&mapp->dam_report_set);
476*1b115575SJohn Danielson 	mapp->dam_flags |= DAM_SETADD;
477*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
4784c06356bSdh142964 	return (DAM_SUCCESS);
4794c06356bSdh142964 }
4804c06356bSdh142964 
4814c06356bSdh142964 /*
4824c06356bSdh142964  * Report address to full-set report
4834c06356bSdh142964  *
4844c06356bSdh142964  * damapp:	address map handle
4854c06356bSdh142964  * address:	address in ascii string representation
4864c06356bSdh142964  * rindx:	index if address stabilizes
4874c06356bSdh142964  * nvl:		optional nvlist of configuration-private data
4884c06356bSdh142964  * addr_priv:	optional provider-private data (passed to activate/release cb)
4894c06356bSdh142964  *
4904c06356bSdh142964  * Returns:	DAM_SUCCESS
4914c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
4924c06356bSdh142964  *		DAM_MAPFULL	address map exhausted
4934c06356bSdh142964  *		DAM_FAILURE	General failure
4944c06356bSdh142964  */
4954c06356bSdh142964 int
4964c06356bSdh142964 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
4974c06356bSdh142964     nvlist_t *nvl, void *addr_priv)
4984c06356bSdh142964 {
4994c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5004c06356bSdh142964 	id_t addrid;
5014c06356bSdh142964 	dam_da_t *passp;
5024c06356bSdh142964 
503*1b115575SJohn Danielson 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
5044c06356bSdh142964 		return (DAM_EINVAL);
5054c06356bSdh142964 
506*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
507*1b115575SJohn Danielson 	    char *, address, dam_t *, mapp);
5084c06356bSdh142964 
509*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
510*1b115575SJohn Danielson 	if (!(mapp->dam_flags & DAM_SETADD)) {
511*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
512*1b115575SJohn Danielson 		return (DAM_FAILURE);
513*1b115575SJohn Danielson 	}
514*1b115575SJohn Danielson 
5154c06356bSdh142964 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
516*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
5174c06356bSdh142964 		return (DAM_MAPFULL);
5184c06356bSdh142964 	}
5194c06356bSdh142964 
5204c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
5214c06356bSdh142964 	ASSERT(passp);
5224c06356bSdh142964 	if (DAM_IN_REPORT(mapp, addrid)) {
523*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
524*1b115575SJohn Danielson 		    mapp->dam_name, char *, address, dam_t *, mapp);
525*1b115575SJohn Danielson 		dam_addr_report_release(mapp, addrid);
5264c06356bSdh142964 		passp->da_jitter++;
5274c06356bSdh142964 	}
5284c06356bSdh142964 	passp->da_ppriv_rpt = addr_priv;
5294c06356bSdh142964 	if (nvl)
5304c06356bSdh142964 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
5314c06356bSdh142964 	bitset_add(&mapp->dam_report_set, addrid);
5324c06356bSdh142964 	if (ridx)
5334c06356bSdh142964 		*ridx = (damap_id_t)addrid;
534*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
5354c06356bSdh142964 	return (DAM_SUCCESS);
5364c06356bSdh142964 }
5374c06356bSdh142964 
5384c06356bSdh142964 /*
5394c06356bSdh142964  * Commit full-set report for stabilization
5404c06356bSdh142964  *
5414c06356bSdh142964  * damapp:	address map handle
5424c06356bSdh142964  * flags:	(currently 0)
5434c06356bSdh142964  *
5444c06356bSdh142964  * Returns:	DAM_SUCCESS
5454c06356bSdh142964  *		DAM_EINVAL	Invalid argument(s)
5464c06356bSdh142964  *		DAM_FAILURE	General failure
5474c06356bSdh142964  */
5484c06356bSdh142964 int
5494c06356bSdh142964 damap_addrset_end(damap_t *damapp, int flags)
5504c06356bSdh142964 {
5514c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5524c06356bSdh142964 	int i;
5534c06356bSdh142964 
554*1b115575SJohn Danielson 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
5554c06356bSdh142964 		return (DAM_EINVAL);
5564c06356bSdh142964 
557*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
558*1b115575SJohn Danielson 	    dam_t *, mapp);
5594c06356bSdh142964 
560*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
561*1b115575SJohn Danielson 	if (!(mapp->dam_flags & DAM_SETADD)) {
562*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
563*1b115575SJohn Danielson 		return (DAM_FAILURE);
564*1b115575SJohn Danielson 	}
565*1b115575SJohn Danielson 
566*1b115575SJohn Danielson 	if (flags & DAMAP_END_RESET) {
567*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
568*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
5694c06356bSdh142964 		dam_sched_tmo(mapp, 0, NULL);
5704c06356bSdh142964 		for (i = 1; i < mapp->dam_high; i++)
5714c06356bSdh142964 			if (DAM_IN_REPORT(mapp, i))
572*1b115575SJohn Danielson 				dam_addr_report_release(mapp, i);
5734c06356bSdh142964 	} else {
5744c06356bSdh142964 		mapp->dam_last_update = gethrtime();
575*1b115575SJohn Danielson 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
5764c06356bSdh142964 	}
577*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
5784c06356bSdh142964 	return (DAM_SUCCESS);
5794c06356bSdh142964 }
5804c06356bSdh142964 
5814c06356bSdh142964 /*
5824c06356bSdh142964  * Return nvlist registered with reported address
5834c06356bSdh142964  *
5844c06356bSdh142964  * damapp:	address map handle
585*1b115575SJohn Danielson  * addrid:	address ID
5864c06356bSdh142964  *
5874c06356bSdh142964  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
5884c06356bSdh142964  *		NULL
5894c06356bSdh142964  */
5904c06356bSdh142964 nvlist_t *
5914c06356bSdh142964 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
5924c06356bSdh142964 {
5934c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
5944c06356bSdh142964 	dam_da_t *pass;
5954c06356bSdh142964 
596*1b115575SJohn Danielson 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
597*1b115575SJohn Danielson 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
5984c06356bSdh142964 			return (pass->da_nvl);
5994c06356bSdh142964 	}
6004c06356bSdh142964 	return (NULL);
6014c06356bSdh142964 }
6024c06356bSdh142964 
6034c06356bSdh142964 /*
6044c06356bSdh142964  * Return address string
6054c06356bSdh142964  *
6064c06356bSdh142964  * damapp:	address map handle
607*1b115575SJohn Danielson  * addrid:	address ID
6084c06356bSdh142964  *
6094c06356bSdh142964  * Returns:	char *		Address string
6104c06356bSdh142964  *		NULL
6114c06356bSdh142964  */
6124c06356bSdh142964 char *
613*1b115575SJohn Danielson damap_id2addr(damap_t *damapp, damap_id_t addrid)
6144c06356bSdh142964 {
6154c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6164c06356bSdh142964 
617*1b115575SJohn Danielson 	if (mapp->dam_high)
618*1b115575SJohn Danielson 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
619*1b115575SJohn Danielson 	else
620*1b115575SJohn Danielson 		return (NULL);
6214c06356bSdh142964 }
6224c06356bSdh142964 
6234c06356bSdh142964 /*
6244c06356bSdh142964  * Release address reference in map
6254c06356bSdh142964  *
6264c06356bSdh142964  * damapp:	address map handle
627*1b115575SJohn Danielson  * addrid:	address ID
6284c06356bSdh142964  */
6294c06356bSdh142964 void
6304c06356bSdh142964 damap_id_rele(damap_t *damapp, damap_id_t addrid)
6314c06356bSdh142964 {
6324c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
633*1b115575SJohn Danielson 	dam_da_t *passp;
634*1b115575SJohn Danielson 	char *addr;
6354c06356bSdh142964 
636*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
637*1b115575SJohn Danielson 	ASSERT(passp);
638*1b115575SJohn Danielson 
639*1b115575SJohn Danielson 	addr = damap_id2addr(damapp, addrid);
640*1b115575SJohn Danielson 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
641*1b115575SJohn Danielson 	    dam_t *, mapp, int, passp->da_ref);
642*1b115575SJohn Danielson 
643*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
644*1b115575SJohn Danielson 
645*1b115575SJohn Danielson 	/*
646*1b115575SJohn Danielson 	 * teardown address if last outstanding reference
647*1b115575SJohn Danielson 	 */
648*1b115575SJohn Danielson 	if (--passp->da_ref == 0)
649*1b115575SJohn Danielson 		dam_addr_release(mapp, (id_t)addrid);
650*1b115575SJohn Danielson 
651*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
6524c06356bSdh142964 }
6534c06356bSdh142964 
6544c06356bSdh142964 /*
6554c06356bSdh142964  * Return current reference count on address reference in map
6564c06356bSdh142964  *
6574c06356bSdh142964  * damapp:	address map handle
658*1b115575SJohn Danielson  * addrid:	address ID
6594c06356bSdh142964  *
6604c06356bSdh142964  * Returns:	DAM_SUCCESS
6614c06356bSdh142964  *		DAM_FAILURE
6624c06356bSdh142964  */
6634c06356bSdh142964 int
664*1b115575SJohn Danielson damap_id_ref(damap_t *damapp, damap_id_t addrid)
6654c06356bSdh142964 {
6664c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6674c06356bSdh142964 	dam_da_t *passp;
6684c06356bSdh142964 	int ref = -1;
6694c06356bSdh142964 
670*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
6714c06356bSdh142964 	if (passp)
6724c06356bSdh142964 		ref = passp->da_ref;
673*1b115575SJohn Danielson 
6744c06356bSdh142964 	return (ref);
6754c06356bSdh142964 }
6764c06356bSdh142964 
6774c06356bSdh142964 /*
6784c06356bSdh142964  * Return next address ID in list
6794c06356bSdh142964  *
6804c06356bSdh142964  * damapp:	address map handle
6814c06356bSdh142964  * damap_list:	address ID list passed to config|unconfig
6824c06356bSdh142964  *		returned by look by lookup_all
6834c06356bSdh142964  * last:	last ID returned, 0 is start of list
6844c06356bSdh142964  *
6854c06356bSdh142964  * Returns:	addrid		Next ID from the list
6864c06356bSdh142964  *		0		End of the list
6874c06356bSdh142964  */
6884c06356bSdh142964 damap_id_t
6894c06356bSdh142964 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
6904c06356bSdh142964 {
6914c06356bSdh142964 	int i, start;
6924c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
6934c06356bSdh142964 	bitset_t *dam_list = (bitset_t *)damap_list;
6944c06356bSdh142964 
6954c06356bSdh142964 	if (!mapp || !dam_list)
6964c06356bSdh142964 		return ((damap_id_t)0);
6974c06356bSdh142964 
6984c06356bSdh142964 	start = (int)last + 1;
699*1b115575SJohn Danielson 	for (i = start; i < mapp->dam_high; i++) {
700*1b115575SJohn Danielson 		if (bitset_in_set(dam_list, i)) {
7014c06356bSdh142964 			return ((damap_id_t)i);
702*1b115575SJohn Danielson 		}
703*1b115575SJohn Danielson 	}
7044c06356bSdh142964 	return ((damap_id_t)0);
7054c06356bSdh142964 }
7064c06356bSdh142964 
7074c06356bSdh142964 /*
7084c06356bSdh142964  * Set config private data
7094c06356bSdh142964  *
7104c06356bSdh142964  * damapp:	address map handle
711*1b115575SJohn Danielson  * addrid:	address ID
7124c06356bSdh142964  * cfg_priv:	configuration private data
7134c06356bSdh142964  *
7144c06356bSdh142964  */
7154c06356bSdh142964 void
716*1b115575SJohn Danielson damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
7174c06356bSdh142964 {
7184c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7194c06356bSdh142964 	dam_da_t *passp;
7204c06356bSdh142964 
721*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
722*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
7234c06356bSdh142964 	if (!passp) {
724*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
7254c06356bSdh142964 		return;
7264c06356bSdh142964 	}
7274c06356bSdh142964 	passp->da_cfg_priv = cfg_priv;
728*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
7294c06356bSdh142964 }
7304c06356bSdh142964 
7314c06356bSdh142964 /*
7324c06356bSdh142964  * Get config private data
7334c06356bSdh142964  *
7344c06356bSdh142964  * damapp:	address map handle
735*1b115575SJohn Danielson  * addrid:	address ID
7364c06356bSdh142964  *
7374c06356bSdh142964  * Returns:	configuration private data
7384c06356bSdh142964  */
7394c06356bSdh142964 void *
740*1b115575SJohn Danielson damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
7414c06356bSdh142964 {
7424c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7434c06356bSdh142964 	dam_da_t *passp;
7444c06356bSdh142964 	void *rv;
7454c06356bSdh142964 
746*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
747*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
7484c06356bSdh142964 	if (!passp) {
749*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
7504c06356bSdh142964 		return (NULL);
7514c06356bSdh142964 	}
7524c06356bSdh142964 	rv = passp->da_cfg_priv;
753*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
7544c06356bSdh142964 	return (rv);
7554c06356bSdh142964 }
7564c06356bSdh142964 
7574c06356bSdh142964 /*
7584c06356bSdh142964  * Lookup a single address in the active address map
7594c06356bSdh142964  *
7604c06356bSdh142964  * damapp:	address map handle
7614c06356bSdh142964  * address:	address string
7624c06356bSdh142964  *
7634c06356bSdh142964  * Returns:	ID of active/stable address
7644c06356bSdh142964  *		0	Address not in stable set
7654c06356bSdh142964  *
7664c06356bSdh142964  * Future: Allow the caller to wait for stabilize before returning not found.
7674c06356bSdh142964  */
7684c06356bSdh142964 damap_id_t
7694c06356bSdh142964 damap_lookup(damap_t *damapp, char *address)
7704c06356bSdh142964 {
7714c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
7724c06356bSdh142964 	id_t addrid = 0;
7734c06356bSdh142964 	dam_da_t *passp = NULL;
7744c06356bSdh142964 
775*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
776*1b115575SJohn Danielson 	    char *, address, dam_t *, mapp);
777*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
778*1b115575SJohn Danielson 	if (!mapp->dam_high)
779*1b115575SJohn Danielson 		addrid = 0;
780*1b115575SJohn Danielson 	else
7814c06356bSdh142964 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
7824c06356bSdh142964 	if (addrid) {
7834c06356bSdh142964 		if (DAM_IS_STABLE(mapp, addrid)) {
7844c06356bSdh142964 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
7854c06356bSdh142964 			ASSERT(passp);
7864c06356bSdh142964 			if (passp) {
7874c06356bSdh142964 				passp->da_ref++;
7884c06356bSdh142964 			} else {
7894c06356bSdh142964 				addrid = 0;
7904c06356bSdh142964 			}
7914c06356bSdh142964 		} else {
7924c06356bSdh142964 			addrid = 0;
7934c06356bSdh142964 		}
7944c06356bSdh142964 	}
795*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
796*1b115575SJohn Danielson 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
797*1b115575SJohn Danielson 	    char *, address, dam_t *, mapp, int, addrid);
7984c06356bSdh142964 	return ((damap_id_t)addrid);
7994c06356bSdh142964 }
8004c06356bSdh142964 
8014c06356bSdh142964 
8024c06356bSdh142964 /*
8034c06356bSdh142964  * Return the list of stable addresses in the map
8044c06356bSdh142964  *
8054c06356bSdh142964  * damapp:	address map handle
8064c06356bSdh142964  * id_listp:	pointer to list of address IDs in stable map (returned)
8074c06356bSdh142964  *
8084c06356bSdh142964  * Returns:	# of entries returned in alist
8094c06356bSdh142964  */
8104c06356bSdh142964 int
8114c06356bSdh142964 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
8124c06356bSdh142964 {
8134c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
8144c06356bSdh142964 	int mapsz = mapp->dam_size;
8154c06356bSdh142964 	int n_ids, i;
8164c06356bSdh142964 	bitset_t *bsp;
817*1b115575SJohn Danielson 	char	 *addrp;
8184c06356bSdh142964 	dam_da_t *passp;
8194c06356bSdh142964 
820*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
821*1b115575SJohn Danielson 	    dam_t *, mapp);
822*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
823*1b115575SJohn Danielson 	if (!mapp->dam_high) {
824*1b115575SJohn Danielson 		*id_listp = (damap_id_list_t)NULL;
825*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
826*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
827*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp, int, 0);
828*1b115575SJohn Danielson 		return (0);
829*1b115575SJohn Danielson 	}
8304c06356bSdh142964 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
8314c06356bSdh142964 	bitset_init(bsp);
8324c06356bSdh142964 	bitset_resize(bsp, mapsz);
8334c06356bSdh142964 	bitset_copy(&mapp->dam_active_set, bsp);
8344c06356bSdh142964 	for (n_ids = 0, i = 1; i < mapsz; i++) {
8354c06356bSdh142964 		if (bitset_in_set(bsp, i)) {
8364c06356bSdh142964 			passp = ddi_get_soft_state(mapp->dam_da, i);
8374c06356bSdh142964 			ASSERT(passp);
8384c06356bSdh142964 			if (passp) {
839*1b115575SJohn Danielson 				addrp = damap_id2addr(damapp, i);
840*1b115575SJohn Danielson 				DTRACE_PROBE3(damap__lookup__all__item, char *,
841*1b115575SJohn Danielson 				    mapp->dam_name, char *, addrp, dam_t *,
842*1b115575SJohn Danielson 				    mapp);
8434c06356bSdh142964 				passp->da_ref++;
8444c06356bSdh142964 				n_ids++;
8454c06356bSdh142964 			}
8464c06356bSdh142964 		}
8474c06356bSdh142964 	}
8484c06356bSdh142964 	if (n_ids) {
8494c06356bSdh142964 		*id_listp = (damap_id_list_t)bsp;
850*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
8514c06356bSdh142964 		return (n_ids);
8524c06356bSdh142964 	} else {
8534c06356bSdh142964 		*id_listp = (damap_id_list_t)NULL;
8544c06356bSdh142964 		bitset_fini(bsp);
8554c06356bSdh142964 		kmem_free(bsp, sizeof (*bsp));
856*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
8574c06356bSdh142964 		return (0);
8584c06356bSdh142964 	}
8594c06356bSdh142964 }
8604c06356bSdh142964 
8614c06356bSdh142964 /*
8624c06356bSdh142964  * Release the address list returned by damap_lookup_all()
8634c06356bSdh142964  *
8644c06356bSdh142964  * mapp:	address map handle
8654c06356bSdh142964  * id_list:	list of address IDs returned in damap_lookup_all()
8664c06356bSdh142964  */
8674c06356bSdh142964 void
8684c06356bSdh142964 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
8694c06356bSdh142964 {
8704c06356bSdh142964 	dam_t *mapp = (dam_t *)damapp;
8714c06356bSdh142964 	int i;
8724c06356bSdh142964 
8734c06356bSdh142964 	if (id_list == NULL)
8744c06356bSdh142964 		return;
8754c06356bSdh142964 
876*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
8774c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
8784c06356bSdh142964 		if (bitset_in_set((bitset_t *)id_list, i))
879*1b115575SJohn Danielson 			(void) dam_addr_release(mapp, i);
8804c06356bSdh142964 	}
881*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
8824c06356bSdh142964 	bitset_fini((bitset_t *)id_list);
8834c06356bSdh142964 	kmem_free((void *)id_list, sizeof (bitset_t));
8844c06356bSdh142964 }
8854c06356bSdh142964 
8864c06356bSdh142964 /*
887*1b115575SJohn Danielson  * activate an address that has passed the stabilization interval
8884c06356bSdh142964  */
8894c06356bSdh142964 static void
890*1b115575SJohn Danielson dam_addr_activate(dam_t *mapp, id_t addrid)
8914c06356bSdh142964 {
8924c06356bSdh142964 	dam_da_t *passp;
893*1b115575SJohn Danielson 	int config_rv;
8944c06356bSdh142964 	char *addrstr;
8954c06356bSdh142964 
896*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
897*1b115575SJohn Danielson 	bitset_add(&mapp->dam_active_set, addrid);
898*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
8994c06356bSdh142964 	ASSERT(passp);
900*1b115575SJohn Danielson 
9014c06356bSdh142964 	/*
9024c06356bSdh142964 	 * copy the reported nvlist and provider private data
9034c06356bSdh142964 	 */
904*1b115575SJohn Danielson 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
905*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
906*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
9074c06356bSdh142964 	passp->da_nvl = passp->da_nvl_rpt;
9084c06356bSdh142964 	passp->da_ppriv = passp->da_ppriv_rpt;
9094c06356bSdh142964 	passp->da_ppriv_rpt = NULL;
9104c06356bSdh142964 	passp->da_nvl_rpt = NULL;
9114c06356bSdh142964 	passp->da_last_stable = gethrtime();
9124c06356bSdh142964 	passp->da_stable_cnt++;
913*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
914*1b115575SJohn Danielson 	if (mapp->dam_activate_cb) {
915*1b115575SJohn Danielson 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
916*1b115575SJohn Danielson 		    addrid, &passp->da_ppriv_rpt);
9174c06356bSdh142964 	}
9184c06356bSdh142964 
9194c06356bSdh142964 	/*
920*1b115575SJohn Danielson 	 * call the address-specific configuration action as part of
921*1b115575SJohn Danielson 	 * activation.
9224c06356bSdh142964 	 */
923*1b115575SJohn Danielson 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
924*1b115575SJohn Danielson 	    addrid);
925*1b115575SJohn Danielson 	if (config_rv != DAM_SUCCESS) {
926*1b115575SJohn Danielson 		mutex_enter(&mapp->dam_lock);
927*1b115575SJohn Danielson 		passp->da_flags |= DA_FAILED_CONFIG;
928*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
929*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__addr__activate__config__failure,
930*1b115575SJohn Danielson 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
9314c06356bSdh142964 	}
932*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__activate__end, char *, mapp->dam_name,
933*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
9344c06356bSdh142964 }
9354c06356bSdh142964 
9364c06356bSdh142964 /*
937*1b115575SJohn Danielson  * deactivate a previously stable address
9384c06356bSdh142964  */
9394c06356bSdh142964 static void
940*1b115575SJohn Danielson dam_addr_deactivate(dam_t *mapp, id_t addrid)
9414c06356bSdh142964 {
9424c06356bSdh142964 	dam_da_t *passp;
943*1b115575SJohn Danielson 	char *addrstr;
9444c06356bSdh142964 
945*1b115575SJohn Danielson 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
946*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
947*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
948*1b115575SJohn Danielson 
949*1b115575SJohn Danielson 	/*
950*1b115575SJohn Danielson 	 * call the unconfiguration callback
951*1b115575SJohn Danielson 	 */
952*1b115575SJohn Danielson 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
953*1b115575SJohn Danielson 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
954*1b115575SJohn Danielson 	ASSERT(passp);
955*1b115575SJohn Danielson 	if (mapp->dam_deactivate_cb)
956*1b115575SJohn Danielson 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
957*1b115575SJohn Danielson 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
958*1b115575SJohn Danielson 		    addrid, passp->da_ppriv);
959*1b115575SJohn Danielson 
960*1b115575SJohn Danielson 	/*
961*1b115575SJohn Danielson 	 * clear the active bit and free the backing info for
962*1b115575SJohn Danielson 	 * this address
963*1b115575SJohn Danielson 	 */
964*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
965*1b115575SJohn Danielson 	bitset_del(&mapp->dam_active_set, addrid);
966*1b115575SJohn Danielson 	passp->da_ppriv = NULL;
967*1b115575SJohn Danielson 	if (passp->da_nvl)
968*1b115575SJohn Danielson 		nvlist_free(passp->da_nvl);
969*1b115575SJohn Danielson 	passp->da_nvl = NULL;
970*1b115575SJohn Danielson 	passp->da_ppriv_rpt = NULL;
971*1b115575SJohn Danielson 	if (passp->da_nvl_rpt)
972*1b115575SJohn Danielson 		nvlist_free(passp->da_nvl_rpt);
973*1b115575SJohn Danielson 	passp->da_nvl_rpt = NULL;
974*1b115575SJohn Danielson 
975*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
976*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
977*1b115575SJohn Danielson 
978*1b115575SJohn Danielson 	(void) dam_addr_release(mapp, addrid);
979*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
980*1b115575SJohn Danielson }
981*1b115575SJohn Danielson 
982*1b115575SJohn Danielson /*
983*1b115575SJohn Danielson  * taskq callback for multi-thread activation
984*1b115575SJohn Danielson  */
985*1b115575SJohn Danielson static void
986*1b115575SJohn Danielson dam_tq_config(void *arg)
987*1b115575SJohn Danielson {
988*1b115575SJohn Danielson 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
989*1b115575SJohn Danielson 
990*1b115575SJohn Danielson 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
991*1b115575SJohn Danielson 	kmem_free(tqd, sizeof (*tqd));
992*1b115575SJohn Danielson }
993*1b115575SJohn Danielson 
994*1b115575SJohn Danielson /*
995*1b115575SJohn Danielson  * taskq callback for multi-thread deactivation
996*1b115575SJohn Danielson  */
997*1b115575SJohn Danielson static void
998*1b115575SJohn Danielson dam_tq_unconfig(void *arg)
999*1b115575SJohn Danielson {
1000*1b115575SJohn Danielson 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1001*1b115575SJohn Danielson 
1002*1b115575SJohn Danielson 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1003*1b115575SJohn Danielson 	kmem_free(tqd, sizeof (*tqd));
1004*1b115575SJohn Danielson }
1005*1b115575SJohn Danielson 
1006*1b115575SJohn Danielson /*
1007*1b115575SJohn Danielson  * Activate a set of stabilized addresses
1008*1b115575SJohn Danielson  */
1009*1b115575SJohn Danielson static void
1010*1b115575SJohn Danielson dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1011*1b115575SJohn Danielson {
1012*1b115575SJohn Danielson 
1013*1b115575SJohn Danielson 	int i, nset;
1014*1b115575SJohn Danielson 	taskq_t *tqp = NULL;
1015*1b115575SJohn Danielson 	cfg_tqd_t *tqd = NULL;
1016*1b115575SJohn Danielson 	char tqn[TASKQ_NAMELEN];
1017*1b115575SJohn Danielson 	extern pri_t maxclsyspri;
1018*1b115575SJohn Danielson 
1019*1b115575SJohn Danielson 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1020*1b115575SJohn Danielson 		/*
1021*1b115575SJohn Danielson 		 * calculate the # of taskq threads to create
1022*1b115575SJohn Danielson 		 */
1023*1b115575SJohn Danielson 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1024*1b115575SJohn Danielson 			if (bitset_in_set(activate, i))
1025*1b115575SJohn Danielson 				nset++;
1026*1b115575SJohn Danielson 		ASSERT(nset);
1027*1b115575SJohn Danielson 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1028*1b115575SJohn Danielson 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1029*1b115575SJohn Danielson 		    INT_MAX, TASKQ_PREPOPULATE);
1030*1b115575SJohn Danielson 	}
1031*1b115575SJohn Danielson 	for (i = 1; i < mapp->dam_high; i++) {
1032*1b115575SJohn Danielson 		if (bitset_in_set(activate, i)) {
1033*1b115575SJohn Danielson 			if (!tqp)
1034*1b115575SJohn Danielson 				dam_addr_activate(mapp, i);
1035*1b115575SJohn Danielson 			else {
1036*1b115575SJohn Danielson 				/*
1037*1b115575SJohn Danielson 				 * multi-threaded activation
1038*1b115575SJohn Danielson 				 */
1039*1b115575SJohn Danielson 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1040*1b115575SJohn Danielson 				tqd->tqd_mapp = mapp;
1041*1b115575SJohn Danielson 				tqd->tqd_id = i;
1042*1b115575SJohn Danielson 				(void) taskq_dispatch(tqp, dam_tq_config,
1043*1b115575SJohn Danielson 				    tqd, KM_SLEEP);
1044*1b115575SJohn Danielson 			}
1045*1b115575SJohn Danielson 		}
1046*1b115575SJohn Danielson 	}
1047*1b115575SJohn Danielson 	if (tqp) {
1048*1b115575SJohn Danielson 		taskq_wait(tqp);
1049*1b115575SJohn Danielson 		taskq_destroy(tqp);
1050*1b115575SJohn Danielson 	}
1051*1b115575SJohn Danielson }
1052*1b115575SJohn Danielson 
1053*1b115575SJohn Danielson /*
1054*1b115575SJohn Danielson  * Deactivate a set of stabilized addresses
1055*1b115575SJohn Danielson  */
1056*1b115575SJohn Danielson static void
1057*1b115575SJohn Danielson dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1058*1b115575SJohn Danielson {
1059*1b115575SJohn Danielson 	int i, nset;
1060*1b115575SJohn Danielson 	taskq_t *tqp = NULL;
1061*1b115575SJohn Danielson 	cfg_tqd_t *tqd = NULL;
1062*1b115575SJohn Danielson 	char tqn[TASKQ_NAMELEN];
1063*1b115575SJohn Danielson 
1064*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
1065*1b115575SJohn Danielson 	    dam_t *, mapp);
1066*1b115575SJohn Danielson 
1067*1b115575SJohn Danielson 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1068*1b115575SJohn Danielson 		/*
1069*1b115575SJohn Danielson 		 * compute the # of taskq threads to dispatch
1070*1b115575SJohn Danielson 		 */
1071*1b115575SJohn Danielson 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1072*1b115575SJohn Danielson 			if (bitset_in_set(deactivate, i))
1073*1b115575SJohn Danielson 				nset++;
1074*1b115575SJohn Danielson 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1075*1b115575SJohn Danielson 		    mapp->dam_name);
1076*1b115575SJohn Danielson 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1077*1b115575SJohn Danielson 		    INT_MAX, TASKQ_PREPOPULATE);
1078*1b115575SJohn Danielson 	}
1079*1b115575SJohn Danielson 	for (i = 1; i < mapp->dam_high; i++) {
1080*1b115575SJohn Danielson 		if (bitset_in_set(deactivate, i)) {
1081*1b115575SJohn Danielson 			if (!tqp) {
1082*1b115575SJohn Danielson 				dam_addr_deactivate(mapp, i);
1083*1b115575SJohn Danielson 			} else {
1084*1b115575SJohn Danielson 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1085*1b115575SJohn Danielson 				tqd->tqd_mapp = mapp;
1086*1b115575SJohn Danielson 				tqd->tqd_id = i;
1087*1b115575SJohn Danielson 				(void) taskq_dispatch(tqp,
1088*1b115575SJohn Danielson 				    dam_tq_unconfig, tqd, KM_SLEEP);
1089*1b115575SJohn Danielson 			}
1090*1b115575SJohn Danielson 		}
1091*1b115575SJohn Danielson 	}
1092*1b115575SJohn Danielson 
1093*1b115575SJohn Danielson 	if (tqp) {
1094*1b115575SJohn Danielson 		taskq_wait(tqp);
1095*1b115575SJohn Danielson 		taskq_destroy(tqp);
1096*1b115575SJohn Danielson 	}
1097*1b115575SJohn Danielson }
1098*1b115575SJohn Danielson 
1099*1b115575SJohn Danielson /*
1100*1b115575SJohn Danielson  * Release a previously activated address
1101*1b115575SJohn Danielson  */
1102*1b115575SJohn Danielson static void
1103*1b115575SJohn Danielson dam_addr_release(dam_t *mapp, id_t addrid)
1104*1b115575SJohn Danielson {
1105*1b115575SJohn Danielson 	dam_da_t *passp;
1106*1b115575SJohn Danielson 	char	 *addrstr;
1107*1b115575SJohn Danielson 
1108*1b115575SJohn Danielson 
1109*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
11104c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
11114c06356bSdh142964 	ASSERT(passp);
11124c06356bSdh142964 
1113*1b115575SJohn Danielson 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1114*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
1115*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
11164c06356bSdh142964 
11174c06356bSdh142964 	/*
1118*1b115575SJohn Danielson 	 * defer releasing the address until outstanding references
1119*1b115575SJohn Danielson 	 * are released
11204c06356bSdh142964 	 */
1121*1b115575SJohn Danielson 	if (passp->da_ref > 1) {
1122*1b115575SJohn Danielson 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1123*1b115575SJohn Danielson 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
1124*1b115575SJohn Danielson 		    int, passp->da_ref);
11254c06356bSdh142964 		return;
11264c06356bSdh142964 	}
1127*1b115575SJohn Danielson 
1128*1b115575SJohn Danielson 	/*
1129*1b115575SJohn Danielson 	 * allow pending reports to stabilize
1130*1b115575SJohn Danielson 	 */
1131*1b115575SJohn Danielson 	if (DAM_IN_REPORT(mapp, addrid)) {
1132*1b115575SJohn Danielson 		DTRACE_PROBE3(damap__addr__release__report__pending,
1133*1b115575SJohn Danielson 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
1134*1b115575SJohn Danielson 		return;
1135*1b115575SJohn Danielson 	}
1136*1b115575SJohn Danielson 
11374c06356bSdh142964 	ddi_strid_free(mapp->dam_addr_hash, addrid);
11384c06356bSdh142964 	ddi_soft_state_free(mapp->dam_da, addrid);
11394c06356bSdh142964 }
11404c06356bSdh142964 
11414c06356bSdh142964 /*
11424c06356bSdh142964  * process stabilized address reports
11434c06356bSdh142964  */
11444c06356bSdh142964 static void
1145*1b115575SJohn Danielson dam_stabilize_map(void *arg)
11464c06356bSdh142964 {
11474c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
11484c06356bSdh142964 	bitset_t delta;
11494c06356bSdh142964 	bitset_t cfg;
11504c06356bSdh142964 	bitset_t uncfg;
11514c06356bSdh142964 	int has_cfg, has_uncfg;
1152*1b115575SJohn Danielson 	uint32_t i, n_active;
1153*1b115575SJohn Danielson 
1154*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
1155*1b115575SJohn Danielson 	    dam_t *, mapp);
11564c06356bSdh142964 
11574c06356bSdh142964 	bitset_init(&delta);
11584c06356bSdh142964 	bitset_resize(&delta, mapp->dam_size);
11594c06356bSdh142964 	bitset_init(&cfg);
11604c06356bSdh142964 	bitset_resize(&cfg, mapp->dam_size);
11614c06356bSdh142964 	bitset_init(&uncfg);
11624c06356bSdh142964 	bitset_resize(&uncfg, mapp->dam_size);
11634c06356bSdh142964 
1164*1b115575SJohn Danielson 	/*
1165*1b115575SJohn Danielson 	 * determine which addresses have changed during
1166*1b115575SJohn Danielson 	 * this stabilization cycle
1167*1b115575SJohn Danielson 	 */
1168*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
1169*1b115575SJohn Danielson 	ASSERT(mapp->dam_flags & DAM_SPEND);
11704c06356bSdh142964 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
11714c06356bSdh142964 	    &delta)) {
1172*1b115575SJohn Danielson 		/*
1173*1b115575SJohn Danielson 		 * no difference
1174*1b115575SJohn Danielson 		 */
11754c06356bSdh142964 		bitset_zero(&mapp->dam_stable_set);
1176*1b115575SJohn Danielson 		mapp->dam_flags  &= ~DAM_SPEND;
1177*1b115575SJohn Danielson 		cv_signal(&mapp->dam_cv);
1178*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
11794c06356bSdh142964 		bitset_fini(&uncfg);
11804c06356bSdh142964 		bitset_fini(&cfg);
11814c06356bSdh142964 		bitset_fini(&delta);
1182*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
1183*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
11844c06356bSdh142964 		return;
11854c06356bSdh142964 	}
1186*1b115575SJohn Danielson 
1187*1b115575SJohn Danielson 	/*
1188*1b115575SJohn Danielson 	 * compute the sets of addresses to be activated and deactivated
1189*1b115575SJohn Danielson 	 */
11904c06356bSdh142964 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
11914c06356bSdh142964 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1192*1b115575SJohn Danielson 
1193*1b115575SJohn Danielson 	/*
1194*1b115575SJohn Danielson 	 * drop map lock while invoking callouts
1195*1b115575SJohn Danielson 	 */
1196*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
1197*1b115575SJohn Danielson 
1198*1b115575SJohn Danielson 	/*
1199*1b115575SJohn Danielson 	 * activate all newly stable addresss
1200*1b115575SJohn Danielson 	 */
1201*1b115575SJohn Danielson 	if (has_cfg)
12024c06356bSdh142964 		dam_addrset_activate(mapp, &cfg);
1203*1b115575SJohn Danielson 
1204*1b115575SJohn Danielson 	/*
1205*1b115575SJohn Danielson 	 * deactivate addresss which are no longer in the map
1206*1b115575SJohn Danielson 	 */
1207*1b115575SJohn Danielson 	if (has_uncfg)
1208*1b115575SJohn Danielson 		dam_addrset_deactivate(mapp, &uncfg);
1209*1b115575SJohn Danielson 
1210*1b115575SJohn Danielson 
1211*1b115575SJohn Danielson 	/*
1212*1b115575SJohn Danielson 	 * timestamp the last stable time and increment the kstat keeping
1213*1b115575SJohn Danielson 	 * the # of of stable cycles for the map
1214*1b115575SJohn Danielson 	 */
1215*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
12164c06356bSdh142964 	bitset_zero(&mapp->dam_stable_set);
12174c06356bSdh142964 	mapp->dam_last_stable = gethrtime();
12184c06356bSdh142964 	mapp->dam_stable_cnt++;
1219*1b115575SJohn Danielson 	DAM_INCR_STAT(mapp, dam_cycles);
1220*1b115575SJohn Danielson 
1221*1b115575SJohn Danielson 	/*
1222*1b115575SJohn Danielson 	 * determine the number of stable addresses
1223*1b115575SJohn Danielson 	 * and update the n_active kstat for this map
1224*1b115575SJohn Danielson 	 */
1225*1b115575SJohn Danielson 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1226*1b115575SJohn Danielson 		if (bitset_in_set(&mapp->dam_active_set, i))
1227*1b115575SJohn Danielson 			n_active++;
1228*1b115575SJohn Danielson 	DAM_SET_STAT(mapp, dam_active, n_active);
1229*1b115575SJohn Danielson 
1230*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
1231*1b115575SJohn Danielson 	    dam_t *, mapp, int, n_active);
1232*1b115575SJohn Danielson 
1233*1b115575SJohn Danielson 	mapp->dam_flags  &= ~DAM_SPEND;
1234*1b115575SJohn Danielson 	cv_signal(&mapp->dam_cv);
1235*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
12364c06356bSdh142964 	bitset_fini(&uncfg);
12374c06356bSdh142964 	bitset_fini(&cfg);
12384c06356bSdh142964 	bitset_fini(&delta);
12394c06356bSdh142964 }
12404c06356bSdh142964 
12414c06356bSdh142964 /*
12424c06356bSdh142964  * per-address stabilization timeout
12434c06356bSdh142964  */
12444c06356bSdh142964 static void
12454c06356bSdh142964 dam_addr_stable_cb(void *arg)
12464c06356bSdh142964 {
12474c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
12484c06356bSdh142964 	int i;
12494c06356bSdh142964 	dam_da_t *passp;
12504c06356bSdh142964 	int spend = 0;
12514c06356bSdh142964 	int tpend = 0;
12524c06356bSdh142964 	int64_t	next_tmov = mapp->dam_stabletmo;
12534c06356bSdh142964 	int64_t tmo_delta;
1254d3d50737SRafael Vanoni 	int64_t ts = ddi_get_lbolt64();
12554c06356bSdh142964 
1256*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
12574c06356bSdh142964 	if (mapp->dam_tid == 0) {
1258*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
1259*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
1260*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
12614c06356bSdh142964 		return;
12624c06356bSdh142964 	}
12634c06356bSdh142964 	mapp->dam_tid = 0;
1264*1b115575SJohn Danielson 
12654c06356bSdh142964 	/*
12664c06356bSdh142964 	 * If still under stabilization, reschedule timeout,
1267*1b115575SJohn Danielson 	 * otherwise dispatch the task to activate and deactivate the
1268*1b115575SJohn Danielson 	 * new stable address
12694c06356bSdh142964 	 */
12704c06356bSdh142964 	if (mapp->dam_flags & DAM_SPEND) {
1271*1b115575SJohn Danielson 		DAM_INCR_STAT(mapp, dam_overrun);
12724c06356bSdh142964 		mapp->dam_stable_overrun++;
12734c06356bSdh142964 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
1274*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
1275*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
1276*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
12774c06356bSdh142964 		return;
12784c06356bSdh142964 	}
12794c06356bSdh142964 
1280*1b115575SJohn Danielson 	DAM_SET_STAT(mapp, dam_overrun, 0);
1281*1b115575SJohn Danielson 	mapp->dam_stable_overrun = 0;
1282*1b115575SJohn Danielson 
1283*1b115575SJohn Danielson 	/*
1284*1b115575SJohn Danielson 	 * copy the current active set to the stable map
1285*1b115575SJohn Danielson 	 * for each address being reported, decrement its
1286*1b115575SJohn Danielson 	 * stabilize deadline, and if stable, add or remove the
1287*1b115575SJohn Danielson 	 * address from the stable set
1288*1b115575SJohn Danielson 	 */
12894c06356bSdh142964 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
12904c06356bSdh142964 	for (i = 1; i < mapp->dam_high; i++) {
12914c06356bSdh142964 		if (!bitset_in_set(&mapp->dam_report_set, i))
12924c06356bSdh142964 			continue;
12934c06356bSdh142964 		passp = ddi_get_soft_state(mapp->dam_da, i);
12944c06356bSdh142964 		ASSERT(passp);
12954c06356bSdh142964 
12964c06356bSdh142964 		/* report has stabilized */
12974c06356bSdh142964 		if (passp->da_deadline <= ts) {
12984c06356bSdh142964 			bitset_del(&mapp->dam_report_set, i);
1299*1b115575SJohn Danielson 			if (passp->da_flags & DA_RELE)
13004c06356bSdh142964 				bitset_del(&mapp->dam_stable_set, i);
1301*1b115575SJohn Danielson 			else
13024c06356bSdh142964 				bitset_add(&mapp->dam_stable_set, i);
13034c06356bSdh142964 			spend++;
13044c06356bSdh142964 			continue;
13054c06356bSdh142964 		}
13064c06356bSdh142964 
13074c06356bSdh142964 		/*
1308*1b115575SJohn Danielson 		 * not stabilized, determine next map timeout
13094c06356bSdh142964 		 */
13104c06356bSdh142964 		tpend++;
13114c06356bSdh142964 		tmo_delta = passp->da_deadline - ts;
13124c06356bSdh142964 		if (tmo_delta < next_tmov)
13134c06356bSdh142964 			next_tmov = tmo_delta;
13144c06356bSdh142964 	}
13154c06356bSdh142964 
13164c06356bSdh142964 	/*
1317*1b115575SJohn Danielson 	 * schedule system_taskq activation of stabilized reports
13184c06356bSdh142964 	 */
13194c06356bSdh142964 	if (spend) {
1320*1b115575SJohn Danielson 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
1321*1b115575SJohn Danielson 		    mapp, TQ_NOSLEEP)) {
1322*1b115575SJohn Danielson 			mapp->dam_flags  |= DAM_SPEND;
1323*1b115575SJohn Danielson 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
1324*1b115575SJohn Danielson 			    mapp->dam_name, dam_t *, mapp);
1325*1b115575SJohn Danielson 		} else {
13264c06356bSdh142964 			tpend++;
13274c06356bSdh142964 		}
1328*1b115575SJohn Danielson 	}
13294c06356bSdh142964 
13304c06356bSdh142964 	/*
1331*1b115575SJohn Danielson 	 * reschedule the stabilization timer if there are reports
1332*1b115575SJohn Danielson 	 * still pending
13334c06356bSdh142964 	 */
13344c06356bSdh142964 	if (tpend)
13354c06356bSdh142964 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
1336*1b115575SJohn Danielson 
1337*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
13384c06356bSdh142964 }
13394c06356bSdh142964 
13404c06356bSdh142964 /*
1341*1b115575SJohn Danielson  * fullset stabilization timeout callback
13424c06356bSdh142964  */
13434c06356bSdh142964 static void
1344*1b115575SJohn Danielson dam_addrset_stable_cb(void *arg)
13454c06356bSdh142964 {
13464c06356bSdh142964 	dam_t *mapp = (dam_t *)arg;
13474c06356bSdh142964 
1348*1b115575SJohn Danielson 	mutex_enter(&mapp->dam_lock);
13494c06356bSdh142964 	if (mapp->dam_tid == 0) {
1350*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
1351*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1352*1b115575SJohn Danielson 		    char *, mapp->dam_name, dam_t *, mapp);
13534c06356bSdh142964 		return;
13544c06356bSdh142964 	}
13554c06356bSdh142964 	mapp->dam_tid = 0;
13564c06356bSdh142964 
13574c06356bSdh142964 	/*
1358*1b115575SJohn Danielson 	 * If map still underoing stabilization reschedule timeout,
1359*1b115575SJohn Danielson 	 * else dispatch the task to configure the new stable set of
1360*1b115575SJohn Danielson 	 * addresses.
13614c06356bSdh142964 	 */
1362*1b115575SJohn Danielson 	if ((mapp->dam_flags & DAM_SPEND) || (taskq_dispatch(system_taskq,
1363*1b115575SJohn Danielson 	    dam_stabilize_map, mapp, TQ_NOSLEEP) == NULL)) {
1364*1b115575SJohn Danielson 		DAM_INCR_STAT(mapp, dam_overrun);
13654c06356bSdh142964 		mapp->dam_stable_overrun++;
1366*1b115575SJohn Danielson 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
1367*1b115575SJohn Danielson 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
1368*1b115575SJohn Danielson 		    mapp->dam_name, dam_t *, mapp);
1369*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
1370*1b115575SJohn Danielson 		return;
1371*1b115575SJohn Danielson 	}
1372*1b115575SJohn Danielson 
1373*1b115575SJohn Danielson 	DAM_SET_STAT(mapp, dam_overrun, 0);
1374*1b115575SJohn Danielson 	mapp->dam_stable_overrun = 0;
13754c06356bSdh142964 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
13764c06356bSdh142964 	bitset_zero(&mapp->dam_report_set);
1377*1b115575SJohn Danielson 	mapp->dam_flags |= DAM_SPEND;
1378*1b115575SJohn Danielson 	mapp->dam_flags &= ~DAM_SETADD;
1379*1b115575SJohn Danielson 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
1380*1b115575SJohn Danielson 	    mapp->dam_name, dam_t *, mapp);
1381*1b115575SJohn Danielson 	mutex_exit(&mapp->dam_lock);
13824c06356bSdh142964 }
13834c06356bSdh142964 
13844c06356bSdh142964 /*
1385*1b115575SJohn Danielson  * schedule map timeout 'tmo_ms' ticks
1386*1b115575SJohn Danielson  * if map timer is currently running, cancel if tmo_ms == 0
13874c06356bSdh142964  */
13884c06356bSdh142964 static void
13894c06356bSdh142964 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
13904c06356bSdh142964 {
13914c06356bSdh142964 	timeout_id_t tid;
13924c06356bSdh142964 
1393*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp,
1394*1b115575SJohn Danielson 	    clock_t, tmo_ms);
13954c06356bSdh142964 
1396*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
1397*1b115575SJohn Danielson 	if ((tid = mapp->dam_tid) != 0) {
1398*1b115575SJohn Danielson 		if (tmo_ms == 0) {
1399*1b115575SJohn Danielson 			mapp->dam_tid = 0;
1400*1b115575SJohn Danielson 			mutex_exit(&mapp->dam_lock);
1401*1b115575SJohn Danielson 			(void) untimeout(tid);
1402*1b115575SJohn Danielson 			mutex_enter(&mapp->dam_lock);
1403*1b115575SJohn Danielson 		}
1404*1b115575SJohn Danielson 	} else {
14054c06356bSdh142964 		if (tmo_cb && (tmo_ms != 0))
14064c06356bSdh142964 			mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
14074c06356bSdh142964 	}
1408*1b115575SJohn Danielson }
14094c06356bSdh142964 
14104c06356bSdh142964 /*
1411*1b115575SJohn Danielson  * report addition or removal of an address
14124c06356bSdh142964  */
14134c06356bSdh142964 static void
1414*1b115575SJohn Danielson dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
14154c06356bSdh142964 {
1416*1b115575SJohn Danielson 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1417*1b115575SJohn Danielson 
1418*1b115575SJohn Danielson 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
1419*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
1420*1b115575SJohn Danielson 
1421*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
14224c06356bSdh142964 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
14234c06356bSdh142964 	passp->da_last_report = gethrtime();
14244c06356bSdh142964 	mapp->dam_last_update = gethrtime();
14254c06356bSdh142964 	passp->da_report_cnt++;
1426d3d50737SRafael Vanoni 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo;
1427*1b115575SJohn Danielson 	if (rpt_type == RPT_ADDR_DEL)
14284c06356bSdh142964 		passp->da_flags |= DA_RELE;
1429*1b115575SJohn Danielson 	else if (rpt_type == RPT_ADDR_ADD)
14304c06356bSdh142964 		passp->da_flags &= ~DA_RELE;
14314c06356bSdh142964 	bitset_add(&mapp->dam_report_set, addrid);
14324c06356bSdh142964 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
14334c06356bSdh142964 }
14344c06356bSdh142964 
14354c06356bSdh142964 /*
14364c06356bSdh142964  * release an address report
14374c06356bSdh142964  */
14384c06356bSdh142964 static void
1439*1b115575SJohn Danielson dam_addr_report_release(dam_t *mapp, id_t addrid)
14404c06356bSdh142964 {
14414c06356bSdh142964 	dam_da_t *passp;
1442*1b115575SJohn Danielson 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
14434c06356bSdh142964 
1444*1b115575SJohn Danielson 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
1445*1b115575SJohn Danielson 	    char *, addrstr, dam_t *, mapp);
1446*1b115575SJohn Danielson 
1447*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
14484c06356bSdh142964 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
14494c06356bSdh142964 	ASSERT(passp);
1450*1b115575SJohn Danielson 	/*
1451*1b115575SJohn Danielson 	 * clear the report bit
1452*1b115575SJohn Danielson 	 * if the address has a registered deactivation handler and
1453*1b115575SJohn Danielson 	 * the address has not stabilized, deactivate the address
1454*1b115575SJohn Danielson 	 */
1455*1b115575SJohn Danielson 	bitset_del(&mapp->dam_report_set, addrid);
1456*1b115575SJohn Danielson 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb) {
1457*1b115575SJohn Danielson 		mutex_exit(&mapp->dam_lock);
1458*1b115575SJohn Danielson 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1459*1b115575SJohn Danielson 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1460*1b115575SJohn Danielson 		    addrid, passp->da_ppriv_rpt);
1461*1b115575SJohn Danielson 		mutex_enter(&mapp->dam_lock);
1462*1b115575SJohn Danielson 	}
14634c06356bSdh142964 	passp->da_ppriv_rpt = NULL;
14644c06356bSdh142964 	if (passp->da_nvl_rpt)
14654c06356bSdh142964 		nvlist_free(passp->da_nvl_rpt);
14664c06356bSdh142964 }
14674c06356bSdh142964 
14684c06356bSdh142964 /*
14694c06356bSdh142964  * return the map ID of an address
14704c06356bSdh142964  */
14714c06356bSdh142964 static id_t
14724c06356bSdh142964 dam_get_addrid(dam_t *mapp, char *address)
14734c06356bSdh142964 {
14744c06356bSdh142964 	damap_id_t addrid;
14754c06356bSdh142964 	dam_da_t *passp;
14764c06356bSdh142964 
1477*1b115575SJohn Danielson 	ASSERT(mutex_owned(&mapp->dam_lock));
14784c06356bSdh142964 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1479*1b115575SJohn Danielson 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
14804c06356bSdh142964 		    address)) == (damap_id_t)0) {
14814c06356bSdh142964 			return (0);
14824c06356bSdh142964 		}
14834c06356bSdh142964 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
14844c06356bSdh142964 		    DDI_SUCCESS) {
14854c06356bSdh142964 			ddi_strid_free(mapp->dam_addr_hash, addrid);
14864c06356bSdh142964 			return (0);
14874c06356bSdh142964 		}
1488*1b115575SJohn Danielson 
14894c06356bSdh142964 		if (addrid >= mapp->dam_high)
14904c06356bSdh142964 			mapp->dam_high = addrid + 1;
1491*1b115575SJohn Danielson 
1492*1b115575SJohn Danielson 		/*
1493*1b115575SJohn Danielson 		 * expand bitmaps if ID has outgrown old map size
1494*1b115575SJohn Danielson 		 */
1495*1b115575SJohn Danielson 		if (mapp->dam_high > mapp->dam_size) {
1496*1b115575SJohn Danielson 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1497*1b115575SJohn Danielson 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1498*1b115575SJohn Danielson 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1499*1b115575SJohn Danielson 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
15004c06356bSdh142964 		}
1501*1b115575SJohn Danielson 
15024c06356bSdh142964 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
1503*1b115575SJohn Danielson 		passp->da_ref = 1;
1504*1b115575SJohn Danielson 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1505*1b115575SJohn Danielson 		    addrid); /* for mdb */
1506*1b115575SJohn Danielson 	}
15074c06356bSdh142964 	return (addrid);
15084c06356bSdh142964 }
15094c06356bSdh142964 
15104c06356bSdh142964 /*
15114c06356bSdh142964  * create and install map statistics
15124c06356bSdh142964  */
15134c06356bSdh142964 static int
15144c06356bSdh142964 dam_kstat_create(dam_t *mapp)
15154c06356bSdh142964 {
15164c06356bSdh142964 	kstat_t			*mapsp;
15174c06356bSdh142964 	struct dam_kstats	*statsp;
15184c06356bSdh142964 
15194c06356bSdh142964 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
15204c06356bSdh142964 	    KSTAT_TYPE_NAMED,
15214c06356bSdh142964 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1522*1b115575SJohn Danielson 
1523*1b115575SJohn Danielson 	if (mapsp == NULL)
15244c06356bSdh142964 		return (DDI_FAILURE);
15254c06356bSdh142964 
15264c06356bSdh142964 	statsp = (struct dam_kstats *)mapsp->ks_data;
1527*1b115575SJohn Danielson 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1528*1b115575SJohn Danielson 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1529*1b115575SJohn Danielson 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1530*1b115575SJohn Danielson 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
15314c06356bSdh142964 	kstat_install(mapsp);
15324c06356bSdh142964 	mapp->dam_kstatsp = mapsp;
15334c06356bSdh142964 	return (DDI_SUCCESS);
15344c06356bSdh142964 }
1535