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