xref: /titanic_52/usr/src/uts/common/os/damap.c (revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac)
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 /*
438  * Initiate full-set report
439  *
440  * damapp:	address map
441  *
442  * Returns:	DAM_SUCCESS
443  *		DAM_EINVAL	Invalid argument(s)
444  */
445 int
446 damap_addrset_begin(damap_t *damapp)
447 {
448 	dam_t *mapp = (dam_t *)damapp;
449 	int i;
450 
451 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
452 		return (DAM_EINVAL);
453 
454 	DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *,
455 	    mapp);
456 	mutex_enter(&mapp->dam_lock);
457 	if (dam_map_alloc(mapp) != DAM_SUCCESS) {
458 		mutex_exit(&mapp->dam_lock);
459 		return (DAM_MAPFULL);
460 	}
461 	if (mapp->dam_flags & DAM_SETADD) {
462 		DTRACE_PROBE2(damap__addrset__begin__reset, char *,
463 		    mapp->dam_name, dam_t *, mapp);
464 		/*
465 		 * cancel stabilization timeout
466 		 */
467 		dam_sched_tmo(mapp, 0, NULL);
468 		DAM_INCR_STAT(mapp, dam_jitter);
469 
470 		/*
471 		 * clear pending reports
472 		 */
473 		for (i = 1; i < mapp->dam_high; i++) {
474 			if (DAM_IN_REPORT(mapp, i))
475 				dam_addr_report_release(mapp, i);
476 		}
477 	}
478 	bitset_zero(&mapp->dam_report_set);
479 	mapp->dam_flags |= DAM_SETADD;
480 	mutex_exit(&mapp->dam_lock);
481 	return (DAM_SUCCESS);
482 }
483 
484 /*
485  * Report address to full-set report
486  *
487  * damapp:	address map handle
488  * address:	address in ascii string representation
489  * rindx:	index if address stabilizes
490  * nvl:		optional nvlist of configuration-private data
491  * addr_priv:	optional provider-private data (passed to activate/release cb)
492  *
493  * Returns:	DAM_SUCCESS
494  *		DAM_EINVAL	Invalid argument(s)
495  *		DAM_MAPFULL	address map exhausted
496  *		DAM_FAILURE	General failure
497  */
498 int
499 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
500     nvlist_t *nvl, void *addr_priv)
501 {
502 	dam_t *mapp = (dam_t *)damapp;
503 	id_t addrid;
504 	dam_da_t *passp;
505 
506 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
507 		return (DAM_EINVAL);
508 
509 	DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name,
510 	    char *, address, dam_t *, mapp);
511 
512 	mutex_enter(&mapp->dam_lock);
513 	if (!(mapp->dam_flags & DAM_SETADD)) {
514 		mutex_exit(&mapp->dam_lock);
515 		return (DAM_FAILURE);
516 	}
517 
518 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
519 		mutex_exit(&mapp->dam_lock);
520 		return (DAM_MAPFULL);
521 	}
522 
523 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
524 	ASSERT(passp);
525 	if (DAM_IN_REPORT(mapp, addrid)) {
526 		DTRACE_PROBE3(damap__addrset__add__jitter, char *,
527 		    mapp->dam_name, char *, address, dam_t *, mapp);
528 		dam_addr_report_release(mapp, addrid);
529 		passp->da_jitter++;
530 	}
531 	passp->da_ppriv_rpt = addr_priv;
532 	if (nvl)
533 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
534 	bitset_add(&mapp->dam_report_set, addrid);
535 	if (ridx)
536 		*ridx = (damap_id_t)addrid;
537 	mutex_exit(&mapp->dam_lock);
538 	return (DAM_SUCCESS);
539 }
540 
541 /*
542  * Commit full-set report for stabilization
543  *
544  * damapp:	address map handle
545  * flags:	(currently 0)
546  *
547  * Returns:	DAM_SUCCESS
548  *		DAM_EINVAL	Invalid argument(s)
549  *		DAM_FAILURE	General failure
550  */
551 int
552 damap_addrset_end(damap_t *damapp, int flags)
553 {
554 	dam_t *mapp = (dam_t *)damapp;
555 	int i;
556 
557 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
558 		return (DAM_EINVAL);
559 
560 	DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name,
561 	    dam_t *, mapp);
562 
563 	mutex_enter(&mapp->dam_lock);
564 	if (!(mapp->dam_flags & DAM_SETADD)) {
565 		mutex_exit(&mapp->dam_lock);
566 		return (DAM_FAILURE);
567 	}
568 
569 	if (flags & DAMAP_END_RESET) {
570 		DTRACE_PROBE2(damap__addrset__end__reset, char *,
571 		    mapp->dam_name, dam_t *, mapp);
572 		dam_sched_tmo(mapp, 0, NULL);
573 		for (i = 1; i < mapp->dam_high; i++)
574 			if (DAM_IN_REPORT(mapp, i))
575 				dam_addr_report_release(mapp, i);
576 	} else {
577 		mapp->dam_last_update = gethrtime();
578 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb);
579 	}
580 	mutex_exit(&mapp->dam_lock);
581 	return (DAM_SUCCESS);
582 }
583 
584 /*
585  * Return nvlist registered with reported address
586  *
587  * damapp:	address map handle
588  * addrid:	address ID
589  *
590  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
591  *		NULL
592  */
593 nvlist_t *
594 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
595 {
596 	dam_t *mapp = (dam_t *)damapp;
597 	dam_da_t *pass;
598 
599 	if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
600 		if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
601 			return (pass->da_nvl);
602 	}
603 	return (NULL);
604 }
605 
606 /*
607  * Return address string
608  *
609  * damapp:	address map handle
610  * addrid:	address ID
611  *
612  * Returns:	char *		Address string
613  *		NULL
614  */
615 char *
616 damap_id2addr(damap_t *damapp, damap_id_t addrid)
617 {
618 	dam_t *mapp = (dam_t *)damapp;
619 
620 	if (mapp->dam_high)
621 		return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
622 	else
623 		return (NULL);
624 }
625 
626 /*
627  * Release address reference in map
628  *
629  * damapp:	address map handle
630  * addrid:	address ID
631  */
632 void
633 damap_id_rele(damap_t *damapp, damap_id_t addrid)
634 {
635 	dam_t *mapp = (dam_t *)damapp;
636 	dam_da_t *passp;
637 	char *addr;
638 
639 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
640 	ASSERT(passp);
641 
642 	addr = damap_id2addr(damapp, addrid);
643 	DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr,
644 	    dam_t *, mapp, int, passp->da_ref);
645 
646 	mutex_enter(&mapp->dam_lock);
647 
648 	/*
649 	 * teardown address if last outstanding reference
650 	 */
651 	if (--passp->da_ref == 0)
652 		dam_addr_release(mapp, (id_t)addrid);
653 
654 	mutex_exit(&mapp->dam_lock);
655 }
656 
657 /*
658  * Return current reference count on address reference in map
659  *
660  * damapp:	address map handle
661  * addrid:	address ID
662  *
663  * Returns:	DAM_SUCCESS
664  *		DAM_FAILURE
665  */
666 int
667 damap_id_ref(damap_t *damapp, damap_id_t addrid)
668 {
669 	dam_t *mapp = (dam_t *)damapp;
670 	dam_da_t *passp;
671 	int ref = -1;
672 
673 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
674 	if (passp)
675 		ref = passp->da_ref;
676 
677 	return (ref);
678 }
679 
680 /*
681  * Return next address ID in list
682  *
683  * damapp:	address map handle
684  * damap_list:	address ID list passed to config|unconfig
685  *		returned by look by lookup_all
686  * last:	last ID returned, 0 is start of list
687  *
688  * Returns:	addrid		Next ID from the list
689  *		0		End of the list
690  */
691 damap_id_t
692 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
693 {
694 	int i, start;
695 	dam_t *mapp = (dam_t *)damapp;
696 	bitset_t *dam_list = (bitset_t *)damap_list;
697 
698 	if (!mapp || !dam_list)
699 		return ((damap_id_t)0);
700 
701 	start = (int)last + 1;
702 	for (i = start; i < mapp->dam_high; i++) {
703 		if (bitset_in_set(dam_list, i)) {
704 			return ((damap_id_t)i);
705 		}
706 	}
707 	return ((damap_id_t)0);
708 }
709 
710 /*
711  * Set config private data
712  *
713  * damapp:	address map handle
714  * addrid:	address ID
715  * cfg_priv:	configuration private data
716  *
717  */
718 void
719 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
720 {
721 	dam_t *mapp = (dam_t *)damapp;
722 	dam_da_t *passp;
723 
724 	mutex_enter(&mapp->dam_lock);
725 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
726 	if (!passp) {
727 		mutex_exit(&mapp->dam_lock);
728 		return;
729 	}
730 	passp->da_cfg_priv = cfg_priv;
731 	mutex_exit(&mapp->dam_lock);
732 }
733 
734 /*
735  * Get config private data
736  *
737  * damapp:	address map handle
738  * addrid:	address ID
739  *
740  * Returns:	configuration private data
741  */
742 void *
743 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
744 {
745 	dam_t *mapp = (dam_t *)damapp;
746 	dam_da_t *passp;
747 	void *rv;
748 
749 	mutex_enter(&mapp->dam_lock);
750 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
751 	if (!passp) {
752 		mutex_exit(&mapp->dam_lock);
753 		return (NULL);
754 	}
755 	rv = passp->da_cfg_priv;
756 	mutex_exit(&mapp->dam_lock);
757 	return (rv);
758 }
759 
760 /*
761  * Lookup a single address in the active address map
762  *
763  * damapp:	address map handle
764  * address:	address string
765  *
766  * Returns:	ID of active/stable address
767  *		0	Address not in stable set
768  *
769  * Future: Allow the caller to wait for stabilize before returning not found.
770  */
771 damap_id_t
772 damap_lookup(damap_t *damapp, char *address)
773 {
774 	dam_t *mapp = (dam_t *)damapp;
775 	id_t addrid = 0;
776 	dam_da_t *passp = NULL;
777 
778 	DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name,
779 	    char *, address, dam_t *, mapp);
780 	mutex_enter(&mapp->dam_lock);
781 	if (!mapp->dam_high)
782 		addrid = 0;
783 	else
784 		addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
785 	if (addrid) {
786 		if (DAM_IS_STABLE(mapp, addrid)) {
787 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
788 			ASSERT(passp);
789 			if (passp) {
790 				passp->da_ref++;
791 			} else {
792 				addrid = 0;
793 			}
794 		} else {
795 			addrid = 0;
796 		}
797 	}
798 	mutex_exit(&mapp->dam_lock);
799 	DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name,
800 	    char *, address, dam_t *, mapp, int, addrid);
801 	return ((damap_id_t)addrid);
802 }
803 
804 
805 /*
806  * Return the list of stable addresses in the map
807  *
808  * damapp:	address map handle
809  * id_listp:	pointer to list of address IDs in stable map (returned)
810  *
811  * Returns:	# of entries returned in alist
812  */
813 int
814 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
815 {
816 	dam_t *mapp = (dam_t *)damapp;
817 	int mapsz = mapp->dam_size;
818 	int n_ids, i;
819 	bitset_t *bsp;
820 	char	 *addrp;
821 	dam_da_t *passp;
822 
823 	DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name,
824 	    dam_t *, mapp);
825 	mutex_enter(&mapp->dam_lock);
826 	if (!mapp->dam_high) {
827 		*id_listp = (damap_id_list_t)NULL;
828 		mutex_exit(&mapp->dam_lock);
829 		DTRACE_PROBE3(damap__lookup__all__nomap, char *,
830 		    mapp->dam_name, dam_t *, mapp, int, 0);
831 		return (0);
832 	}
833 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
834 	bitset_init(bsp);
835 	bitset_resize(bsp, mapsz);
836 	bitset_copy(&mapp->dam_active_set, bsp);
837 	for (n_ids = 0, i = 1; i < mapsz; i++) {
838 		if (bitset_in_set(bsp, i)) {
839 			passp = ddi_get_soft_state(mapp->dam_da, i);
840 			ASSERT(passp);
841 			if (passp) {
842 				addrp = damap_id2addr(damapp, i);
843 				DTRACE_PROBE3(damap__lookup__all__item, char *,
844 				    mapp->dam_name, char *, addrp, dam_t *,
845 				    mapp);
846 				passp->da_ref++;
847 				n_ids++;
848 			}
849 		}
850 	}
851 	if (n_ids) {
852 		*id_listp = (damap_id_list_t)bsp;
853 		mutex_exit(&mapp->dam_lock);
854 		return (n_ids);
855 	} else {
856 		*id_listp = (damap_id_list_t)NULL;
857 		bitset_fini(bsp);
858 		kmem_free(bsp, sizeof (*bsp));
859 		mutex_exit(&mapp->dam_lock);
860 		return (0);
861 	}
862 }
863 
864 /*
865  * Release the address list returned by damap_lookup_all()
866  *
867  * mapp:	address map handle
868  * id_list:	list of address IDs returned in damap_lookup_all()
869  */
870 void
871 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
872 {
873 	dam_t *mapp = (dam_t *)damapp;
874 	int i;
875 
876 	if (id_list == NULL)
877 		return;
878 
879 	mutex_enter(&mapp->dam_lock);
880 	for (i = 1; i < mapp->dam_high; i++) {
881 		if (bitset_in_set((bitset_t *)id_list, i))
882 			(void) dam_addr_release(mapp, i);
883 	}
884 	mutex_exit(&mapp->dam_lock);
885 	bitset_fini((bitset_t *)id_list);
886 	kmem_free((void *)id_list, sizeof (bitset_t));
887 }
888 
889 /*
890  * activate an address that has passed the stabilization interval
891  */
892 static void
893 dam_addr_activate(dam_t *mapp, id_t addrid)
894 {
895 	dam_da_t *passp;
896 	int config_rv;
897 	char *addrstr;
898 
899 	mutex_enter(&mapp->dam_lock);
900 	bitset_add(&mapp->dam_active_set, addrid);
901 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
902 	ASSERT(passp);
903 
904 	/*
905 	 * copy the reported nvlist and provider private data
906 	 */
907 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
908 	DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name,
909 	    char *, addrstr, dam_t *, mapp);
910 	passp->da_nvl = passp->da_nvl_rpt;
911 	passp->da_ppriv = passp->da_ppriv_rpt;
912 	passp->da_ppriv_rpt = NULL;
913 	passp->da_nvl_rpt = NULL;
914 	passp->da_last_stable = gethrtime();
915 	passp->da_stable_cnt++;
916 	mutex_exit(&mapp->dam_lock);
917 	if (mapp->dam_activate_cb) {
918 		(*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
919 		    addrid, &passp->da_ppriv_rpt);
920 	}
921 
922 	/*
923 	 * call the address-specific configuration action as part of
924 	 * activation.
925 	 */
926 	config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
927 	    addrid);
928 	if (config_rv != DAM_SUCCESS) {
929 		mutex_enter(&mapp->dam_lock);
930 		passp->da_flags |= DA_FAILED_CONFIG;
931 		mutex_exit(&mapp->dam_lock);
932 		DTRACE_PROBE3(damap__addr__activate__config__failure,
933 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
934 		dam_deact_cleanup(mapp, addrid, addrstr,
935 		    DAMAP_DEACT_RSN_CFG_FAIL);
936 	} else {
937 		DTRACE_PROBE3(damap__addr__activate__end, char *,
938 		    mapp->dam_name, char *, addrstr, dam_t *, mapp);
939 	}
940 }
941 
942 /*
943  * deactivate a previously stable address
944  */
945 static void
946 dam_addr_deactivate(dam_t *mapp, id_t addrid)
947 {
948 	char *addrstr;
949 
950 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
951 	DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name,
952 	    char *, addrstr, dam_t *, mapp);
953 
954 	/*
955 	 * call the unconfiguration callback
956 	 */
957 	(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
958 	dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
959 }
960 
961 static void
962 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
963     damap_deact_rsn_t deact_rsn)
964 {
965 	dam_da_t *passp;
966 
967 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
968 	ASSERT(passp);
969 	if (mapp->dam_deactivate_cb)
970 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
971 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
972 		    addrid, passp->da_ppriv, deact_rsn);
973 
974 	/*
975 	 * clear the active bit and free the backing info for
976 	 * this address
977 	 */
978 	mutex_enter(&mapp->dam_lock);
979 	bitset_del(&mapp->dam_active_set, addrid);
980 	passp->da_ppriv = NULL;
981 	if (passp->da_nvl)
982 		nvlist_free(passp->da_nvl);
983 	passp->da_nvl = NULL;
984 	passp->da_ppriv_rpt = NULL;
985 	if (passp->da_nvl_rpt)
986 		nvlist_free(passp->da_nvl_rpt);
987 	passp->da_nvl_rpt = NULL;
988 
989 	DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name,
990 	    char *, addrstr, dam_t *, mapp);
991 
992 	(void) dam_addr_release(mapp, addrid);
993 	mutex_exit(&mapp->dam_lock);
994 }
995 
996 /*
997  * taskq callback for multi-thread activation
998  */
999 static void
1000 dam_tq_config(void *arg)
1001 {
1002 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1003 
1004 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1005 	kmem_free(tqd, sizeof (*tqd));
1006 }
1007 
1008 /*
1009  * taskq callback for multi-thread deactivation
1010  */
1011 static void
1012 dam_tq_unconfig(void *arg)
1013 {
1014 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1015 
1016 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1017 	kmem_free(tqd, sizeof (*tqd));
1018 }
1019 
1020 /*
1021  * Activate a set of stabilized addresses
1022  */
1023 static void
1024 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1025 {
1026 
1027 	int i, nset;
1028 	taskq_t *tqp = NULL;
1029 	cfg_tqd_t *tqd = NULL;
1030 	char tqn[TASKQ_NAMELEN];
1031 	extern pri_t maxclsyspri;
1032 
1033 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1034 		/*
1035 		 * calculate the # of taskq threads to create
1036 		 */
1037 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1038 			if (bitset_in_set(activate, i))
1039 				nset++;
1040 		ASSERT(nset);
1041 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1042 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1043 		    INT_MAX, TASKQ_PREPOPULATE);
1044 	}
1045 	for (i = 1; i < mapp->dam_high; i++) {
1046 		if (bitset_in_set(activate, i)) {
1047 			if (!tqp)
1048 				dam_addr_activate(mapp, i);
1049 			else {
1050 				/*
1051 				 * multi-threaded activation
1052 				 */
1053 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1054 				tqd->tqd_mapp = mapp;
1055 				tqd->tqd_id = i;
1056 				(void) taskq_dispatch(tqp, dam_tq_config,
1057 				    tqd, TQ_SLEEP);
1058 			}
1059 		}
1060 	}
1061 	if (tqp) {
1062 		taskq_wait(tqp);
1063 		taskq_destroy(tqp);
1064 	}
1065 }
1066 
1067 /*
1068  * Deactivate a set of stabilized addresses
1069  */
1070 static void
1071 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1072 {
1073 	int i, nset;
1074 	taskq_t *tqp = NULL;
1075 	cfg_tqd_t *tqd = NULL;
1076 	char tqn[TASKQ_NAMELEN];
1077 
1078 	DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name,
1079 	    dam_t *, mapp);
1080 
1081 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1082 		/*
1083 		 * compute the # of taskq threads to dispatch
1084 		 */
1085 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1086 			if (bitset_in_set(deactivate, i))
1087 				nset++;
1088 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1089 		    mapp->dam_name);
1090 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1091 		    INT_MAX, TASKQ_PREPOPULATE);
1092 	}
1093 	for (i = 1; i < mapp->dam_high; i++) {
1094 		if (bitset_in_set(deactivate, i)) {
1095 			if (!tqp) {
1096 				dam_addr_deactivate(mapp, i);
1097 			} else {
1098 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1099 				tqd->tqd_mapp = mapp;
1100 				tqd->tqd_id = i;
1101 				(void) taskq_dispatch(tqp,
1102 				    dam_tq_unconfig, tqd, TQ_SLEEP);
1103 			}
1104 		}
1105 	}
1106 
1107 	if (tqp) {
1108 		taskq_wait(tqp);
1109 		taskq_destroy(tqp);
1110 	}
1111 }
1112 
1113 /*
1114  * Release a previously activated address
1115  */
1116 static void
1117 dam_addr_release(dam_t *mapp, id_t addrid)
1118 {
1119 	dam_da_t *passp;
1120 	char	 *addrstr;
1121 
1122 
1123 	ASSERT(mutex_owned(&mapp->dam_lock));
1124 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1125 	ASSERT(passp);
1126 
1127 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1128 	DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name,
1129 	    char *, addrstr, dam_t *, mapp);
1130 
1131 	/*
1132 	 * defer releasing the address until outstanding references
1133 	 * are released
1134 	 */
1135 	if (passp->da_ref > 1) {
1136 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1137 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp,
1138 		    int, passp->da_ref);
1139 		return;
1140 	}
1141 
1142 	/*
1143 	 * allow pending reports to stabilize
1144 	 */
1145 	if (DAM_IN_REPORT(mapp, addrid)) {
1146 		DTRACE_PROBE3(damap__addr__release__report__pending,
1147 		    char *, mapp->dam_name, char *, addrstr, dam_t *, mapp);
1148 		return;
1149 	}
1150 
1151 	ddi_strid_free(mapp->dam_addr_hash, addrid);
1152 	ddi_soft_state_free(mapp->dam_da, addrid);
1153 }
1154 
1155 /*
1156  * process stabilized address reports
1157  */
1158 static void
1159 dam_stabilize_map(void *arg)
1160 {
1161 	dam_t *mapp = (dam_t *)arg;
1162 	bitset_t delta;
1163 	bitset_t cfg;
1164 	bitset_t uncfg;
1165 	int has_cfg, has_uncfg;
1166 	uint32_t i, n_active;
1167 
1168 	DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name,
1169 	    dam_t *, mapp);
1170 
1171 	bitset_init(&delta);
1172 	bitset_resize(&delta, mapp->dam_size);
1173 	bitset_init(&cfg);
1174 	bitset_resize(&cfg, mapp->dam_size);
1175 	bitset_init(&uncfg);
1176 	bitset_resize(&uncfg, mapp->dam_size);
1177 
1178 	/*
1179 	 * determine which addresses have changed during
1180 	 * this stabilization cycle
1181 	 */
1182 	mutex_enter(&mapp->dam_lock);
1183 	ASSERT(mapp->dam_flags & DAM_SPEND);
1184 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1185 	    &delta)) {
1186 		/*
1187 		 * no difference
1188 		 */
1189 		bitset_zero(&mapp->dam_stable_set);
1190 		mapp->dam_flags  &= ~DAM_SPEND;
1191 		cv_signal(&mapp->dam_cv);
1192 		mutex_exit(&mapp->dam_lock);
1193 		bitset_fini(&uncfg);
1194 		bitset_fini(&cfg);
1195 		bitset_fini(&delta);
1196 		DTRACE_PROBE2(damap__stabilize__map__nochange, char *,
1197 		    mapp->dam_name, dam_t *, mapp);
1198 		return;
1199 	}
1200 
1201 	/*
1202 	 * compute the sets of addresses to be activated and deactivated
1203 	 */
1204 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1205 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1206 
1207 	/*
1208 	 * drop map lock while invoking callouts
1209 	 */
1210 	mutex_exit(&mapp->dam_lock);
1211 
1212 	/*
1213 	 * activate all newly stable addresss
1214 	 */
1215 	if (has_cfg)
1216 		dam_addrset_activate(mapp, &cfg);
1217 
1218 	/*
1219 	 * deactivate addresss which are no longer in the map
1220 	 */
1221 	if (has_uncfg)
1222 		dam_addrset_deactivate(mapp, &uncfg);
1223 
1224 
1225 	/*
1226 	 * timestamp the last stable time and increment the kstat keeping
1227 	 * the # of of stable cycles for the map
1228 	 */
1229 	mutex_enter(&mapp->dam_lock);
1230 	bitset_zero(&mapp->dam_stable_set);
1231 	mapp->dam_last_stable = gethrtime();
1232 	mapp->dam_stable_cnt++;
1233 	DAM_INCR_STAT(mapp, dam_cycles);
1234 
1235 	/*
1236 	 * determine the number of stable addresses
1237 	 * and update the n_active kstat for this map
1238 	 */
1239 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1240 		if (bitset_in_set(&mapp->dam_active_set, i))
1241 			n_active++;
1242 	DAM_SET_STAT(mapp, dam_active, n_active);
1243 
1244 	DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name,
1245 	    dam_t *, mapp, int, n_active);
1246 
1247 	mapp->dam_flags  &= ~DAM_SPEND;
1248 	cv_signal(&mapp->dam_cv);
1249 	mutex_exit(&mapp->dam_lock);
1250 	bitset_fini(&uncfg);
1251 	bitset_fini(&cfg);
1252 	bitset_fini(&delta);
1253 }
1254 
1255 /*
1256  * per-address stabilization timeout
1257  */
1258 static void
1259 dam_addr_stable_cb(void *arg)
1260 {
1261 	dam_t *mapp = (dam_t *)arg;
1262 	int i;
1263 	dam_da_t *passp;
1264 	int spend = 0;
1265 	int tpend = 0;
1266 	int64_t	next_tmov = mapp->dam_stabletmo;
1267 	int64_t tmo_delta;
1268 	int64_t ts = ddi_get_lbolt64();
1269 
1270 	mutex_enter(&mapp->dam_lock);
1271 	if (mapp->dam_tid == 0) {
1272 		DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *,
1273 		    mapp->dam_name, dam_t *, mapp);
1274 		mutex_exit(&mapp->dam_lock);
1275 		return;
1276 	}
1277 	mapp->dam_tid = 0;
1278 
1279 	/*
1280 	 * If still under stabilization, reschedule timeout,
1281 	 * otherwise dispatch the task to activate and deactivate the
1282 	 * new stable address
1283 	 */
1284 	if (mapp->dam_flags & DAM_SPEND) {
1285 		DAM_INCR_STAT(mapp, dam_overrun);
1286 		mapp->dam_stable_overrun++;
1287 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
1288 		DTRACE_PROBE2(damap__map__addr__stable__overrun, char *,
1289 		    mapp->dam_name, dam_t *, mapp);
1290 		mutex_exit(&mapp->dam_lock);
1291 		return;
1292 	}
1293 
1294 	DAM_SET_STAT(mapp, dam_overrun, 0);
1295 	mapp->dam_stable_overrun = 0;
1296 
1297 	/*
1298 	 * copy the current active set to the stable map
1299 	 * for each address being reported, decrement its
1300 	 * stabilize deadline, and if stable, add or remove the
1301 	 * address from the stable set
1302 	 */
1303 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
1304 	for (i = 1; i < mapp->dam_high; i++) {
1305 		if (!bitset_in_set(&mapp->dam_report_set, i))
1306 			continue;
1307 		passp = ddi_get_soft_state(mapp->dam_da, i);
1308 		ASSERT(passp);
1309 
1310 		/* report has stabilized */
1311 		if (passp->da_deadline <= ts) {
1312 			bitset_del(&mapp->dam_report_set, i);
1313 			if (passp->da_flags & DA_RELE)
1314 				bitset_del(&mapp->dam_stable_set, i);
1315 			else
1316 				bitset_add(&mapp->dam_stable_set, i);
1317 			spend++;
1318 			continue;
1319 		}
1320 
1321 		/*
1322 		 * not stabilized, determine next map timeout
1323 		 */
1324 		tpend++;
1325 		tmo_delta = passp->da_deadline - ts;
1326 		if (tmo_delta < next_tmov)
1327 			next_tmov = tmo_delta;
1328 	}
1329 
1330 	/*
1331 	 * schedule system_taskq activation of stabilized reports
1332 	 */
1333 	if (spend) {
1334 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
1335 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1336 			mapp->dam_flags  |= DAM_SPEND;
1337 			DTRACE_PROBE2(damap__map__addr__stable__start, char *,
1338 			    mapp->dam_name, dam_t *, mapp);
1339 		} else {
1340 			tpend++;
1341 
1342 			/*
1343 			 * Avoid waiting the entire stabalization
1344 			 * time again if taskq_diskpatch fails.
1345 			 */
1346 			tmo_delta = drv_usectohz(
1347 			    damap_taskq_dispatch_retry_usec);
1348 			if (tmo_delta < next_tmov)
1349 				next_tmov = tmo_delta;
1350 		}
1351 	}
1352 
1353 	/*
1354 	 * reschedule the stabilization timer if there are reports
1355 	 * still pending
1356 	 */
1357 	if (tpend)
1358 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
1359 
1360 	mutex_exit(&mapp->dam_lock);
1361 }
1362 
1363 /*
1364  * fullset stabilization timeout callback
1365  */
1366 static void
1367 dam_addrset_stable_cb(void *arg)
1368 {
1369 	dam_t *mapp = (dam_t *)arg;
1370 
1371 	mutex_enter(&mapp->dam_lock);
1372 	if (mapp->dam_tid == 0) {
1373 		mutex_exit(&mapp->dam_lock);
1374 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1375 		    char *, mapp->dam_name, dam_t *, mapp);
1376 		return;
1377 	}
1378 	mapp->dam_tid = 0;
1379 
1380 	/*
1381 	 * If map still underoing stabilization reschedule timeout,
1382 	 * else dispatch the task to configure the new stable set of
1383 	 * addresses.
1384 	 */
1385 	if ((mapp->dam_flags & DAM_SPEND) ||
1386 	    (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1387 	    TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1388 		DAM_INCR_STAT(mapp, dam_overrun);
1389 		mapp->dam_stable_overrun++;
1390 		dam_sched_tmo(mapp,
1391 		    drv_usectohz(damap_taskq_dispatch_retry_usec),
1392 		    dam_addrset_stable_cb);
1393 
1394 		DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *,
1395 		    mapp->dam_name, dam_t *, mapp);
1396 		mutex_exit(&mapp->dam_lock);
1397 		return;
1398 	}
1399 
1400 	DAM_SET_STAT(mapp, dam_overrun, 0);
1401 	mapp->dam_stable_overrun = 0;
1402 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1403 	bitset_zero(&mapp->dam_report_set);
1404 	mapp->dam_flags |= DAM_SPEND;
1405 	mapp->dam_flags &= ~DAM_SETADD;
1406 	DTRACE_PROBE2(damap__map__addrset__stable__start, char *,
1407 	    mapp->dam_name, dam_t *, mapp);
1408 	mutex_exit(&mapp->dam_lock);
1409 }
1410 
1411 /*
1412  * schedule map timeout 'tmo_ms' ticks
1413  * if map timer is currently running, cancel if tmo_ms == 0
1414  */
1415 static void
1416 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
1417 {
1418 	timeout_id_t tid;
1419 
1420 	DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp,
1421 	    clock_t, tmo_ms);
1422 
1423 	ASSERT(mutex_owned(&mapp->dam_lock));
1424 	if ((tid = mapp->dam_tid) != 0) {
1425 		if (tmo_ms == 0) {
1426 			mapp->dam_tid = 0;
1427 			mutex_exit(&mapp->dam_lock);
1428 			(void) untimeout(tid);
1429 			mutex_enter(&mapp->dam_lock);
1430 		}
1431 	} else {
1432 		if (tmo_cb && (tmo_ms != 0))
1433 			mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
1434 	}
1435 }
1436 
1437 /*
1438  * report addition or removal of an address
1439  */
1440 static void
1441 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1442 {
1443 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1444 
1445 	DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name,
1446 	    char *, addrstr, dam_t *, mapp, int, rpt_type);
1447 
1448 	ASSERT(mutex_owned(&mapp->dam_lock));
1449 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
1450 	passp->da_last_report = gethrtime();
1451 	mapp->dam_last_update = gethrtime();
1452 	passp->da_report_cnt++;
1453 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo;
1454 	if (rpt_type == RPT_ADDR_DEL)
1455 		passp->da_flags |= DA_RELE;
1456 	else if (rpt_type == RPT_ADDR_ADD)
1457 		passp->da_flags &= ~DA_RELE;
1458 	bitset_add(&mapp->dam_report_set, addrid);
1459 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
1460 }
1461 
1462 /*
1463  * release an address report
1464  */
1465 static void
1466 dam_addr_report_release(dam_t *mapp, id_t addrid)
1467 {
1468 	dam_da_t *passp;
1469 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1470 
1471 	DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name,
1472 	    char *, addrstr, dam_t *, mapp);
1473 
1474 	ASSERT(mutex_owned(&mapp->dam_lock));
1475 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1476 	ASSERT(passp);
1477 	/*
1478 	 * clear the report bit
1479 	 * if the address has a registered deactivation handler and
1480 	 * we are holding a private data pointer and the address has not
1481 	 * stabilized, deactivate the address (private data).
1482 	 */
1483 	bitset_del(&mapp->dam_report_set, addrid);
1484 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1485 	    passp->da_ppriv_rpt) {
1486 		mutex_exit(&mapp->dam_lock);
1487 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1488 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1489 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1490 		mutex_enter(&mapp->dam_lock);
1491 	}
1492 	passp->da_ppriv_rpt = NULL;
1493 	if (passp->da_nvl_rpt)
1494 		nvlist_free(passp->da_nvl_rpt);
1495 }
1496 
1497 /*
1498  * return the map ID of an address
1499  */
1500 static id_t
1501 dam_get_addrid(dam_t *mapp, char *address)
1502 {
1503 	damap_id_t addrid;
1504 	dam_da_t *passp;
1505 
1506 	ASSERT(mutex_owned(&mapp->dam_lock));
1507 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1508 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1509 		    address)) == (damap_id_t)0) {
1510 			return (0);
1511 		}
1512 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1513 		    DDI_SUCCESS) {
1514 			ddi_strid_free(mapp->dam_addr_hash, addrid);
1515 			return (0);
1516 		}
1517 
1518 		if (addrid >= mapp->dam_high)
1519 			mapp->dam_high = addrid + 1;
1520 
1521 		/*
1522 		 * expand bitmaps if ID has outgrown old map size
1523 		 */
1524 		if (mapp->dam_high > mapp->dam_size) {
1525 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1526 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1527 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1528 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1529 		}
1530 
1531 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
1532 		passp->da_ref = 1;
1533 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1534 		    addrid); /* for mdb */
1535 	}
1536 	return (addrid);
1537 }
1538 
1539 /*
1540  * create and install map statistics
1541  */
1542 static int
1543 dam_kstat_create(dam_t *mapp)
1544 {
1545 	kstat_t			*mapsp;
1546 	struct dam_kstats	*statsp;
1547 
1548 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1549 	    KSTAT_TYPE_NAMED,
1550 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1551 
1552 	if (mapsp == NULL)
1553 		return (DDI_FAILURE);
1554 
1555 	statsp = (struct dam_kstats *)mapsp->ks_data;
1556 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1557 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1558 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1559 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1560 	kstat_install(mapsp);
1561 	mapp->dam_kstatsp = mapsp;
1562 	return (DDI_SUCCESS);
1563 }
1564