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