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