xref: /titanic_52/usr/src/uts/common/os/damap.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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 	if (passp->da_nvl)
1114 		nvlist_free(passp->da_nvl);
1115 	passp->da_nvl = NULL;
1116 	passp->da_ppriv_rpt = NULL;
1117 	if (passp->da_nvl_rpt)
1118 		nvlist_free(passp->da_nvl_rpt);
1119 	passp->da_nvl_rpt = NULL;
1120 
1121 	DTRACE_PROBE3(damap__addr__deactivate__end,
1122 	    char *, mapp->dam_name, dam_t *, mapp,
1123 	    char *, addrstr);
1124 
1125 	(void) dam_addr_release(mapp, addrid);
1126 	mutex_exit(&mapp->dam_lock);
1127 }
1128 
1129 /*
1130  * taskq callback for multi-thread activation
1131  */
1132 static void
1133 dam_tq_config(void *arg)
1134 {
1135 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1136 
1137 	dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1138 	kmem_free(tqd, sizeof (*tqd));
1139 }
1140 
1141 /*
1142  * taskq callback for multi-thread deactivation
1143  */
1144 static void
1145 dam_tq_unconfig(void *arg)
1146 {
1147 	cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1148 
1149 	dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1150 	kmem_free(tqd, sizeof (*tqd));
1151 }
1152 
1153 /*
1154  * Activate a set of stabilized addresses
1155  */
1156 static void
1157 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1158 {
1159 
1160 	int i, nset;
1161 	taskq_t *tqp = NULL;
1162 	cfg_tqd_t *tqd = NULL;
1163 	char tqn[TASKQ_NAMELEN];
1164 	extern pri_t maxclsyspri;
1165 
1166 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1167 		/*
1168 		 * calculate the # of taskq threads to create
1169 		 */
1170 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1171 			if (bitset_in_set(activate, i))
1172 				nset++;
1173 		ASSERT(nset);
1174 		(void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1175 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1176 		    INT_MAX, TASKQ_PREPOPULATE);
1177 	}
1178 	for (i = 1; i < mapp->dam_high; i++) {
1179 		if (bitset_in_set(activate, i)) {
1180 			if (!tqp)
1181 				dam_addr_activate(mapp, i);
1182 			else {
1183 				/*
1184 				 * multi-threaded activation
1185 				 */
1186 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1187 				tqd->tqd_mapp = mapp;
1188 				tqd->tqd_id = i;
1189 				(void) taskq_dispatch(tqp, dam_tq_config,
1190 				    tqd, TQ_SLEEP);
1191 			}
1192 		}
1193 	}
1194 	if (tqp) {
1195 		taskq_wait(tqp);
1196 		taskq_destroy(tqp);
1197 	}
1198 }
1199 
1200 /*
1201  * Deactivate a set of stabilized addresses
1202  */
1203 static void
1204 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1205 {
1206 	int i, nset;
1207 	taskq_t *tqp = NULL;
1208 	cfg_tqd_t *tqd = NULL;
1209 	char tqn[TASKQ_NAMELEN];
1210 
1211 	DTRACE_PROBE2(damap__addrset__deactivate,
1212 	    char *, mapp->dam_name, dam_t *, mapp);
1213 
1214 	if (mapp->dam_options & DAMAP_MTCONFIG) {
1215 		/*
1216 		 * compute the # of taskq threads to dispatch
1217 		 */
1218 		for (i = 1, nset = 0; i < mapp->dam_high; i++)
1219 			if (bitset_in_set(deactivate, i))
1220 				nset++;
1221 		(void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1222 		    mapp->dam_name);
1223 		tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1224 		    INT_MAX, TASKQ_PREPOPULATE);
1225 	}
1226 	for (i = 1; i < mapp->dam_high; i++) {
1227 		if (bitset_in_set(deactivate, i)) {
1228 			if (!tqp) {
1229 				dam_addr_deactivate(mapp, i);
1230 			} else {
1231 				tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1232 				tqd->tqd_mapp = mapp;
1233 				tqd->tqd_id = i;
1234 				(void) taskq_dispatch(tqp,
1235 				    dam_tq_unconfig, tqd, TQ_SLEEP);
1236 			}
1237 		}
1238 	}
1239 
1240 	if (tqp) {
1241 		taskq_wait(tqp);
1242 		taskq_destroy(tqp);
1243 	}
1244 }
1245 
1246 /*
1247  * Release a previously activated address
1248  */
1249 static void
1250 dam_addr_release(dam_t *mapp, id_t addrid)
1251 {
1252 	dam_da_t *passp;
1253 	char	 *addrstr;
1254 
1255 
1256 	ASSERT(mutex_owned(&mapp->dam_lock));
1257 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1258 	ASSERT(passp);
1259 
1260 	addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1261 	DTRACE_PROBE3(damap__addr__release,
1262 	    char *, mapp->dam_name, dam_t *, mapp,
1263 	    char *, addrstr);
1264 
1265 	/*
1266 	 * defer releasing the address until outstanding references
1267 	 * are released
1268 	 */
1269 	if (passp->da_ref > 1) {
1270 		DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1271 		    char *, mapp->dam_name, dam_t *, mapp,
1272 		    char *, addrstr, int, passp->da_ref);
1273 		return;
1274 	}
1275 
1276 	/*
1277 	 * allow pending reports to stabilize
1278 	 */
1279 	if (DAM_IN_REPORT(mapp, addrid)) {
1280 		DTRACE_PROBE3(damap__addr__release__report__pending,
1281 		    char *, mapp->dam_name, dam_t *, mapp,
1282 		    char *, addrstr);
1283 		return;
1284 	}
1285 
1286 	ddi_strid_free(mapp->dam_addr_hash, addrid);
1287 	ddi_soft_state_free(mapp->dam_da, addrid);
1288 }
1289 
1290 /*
1291  * process stabilized address reports
1292  */
1293 static void
1294 dam_stabilize_map(void *arg)
1295 {
1296 	dam_t *mapp = (dam_t *)arg;
1297 	bitset_t delta;
1298 	bitset_t cfg;
1299 	bitset_t uncfg;
1300 	int has_cfg, has_uncfg;
1301 	uint32_t i, n_active;
1302 
1303 	DTRACE_PROBE2(damap__stabilize__map,
1304 	    char *, mapp->dam_name, dam_t *, mapp);
1305 
1306 	bitset_init(&delta);
1307 	bitset_resize(&delta, mapp->dam_size);
1308 	bitset_init(&cfg);
1309 	bitset_resize(&cfg, mapp->dam_size);
1310 	bitset_init(&uncfg);
1311 	bitset_resize(&uncfg, mapp->dam_size);
1312 
1313 	/*
1314 	 * determine which addresses have changed during
1315 	 * this stabilization cycle
1316 	 */
1317 	mutex_enter(&mapp->dam_lock);
1318 	ASSERT(mapp->dam_flags & DAM_SPEND);
1319 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1320 	    &delta)) {
1321 		/*
1322 		 * no difference
1323 		 */
1324 		bitset_zero(&mapp->dam_stable_set);
1325 		mapp->dam_flags &= ~DAM_SPEND;
1326 		cv_signal(&mapp->dam_sync_cv);
1327 		mutex_exit(&mapp->dam_lock);
1328 
1329 		bitset_fini(&uncfg);
1330 		bitset_fini(&cfg);
1331 		bitset_fini(&delta);
1332 		DTRACE_PROBE2(damap__stabilize__map__nochange,
1333 		    char *, mapp->dam_name, dam_t *, mapp);
1334 		return;
1335 	}
1336 
1337 	/*
1338 	 * compute the sets of addresses to be activated and deactivated
1339 	 */
1340 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1341 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1342 
1343 	/*
1344 	 * drop map lock while invoking callouts
1345 	 */
1346 	mutex_exit(&mapp->dam_lock);
1347 
1348 	/*
1349 	 * activate all newly stable addresss
1350 	 */
1351 	if (has_cfg)
1352 		dam_addrset_activate(mapp, &cfg);
1353 
1354 	/*
1355 	 * deactivate addresss which are no longer in the map
1356 	 */
1357 	if (has_uncfg)
1358 		dam_addrset_deactivate(mapp, &uncfg);
1359 
1360 
1361 	/*
1362 	 * timestamp the last stable time and increment the kstat keeping
1363 	 * the # of of stable cycles for the map
1364 	 */
1365 	mutex_enter(&mapp->dam_lock);
1366 	bitset_zero(&mapp->dam_stable_set);
1367 	mapp->dam_last_stable = gethrtime();
1368 	mapp->dam_stable_cnt++;
1369 	DAM_INCR_STAT(mapp, dam_cycles);
1370 
1371 	/*
1372 	 * determine the number of stable addresses
1373 	 * and update the n_active kstat for this map
1374 	 */
1375 	for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1376 		if (bitset_in_set(&mapp->dam_active_set, i))
1377 			n_active++;
1378 	DAM_SET_STAT(mapp, dam_active, n_active);
1379 
1380 	DTRACE_PROBE3(damap__map__stable__end,
1381 	    char *, mapp->dam_name, dam_t *, mapp,
1382 	    int, n_active);
1383 
1384 	mapp->dam_flags &= ~DAM_SPEND;
1385 	cv_signal(&mapp->dam_sync_cv);
1386 	mutex_exit(&mapp->dam_lock);
1387 
1388 	bitset_fini(&uncfg);
1389 	bitset_fini(&cfg);
1390 	bitset_fini(&delta);
1391 }
1392 
1393 /*
1394  * per-address stabilization timeout
1395  */
1396 static void
1397 dam_addr_stable_cb(void *arg)
1398 {
1399 	dam_t *mapp = (dam_t *)arg;
1400 	int i;
1401 	dam_da_t *passp;
1402 	int spend = 0;
1403 	int tpend = 0;
1404 	int64_t ts, next_ticks, delta_ticks;
1405 
1406 	mutex_enter(&mapp->dam_lock);
1407 	if (mapp->dam_tid == 0) {
1408 		DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1409 		    char *, mapp->dam_name, dam_t *, mapp);
1410 		mutex_exit(&mapp->dam_lock);
1411 		return;
1412 	}
1413 	mapp->dam_tid = 0;
1414 
1415 	/*
1416 	 * If still under stabilization, reschedule timeout,
1417 	 * otherwise dispatch the task to activate and deactivate the
1418 	 * new stable address
1419 	 */
1420 	if (mapp->dam_flags & DAM_SPEND) {
1421 		DAM_INCR_STAT(mapp, dam_overrun);
1422 		mapp->dam_stable_overrun++;
1423 		DTRACE_PROBE2(damap__map__addr__stable__overrun,
1424 		    char *, mapp->dam_name, dam_t *, mapp);
1425 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1426 		    mapp->dam_stable_ticks);
1427 		mutex_exit(&mapp->dam_lock);
1428 		return;
1429 	}
1430 
1431 	DAM_SET_STAT(mapp, dam_overrun, 0);
1432 	mapp->dam_stable_overrun = 0;
1433 
1434 	/* See if any reports stabalized and compute next timeout. */
1435 	ts = ddi_get_lbolt64();
1436 	next_ticks = mapp->dam_stable_ticks;
1437 	for (i = 1; i < mapp->dam_high; i++) {
1438 		if (bitset_in_set(&mapp->dam_report_set, i)) {
1439 			passp = ddi_get_soft_state(mapp->dam_da, i);
1440 			ASSERT(passp);
1441 
1442 			if (passp->da_deadline <= ts)
1443 				spend++;	/* report has stabilized */
1444 			else {
1445 				/* not stabilized, determine next map timeout */
1446 				tpend++;
1447 				delta_ticks = passp->da_deadline - ts;
1448 				if (delta_ticks < next_ticks)
1449 					next_ticks = delta_ticks;
1450 			}
1451 		}
1452 	}
1453 
1454 	/*
1455 	 * schedule system_taskq activation of stabilized reports
1456 	 */
1457 	if (spend) {
1458 		if (taskq_dispatch(system_taskq, dam_stabilize_map,
1459 		    mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1460 			DTRACE_PROBE2(damap__map__addr__stable__start,
1461 			    char *, mapp->dam_name, dam_t *, mapp);
1462 
1463 			/*
1464 			 * The stable_set we compute below stays pending until
1465 			 * processed by dam_stabilize_map. We can't set
1466 			 * DAM_SPEND (or bitset_del things from the
1467 			 * report_set) until we *know* that we can handoff the
1468 			 * result to dam_stabilize_map. If dam_stabilize_map
1469 			 * starts executing before we are complete, it will
1470 			 * block on the dam_lock mutex until we are ready.
1471 			 */
1472 			mapp->dam_flags |= DAM_SPEND;
1473 
1474 			/*
1475 			 * Copy the current active_set to the stable_set, then
1476 			 * add or remove stabilized report_set address from
1477 			 * the stable set (and delete them from the report_set).
1478 			 */
1479 			bitset_copy(&mapp->dam_active_set,
1480 			    &mapp->dam_stable_set);
1481 			for (i = 1; i < mapp->dam_high; i++) {
1482 				if (!bitset_in_set(&mapp->dam_report_set, i))
1483 					continue;
1484 
1485 				passp = ddi_get_soft_state(mapp->dam_da, i);
1486 				if (passp->da_deadline > ts)
1487 					continue; /* report not stabilized */
1488 
1489 				/* report has stabilized */
1490 				if (passp->da_flags & DA_RELE)
1491 					bitset_del(&mapp->dam_stable_set, i);
1492 				else
1493 					bitset_add(&mapp->dam_stable_set, i);
1494 
1495 				bitset_del(&mapp->dam_report_set, i);
1496 			}
1497 		} else {
1498 			DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1499 			    char *, mapp->dam_name, dam_t *, mapp);
1500 
1501 			/*
1502 			 * Avoid waiting the entire stabalization
1503 			 * time again if taskq_diskpatch fails.
1504 			 */
1505 			tpend++;
1506 			delta_ticks = drv_usectohz(
1507 			    damap_taskq_dispatch_retry_usec);
1508 			if (delta_ticks < next_ticks)
1509 				next_ticks = delta_ticks;
1510 		}
1511 	}
1512 
1513 	/*
1514 	 * reschedule the stabilization timer if there are reports
1515 	 * still pending
1516 	 */
1517 	if (tpend) {
1518 		DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1519 		    mapp->dam_name, dam_t *, mapp);
1520 		dam_sched_timeout(dam_addr_stable_cb, mapp,
1521 		    (clock_t)next_ticks);
1522 	}
1523 
1524 	mutex_exit(&mapp->dam_lock);
1525 }
1526 
1527 /*
1528  * fullset stabilization timeout callback
1529  */
1530 static void
1531 dam_addrset_stable_cb(void *arg)
1532 {
1533 	dam_t *mapp = (dam_t *)arg;
1534 
1535 	mutex_enter(&mapp->dam_lock);
1536 	if (mapp->dam_tid == 0) {
1537 		mutex_exit(&mapp->dam_lock);
1538 		DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1539 		    char *, mapp->dam_name, dam_t *, mapp);
1540 		return;
1541 	}
1542 	mapp->dam_tid = 0;
1543 
1544 	/*
1545 	 * If map still underoing stabilization reschedule timeout,
1546 	 * else dispatch the task to configure the new stable set of
1547 	 * addresses.
1548 	 */
1549 	if ((mapp->dam_flags & DAM_SPEND) ||
1550 	    (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1551 	    TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1552 		DAM_INCR_STAT(mapp, dam_overrun);
1553 		mapp->dam_stable_overrun++;
1554 		dam_sched_timeout(dam_addrset_stable_cb, mapp,
1555 		    drv_usectohz(damap_taskq_dispatch_retry_usec));
1556 
1557 		DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1558 		    char *, mapp->dam_name, dam_t *, mapp);
1559 		mutex_exit(&mapp->dam_lock);
1560 		return;
1561 	}
1562 
1563 	DAM_SET_STAT(mapp, dam_overrun, 0);
1564 	mapp->dam_stable_overrun = 0;
1565 	bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1566 	bitset_zero(&mapp->dam_report_set);
1567 	mapp->dam_flags |= DAM_SPEND;
1568 	mapp->dam_flags &= ~DAM_SETADD;
1569 	/* NOTE: don't need cv_signal since DAM_SPEND is still set */
1570 
1571 	DTRACE_PROBE2(damap__map__addrset__stable__start,
1572 	    char *, mapp->dam_name, dam_t *, mapp);
1573 	mutex_exit(&mapp->dam_lock);
1574 }
1575 
1576 /*
1577  * schedule map timeout in 'ticks' ticks
1578  * if map timer is currently running, cancel if ticks == 0
1579  */
1580 static void
1581 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1582 {
1583 	timeout_id_t tid;
1584 
1585 	DTRACE_PROBE4(damap__sched__timeout,
1586 	    char *, mapp->dam_name, dam_t *, mapp,
1587 	    int, ticks, timeout_id_t, mapp->dam_tid);
1588 
1589 	ASSERT(mutex_owned(&mapp->dam_lock));
1590 	if ((tid = mapp->dam_tid) != 0) {
1591 		if (ticks == 0) {
1592 			mapp->dam_tid = 0;
1593 			mutex_exit(&mapp->dam_lock);
1594 			(void) untimeout(tid);
1595 			mutex_enter(&mapp->dam_lock);
1596 		}
1597 	} else {
1598 		if (timeout_cb && (ticks != 0))
1599 			mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1600 	}
1601 }
1602 
1603 /*
1604  * report addition or removal of an address
1605  */
1606 static void
1607 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1608 {
1609 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1610 
1611 	DTRACE_PROBE4(damap__addr__report,
1612 	    char *, mapp->dam_name, dam_t *, mapp,
1613 	    char *, addrstr, int, rpt_type);
1614 
1615 	ASSERT(mutex_owned(&mapp->dam_lock));
1616 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
1617 	passp->da_last_report = gethrtime();
1618 	mapp->dam_last_update = gethrtime();
1619 	passp->da_report_cnt++;
1620 	passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1621 	if (rpt_type == RPT_ADDR_DEL)
1622 		passp->da_flags |= DA_RELE;
1623 	else if (rpt_type == RPT_ADDR_ADD)
1624 		passp->da_flags &= ~DA_RELE;
1625 	bitset_add(&mapp->dam_report_set, addrid);
1626 	dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1627 }
1628 
1629 /*
1630  * release an address report
1631  */
1632 static void
1633 dam_addr_report_release(dam_t *mapp, id_t addrid)
1634 {
1635 	dam_da_t *passp;
1636 	char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1637 
1638 	DTRACE_PROBE3(damap__addr__report__release,
1639 	    char *, mapp->dam_name, dam_t *, mapp,
1640 	    char *, addrstr);
1641 
1642 	ASSERT(mutex_owned(&mapp->dam_lock));
1643 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1644 	ASSERT(passp);
1645 	/*
1646 	 * clear the report bit
1647 	 * if the address has a registered deactivation handler and
1648 	 * we are holding a private data pointer and the address has not
1649 	 * stabilized, deactivate the address (private data).
1650 	 */
1651 	bitset_del(&mapp->dam_report_set, addrid);
1652 	if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1653 	    passp->da_ppriv_rpt) {
1654 		mutex_exit(&mapp->dam_lock);
1655 		(*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1656 		    ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1657 		    addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1658 		mutex_enter(&mapp->dam_lock);
1659 	}
1660 	passp->da_ppriv_rpt = NULL;
1661 	if (passp->da_nvl_rpt)
1662 		nvlist_free(passp->da_nvl_rpt);
1663 }
1664 
1665 /*
1666  * return the map ID of an address
1667  */
1668 static id_t
1669 dam_get_addrid(dam_t *mapp, char *address)
1670 {
1671 	damap_id_t addrid;
1672 	dam_da_t *passp;
1673 
1674 	ASSERT(mutex_owned(&mapp->dam_lock));
1675 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1676 		if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1677 		    address)) == (damap_id_t)0) {
1678 			return (0);
1679 		}
1680 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1681 		    DDI_SUCCESS) {
1682 			ddi_strid_free(mapp->dam_addr_hash, addrid);
1683 			return (0);
1684 		}
1685 
1686 		if (addrid >= mapp->dam_high)
1687 			mapp->dam_high = addrid + 1;
1688 
1689 		/*
1690 		 * expand bitmaps if ID has outgrown old map size
1691 		 */
1692 		if (mapp->dam_high > mapp->dam_size) {
1693 			mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1694 			bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1695 			bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1696 			bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1697 		}
1698 
1699 		passp = ddi_get_soft_state(mapp->dam_da, addrid);
1700 		passp->da_ref = 1;
1701 		passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1702 		    addrid); /* for mdb */
1703 	}
1704 	return (addrid);
1705 }
1706 
1707 /*
1708  * create and install map statistics
1709  */
1710 static int
1711 dam_kstat_create(dam_t *mapp)
1712 {
1713 	kstat_t			*mapsp;
1714 	struct dam_kstats	*statsp;
1715 
1716 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1717 	    KSTAT_TYPE_NAMED,
1718 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1719 
1720 	if (mapsp == NULL)
1721 		return (DDI_FAILURE);
1722 
1723 	statsp = (struct dam_kstats *)mapsp->ks_data;
1724 	kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1725 	kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1726 	kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1727 	kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1728 	kstat_install(mapsp);
1729 	mapp->dam_kstatsp = mapsp;
1730 	return (DDI_SUCCESS);
1731 }
1732