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