Merge commit '7e934d3acc051b7ee3ef0d11571fd1225800a607'
[unleashed.git] / kernel / os / damap.c
blob52fad785f556d3e77e26afd770134cb8da2fb70a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
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>
47 #ifdef DEBUG
48 static int damap_debug = 0;
49 #endif /* DEBUG */
51 extern taskq_t *system_taskq;
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 *);
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++; \
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); \
82 * increase damap size by 64 entries at a time
84 #define DAM_SIZE_BUMP 64
86 int damap_taskq_dispatch_retry_usec = 1000;
89 * config/unconfig taskq data
91 typedef struct {
92 dam_t *tqd_mapp;
93 id_t tqd_id;
94 } cfg_tqd_t;
96 extern pri_t maxclsyspri;
99 * Create new device address map
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
106 * activate_arg: address provider activation-callout private
107 * activate_cb: address provider activation callback handler
108 * deactivate_cb: address provider deactivation callback handler
110 * config_arg: configuration-callout private
111 * config_cb: class configuration callout
112 * unconfig_cb: class unconfiguration callout
114 * damapp: pointer to map handle (return)
116 * Returns: DAM_SUCCESS
117 * DAM_EINVAL Invalid argument(s)
118 * DAM_FAILURE General failure
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)
128 dam_t *mapp;
130 if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
131 return (DAM_EINVAL);
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;
152 DTRACE_PROBE5(damap__create,
153 char *, mapp->dam_name, damap_t *, mapp,
154 damap_rptmode_t, mode, int, map_opts, int, stable_usec);
156 return (DAM_SUCCESS);
160 * Allocate backing resources
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.
166 static int
167 dam_map_alloc(dam_t *mapp)
169 void *softstate_p;
171 ASSERT(mutex_owned(&mapp->dam_lock));
172 if (mapp->dam_flags & DAM_DESTROYPEND)
173 return (DAM_FAILURE);
176 * dam_high > 0 signals map allocation complete
178 if (mapp->dam_high)
179 return (DAM_SUCCESS);
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);
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);
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);
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);
205 * Destroy address map
207 * damapp: address map
209 * Returns: DAM_SUCCESS
210 * DAM_EINVAL Invalid argument(s)
211 * DAM_FAILURE General failure
213 void
214 damap_destroy(damap_t *damapp)
216 int i;
217 dam_t *mapp = (dam_t *)damapp;
219 ASSERT(mapp);
221 DTRACE_PROBE2(damap__destroy,
222 char *, mapp->dam_name, damap_t *, mapp);
224 mutex_enter(&mapp->dam_lock);
227 * prevent new reports from being added to the map
229 mapp->dam_flags |= DAM_DESTROYPEND;
231 if (mapp->dam_high) {
232 mutex_exit(&mapp->dam_lock);
234 * wait for outstanding reports to stabilize and cancel
235 * the timer for this map
237 (void) damap_sync(damapp, 0);
238 mutex_enter(&mapp->dam_lock);
239 dam_sched_timeout(NULL, mapp, 0);
242 * map is at full stop
243 * release the contents of the map, invoking the
244 * detactivation protocol as addresses are released
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;
251 ASSERT(DAM_IN_REPORT(mapp, i) == 0);
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);
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);
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));
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.
282 * damapp: address map
283 * sync_usec: micorseconds until we give up on sync completion.
285 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
287 damap_sync(damap_t *damapp, int sync_usec)
289 dam_t *mapp = (dam_t *)damapp;
290 int rv;
292 ASSERT(mapp);
293 DTRACE_PROBE3(damap__map__sync__start,
294 char *, mapp->dam_name, dam_t *, mapp,
295 int, sync_usec);
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
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);
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;
319 } else
320 cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
323 if (rv) {
325 * Delay one stabilization time after the apparent sync above
326 * and verify accuracy - resync if not accurate.
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;
335 mutex_exit(&mapp->dam_lock);
337 DTRACE_PROBE3(damap__map__sync__end,
338 char *, mapp->dam_name, dam_t *, mapp,
339 int, rv);
340 return (rv);
344 * Return 1 if active set is empty
347 damap_is_empty(damap_t *damapp)
349 dam_t *mapp = (dam_t *)damapp;
350 int rv;
352 mutex_enter(&mapp->dam_lock);
353 rv = bitset_is_null(&mapp->dam_active_set);
354 mutex_exit(&mapp->dam_lock);
355 return (rv);
359 * Get the name of a device address map
361 * damapp: address map
363 * Returns: name
365 char *
366 damap_name(damap_t *damapp)
368 dam_t *mapp = (dam_t *)damapp;
370 return (mapp ? mapp->dam_name : "UNKNOWN_damap");
374 * Get the current size of the device address map
376 * damapp: address map
378 * Returns: size
381 damap_size(damap_t *damapp)
383 dam_t *mapp = (dam_t *)damapp;
385 return (mapp->dam_size);
389 * Report an address to per-address report
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)
397 * Returns: DAM_SUCCESS
398 * DAM_EINVAL Invalid argument(s)
399 * DAM_MAPFULL address map exhausted
402 damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
403 nvlist_t *nvl, void *addr_priv)
405 dam_t *mapp = (dam_t *)damapp;
406 id_t addrid;
407 dam_da_t *passp;
409 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
410 return (DAM_EINVAL);
412 DTRACE_PROBE3(damap__addr__add,
413 char *, mapp->dam_name, dam_t *, mapp,
414 char *, address);
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);
423 passp = ddi_get_soft_state(mapp->dam_da, addrid);
424 ASSERT(passp != NULL);
427 * If re-reporting the same address (add or remove) clear
428 * the existing report
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++;
438 passp->da_ppriv_rpt = addr_priv;
439 if (nvl)
440 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
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);
450 * Report removal of address from per-address report
452 * damapp: address map
453 * address: address in ascii string representation
455 * Returns: DAM_SUCCESS
456 * DAM_EINVAL Invalid argument(s)
457 * DAM_FAILURE General failure
460 damap_addr_del(damap_t *damapp, char *address)
462 dam_t *mapp = (dam_t *)damapp;
463 id_t addrid;
464 dam_da_t *passp;
466 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
467 return (DAM_EINVAL);
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);
479 * if reporting the removal of an address which is not in the map
480 * return success
482 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
483 mutex_exit(&mapp->dam_lock);
484 return (DAM_SUCCESS);
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++;
496 dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
497 mutex_exit(&mapp->dam_lock);
498 return (DAM_SUCCESS);
501 static int
502 damap_addrset_flush_locked(damap_t *damapp)
504 dam_t *mapp = (dam_t *)damapp;
505 int idx;
507 ASSERT(mapp);
508 ASSERT(mutex_owned(&mapp->dam_lock));
509 if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
510 return (DAM_EINVAL);
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);
520 * cancel stabilization timeout
522 dam_sched_timeout(NULL, mapp, 0);
523 DAM_INCR_STAT(mapp, dam_jitter);
526 * clear pending reports
528 for (idx = 1; idx < mapp->dam_high; idx++) {
529 if (DAM_IN_REPORT(mapp, idx)) {
530 dam_addr_report_release(mapp, idx);
534 bitset_zero(&mapp->dam_report_set);
535 mapp->dam_flags &= ~DAM_SETADD;
536 cv_signal(&mapp->dam_sync_cv);
539 return (DAM_SUCCESS);
543 * Initiate full-set report
545 * damapp: address map
547 * Returns: DAM_SUCCESS
548 * DAM_EINVAL Invalid argument(s)
551 damap_addrset_begin(damap_t *damapp)
553 dam_t *mapp = (dam_t *)damapp;
554 int rv;
556 if (mapp == NULL) {
557 return (DAM_EINVAL);
560 DTRACE_PROBE2(damap__addrset__begin,
561 char *, mapp->dam_name, dam_t *, mapp);
563 mutex_enter(&mapp->dam_lock);
564 if (dam_map_alloc(mapp) != DAM_SUCCESS) {
565 mutex_exit(&mapp->dam_lock);
567 return (DAM_MAPFULL);
570 rv = damap_addrset_flush_locked(damapp);
571 if (rv == DAM_SUCCESS) {
572 mapp->dam_flags |= DAM_SETADD;
574 mutex_exit(&mapp->dam_lock);
576 return (rv);
580 * Cancel full-set report
582 * damapp: address map
584 * Returns: DAM_SUCCESS
585 * DAM_EINVAL Invalid argument(s)
588 damap_addrset_flush(damap_t *damapp)
590 int rv;
591 dam_t *mapp = (dam_t *)damapp;
593 if (mapp == NULL) {
594 return (DAM_EINVAL);
597 DTRACE_PROBE2(damap__addrset__flush,
598 char *, mapp->dam_name, dam_t *, mapp);
600 mutex_enter(&mapp->dam_lock);
601 rv = damap_addrset_flush_locked(damapp);
602 mutex_exit(&mapp->dam_lock);
604 return (rv);
608 * Report address to full-set report
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)
616 * Returns: DAM_SUCCESS
617 * DAM_EINVAL Invalid argument(s)
618 * DAM_MAPFULL address map exhausted
619 * DAM_FAILURE General failure
622 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
623 nvlist_t *nvl, void *addr_priv)
625 dam_t *mapp = (dam_t *)damapp;
626 id_t addrid;
627 dam_da_t *passp;
629 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
630 return (DAM_EINVAL);
632 DTRACE_PROBE3(damap__addrset__add,
633 char *, mapp->dam_name, dam_t *, mapp, char *, address);
635 mutex_enter(&mapp->dam_lock);
636 if (!(mapp->dam_flags & DAM_SETADD)) {
637 mutex_exit(&mapp->dam_lock);
638 return (DAM_FAILURE);
641 if ((addrid = dam_get_addrid(mapp, address)) == 0) {
642 mutex_exit(&mapp->dam_lock);
643 return (DAM_MAPFULL);
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++;
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);
666 * Commit full-set report for stabilization
668 * damapp: address map handle
669 * flags: (currently 0)
671 * Returns: DAM_SUCCESS
672 * DAM_EINVAL Invalid argument(s)
673 * DAM_FAILURE General failure
676 damap_addrset_end(damap_t *damapp, int flags)
678 dam_t *mapp = (dam_t *)damapp;
679 int i;
681 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
682 return (DAM_EINVAL);
684 DTRACE_PROBE2(damap__addrset__end,
685 char *, mapp->dam_name, dam_t *, mapp);
687 mutex_enter(&mapp->dam_lock);
688 if (!(mapp->dam_flags & DAM_SETADD)) {
689 mutex_exit(&mapp->dam_lock);
690 return (DAM_FAILURE);
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);
705 mutex_exit(&mapp->dam_lock);
706 return (DAM_SUCCESS);
710 * Return nvlist registered with reported address
712 * damapp: address map handle
713 * addrid: address ID
715 * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
716 * NULL
718 nvlist_t *
719 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
721 dam_t *mapp = (dam_t *)damapp;
722 dam_da_t *pass;
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);
728 return (NULL);
732 * Return address string
734 * damapp: address map handle
735 * addrid: address ID
737 * Returns: char * Address string
738 * NULL
740 char *
741 damap_id2addr(damap_t *damapp, damap_id_t addrid)
743 dam_t *mapp = (dam_t *)damapp;
745 if (mapp->dam_high)
746 return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
747 else
748 return (NULL);
752 * Release address reference in map
754 * damapp: address map handle
755 * addrid: address ID
757 void
758 damap_id_rele(damap_t *damapp, damap_id_t addrid)
760 dam_t *mapp = (dam_t *)damapp;
761 dam_da_t *passp;
762 char *addr;
764 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
765 ASSERT(passp);
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);
772 mutex_enter(&mapp->dam_lock);
775 * teardown address if last outstanding reference
777 if (--passp->da_ref == 0)
778 dam_addr_release(mapp, (id_t)addrid);
780 mutex_exit(&mapp->dam_lock);
784 * Return current reference count on address reference in map
786 * damapp: address map handle
787 * addrid: address ID
789 * Returns: DAM_SUCCESS
790 * DAM_FAILURE
793 damap_id_ref(damap_t *damapp, damap_id_t addrid)
795 dam_t *mapp = (dam_t *)damapp;
796 dam_da_t *passp;
797 int ref = -1;
799 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
800 if (passp)
801 ref = passp->da_ref;
803 return (ref);
807 * Return next address ID in list
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
814 * Returns: addrid Next ID from the list
815 * 0 End of the list
817 damap_id_t
818 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
820 int i, start;
821 dam_t *mapp = (dam_t *)damapp;
822 bitset_t *dam_list = (bitset_t *)damap_list;
824 if (!mapp || !dam_list)
825 return ((damap_id_t)0);
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);
833 return ((damap_id_t)0);
837 * Set config private data
839 * damapp: address map handle
840 * addrid: address ID
841 * cfg_priv: configuration private data
844 void
845 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
847 dam_t *mapp = (dam_t *)damapp;
848 dam_da_t *passp;
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;
856 passp->da_cfg_priv = cfg_priv;
857 mutex_exit(&mapp->dam_lock);
861 * Get config private data
863 * damapp: address map handle
864 * addrid: address ID
866 * Returns: configuration private data
868 void *
869 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
871 dam_t *mapp = (dam_t *)damapp;
872 dam_da_t *passp;
873 void *rv;
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);
881 rv = passp->da_cfg_priv;
882 mutex_exit(&mapp->dam_lock);
883 return (rv);
887 * Lookup a single address in the active address map
889 * damapp: address map handle
890 * address: address string
892 * Returns: ID of active/stable address
893 * 0 Address not in stable set
895 * Future: Allow the caller to wait for stabilize before returning not found.
897 damap_id_t
898 damap_lookup(damap_t *damapp, char *address)
900 dam_t *mapp = (dam_t *)damapp;
901 id_t addrid = 0;
902 dam_da_t *passp = NULL;
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;
921 } else {
922 addrid = 0;
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);
934 * Return the list of stable addresses in the map
936 * damapp: address map handle
937 * id_listp: pointer to list of address IDs in stable map (returned)
939 * Returns: # of entries returned in alist
942 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
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;
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);
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++;
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);
993 * Release the address list returned by damap_lookup_all()
995 * mapp: address map handle
996 * id_list: list of address IDs returned in damap_lookup_all()
998 void
999 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
1001 dam_t *mapp = (dam_t *)damapp;
1002 int i;
1004 if (id_list == NULL)
1005 return;
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);
1012 mutex_exit(&mapp->dam_lock);
1013 bitset_fini((bitset_t *)id_list);
1014 kmem_free((void *)id_list, sizeof (bitset_t));
1018 * activate an address that has passed the stabilization interval
1020 static void
1021 dam_addr_activate(dam_t *mapp, id_t addrid)
1023 dam_da_t *passp;
1024 int config_rv;
1025 char *addrstr;
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);
1033 * copy the reported nvlist and provider private data
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);
1052 * call the address-specific configuration action as part of
1053 * activation.
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);
1074 * deactivate a previously stable address
1076 static void
1077 dam_addr_deactivate(dam_t *mapp, id_t addrid)
1079 char *addrstr;
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);
1087 * call the unconfiguration callback
1089 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1090 dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1093 static void
1094 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1095 damap_deact_rsn_t deact_rsn)
1097 dam_da_t *passp;
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);
1107 * clear the active bit and free the backing info for
1108 * this address
1110 mutex_enter(&mapp->dam_lock);
1111 bitset_del(&mapp->dam_active_set, addrid);
1112 passp->da_ppriv = NULL;
1113 nvlist_free(passp->da_nvl);
1114 passp->da_nvl = NULL;
1115 passp->da_ppriv_rpt = NULL;
1116 nvlist_free(passp->da_nvl_rpt);
1117 passp->da_nvl_rpt = NULL;
1119 DTRACE_PROBE3(damap__addr__deactivate__end,
1120 char *, mapp->dam_name, dam_t *, mapp,
1121 char *, addrstr);
1123 (void) dam_addr_release(mapp, addrid);
1124 mutex_exit(&mapp->dam_lock);
1128 * taskq callback for multi-thread activation
1130 static void
1131 dam_tq_config(void *arg)
1133 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1135 dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1136 kmem_free(tqd, sizeof (*tqd));
1140 * taskq callback for multi-thread deactivation
1142 static void
1143 dam_tq_unconfig(void *arg)
1145 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1147 dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1148 kmem_free(tqd, sizeof (*tqd));
1152 * Activate a set of stabilized addresses
1154 static void
1155 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1158 int i, nset;
1159 taskq_t *tqp = NULL;
1160 cfg_tqd_t *tqd = NULL;
1161 char tqn[TASKQ_NAMELEN];
1162 extern pri_t maxclsyspri;
1164 if (mapp->dam_options & DAMAP_MTCONFIG) {
1166 * calculate the # of taskq threads to create
1168 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1169 if (bitset_in_set(activate, i))
1170 nset++;
1171 ASSERT(nset);
1172 (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1173 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1174 INT_MAX, TASKQ_PREPOPULATE);
1176 for (i = 1; i < mapp->dam_high; i++) {
1177 if (bitset_in_set(activate, i)) {
1178 if (!tqp)
1179 dam_addr_activate(mapp, i);
1180 else {
1182 * multi-threaded activation
1184 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1185 tqd->tqd_mapp = mapp;
1186 tqd->tqd_id = i;
1187 (void) taskq_dispatch(tqp, dam_tq_config,
1188 tqd, TQ_SLEEP);
1192 if (tqp) {
1193 taskq_wait(tqp);
1194 taskq_destroy(tqp);
1199 * Deactivate a set of stabilized addresses
1201 static void
1202 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1204 int i, nset;
1205 taskq_t *tqp = NULL;
1206 cfg_tqd_t *tqd = NULL;
1207 char tqn[TASKQ_NAMELEN];
1209 DTRACE_PROBE2(damap__addrset__deactivate,
1210 char *, mapp->dam_name, dam_t *, mapp);
1212 if (mapp->dam_options & DAMAP_MTCONFIG) {
1214 * compute the # of taskq threads to dispatch
1216 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1217 if (bitset_in_set(deactivate, i))
1218 nset++;
1219 (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1220 mapp->dam_name);
1221 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1222 INT_MAX, TASKQ_PREPOPULATE);
1224 for (i = 1; i < mapp->dam_high; i++) {
1225 if (bitset_in_set(deactivate, i)) {
1226 if (!tqp) {
1227 dam_addr_deactivate(mapp, i);
1228 } else {
1229 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1230 tqd->tqd_mapp = mapp;
1231 tqd->tqd_id = i;
1232 (void) taskq_dispatch(tqp,
1233 dam_tq_unconfig, tqd, TQ_SLEEP);
1238 if (tqp) {
1239 taskq_wait(tqp);
1240 taskq_destroy(tqp);
1245 * Release a previously activated address
1247 static void
1248 dam_addr_release(dam_t *mapp, id_t addrid)
1250 dam_da_t *passp;
1251 char *addrstr;
1254 ASSERT(mutex_owned(&mapp->dam_lock));
1255 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1256 ASSERT(passp);
1258 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1259 DTRACE_PROBE3(damap__addr__release,
1260 char *, mapp->dam_name, dam_t *, mapp,
1261 char *, addrstr);
1264 * defer releasing the address until outstanding references
1265 * are released
1267 if (passp->da_ref > 1) {
1268 DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1269 char *, mapp->dam_name, dam_t *, mapp,
1270 char *, addrstr, int, passp->da_ref);
1271 return;
1275 * allow pending reports to stabilize
1277 if (DAM_IN_REPORT(mapp, addrid)) {
1278 DTRACE_PROBE3(damap__addr__release__report__pending,
1279 char *, mapp->dam_name, dam_t *, mapp,
1280 char *, addrstr);
1281 return;
1284 ddi_strid_free(mapp->dam_addr_hash, addrid);
1285 ddi_soft_state_free(mapp->dam_da, addrid);
1289 * process stabilized address reports
1291 static void
1292 dam_stabilize_map(void *arg)
1294 dam_t *mapp = (dam_t *)arg;
1295 bitset_t delta;
1296 bitset_t cfg;
1297 bitset_t uncfg;
1298 int has_cfg, has_uncfg;
1299 uint32_t i, n_active;
1301 DTRACE_PROBE2(damap__stabilize__map,
1302 char *, mapp->dam_name, dam_t *, mapp);
1304 bitset_init(&delta);
1305 bitset_resize(&delta, mapp->dam_size);
1306 bitset_init(&cfg);
1307 bitset_resize(&cfg, mapp->dam_size);
1308 bitset_init(&uncfg);
1309 bitset_resize(&uncfg, mapp->dam_size);
1312 * determine which addresses have changed during
1313 * this stabilization cycle
1315 mutex_enter(&mapp->dam_lock);
1316 ASSERT(mapp->dam_flags & DAM_SPEND);
1317 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1318 &delta)) {
1320 * no difference
1322 bitset_zero(&mapp->dam_stable_set);
1323 mapp->dam_flags &= ~DAM_SPEND;
1324 cv_signal(&mapp->dam_sync_cv);
1325 mutex_exit(&mapp->dam_lock);
1327 bitset_fini(&uncfg);
1328 bitset_fini(&cfg);
1329 bitset_fini(&delta);
1330 DTRACE_PROBE2(damap__stabilize__map__nochange,
1331 char *, mapp->dam_name, dam_t *, mapp);
1332 return;
1336 * compute the sets of addresses to be activated and deactivated
1338 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1339 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1342 * drop map lock while invoking callouts
1344 mutex_exit(&mapp->dam_lock);
1347 * activate all newly stable addresss
1349 if (has_cfg)
1350 dam_addrset_activate(mapp, &cfg);
1353 * deactivate addresss which are no longer in the map
1355 if (has_uncfg)
1356 dam_addrset_deactivate(mapp, &uncfg);
1360 * timestamp the last stable time and increment the kstat keeping
1361 * the # of of stable cycles for the map
1363 mutex_enter(&mapp->dam_lock);
1364 bitset_zero(&mapp->dam_stable_set);
1365 mapp->dam_last_stable = gethrtime();
1366 mapp->dam_stable_cnt++;
1367 DAM_INCR_STAT(mapp, dam_cycles);
1370 * determine the number of stable addresses
1371 * and update the n_active kstat for this map
1373 for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1374 if (bitset_in_set(&mapp->dam_active_set, i))
1375 n_active++;
1376 DAM_SET_STAT(mapp, dam_active, n_active);
1378 DTRACE_PROBE3(damap__map__stable__end,
1379 char *, mapp->dam_name, dam_t *, mapp,
1380 int, n_active);
1382 mapp->dam_flags &= ~DAM_SPEND;
1383 cv_signal(&mapp->dam_sync_cv);
1384 mutex_exit(&mapp->dam_lock);
1386 bitset_fini(&uncfg);
1387 bitset_fini(&cfg);
1388 bitset_fini(&delta);
1392 * per-address stabilization timeout
1394 static void
1395 dam_addr_stable_cb(void *arg)
1397 dam_t *mapp = (dam_t *)arg;
1398 int i;
1399 dam_da_t *passp;
1400 int spend = 0;
1401 int tpend = 0;
1402 int64_t ts, next_ticks, delta_ticks;
1404 mutex_enter(&mapp->dam_lock);
1405 if (mapp->dam_tid == 0) {
1406 DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1407 char *, mapp->dam_name, dam_t *, mapp);
1408 mutex_exit(&mapp->dam_lock);
1409 return;
1411 mapp->dam_tid = 0;
1414 * If still under stabilization, reschedule timeout,
1415 * otherwise dispatch the task to activate and deactivate the
1416 * new stable address
1418 if (mapp->dam_flags & DAM_SPEND) {
1419 DAM_INCR_STAT(mapp, dam_overrun);
1420 mapp->dam_stable_overrun++;
1421 DTRACE_PROBE2(damap__map__addr__stable__overrun,
1422 char *, mapp->dam_name, dam_t *, mapp);
1423 dam_sched_timeout(dam_addr_stable_cb, mapp,
1424 mapp->dam_stable_ticks);
1425 mutex_exit(&mapp->dam_lock);
1426 return;
1429 DAM_SET_STAT(mapp, dam_overrun, 0);
1430 mapp->dam_stable_overrun = 0;
1432 /* See if any reports stabalized and compute next timeout. */
1433 ts = ddi_get_lbolt64();
1434 next_ticks = mapp->dam_stable_ticks;
1435 for (i = 1; i < mapp->dam_high; i++) {
1436 if (bitset_in_set(&mapp->dam_report_set, i)) {
1437 passp = ddi_get_soft_state(mapp->dam_da, i);
1438 ASSERT(passp);
1440 if (passp->da_deadline <= ts)
1441 spend++; /* report has stabilized */
1442 else {
1443 /* not stabilized, determine next map timeout */
1444 tpend++;
1445 delta_ticks = passp->da_deadline - ts;
1446 if (delta_ticks < next_ticks)
1447 next_ticks = delta_ticks;
1453 * schedule system_taskq activation of stabilized reports
1455 if (spend) {
1456 if (taskq_dispatch(system_taskq, dam_stabilize_map,
1457 mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1458 DTRACE_PROBE2(damap__map__addr__stable__start,
1459 char *, mapp->dam_name, dam_t *, mapp);
1462 * The stable_set we compute below stays pending until
1463 * processed by dam_stabilize_map. We can't set
1464 * DAM_SPEND (or bitset_del things from the
1465 * report_set) until we *know* that we can handoff the
1466 * result to dam_stabilize_map. If dam_stabilize_map
1467 * starts executing before we are complete, it will
1468 * block on the dam_lock mutex until we are ready.
1470 mapp->dam_flags |= DAM_SPEND;
1473 * Copy the current active_set to the stable_set, then
1474 * add or remove stabilized report_set address from
1475 * the stable set (and delete them from the report_set).
1477 bitset_copy(&mapp->dam_active_set,
1478 &mapp->dam_stable_set);
1479 for (i = 1; i < mapp->dam_high; i++) {
1480 if (!bitset_in_set(&mapp->dam_report_set, i))
1481 continue;
1483 passp = ddi_get_soft_state(mapp->dam_da, i);
1484 if (passp->da_deadline > ts)
1485 continue; /* report not stabilized */
1487 /* report has stabilized */
1488 if (passp->da_flags & DA_RELE)
1489 bitset_del(&mapp->dam_stable_set, i);
1490 else
1491 bitset_add(&mapp->dam_stable_set, i);
1493 bitset_del(&mapp->dam_report_set, i);
1495 } else {
1496 DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1497 char *, mapp->dam_name, dam_t *, mapp);
1500 * Avoid waiting the entire stabalization
1501 * time again if taskq_diskpatch fails.
1503 tpend++;
1504 delta_ticks = drv_usectohz(
1505 damap_taskq_dispatch_retry_usec);
1506 if (delta_ticks < next_ticks)
1507 next_ticks = delta_ticks;
1512 * reschedule the stabilization timer if there are reports
1513 * still pending
1515 if (tpend) {
1516 DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1517 mapp->dam_name, dam_t *, mapp);
1518 dam_sched_timeout(dam_addr_stable_cb, mapp,
1519 (clock_t)next_ticks);
1522 mutex_exit(&mapp->dam_lock);
1526 * fullset stabilization timeout callback
1528 static void
1529 dam_addrset_stable_cb(void *arg)
1531 dam_t *mapp = (dam_t *)arg;
1533 mutex_enter(&mapp->dam_lock);
1534 if (mapp->dam_tid == 0) {
1535 mutex_exit(&mapp->dam_lock);
1536 DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1537 char *, mapp->dam_name, dam_t *, mapp);
1538 return;
1540 mapp->dam_tid = 0;
1543 * If map still underoing stabilization reschedule timeout,
1544 * else dispatch the task to configure the new stable set of
1545 * addresses.
1547 if ((mapp->dam_flags & DAM_SPEND) ||
1548 (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1549 TQ_NOSLEEP | TQ_NOQUEUE) == 0)) {
1550 DAM_INCR_STAT(mapp, dam_overrun);
1551 mapp->dam_stable_overrun++;
1552 dam_sched_timeout(dam_addrset_stable_cb, mapp,
1553 drv_usectohz(damap_taskq_dispatch_retry_usec));
1555 DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1556 char *, mapp->dam_name, dam_t *, mapp);
1557 mutex_exit(&mapp->dam_lock);
1558 return;
1561 DAM_SET_STAT(mapp, dam_overrun, 0);
1562 mapp->dam_stable_overrun = 0;
1563 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1564 bitset_zero(&mapp->dam_report_set);
1565 mapp->dam_flags |= DAM_SPEND;
1566 mapp->dam_flags &= ~DAM_SETADD;
1567 /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1569 DTRACE_PROBE2(damap__map__addrset__stable__start,
1570 char *, mapp->dam_name, dam_t *, mapp);
1571 mutex_exit(&mapp->dam_lock);
1575 * schedule map timeout in 'ticks' ticks
1576 * if map timer is currently running, cancel if ticks == 0
1578 static void
1579 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1581 timeout_id_t tid;
1583 DTRACE_PROBE4(damap__sched__timeout,
1584 char *, mapp->dam_name, dam_t *, mapp,
1585 int, ticks, timeout_id_t, mapp->dam_tid);
1587 ASSERT(mutex_owned(&mapp->dam_lock));
1588 if ((tid = mapp->dam_tid) != 0) {
1589 if (ticks == 0) {
1590 mapp->dam_tid = 0;
1591 mutex_exit(&mapp->dam_lock);
1592 (void) untimeout(tid);
1593 mutex_enter(&mapp->dam_lock);
1595 } else {
1596 if (timeout_cb && (ticks != 0))
1597 mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1602 * report addition or removal of an address
1604 static void
1605 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1607 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1609 DTRACE_PROBE4(damap__addr__report,
1610 char *, mapp->dam_name, dam_t *, mapp,
1611 char *, addrstr, int, rpt_type);
1613 ASSERT(mutex_owned(&mapp->dam_lock));
1614 ASSERT(!DAM_IN_REPORT(mapp, addrid));
1615 passp->da_last_report = gethrtime();
1616 mapp->dam_last_update = gethrtime();
1617 passp->da_report_cnt++;
1618 passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1619 if (rpt_type == RPT_ADDR_DEL)
1620 passp->da_flags |= DA_RELE;
1621 else if (rpt_type == RPT_ADDR_ADD)
1622 passp->da_flags &= ~DA_RELE;
1623 bitset_add(&mapp->dam_report_set, addrid);
1624 dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1628 * release an address report
1630 static void
1631 dam_addr_report_release(dam_t *mapp, id_t addrid)
1633 dam_da_t *passp;
1634 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1636 DTRACE_PROBE3(damap__addr__report__release,
1637 char *, mapp->dam_name, dam_t *, mapp,
1638 char *, addrstr);
1640 ASSERT(mutex_owned(&mapp->dam_lock));
1641 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1642 ASSERT(passp);
1644 * clear the report bit
1645 * if the address has a registered deactivation handler and
1646 * we are holding a private data pointer and the address has not
1647 * stabilized, deactivate the address (private data).
1649 bitset_del(&mapp->dam_report_set, addrid);
1650 if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1651 passp->da_ppriv_rpt) {
1652 mutex_exit(&mapp->dam_lock);
1653 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1654 ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1655 addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1656 mutex_enter(&mapp->dam_lock);
1658 passp->da_ppriv_rpt = NULL;
1659 nvlist_free(passp->da_nvl_rpt);
1663 * return the map ID of an address
1665 static id_t
1666 dam_get_addrid(dam_t *mapp, char *address)
1668 damap_id_t addrid;
1669 dam_da_t *passp;
1671 ASSERT(mutex_owned(&mapp->dam_lock));
1672 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1673 if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1674 address)) == (damap_id_t)0) {
1675 return (0);
1677 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1678 DDI_SUCCESS) {
1679 ddi_strid_free(mapp->dam_addr_hash, addrid);
1680 return (0);
1683 if (addrid >= mapp->dam_high)
1684 mapp->dam_high = addrid + 1;
1687 * expand bitmaps if ID has outgrown old map size
1689 if (mapp->dam_high > mapp->dam_size) {
1690 mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1691 bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1692 bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1693 bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1696 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1697 passp->da_ref = 1;
1698 passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1699 addrid); /* for mdb */
1701 return (addrid);
1705 * create and install map statistics
1707 static int
1708 dam_kstat_create(dam_t *mapp)
1710 kstat_t *mapsp;
1711 struct dam_kstats *statsp;
1713 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1714 KSTAT_TYPE_NAMED,
1715 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1717 if (mapsp == NULL)
1718 return (DDI_FAILURE);
1720 statsp = (struct dam_kstats *)mapsp->ks_data;
1721 kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1722 kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1723 kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1724 kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1725 kstat_install(mapsp);
1726 mapp->dam_kstatsp = mapsp;
1727 return (DDI_SUCCESS);