xref: /illumos-gate/usr/src/uts/common/os/damap.c (revision 134a1f4e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/note.h>
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/buf.h>
31 #include <sys/kmem.h>
32 #include <sys/cmn_err.h>
33 #include <sys/debug.h>
34 #include <sys/sunndi.h>
35 #include <sys/kstat.h>
36 #include <sys/conf.h>
37 #include <sys/ddi_timer.h>
38 #include <sys/devctl.h>
39 #include <sys/callb.h>
40 #include <sys/sysevent.h>
41 #include <sys/taskq.h>
42 #include <sys/ddi.h>
43 #include <sys/bitset.h>
44 #include <sys/damap.h>
45 #include <sys/damap_impl.h>
46 
47 #ifdef DEBUG
48 static int damap_debug = 0;
49 #endif /* DEBUG */
50 
51 extern taskq_t *system_taskq;
52 
53 static void dam_addrset_activate(dam_t *, bitset_t *);
54 static void dam_addrset_deactivate(dam_t *, bitset_t *);
55 static void dam_stabilize_map(void *);
56 static void dam_addr_stable_cb(void *);
57 static void dam_addrset_stable_cb(void *);
58 static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
59 static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
60 static void dam_addr_release(dam_t *, id_t);
61 static void dam_addr_report_release(dam_t *, id_t);
62 static void dam_addr_deactivate(dam_t *, id_t);
63 static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
64 static id_t dam_get_addrid(dam_t *, char *);
65 static int dam_kstat_create(dam_t *);
66 static int dam_map_alloc(dam_t *);
67 
68 #define	DAM_INCR_STAT(mapp, stat)				\
69 	if ((mapp)->dam_kstatsp) {				\
70 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
71 		stp->stat.value.ui32++;				\
72 	}
73 
74 #define	DAM_SET_STAT(mapp, stat, val)				\
75 	if ((mapp)->dam_kstatsp) {				\
76 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
77 		stp->stat.value.ui32 = (val);			\
78 	}
79 
80 
81 /*
82  * increase damap size by 64 entries at a time
83  */
84 #define	DAM_SIZE_BUMP	64
85 
86 int	damap_taskq_dispatch_retry_usec = 1000;
87 
88 /*
89  * config/unconfig taskq data
90  */
91 typedef struct {
92 	dam_t *tqd_mapp;
93 	id_t tqd_id;
94 } cfg_tqd_t;
95 
96 extern pri_t maxclsyspri;
97 
98 /*
99  * Create new device address map
100  *
101  * name:		map name (kstat unique)
102  * size:		max # of map entries
103  * mode:		style of address reports: per-address or fullset
104  * stable_usec:		# of quiescent microseconds before report/map is stable
105  *
106  * activate_arg:	address provider activation-callout private
107  * activate_cb:		address provider activation callback handler
108  * deactivate_cb:	address provider deactivation callback handler
109  *
110  * config_arg:		configuration-callout private
111  * config_cb:		class configuration callout
112  * unconfig_cb:		class unconfiguration callout
113  *
114  * damapp:		pointer to map handle (return)
115  *
116  * Returns:	DAM_SUCCESS
117  *		DAM_EINVAL	Invalid argument(s)
118  *		DAM_FAILURE	General failure
119  */
120 int
121 damap_create(char *name, damap_rptmode_t mode, int map_opts,
122     int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
123     damap_deactivate_cb_t deactivate_cb,
124     void *config_arg, damap_configure_cb_t configure_cb,
125     damap_unconfig_cb_t unconfig_cb,
126     damap_t **damapp)
127 {
128 	dam_t *mapp;
129 
130 	if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
131 		return (DAM_EINVAL);
132 
133 	DTRACE_PROBE3(damap__create, char *, name,
134 	    damap_rptmode_t, mode, int, stable_usec);
135 
136 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
137 	mapp->dam_options = map_opts;
138 	mapp->dam_stable_ticks = drv_usectohz(stable_usec);
139 	mapp->dam_size = 0;
140 	mapp->dam_rptmode = mode;
141 	mapp->dam_activate_arg = activate_arg;
142 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
143 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
144 	mapp->dam_config_arg = config_arg;
145 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
146 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
147 	mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
148 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
149 	cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
150 	bitset_init(&mapp->dam_active_set);
151 	bitset_init(&mapp->dam_stable_set);
152 	bitset_init(&mapp->dam_report_set);
153 	*damapp = (damap_t *)mapp;
154 	return (DAM_SUCCESS);
155 }
156 
157 /*
158  * Allocate backing resources
159  *
160  * DAMs are lightly backed on create - major allocations occur
161  * at the time a report is made to the map, and are extended on
162  * a demand basis.
163  */
164 static int
165 dam_map_alloc(dam_t *mapp)
166 {
167 	void *softstate_p;
168 
169 	ASSERT(mutex_owned(&mapp->dam_lock));
170 	if (mapp->dam_flags & DAM_DESTROYPEND)
171 		return (DAM_FAILURE);
172 
173 	/*
174 	 * dam_high > 0 signals map allocation complete
175 	 */
176 	if (mapp->dam_high)
177 		return (DAM_SUCCESS);
178 
179 	mapp->dam_size = DAM_SIZE_BUMP;
180 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
181 	    mapp->dam_size) != DDI_SUCCESS)
182 		return (DAM_FAILURE);
183 
184 	if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
185 	    DDI_SUCCESS) {
186 		ddi_soft_state_fini(softstate_p);
187 		return (DAM_FAILURE);
188 	}
189 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
190 		ddi_soft_state_fini(softstate_p);
191 		ddi_strid_fini(&mapp->dam_addr_hash);
192 		return (DAM_FAILURE);
193 	}
194 	mapp->dam_da = softstate_p;
195 	mapp->dam_high = 1;
196 	bitset_resize(&mapp->dam_active_set, mapp->dam_size);
197 	bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
198 	bitset_resize(&mapp->dam_report_set, mapp->dam_size);
199 	return (DAM_SUCCESS);
200 }
201 
202 /*
203  * Destroy address map
204  *
205  * damapp:	address map
206  *
207  * Returns:	DAM_SUCCESS
208  *		DAM_EINVAL	Invalid argument(s)
209  *		DAM_FAILURE	General failure
210  */
211 void
212 damap_destroy(damap_t *damapp)
213 {
214 	int i;
215 	dam_t *mapp = (dam_t *)damapp;
216 
217 	ASSERT(mapp);
218 
219 	DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name);
220 
221 	mutex_enter(&mapp->dam_lock);
222 
223 	/*
224 	 * prevent new reports from being added to the map
225 	 */
226 	mapp->dam_flags |= DAM_DESTROYPEND;
227 
228 	if (mapp->dam_high) {
229 		mutex_exit(&mapp->dam_lock);
230 		/*
231 		 * wait for outstanding reports to stabilize and cancel
232 		 * the timer for this map
233 		 */
234 		(void) damap_sync(damapp, 0);
235 		mutex_enter(&mapp->dam_lock);
236 		dam_sched_timeout(NULL, mapp, 0);
237 
238 		/*
239 		 * map is at full stop
240 		 * release the contents of the map, invoking the
241 		 * detactivation protocol as addresses are released
242 		 */
243 		mutex_exit(&mapp->dam_lock);
244 		for (i = 1; i < mapp->dam_high; i++) {
245 			if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
246 				continue;
247 
248 			ASSERT(DAM_IN_REPORT(mapp, i) == 0);
249 
250 			if (DAM_IS_STABLE(mapp, i)) {
251 				dam_addr_deactivate(mapp, i);
252 			} else {
253 				ddi_strid_free(mapp->dam_addr_hash, i);
254 				ddi_soft_state_free(mapp->dam_da, i);
255 			}
256 		}
257 		ddi_strid_fini(&mapp->dam_addr_hash);
258 		ddi_soft_state_fini(&mapp->dam_da);
259 		kstat_delete(mapp->dam_kstatsp);
260 	} else
261 		mutex_exit(&mapp->dam_lock);
262 
263 	bitset_fini(&mapp->dam_active_set);
264 	bitset_fini(&mapp->dam_stable_set);
265 	bitset_fini(&mapp->dam_report_set);
266 	mutex_destroy(&mapp->dam_lock);
267 	cv_destroy(&mapp->dam_sync_cv);
268 	if (mapp->dam_name)
269 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
270 	kmem_free(mapp, sizeof (*mapp));
271 }
272 
273 /*
274  * Wait for map stability.  If sync was successfull then return 1.
275  * If called with a non-zero sync_usec, then a return value of 0 means a
276  * timeout occurred prior to sync completion. NOTE: if sync_usec is
277  * non-zero, it should be much longer than dam_stable_ticks.
278  *
279  * damapp:	address map
280  * sync_usec:	micorseconds until we give up on sync completion.
281  */
282 #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
283 int
284 damap_sync(damap_t *damapp, int sync_usec)
285 {
286 	dam_t	*mapp = (dam_t *)damapp;
287 	int	rv;
288 
289 	ASSERT(mapp);
290 	DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name,
291 	    dam_t *, mapp);
292 
293 	/*
294 	 * Block when waiting for
295 	 *	a) stabilization pending or a fullset update pending
296 	 *	b) the report set to finalize (bitset is null)
297 	 *	c) any scheduled timeouts to fire
298 	 */
299 	rv = 1;					/* return synced */
300 	mutex_enter(&mapp->dam_lock);
301 again:	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
302 	    (!bitset_is_null(&mapp->dam_report_set)) ||
303 	    (mapp->dam_tid != 0)) {
304 		DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name,
305 		    dam_t *, mapp);
306 
307 		/* Wait for condition relayed via timeout */
308 		if (sync_usec) {
309 			if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
310 			    drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
311 				mapp->dam_sync_to_cnt++;
312 				rv = 0;		/* return timeout */
313 				break;
314 			}
315 		} else
316 			cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
317 	}
318 
319 	if (rv) {
320 		/*
321 		 * Delay one stabilization time after the apparent sync above
322 		 * and verify accuracy - resync if not accurate.
323 		 */
324 		(void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
325 		    mapp->dam_stable_ticks, TR_MICROSEC);
326 		if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
327 		    (!bitset_is_null(&mapp->dam_report_set)) ||
328 		    (mapp->dam_tid != 0)))
329 			goto again;
330 	}
331 	mutex_exit(&mapp->dam_lock);
332 
333 	DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name,
334 	    int, rv, dam_t *, mapp);
335 	return (rv);
336 }
337 
338 /*
339  * Return 1 if active set is empty
340  */
341 int
342 damap_is_empty(damap_t *damapp)
343 {
344 	dam_t	*mapp = (dam_t *)damapp;
345 	int	rv;
346 
347 	mutex_enter(&mapp->dam_lock);
348 	rv = bitset_is_null(&mapp->dam_active_set);
349 	mutex_exit(&mapp->dam_lock);
350 	return (rv);
351 }
352 
353 /*
354  * Get the name of a device address map
355  *
356  * damapp:	address map
357  *
358  * Returns:	name
359  */
360 char *
361 damap_name(damap_t *damapp)
362 {
363 	dam_t *mapp = (dam_t *)damapp;
364 
365 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
366 }
367 
368 /*
369  * Get the current size of the device address map
370  *
371  * damapp:	address map
372  *
373  * Returns:	size
374  */
375 int
376 damap_size(damap_t *damapp)
377 {
378 	dam_t *mapp = (dam_t *)damapp;
379 
380 	return (mapp->dam_size);
381 }
382 
383 /*
384  * Report an address to per-address report
385  *
386  * damapp:	address map handle
387  * address:	address in ascii string representation
388  * addridp:	address ID
389  * nvl:		optional nvlist of configuration-private data
390  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
391  *
392  * Returns:	DAM_SUCCESS
393  *		DAM_EINVAL	Invalid argument(s)
394  *		DAM_MAPFULL	address map exhausted
395  */
396 int
397 damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
398     nvlist_t *nvl, void *addr_priv)
399 {
400 	dam_t *mapp = (dam_t *)damapp;
401 	id_t addrid;
402 	dam_da_t *passp;
403 
404 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
405 		return (DAM_EINVAL);
406 
407 	DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name,
408 	    char *, address, dam_t *, mapp);
409 
410 	mutex_enter(&mapp->dam_lock);
411 	if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
412 	    ((addrid = dam_get_addrid(mapp, address)) == 0)) {
413 		mutex_exit(&mapp->dam_lock);
414 		return (DAM_MAPFULL);
415 	}
416 
417 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
418 	ASSERT(passp != NULL);
419 
420 	/*
421 	 * If re-reporting the same address (add or remove) clear
422 	 * the existing report
423 	 */
424 	if (DAM_IN_REPORT(mapp, addrid)) {
425 		DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name,
426 		    char *, address, dam_t *, mapp);
427 		DAM_INCR_STAT(mapp, dam_jitter);
428 		dam_addr_report_release(mapp, addrid);
429 		passp->da_jitter++;
430 	}
431 	passp->da_ppriv_rpt = addr_priv;
432 	if (nvl)
433 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
434 
435 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
436 	if (addridp != NULL)
437 		*addridp = (damap_id_t)addrid;
438 	mutex_exit(&mapp->dam_lock);
439 	return (DAM_SUCCESS);
440 }
441 
442 /*
443  * Report removal of address from per-address report
444  *
445  * damapp:	address map
446  * address:	address in ascii string representation
447  *
448  * Returns:	DAM_SUCCESS
449  *		DAM_EINVAL	Invalid argument(s)
450  *		DAM_FAILURE	General failure
451  */
452 int
453 damap_addr_del(damap_t *damapp, char *address)
454 {
455 	dam_t *mapp = (dam_t *)damapp;
456 	id_t addrid;
457 	dam_da_t *passp;
458 
459 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
460 		return (DAM_EINVAL);
461 
462 	DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name,
463 	    char *, address, dam_t *, mapp);
464 	mutex_enter(&mapp->dam_lock);
465 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
466 		mutex_exit(&mapp->dam_lock);
467 		return (DAM_MAPFULL);
468 	}
469 
470 	/*
471 	 * if reporting the removal of an address which is not in the map
472 	 * return success
473 	 */
474 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
475 		mutex_exit(&mapp->dam_lock);
476 		return (DAM_SUCCESS);
477 	}
478 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
479 	ASSERT(passp);
480 	if (DAM_IN_REPORT(mapp, addrid)) {
481 		DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name,
482 		    char *, address, dam_t *, mapp);
483 		DAM_INCR_STAT(mapp, dam_jitter);
484 		dam_addr_report_release(mapp, addrid);
485 		passp->da_jitter++;
486 	}
487 	dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
488 	mutex_exit(&mapp->dam_lock);
489 	return (DAM_SUCCESS);
490 }
491 
492 static int
493 damap_addrset_flush_locked(damap_t *damapp)
494 {
495 	dam_t	*mapp = (dam_t *)damapp;
496 	int	idx;
497 
498 	ASSERT(mapp);
499 	ASSERT(mutex_owned(&mapp->dam_lock));
500 	if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
501 		return (DAM_EINVAL);
502 	}
503 
504 	DTRACE_PROBE2(damap__addrset__flush__locked__enter, char *,
505 	    mapp->dam_name, dam_t *, mapp);
506 	if (mapp->dam_flags & DAM_SETADD) {
507 		DTRACE_PROBE2(damap__addrset__flush__locked__reset, char *,
508 		    mapp->dam_name, dam_t *, mapp);
509 
510 		/*
511 		 * cancel stabilization timeout
512 		 */
513 		dam_sched_timeout(NULL, mapp, 0);
514 		DAM_INCR_STAT(mapp, dam_jitter);
515 
516 		/*
517 		 * clear pending reports
518 		 */
519 		for (idx = 1; idx < mapp->dam_high; idx++) {
520 			if (DAM_IN_REPORT(mapp, idx)) {
521 				dam_addr_report_release(mapp, idx);
522 			}
523 		}
524 
525 		bitset_zero(&mapp->dam_report_set);
526 		mapp->dam_flags &= ~DAM_SETADD;
527 		cv_signal(&mapp->dam_sync_cv);
528 	}
529 
530 	return (DAM_SUCCESS);
531 }
532 
533 /*
534  * Initiate full-set report
535  *
536  * damapp:	address map
537  *
538  * Returns:	DAM_SUCCESS
539  *		DAM_EINVAL	Invalid argument(s)
540  */
541 int
542 damap_addrset_begin(damap_t *damapp)
543 {
544 	dam_t	*mapp = (dam_t *)damapp;
545 	int	rv;
546 
547 	if (mapp == NULL) {
548 		return (DAM_EINVAL);
549 	}
550 
551 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
552 	    mapp);
553 
554 	mutex_enter(&mapp->dam_lock);
555 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
556 		mutex_exit(&mapp->dam_lock);
557 
558 		return (DAM_MAPFULL);
559 	}
560 
561 	rv = damap_addrset_flush_locked(damapp);
562 	if (rv == DAM_SUCCESS) {
563 		mapp->dam_flags |= DAM_SETADD;
564 	}
565 	mutex_exit(&mapp->dam_lock);
566 
567 	return (rv);
568 }
569 
570 /*
571  * Cancel full-set report
572  *
573  * damapp:	address map
574  *
575  * Returns:	DAM_SUCCESS
576  *		DAM_EINVAL	Invalid argument(s)
577  */
578 int
579 damap_addrset_flush(damap_t *damapp)
580 {
581 	int	rv;
582 	dam_t	*mapp = (dam_t *)damapp;
583 
584 	if (mapp == NULL) {
585 		return (DAM_EINVAL);
586 	}
587 
588 	DTRACE_PROBE2(damap__addrset__flush, char *, mapp->dam_name,
589 	    dam_t *, mapp);
590 
591 	mutex_enter(&mapp->dam_lock);
592 	rv = damap_addrset_flush_locked(damapp);
593 	mutex_exit(&mapp->dam_lock);
594 
595 	return (rv);
596 }
597 
598 /*
599  * Report address to full-set report
600  *
601  * damapp:	address map handle
602  * address:	address in ascii string representation
603  * rindx:	index if address stabilizes
604  * nvl:		optional nvlist of configuration-private data
605  * addr_priv:	optional provider-private data (passed to activate/release cb)
606  *
607  * Returns:	DAM_SUCCESS
608  *		DAM_EINVAL	Invalid argument(s)
609  *		DAM_MAPFULL	address map exhausted
610  *		DAM_FAILURE	General failure
611  */
612 int
613 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
614     nvlist_t *nvl, void *addr_priv)
615 {
616 	dam_t *mapp = (dam_t *)damapp;
617 	id_t addrid;
618 	dam_da_t *passp;
619 
620 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
621 		return (DAM_EINVAL);
622 
623 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
624 	    char *, address, dam_t *, mapp);
625 
626 	mutex_enter(&mapp->dam_lock);
627 	if (!(mapp->dam_flags & DAM_SETADD)) {
628 		mutex_exit(&mapp->dam_lock);
629 		return (DAM_FAILURE);
630 	}
631 
632 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
633 		mutex_exit(&mapp->dam_lock);
634 		return (DAM_MAPFULL);
635 	}
636 
637 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
638 	ASSERT(passp);
639 	if (DAM_IN_REPORT(mapp, addrid)) {
640 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
641 		    mapp->dam_name, char *, address, dam_t *, mapp);
642 		dam_addr_report_release(mapp, addrid);
643 		passp->da_jitter++;
644 	}
645 	passp->da_ppriv_rpt = addr_priv;
646 	if (nvl)
647 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
648 	bitset_add(&mapp->dam_report_set, addrid);
649 	if (ridx)
650 		*ridx = (damap_id_t)addrid;
651 	mutex_exit(&mapp->dam_lock);
652 	return (DAM_SUCCESS);
653 }
654 
655 /*
656  * Commit full-set report for stabilization
657  *
658  * damapp:	address map handle
659  * flags:	(currently 0)
660  *
661  * Returns:	DAM_SUCCESS
662  *		DAM_EINVAL	Invalid argument(s)
663  *		DAM_FAILURE	General failure
664  */
665 int
666 damap_addrset_end(damap_t *damapp, int flags)
667 {
668 	dam_t *mapp = (dam_t *)damapp;
669 	int i;
670 
671 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
672 		return (DAM_EINVAL);
673 
674 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
675 	    dam_t *, mapp);
676 
677 	mutex_enter(&mapp->dam_lock);
678 	if (!(mapp->dam_flags & DAM_SETADD)) {
679 		mutex_exit(&mapp->dam_lock);
680 		return (DAM_FAILURE);
681 	}
682 
683 	if (flags & DAMAP_END_RESET) {
684 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
685 		    mapp->dam_name, dam_t *, mapp);
686 		dam_sched_timeout(NULL, mapp, 0);
687 		for (i = 1; i < mapp->dam_high; i++)
688 			if (DAM_IN_REPORT(mapp, i))
689 				dam_addr_report_release(mapp, i);
690 	} else {
691 		mapp->dam_last_update = gethrtime();
692 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
693 		    mapp->dam_stable_ticks);
694 	}
695 	mutex_exit(&mapp->dam_lock);
696 	return (DAM_SUCCESS);
697 }
698 
699 /*
700  * Return nvlist registered with reported address
701  *
702  * damapp:	address map handle
703  * addrid:	address ID
704  *
705  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
706  *		NULL
707  */
708 nvlist_t *
709 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
710 {
711 	dam_t *mapp = (dam_t *)damapp;
712 	dam_da_t *pass;
713 
714 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
715 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
716 			return (pass->da_nvl);
717 	}
718 	return (NULL);
719 }
720 
721 /*
722  * Return address string
723  *
724  * damapp:	address map handle
725  * addrid:	address ID
726  *
727  * Returns:	char *		Address string
728  *		NULL
729  */
730 char *
731 damap_id2addr(damap_t *damapp, damap_id_t addrid)
732 {
733 	dam_t *mapp = (dam_t *)damapp;
734 
735 	if (mapp->dam_high)
736 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
737 	else
738 		return (NULL);
739 }
740 
741 /*
742  * Release address reference in map
743  *
744  * damapp:	address map handle
745  * addrid:	address ID
746  */
747 void
748 damap_id_rele(damap_t *damapp, damap_id_t addrid)
749 {
750 	dam_t *mapp = (dam_t *)damapp;
751 	dam_da_t *passp;
752 	char *addr;
753 
754 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
755 	ASSERT(passp);
756 
757 	addr = damap_id2addr(damapp, addrid);
758 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
759 	    dam_t *, mapp, int, passp->da_ref);
760 
761 	mutex_enter(&mapp->dam_lock);
762 
763 	/*
764 	 * teardown address if last outstanding reference
765 	 */
766 	if (--passp->da_ref == 0)
767 		dam_addr_release(mapp, (id_t)addrid);
768 
769 	mutex_exit(&mapp->dam_lock);
770 }
771 
772 /*
773  * Return current reference count on address reference in map
774  *
775  * damapp:	address map handle
776  * addrid:	address ID
777  *
778  * Returns:	DAM_SUCCESS
779  *		DAM_FAILURE
780  */
781 int
782 damap_id_ref(damap_t *damapp, damap_id_t addrid)
783 {
784 	dam_t *mapp = (dam_t *)damapp;
785 	dam_da_t *passp;
786 	int ref = -1;
787 
788 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
789 	if (passp)
790 		ref = passp->da_ref;
791 
792 	return (ref);
793 }
794 
795 /*
796  * Return next address ID in list
797  *
798  * damapp:	address map handle
799  * damap_list:	address ID list passed to config|unconfig
800  *		returned by look by lookup_all
801  * last:	last ID returned, 0 is start of list
802  *
803  * Returns:	addrid		Next ID from the list
804  *		0		End of the list
805  */
806 damap_id_t
807 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
808 {
809 	int i, start;
810 	dam_t *mapp = (dam_t *)damapp;
811 	bitset_t *dam_list = (bitset_t *)damap_list;
812 
813 	if (!mapp || !dam_list)
814 		return ((damap_id_t)0);
815 
816 	start = (int)last + 1;
817 	for (i = start; i < mapp->dam_high; i++) {
818 		if (bitset_in_set(dam_list, i)) {
819 			return ((damap_id_t)i);
820 		}
821 	}
822 	return ((damap_id_t)0);
823 }
824 
825 /*
826  * Set config private data
827  *
828  * damapp:	address map handle
829  * addrid:	address ID
830  * cfg_priv:	configuration private data
831  *
832  */
833 void
834 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
835 {
836 	dam_t *mapp = (dam_t *)damapp;
837 	dam_da_t *passp;
838 
839 	mutex_enter(&mapp->dam_lock);
840 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
841 	if (!passp) {
842 		mutex_exit(&mapp->dam_lock);
843 		return;
844 	}
845 	passp->da_cfg_priv = cfg_priv;
846 	mutex_exit(&mapp->dam_lock);
847 }
848 
849 /*
850  * Get config private data
851  *
852  * damapp:	address map handle
853  * addrid:	address ID
854  *
855  * Returns:	configuration private data
856  */
857 void *
858 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
859 {
860 	dam_t *mapp = (dam_t *)damapp;
861 	dam_da_t *passp;
862 	void *rv;
863 
864 	mutex_enter(&mapp->dam_lock);
865 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
866 	if (!passp) {
867 		mutex_exit(&mapp->dam_lock);
868 		return (NULL);
869 	}
870 	rv = passp->da_cfg_priv;
871 	mutex_exit(&mapp->dam_lock);
872 	return (rv);
873 }
874 
875 /*
876  * Lookup a single address in the active address map
877  *
878  * damapp:	address map handle
879  * address:	address string
880  *
881  * Returns:	ID of active/stable address
882  *		0	Address not in stable set
883  *
884  * Future: Allow the caller to wait for stabilize before returning not found.
885  */
886 damap_id_t
887 damap_lookup(damap_t *damapp, char *address)
888 {
889 	dam_t *mapp = (dam_t *)damapp;
890 	id_t addrid = 0;
891 	dam_da_t *passp = NULL;
892 
893 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
894 	    char *, address, dam_t *, mapp);
895 	mutex_enter(&mapp->dam_lock);
896 	if (!mapp->dam_high)
897 		addrid = 0;
898 	else
899 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
900 	if (addrid) {
901 		if (DAM_IS_STABLE(mapp, addrid)) {
902 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
903 			ASSERT(passp);
904 			if (passp) {
905 				passp->da_ref++;
906 			} else {
907 				addrid = 0;
908 			}
909 		} else {
910 			addrid = 0;
911 		}
912 	}
913 	mutex_exit(&mapp->dam_lock);
914 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
915 	    char *, address, dam_t *, mapp, int, addrid);
916 	return ((damap_id_t)addrid);
917 }
918 
919 
920 /*
921  * Return the list of stable addresses in the map
922  *
923  * damapp:	address map handle
924  * id_listp:	pointer to list of address IDs in stable map (returned)
925  *
926  * Returns:	# of entries returned in alist
927  */
928 int
929 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
930 {
931 	dam_t *mapp = (dam_t *)damapp;
932 	int mapsz = mapp->dam_size;
933 	int n_ids, i;
934 	bitset_t *bsp;
935 	char	 *addrp;
936 	dam_da_t *passp;
937 
938 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
939 	    dam_t *, mapp);
940 	mutex_enter(&mapp->dam_lock);
941 	if (!mapp->dam_high) {
942 		*id_listp = (damap_id_list_t)NULL;
943 		mutex_exit(&mapp->dam_lock);
944 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
945 		    mapp->dam_name, dam_t *, mapp, int, 0);
946 		return (0);
947 	}
948 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
949 	bitset_init(bsp);
950 	bitset_resize(bsp, mapsz);
951 	bitset_copy(&mapp->dam_active_set, bsp);
952 	for (n_ids = 0, i = 1; i < mapsz; i++) {
953 		if (bitset_in_set(bsp, i)) {
954 			passp = ddi_get_soft_state(mapp->dam_da, i);
955 			ASSERT(passp);
956 			if (passp) {
957 				addrp = damap_id2addr(damapp, i);
958 				DTRACE_PROBE3(damap__lookup__all__item, char *,
959 				    mapp->dam_name, char *, addrp, dam_t *,
960 				    mapp);
961 				passp->da_ref++;
962 				n_ids++;
963 			}
964 		}
965 	}
966 	if (n_ids) {
967 		*id_listp = (damap_id_list_t)bsp;
968 		mutex_exit(&mapp->dam_lock);
969 		return (n_ids);
970 	} else {
971 		*id_listp = (damap_id_list_t)NULL;
972 		bitset_fini(bsp);
973 		kmem_free(bsp, sizeof (*bsp));
974 		mutex_exit(&mapp->dam_lock);
975 		return (0);
976 	}
977 }
978 
979 /*
980  * Release the address list returned by damap_lookup_all()
981  *
982  * mapp:	address map handle
983  * id_list:	list of address IDs returned in damap_lookup_all()
984  */
985 void
986 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
987 {
988 	dam_t *mapp = (dam_t *)damapp;
989 	int i;
990 
991 	if (id_list == NULL)
992 		return;
993 
994 	mutex_enter(&mapp->dam_lock);
995 	for (i = 1; i < mapp->dam_high; i++) {
996 		if (bitset_in_set((bitset_t *)id_list, i))
997 			(void) dam_addr_release(mapp, i);
998 	}
999 	mutex_exit(&mapp->dam_lock);
1000 	bitset_fini((bitset_t *)id_list);
1001 	kmem_free((void *)id_list, sizeof (bitset_t));
1002 }
1003 
1004 /*
1005  * activate an address that has passed the stabilization interval
1006  */
1007 static void
1008 dam_addr_activate(dam_t *mapp, id_t addrid)
1009 {
1010 	dam_da_t *passp;
1011 	int config_rv;
1012 	char *addrstr;
1013 
1014 	mutex_enter(&mapp->dam_lock);
1015 	bitset_add(&mapp->dam_active_set, addrid);
1016 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1017 	ASSERT(passp);
1018 
1019 	/*
1020 	 * copy the reported nvlist and provider private data
1021 	 */
1022 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1023 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
1024 	    char *, addrstr, dam_t *, mapp);
1025 	passp->da_nvl = passp->da_nvl_rpt;
1026 	passp->da_ppriv = passp->da_ppriv_rpt;
1027 	passp->da_ppriv_rpt = NULL;
1028 	passp->da_nvl_rpt = NULL;
1029 	passp->da_last_stable = gethrtime();
1030 	passp->da_stable_cnt++;
1031 	mutex_exit(&mapp->dam_lock);
1032 	if (mapp->dam_activate_cb) {
1033 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
1034 		    addrid, &passp->da_ppriv_rpt);
1035 	}
1036 
1037 	/*
1038 	 * call the address-specific configuration action as part of
1039 	 * activation.
1040 	 */
1041 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
1042 	    addrid);
1043 	if (config_rv != DAM_SUCCESS) {
1044 		mutex_enter(&mapp->dam_lock);
1045 		passp->da_flags |= DA_FAILED_CONFIG;
1046 		mutex_exit(&mapp->dam_lock);
1047 		DTRACE_PROBE3(damap__addr__activate__config__failure,
1048 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
1049 		dam_deact_cleanup(mapp, addrid, addrstr,
1050 		    DAMAP_DEACT_RSN_CFG_FAIL);
1051 	} else {
1052 		DTRACE_PROBE3(damap__addr__activate__end, char *,
1053 		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
1054 	}
1055 }
1056 
1057 /*
1058  * deactivate a previously stable address
1059  */
1060 static void
1061 dam_addr_deactivate(dam_t *mapp, id_t addrid)
1062 {
1063 	char *addrstr;
1064 
1065 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1066 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
1067 	    char *, addrstr, dam_t *, mapp);
1068 
1069 	/*
1070 	 * call the unconfiguration callback
1071 	 */
1072 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1073 	dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1074 }
1075 
1076 static void
1077 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1078     damap_deact_rsn_t deact_rsn)
1079 {
1080 	dam_da_t *passp;
1081 
1082 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1083 	ASSERT(passp);
1084 	if (mapp->dam_deactivate_cb)
1085 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1086 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1087 		    addrid, passp->da_ppriv, deact_rsn);
1088 
1089 	/*
1090 	 * clear the active bit and free the backing info for
1091 	 * this address
1092 	 */
1093 	mutex_enter(&mapp->dam_lock);
1094 	bitset_del(&mapp->dam_active_set, addrid);
1095 	passp->da_ppriv = NULL;
1096 	if (passp->da_nvl)
1097 		nvlist_free(passp->da_nvl);
1098 	passp->da_nvl = NULL;
1099 	passp->da_ppriv_rpt = NULL;
1100 	if (passp->da_nvl_rpt)
1101 		nvlist_free(passp->da_nvl_rpt);
1102 	passp->da_nvl_rpt = NULL;
1103 
1104 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
1105 	    char *, addrstr, dam_t *, mapp);
1106 
1107 	(void) dam_addr_release(mapp, addrid);
1108 	mutex_exit(&mapp->dam_lock);
1109 }
1110 
1111 /*
1112  * taskq callback for multi-thread activation
1113  */
1114 static void
1115 dam_tq_config(void *arg)
1116 {
1117 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1118 
1119 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1120 	kmem_free(tqd, sizeof (*tqd));
1121 }
1122 
1123 /*
1124  * taskq callback for multi-thread deactivation
1125  */
1126 static void
1127 dam_tq_unconfig(void *arg)
1128 {
1129 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1130 
1131 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1132 	kmem_free(tqd, sizeof (*tqd));
1133 }
1134 
1135 /*
1136  * Activate a set of stabilized addresses
1137  */
1138 static void
1139 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1140 {
1141 
1142 	int i, nset;
1143 	taskq_t *tqp = NULL;
1144 	cfg_tqd_t *tqd = NULL;
1145 	char tqn[TASKQ_NAMELEN];
1146 	extern pri_t maxclsyspri;
1147 
1148 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1149 		/*
1150 		 * calculate the # of taskq threads to create
1151 		 */
1152 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1153 			if (bitset_in_set(activate, i))
1154 				nset++;
1155 		ASSERT(nset);
1156 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1157 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1158 		    INT_MAX, TASKQ_PREPOPULATE);
1159 	}
1160 	for (i = 1; i < mapp->dam_high; i++) {
1161 		if (bitset_in_set(activate, i)) {
1162 			if (!tqp)
1163 				dam_addr_activate(mapp, i);
1164 			else {
1165 				/*
1166 				 * multi-threaded activation
1167 				 */
1168 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1169 				tqd->tqd_mapp = mapp;
1170 				tqd->tqd_id = i;
1171 				(void) taskq_dispatch(tqp, dam_tq_config,
1172 				    tqd, TQ_SLEEP);
1173 			}
1174 		}
1175 	}
1176 	if (tqp) {
1177 		taskq_wait(tqp);
1178 		taskq_destroy(tqp);
1179 	}
1180 }
1181 
1182 /*
1183  * Deactivate a set of stabilized addresses
1184  */
1185 static void
1186 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1187 {
1188 	int i, nset;
1189 	taskq_t *tqp = NULL;
1190 	cfg_tqd_t *tqd = NULL;
1191 	char tqn[TASKQ_NAMELEN];
1192 
1193 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
1194 	    dam_t *, mapp);
1195 
1196 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1197 		/*
1198 		 * compute the # of taskq threads to dispatch
1199 		 */
1200 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1201 			if (bitset_in_set(deactivate, i))
1202 				nset++;
1203 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1204 		    mapp->dam_name);
1205 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1206 		    INT_MAX, TASKQ_PREPOPULATE);
1207 	}
1208 	for (i = 1; i < mapp->dam_high; i++) {
1209 		if (bitset_in_set(deactivate, i)) {
1210 			if (!tqp) {
1211 				dam_addr_deactivate(mapp, i);
1212 			} else {
1213 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1214 				tqd->tqd_mapp = mapp;
1215 				tqd->tqd_id = i;
1216 				(void) taskq_dispatch(tqp,
1217 				    dam_tq_unconfig, tqd, TQ_SLEEP);
1218 			}
1219 		}
1220 	}
1221 
1222 	if (tqp) {
1223 		taskq_wait(tqp);
1224 		taskq_destroy(tqp);
1225 	}
1226 }
1227 
1228 /*
1229  * Release a previously activated address
1230  */
1231 static void
1232 dam_addr_release(dam_t *mapp, id_t addrid)
1233 {
1234 	dam_da_t *passp;
1235 	char	 *addrstr;
1236 
1237 
1238 	ASSERT(mutex_owned(&mapp->dam_lock));
1239 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1240 	ASSERT(passp);
1241 
1242 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1243 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
1244 	    char *, addrstr, dam_t *, mapp);
1245 
1246 	/*
1247 	 * defer releasing the address until outstanding references
1248 	 * are released
1249 	 */
1250 	if (passp->da_ref > 1) {
1251 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1252 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
1253 		    int, passp->da_ref);
1254 		return;
1255 	}
1256 
1257 	/*
1258 	 * allow pending reports to stabilize
1259 	 */
1260 	if (DAM_IN_REPORT(mapp, addrid)) {
1261 		DTRACE_PROBE3(damap__addr__release__report__pending,
1262 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
1263 		return;
1264 	}
1265 
1266 	ddi_strid_free(mapp->dam_addr_hash, addrid);
1267 	ddi_soft_state_free(mapp->dam_da, addrid);
1268 }
1269 
1270 /*
1271  * process stabilized address reports
1272  */
1273 static void
1274 dam_stabilize_map(void *arg)
1275 {
1276 	dam_t *mapp = (dam_t *)arg;
1277 	bitset_t delta;
1278 	bitset_t cfg;
1279 	bitset_t uncfg;
1280 	int has_cfg, has_uncfg;
1281 	uint32_t i, n_active;
1282 
1283 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
1284 	    dam_t *, mapp);
1285 
1286 	bitset_init(&delta);
1287 	bitset_resize(&delta, mapp->dam_size);
1288 	bitset_init(&cfg);
1289 	bitset_resize(&cfg, mapp->dam_size);
1290 	bitset_init(&uncfg);
1291 	bitset_resize(&uncfg, mapp->dam_size);
1292 
1293 	/*
1294 	 * determine which addresses have changed during
1295 	 * this stabilization cycle
1296 	 */
1297 	mutex_enter(&mapp->dam_lock);
1298 	ASSERT(mapp->dam_flags & DAM_SPEND);
1299 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1300 	    &delta)) {
1301 		/*
1302 		 * no difference
1303 		 */
1304 		bitset_zero(&mapp->dam_stable_set);
1305 		mapp->dam_flags &= ~DAM_SPEND;
1306 		cv_signal(&mapp->dam_sync_cv);
1307 		mutex_exit(&mapp->dam_lock);
1308 
1309 		bitset_fini(&uncfg);
1310 		bitset_fini(&cfg);
1311 		bitset_fini(&delta);
1312 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
1313 		    mapp->dam_name, dam_t *, mapp);
1314 		return;
1315 	}
1316 
1317 	/*
1318 	 * compute the sets of addresses to be activated and deactivated
1319 	 */
1320 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1321 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1322 
1323 	/*
1324 	 * drop map lock while invoking callouts
1325 	 */
1326 	mutex_exit(&mapp->dam_lock);
1327 
1328 	/*
1329 	 * activate all newly stable addresss
1330 	 */
1331 	if (has_cfg)
1332 		dam_addrset_activate(mapp, &cfg);
1333 
1334 	/*
1335 	 * deactivate addresss which are no longer in the map
1336 	 */
1337 	if (has_uncfg)
1338 		dam_addrset_deactivate(mapp, &uncfg);
1339 
1340 
1341 	/*
1342 	 * timestamp the last stable time and increment the kstat keeping
1343 	 * the # of of stable cycles for the map
1344 	 */
1345 	mutex_enter(&mapp->dam_lock);
1346 	bitset_zero(&mapp->dam_stable_set);
1347 	mapp->dam_last_stable = gethrtime();
1348 	mapp->dam_stable_cnt++;
1349 	DAM_INCR_STAT(mapp, dam_cycles);
1350 
1351 	/*
1352 	 * determine the number of stable addresses
1353 	 * and update the n_active kstat for this map
1354 	 */
1355 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1356 		if (bitset_in_set(&mapp->dam_active_set, i))
1357 			n_active++;
1358 	DAM_SET_STAT(mapp, dam_active, n_active);
1359 
1360 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
1361 	    dam_t *, mapp, int, n_active);
1362 
1363 	mapp->dam_flags &= ~DAM_SPEND;
1364 	cv_signal(&mapp->dam_sync_cv);
1365 	mutex_exit(&mapp->dam_lock);
1366 
1367 	bitset_fini(&uncfg);
1368 	bitset_fini(&cfg);
1369 	bitset_fini(&delta);
1370 }
1371 
1372 /*
1373  * per-address stabilization timeout
1374  */
1375 static void
1376 dam_addr_stable_cb(void *arg)
1377 {
1378 	dam_t *mapp = (dam_t *)arg;
1379 	int i;
1380 	dam_da_t *passp;
1381 	int spend = 0;
1382 	int tpend = 0;
1383 	int64_t ts, next_ticks, delta_ticks;
1384 
1385 	mutex_enter(&mapp->dam_lock);
1386 	if (mapp->dam_tid == 0) {
1387 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
1388 		    mapp->dam_name, dam_t *, mapp);
1389 		mutex_exit(&mapp->dam_lock);
1390 		return;
1391 	}
1392 	mapp->dam_tid = 0;
1393 
1394 	/*
1395 	 * If still under stabilization, reschedule timeout,
1396 	 * otherwise dispatch the task to activate and deactivate the
1397 	 * new stable address
1398 	 */
1399 	if (mapp->dam_flags & DAM_SPEND) {
1400 		DAM_INCR_STAT(mapp, dam_overrun);
1401 		mapp->dam_stable_overrun++;
1402 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1403 		    mapp->dam_stable_ticks);
1404 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
1405 		    mapp->dam_name, dam_t *, mapp);
1406 		mutex_exit(&mapp->dam_lock);
1407 		return;
1408 	}
1409 
1410 	DAM_SET_STAT(mapp, dam_overrun, 0);
1411 	mapp->dam_stable_overrun = 0;
1412 
1413 	/*
1414 	 * copy the current active set to the stable map
1415 	 * for each address being reported, decrement its
1416 	 * stabilize deadline, and if stable, add or remove the
1417 	 * address from the stable set
1418 	 */
1419 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
1420 	ts = ddi_get_lbolt64();
1421 	next_ticks = mapp->dam_stable_ticks;
1422 	for (i = 1; i < mapp->dam_high; i++) {
1423 		if (!bitset_in_set(&mapp->dam_report_set, i))
1424 			continue;
1425 		passp = ddi_get_soft_state(mapp->dam_da, i);
1426 		ASSERT(passp);
1427 
1428 		/* report has stabilized */
1429 		if (passp->da_deadline <= ts) {
1430 			bitset_del(&mapp->dam_report_set, i);
1431 			if (passp->da_flags & DA_RELE)
1432 				bitset_del(&mapp->dam_stable_set, i);
1433 			else
1434 				bitset_add(&mapp->dam_stable_set, i);
1435 			spend++;
1436 			continue;
1437 		}
1438 
1439 		/*
1440 		 * not stabilized, determine next map timeout
1441 		 */
1442 		tpend++;
1443 		delta_ticks = passp->da_deadline - ts;
1444 		if (delta_ticks < next_ticks)
1445 			next_ticks = delta_ticks;
1446 	}
1447 
1448 	/*
1449 	 * schedule system_taskq activation of stabilized reports
1450 	 */
1451 	if (spend) {
1452 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
1453 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1454 			mapp->dam_flags |= DAM_SPEND;
1455 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
1456 			    mapp->dam_name, dam_t *, mapp);
1457 		} else {
1458 			tpend++;
1459 
1460 			/*
1461 			 * Avoid waiting the entire stabalization
1462 			 * time again if taskq_diskpatch fails.
1463 			 */
1464 			delta_ticks = drv_usectohz(
1465 			    damap_taskq_dispatch_retry_usec);
1466 			if (delta_ticks < next_ticks)
1467 				next_ticks = delta_ticks;
1468 		}
1469 	}
1470 
1471 	/*
1472 	 * reschedule the stabilization timer if there are reports
1473 	 * still pending
1474 	 */
1475 	if (tpend)
1476 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1477 		    (clock_t)next_ticks);
1478 
1479 	mutex_exit(&mapp->dam_lock);
1480 }
1481 
1482 /*
1483  * fullset stabilization timeout callback
1484  */
1485 static void
1486 dam_addrset_stable_cb(void *arg)
1487 {
1488 	dam_t *mapp = (dam_t *)arg;
1489 
1490 	mutex_enter(&mapp->dam_lock);
1491 	if (mapp->dam_tid == 0) {
1492 		mutex_exit(&mapp->dam_lock);
1493 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1494 		    char *, mapp->dam_name, dam_t *, mapp);
1495 		return;
1496 	}
1497 	mapp->dam_tid = 0;
1498 
1499 	/*
1500 	 * If map still underoing stabilization reschedule timeout,
1501 	 * else dispatch the task to configure the new stable set of
1502 	 * addresses.
1503 	 */
1504 	if ((mapp->dam_flags & DAM_SPEND) ||
1505 	    (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1506 	    TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1507 		DAM_INCR_STAT(mapp, dam_overrun);
1508 		mapp->dam_stable_overrun++;
1509 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
1510 		    drv_usectohz(damap_taskq_dispatch_retry_usec));
1511 
1512 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
1513 		    mapp->dam_name, dam_t *, mapp);
1514 		mutex_exit(&mapp->dam_lock);
1515 		return;
1516 	}
1517 
1518 	DAM_SET_STAT(mapp, dam_overrun, 0);
1519 	mapp->dam_stable_overrun = 0;
1520 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1521 	bitset_zero(&mapp->dam_report_set);
1522 	mapp->dam_flags |= DAM_SPEND;
1523 	mapp->dam_flags &= ~DAM_SETADD;
1524 	/* NOTE: don't need cv_signal since DAM_SPEND is still set */
1525 
1526 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
1527 	    mapp->dam_name, dam_t *, mapp);
1528 	mutex_exit(&mapp->dam_lock);
1529 }
1530 
1531 /*
1532  * schedule map timeout in 'ticks' ticks
1533  * if map timer is currently running, cancel if ticks == 0
1534  */
1535 static void
1536 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1537 {
1538 	timeout_id_t tid;
1539 
1540 	DTRACE_PROBE3(damap__sched__timeout, char *, mapp->dam_name,
1541 	    dam_t *, mapp, int, ticks);
1542 
1543 	ASSERT(mutex_owned(&mapp->dam_lock));
1544 	if ((tid = mapp->dam_tid) != 0) {
1545 		if (ticks == 0) {
1546 			mapp->dam_tid = 0;
1547 			mutex_exit(&mapp->dam_lock);
1548 			(void) untimeout(tid);
1549 			mutex_enter(&mapp->dam_lock);
1550 		}
1551 	} else {
1552 		if (timeout_cb && (ticks != 0))
1553 			mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1554 	}
1555 }
1556 
1557 /*
1558  * report addition or removal of an address
1559  */
1560 static void
1561 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1562 {
1563 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1564 
1565 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
1566 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
1567 
1568 	ASSERT(mutex_owned(&mapp->dam_lock));
1569 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
1570 	passp->da_last_report = gethrtime();
1571 	mapp->dam_last_update = gethrtime();
1572 	passp->da_report_cnt++;
1573 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1574 	if (rpt_type == RPT_ADDR_DEL)
1575 		passp->da_flags |= DA_RELE;
1576 	else if (rpt_type == RPT_ADDR_ADD)
1577 		passp->da_flags &= ~DA_RELE;
1578 	bitset_add(&mapp->dam_report_set, addrid);
1579 	dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1580 }
1581 
1582 /*
1583  * release an address report
1584  */
1585 static void
1586 dam_addr_report_release(dam_t *mapp, id_t addrid)
1587 {
1588 	dam_da_t *passp;
1589 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1590 
1591 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
1592 	    char *, addrstr, dam_t *, mapp);
1593 
1594 	ASSERT(mutex_owned(&mapp->dam_lock));
1595 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1596 	ASSERT(passp);
1597 	/*
1598 	 * clear the report bit
1599 	 * if the address has a registered deactivation handler and
1600 	 * we are holding a private data pointer and the address has not
1601 	 * stabilized, deactivate the address (private data).
1602 	 */
1603 	bitset_del(&mapp->dam_report_set, addrid);
1604 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1605 	    passp->da_ppriv_rpt) {
1606 		mutex_exit(&mapp->dam_lock);
1607 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1608 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1609 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1610 		mutex_enter(&mapp->dam_lock);
1611 	}
1612 	passp->da_ppriv_rpt = NULL;
1613 	if (passp->da_nvl_rpt)
1614 		nvlist_free(passp->da_nvl_rpt);
1615 }
1616 
1617 /*
1618  * return the map ID of an address
1619  */
1620 static id_t
1621 dam_get_addrid(dam_t *mapp, char *address)
1622 {
1623 	damap_id_t addrid;
1624 	dam_da_t *passp;
1625 
1626 	ASSERT(mutex_owned(&mapp->dam_lock));
1627 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1628 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1629 		    address)) == (damap_id_t)0) {
1630 			return (0);
1631 		}
1632 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1633 		    DDI_SUCCESS) {
1634 			ddi_strid_free(mapp->dam_addr_hash, addrid);
1635 			return (0);
1636 		}
1637 
1638 		if (addrid >= mapp->dam_high)
1639 			mapp->dam_high = addrid + 1;
1640 
1641 		/*
1642 		 * expand bitmaps if ID has outgrown old map size
1643 		 */
1644 		if (mapp->dam_high > mapp->dam_size) {
1645 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1646 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1647 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1648 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1649 		}
1650 
1651 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
1652 		passp->da_ref = 1;
1653 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1654 		    addrid); /* for mdb */
1655 	}
1656 	return (addrid);
1657 }
1658 
1659 /*
1660  * create and install map statistics
1661  */
1662 static int
1663 dam_kstat_create(dam_t *mapp)
1664 {
1665 	kstat_t			*mapsp;
1666 	struct dam_kstats	*statsp;
1667 
1668 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1669 	    KSTAT_TYPE_NAMED,
1670 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1671 
1672 	if (mapsp == NULL)
1673 		return (DDI_FAILURE);
1674 
1675 	statsp = (struct dam_kstats *)mapsp->ks_data;
1676 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1677 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1678 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1679 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1680 	kstat_install(mapsp);
1681 	mapp->dam_kstatsp = mapsp;
1682 	return (DDI_SUCCESS);
1683 }
1684