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