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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
32 #include <sys/cmn_err.h>
33 #include <sys/debug.h>
34 #include <sys/sunndi.h>
35 #include <sys/kstat.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>
43 #include <sys/bitset.h>
44 #include <sys/damap.h>
45 #include <sys/damap_impl.h>
48 static int damap_debug
= 0;
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
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
,
130 if (configure_cb
== NULL
|| unconfig_cb
== NULL
|| name
== NULL
)
133 mapp
= kmem_zalloc(sizeof (*mapp
), KM_SLEEP
);
134 mapp
->dam_options
= map_opts
;
135 mapp
->dam_stable_ticks
= drv_usectohz(stable_usec
);
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
167 dam_map_alloc(dam_t
*mapp
)
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
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
) !=
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
;
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
214 damap_destroy(damap_t
*damapp
)
217 dam_t
*mapp
= (dam_t
*)damapp
;
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
)
251 ASSERT(DAM_IN_REPORT(mapp
, i
) == 0);
253 if (DAM_IS_STABLE(mapp
, i
)) {
254 dam_addr_deactivate(mapp
, i
);
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
);
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
);
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
;
293 DTRACE_PROBE3(damap__map__sync__start
,
294 char *, mapp
->dam_name
, dam_t
*, mapp
,
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 */
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 */
320 cv_wait(&mapp
->dam_sync_cv
, &mapp
->dam_lock
);
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)))
335 mutex_exit(&mapp
->dam_lock
);
337 DTRACE_PROBE3(damap__map__sync__end
,
338 char *, mapp
->dam_name
, dam_t
*, mapp
,
344 * Return 1 if active set is empty
347 damap_is_empty(damap_t
*damapp
)
349 dam_t
*mapp
= (dam_t
*)damapp
;
352 mutex_enter(&mapp
->dam_lock
);
353 rv
= bitset_is_null(&mapp
->dam_active_set
);
354 mutex_exit(&mapp
->dam_lock
);
359 * Get the name of a device address map
361 * damapp: address map
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
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
;
409 if (!mapp
|| !address
|| (mapp
->dam_rptmode
!= DAMAP_REPORT_PERADDR
))
412 DTRACE_PROBE3(damap__addr__add
,
413 char *, mapp
->dam_name
, dam_t
*, mapp
,
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
,
434 DAM_INCR_STAT(mapp
, dam_jitter
);
435 dam_addr_report_release(mapp
, addrid
);
438 passp
->da_ppriv_rpt
= addr_priv
;
440 (void) nvlist_dup(nvl
, &passp
->da_nvl_rpt
, KM_SLEEP
);
442 dam_addr_report(mapp
, passp
, addrid
, RPT_ADDR_ADD
);
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
;
466 if (!mapp
|| !address
|| (mapp
->dam_rptmode
!= DAMAP_REPORT_PERADDR
))
469 DTRACE_PROBE3(damap__addr__del
,
470 char *, mapp
->dam_name
, dam_t
*, mapp
,
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
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
);
488 if (DAM_IN_REPORT(mapp
, addrid
)) {
489 DTRACE_PROBE3(damap__addr__del__jitter
,
490 char *, mapp
->dam_name
, dam_t
*, mapp
,
492 DAM_INCR_STAT(mapp
, dam_jitter
);
493 dam_addr_report_release(mapp
, addrid
);
496 dam_addr_report(mapp
, passp
, addrid
, RPT_ADDR_DEL
);
497 mutex_exit(&mapp
->dam_lock
);
498 return (DAM_SUCCESS
);
502 damap_addrset_flush_locked(damap_t
*damapp
)
504 dam_t
*mapp
= (dam_t
*)damapp
;
508 ASSERT(mutex_owned(&mapp
->dam_lock
));
509 if (mapp
->dam_rptmode
!= DAMAP_REPORT_FULLSET
) {
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
;
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
);
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
)
591 dam_t
*mapp
= (dam_t
*)damapp
;
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
);
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
;
629 if (!mapp
|| !address
|| (mapp
->dam_rptmode
!= DAMAP_REPORT_FULLSET
))
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
);
648 if (DAM_IN_REPORT(mapp
, addrid
)) {
649 DTRACE_PROBE3(damap__addrset__add__jitter
,
650 char *, mapp
->dam_name
, dam_t
*, mapp
,
652 dam_addr_report_release(mapp
, addrid
);
655 passp
->da_ppriv_rpt
= addr_priv
;
657 (void) nvlist_dup(nvl
, &passp
->da_nvl_rpt
, KM_SLEEP
);
658 bitset_add(&mapp
->dam_report_set
, addrid
);
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
;
681 if (!mapp
|| (mapp
->dam_rptmode
!= DAMAP_REPORT_FULLSET
))
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
);
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
715 * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
719 damap_id2nvlist(damap_t
*damapp
, damap_id_t addrid
)
721 dam_t
*mapp
= (dam_t
*)damapp
;
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
);
732 * Return address string
734 * damapp: address map handle
737 * Returns: char * Address string
741 damap_id2addr(damap_t
*damapp
, damap_id_t addrid
)
743 dam_t
*mapp
= (dam_t
*)damapp
;
746 return (ddi_strid_id2str(mapp
->dam_addr_hash
, addrid
));
752 * Release address reference in map
754 * damapp: address map handle
758 damap_id_rele(damap_t
*damapp
, damap_id_t addrid
)
760 dam_t
*mapp
= (dam_t
*)damapp
;
764 passp
= ddi_get_soft_state(mapp
->dam_da
, (id_t
)addrid
);
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
789 * Returns: DAM_SUCCESS
793 damap_id_ref(damap_t
*damapp
, damap_id_t addrid
)
795 dam_t
*mapp
= (dam_t
*)damapp
;
799 passp
= ddi_get_soft_state(mapp
->dam_da
, (id_t
)addrid
);
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
818 damap_id_next(damap_t
*damapp
, damap_id_list_t damap_list
, damap_id_t last
)
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
841 * cfg_priv: configuration private data
845 damap_id_priv_set(damap_t
*damapp
, damap_id_t addrid
, void *cfg_priv
)
847 dam_t
*mapp
= (dam_t
*)damapp
;
850 mutex_enter(&mapp
->dam_lock
);
851 passp
= ddi_get_soft_state(mapp
->dam_da
, (id_t
)addrid
);
853 mutex_exit(&mapp
->dam_lock
);
856 passp
->da_cfg_priv
= cfg_priv
;
857 mutex_exit(&mapp
->dam_lock
);
861 * Get config private data
863 * damapp: address map handle
866 * Returns: configuration private data
869 damap_id_priv_get(damap_t
*damapp
, damap_id_t addrid
)
871 dam_t
*mapp
= (dam_t
*)damapp
;
875 mutex_enter(&mapp
->dam_lock
);
876 passp
= ddi_get_soft_state(mapp
->dam_da
, (id_t
)addrid
);
878 mutex_exit(&mapp
->dam_lock
);
881 rv
= passp
->da_cfg_priv
;
882 mutex_exit(&mapp
->dam_lock
);
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.
898 damap_lookup(damap_t
*damapp
, char *address
)
900 dam_t
*mapp
= (dam_t
*)damapp
;
902 dam_da_t
*passp
= NULL
;
904 DTRACE_PROBE3(damap__lookup
,
905 char *, mapp
->dam_name
, dam_t
*, mapp
,
907 mutex_enter(&mapp
->dam_lock
);
911 addrid
= ddi_strid_str2id(mapp
->dam_addr_hash
, address
);
913 if (DAM_IS_STABLE(mapp
, addrid
)) {
914 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
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
;
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
);
961 bsp
= kmem_alloc(sizeof (*bsp
), KM_SLEEP
);
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
);
970 addrp
= damap_id2addr(damapp
, i
);
971 DTRACE_PROBE3(damap__lookup__all__item
,
972 char *, mapp
->dam_name
, dam_t
*, mapp
,
980 *id_listp
= (damap_id_list_t
)bsp
;
981 mutex_exit(&mapp
->dam_lock
);
984 *id_listp
= (damap_id_list_t
)NULL
;
986 kmem_free(bsp
, sizeof (*bsp
));
987 mutex_exit(&mapp
->dam_lock
);
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()
999 damap_id_list_rele(damap_t
*damapp
, damap_id_list_t id_list
)
1001 dam_t
*mapp
= (dam_t
*)damapp
;
1004 if (id_list
== NULL
)
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
1021 dam_addr_activate(dam_t
*mapp
, id_t addrid
)
1027 mutex_enter(&mapp
->dam_lock
);
1028 bitset_add(&mapp
->dam_active_set
, addrid
);
1029 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
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
,
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
1055 config_rv
= (*mapp
->dam_configure_cb
)(mapp
->dam_config_arg
, mapp
,
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
,
1064 dam_deact_cleanup(mapp
, addrid
, addrstr
,
1065 DAMAP_DEACT_RSN_CFG_FAIL
);
1067 DTRACE_PROBE3(damap__addr__activate__end
,
1068 char *, mapp
->dam_name
, dam_t
*, mapp
,
1074 * deactivate a previously stable address
1077 dam_addr_deactivate(dam_t
*mapp
, id_t addrid
)
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
,
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
);
1094 dam_deact_cleanup(dam_t
*mapp
, id_t addrid
, char *addrstr
,
1095 damap_deact_rsn_t deact_rsn
)
1099 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
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
1110 mutex_enter(&mapp
->dam_lock
);
1111 bitset_del(&mapp
->dam_active_set
, addrid
);
1112 passp
->da_ppriv
= NULL
;
1114 nvlist_free(passp
->da_nvl
);
1115 passp
->da_nvl
= NULL
;
1116 passp
->da_ppriv_rpt
= NULL
;
1117 if (passp
->da_nvl_rpt
)
1118 nvlist_free(passp
->da_nvl_rpt
);
1119 passp
->da_nvl_rpt
= NULL
;
1121 DTRACE_PROBE3(damap__addr__deactivate__end
,
1122 char *, mapp
->dam_name
, dam_t
*, mapp
,
1125 (void) dam_addr_release(mapp
, addrid
);
1126 mutex_exit(&mapp
->dam_lock
);
1130 * taskq callback for multi-thread activation
1133 dam_tq_config(void *arg
)
1135 cfg_tqd_t
*tqd
= (cfg_tqd_t
*)arg
;
1137 dam_addr_activate(tqd
->tqd_mapp
, tqd
->tqd_id
);
1138 kmem_free(tqd
, sizeof (*tqd
));
1142 * taskq callback for multi-thread deactivation
1145 dam_tq_unconfig(void *arg
)
1147 cfg_tqd_t
*tqd
= (cfg_tqd_t
*)arg
;
1149 dam_addr_deactivate(tqd
->tqd_mapp
, tqd
->tqd_id
);
1150 kmem_free(tqd
, sizeof (*tqd
));
1154 * Activate a set of stabilized addresses
1157 dam_addrset_activate(dam_t
*mapp
, bitset_t
*activate
)
1161 taskq_t
*tqp
= NULL
;
1162 cfg_tqd_t
*tqd
= NULL
;
1163 char tqn
[TASKQ_NAMELEN
];
1164 extern pri_t maxclsyspri
;
1166 if (mapp
->dam_options
& DAMAP_MTCONFIG
) {
1168 * calculate the # of taskq threads to create
1170 for (i
= 1, nset
= 0; i
< mapp
->dam_high
; i
++)
1171 if (bitset_in_set(activate
, i
))
1174 (void) snprintf(tqn
, sizeof (tqn
), "actv-%s", mapp
->dam_name
);
1175 tqp
= taskq_create(tqn
, nset
, maxclsyspri
, 1,
1176 INT_MAX
, TASKQ_PREPOPULATE
);
1178 for (i
= 1; i
< mapp
->dam_high
; i
++) {
1179 if (bitset_in_set(activate
, i
)) {
1181 dam_addr_activate(mapp
, i
);
1184 * multi-threaded activation
1186 tqd
= kmem_alloc(sizeof (*tqd
), KM_SLEEP
);
1187 tqd
->tqd_mapp
= mapp
;
1189 (void) taskq_dispatch(tqp
, dam_tq_config
,
1201 * Deactivate a set of stabilized addresses
1204 dam_addrset_deactivate(dam_t
*mapp
, bitset_t
*deactivate
)
1207 taskq_t
*tqp
= NULL
;
1208 cfg_tqd_t
*tqd
= NULL
;
1209 char tqn
[TASKQ_NAMELEN
];
1211 DTRACE_PROBE2(damap__addrset__deactivate
,
1212 char *, mapp
->dam_name
, dam_t
*, mapp
);
1214 if (mapp
->dam_options
& DAMAP_MTCONFIG
) {
1216 * compute the # of taskq threads to dispatch
1218 for (i
= 1, nset
= 0; i
< mapp
->dam_high
; i
++)
1219 if (bitset_in_set(deactivate
, i
))
1221 (void) snprintf(tqn
, sizeof (tqn
), "deactv-%s",
1223 tqp
= taskq_create(tqn
, nset
, maxclsyspri
, 1,
1224 INT_MAX
, TASKQ_PREPOPULATE
);
1226 for (i
= 1; i
< mapp
->dam_high
; i
++) {
1227 if (bitset_in_set(deactivate
, i
)) {
1229 dam_addr_deactivate(mapp
, i
);
1231 tqd
= kmem_alloc(sizeof (*tqd
), KM_SLEEP
);
1232 tqd
->tqd_mapp
= mapp
;
1234 (void) taskq_dispatch(tqp
,
1235 dam_tq_unconfig
, tqd
, TQ_SLEEP
);
1247 * Release a previously activated address
1250 dam_addr_release(dam_t
*mapp
, id_t addrid
)
1256 ASSERT(mutex_owned(&mapp
->dam_lock
));
1257 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
1260 addrstr
= ddi_strid_id2str(mapp
->dam_addr_hash
, addrid
);
1261 DTRACE_PROBE3(damap__addr__release
,
1262 char *, mapp
->dam_name
, dam_t
*, mapp
,
1266 * defer releasing the address until outstanding references
1269 if (passp
->da_ref
> 1) {
1270 DTRACE_PROBE4(damap__addr__release__outstanding__refs
,
1271 char *, mapp
->dam_name
, dam_t
*, mapp
,
1272 char *, addrstr
, int, passp
->da_ref
);
1277 * allow pending reports to stabilize
1279 if (DAM_IN_REPORT(mapp
, addrid
)) {
1280 DTRACE_PROBE3(damap__addr__release__report__pending
,
1281 char *, mapp
->dam_name
, dam_t
*, mapp
,
1286 ddi_strid_free(mapp
->dam_addr_hash
, addrid
);
1287 ddi_soft_state_free(mapp
->dam_da
, addrid
);
1291 * process stabilized address reports
1294 dam_stabilize_map(void *arg
)
1296 dam_t
*mapp
= (dam_t
*)arg
;
1300 int has_cfg
, has_uncfg
;
1301 uint32_t i
, n_active
;
1303 DTRACE_PROBE2(damap__stabilize__map
,
1304 char *, mapp
->dam_name
, dam_t
*, mapp
);
1306 bitset_init(&delta
);
1307 bitset_resize(&delta
, mapp
->dam_size
);
1309 bitset_resize(&cfg
, mapp
->dam_size
);
1310 bitset_init(&uncfg
);
1311 bitset_resize(&uncfg
, mapp
->dam_size
);
1314 * determine which addresses have changed during
1315 * this stabilization cycle
1317 mutex_enter(&mapp
->dam_lock
);
1318 ASSERT(mapp
->dam_flags
& DAM_SPEND
);
1319 if (!bitset_xor(&mapp
->dam_active_set
, &mapp
->dam_stable_set
,
1324 bitset_zero(&mapp
->dam_stable_set
);
1325 mapp
->dam_flags
&= ~DAM_SPEND
;
1326 cv_signal(&mapp
->dam_sync_cv
);
1327 mutex_exit(&mapp
->dam_lock
);
1329 bitset_fini(&uncfg
);
1331 bitset_fini(&delta
);
1332 DTRACE_PROBE2(damap__stabilize__map__nochange
,
1333 char *, mapp
->dam_name
, dam_t
*, mapp
);
1338 * compute the sets of addresses to be activated and deactivated
1340 has_cfg
= bitset_and(&delta
, &mapp
->dam_stable_set
, &cfg
);
1341 has_uncfg
= bitset_and(&delta
, &mapp
->dam_active_set
, &uncfg
);
1344 * drop map lock while invoking callouts
1346 mutex_exit(&mapp
->dam_lock
);
1349 * activate all newly stable addresss
1352 dam_addrset_activate(mapp
, &cfg
);
1355 * deactivate addresss which are no longer in the map
1358 dam_addrset_deactivate(mapp
, &uncfg
);
1362 * timestamp the last stable time and increment the kstat keeping
1363 * the # of of stable cycles for the map
1365 mutex_enter(&mapp
->dam_lock
);
1366 bitset_zero(&mapp
->dam_stable_set
);
1367 mapp
->dam_last_stable
= gethrtime();
1368 mapp
->dam_stable_cnt
++;
1369 DAM_INCR_STAT(mapp
, dam_cycles
);
1372 * determine the number of stable addresses
1373 * and update the n_active kstat for this map
1375 for (i
= 1, n_active
= 0; i
< mapp
->dam_high
; i
++)
1376 if (bitset_in_set(&mapp
->dam_active_set
, i
))
1378 DAM_SET_STAT(mapp
, dam_active
, n_active
);
1380 DTRACE_PROBE3(damap__map__stable__end
,
1381 char *, mapp
->dam_name
, dam_t
*, mapp
,
1384 mapp
->dam_flags
&= ~DAM_SPEND
;
1385 cv_signal(&mapp
->dam_sync_cv
);
1386 mutex_exit(&mapp
->dam_lock
);
1388 bitset_fini(&uncfg
);
1390 bitset_fini(&delta
);
1394 * per-address stabilization timeout
1397 dam_addr_stable_cb(void *arg
)
1399 dam_t
*mapp
= (dam_t
*)arg
;
1404 int64_t ts
, next_ticks
, delta_ticks
;
1406 mutex_enter(&mapp
->dam_lock
);
1407 if (mapp
->dam_tid
== 0) {
1408 DTRACE_PROBE2(damap__map__addr__stable__cancelled
,
1409 char *, mapp
->dam_name
, dam_t
*, mapp
);
1410 mutex_exit(&mapp
->dam_lock
);
1416 * If still under stabilization, reschedule timeout,
1417 * otherwise dispatch the task to activate and deactivate the
1418 * new stable address
1420 if (mapp
->dam_flags
& DAM_SPEND
) {
1421 DAM_INCR_STAT(mapp
, dam_overrun
);
1422 mapp
->dam_stable_overrun
++;
1423 DTRACE_PROBE2(damap__map__addr__stable__overrun
,
1424 char *, mapp
->dam_name
, dam_t
*, mapp
);
1425 dam_sched_timeout(dam_addr_stable_cb
, mapp
,
1426 mapp
->dam_stable_ticks
);
1427 mutex_exit(&mapp
->dam_lock
);
1431 DAM_SET_STAT(mapp
, dam_overrun
, 0);
1432 mapp
->dam_stable_overrun
= 0;
1434 /* See if any reports stabalized and compute next timeout. */
1435 ts
= ddi_get_lbolt64();
1436 next_ticks
= mapp
->dam_stable_ticks
;
1437 for (i
= 1; i
< mapp
->dam_high
; i
++) {
1438 if (bitset_in_set(&mapp
->dam_report_set
, i
)) {
1439 passp
= ddi_get_soft_state(mapp
->dam_da
, i
);
1442 if (passp
->da_deadline
<= ts
)
1443 spend
++; /* report has stabilized */
1445 /* not stabilized, determine next map timeout */
1447 delta_ticks
= passp
->da_deadline
- ts
;
1448 if (delta_ticks
< next_ticks
)
1449 next_ticks
= delta_ticks
;
1455 * schedule system_taskq activation of stabilized reports
1458 if (taskq_dispatch(system_taskq
, dam_stabilize_map
,
1459 mapp
, TQ_NOSLEEP
| TQ_NOQUEUE
)) {
1460 DTRACE_PROBE2(damap__map__addr__stable__start
,
1461 char *, mapp
->dam_name
, dam_t
*, mapp
);
1464 * The stable_set we compute below stays pending until
1465 * processed by dam_stabilize_map. We can't set
1466 * DAM_SPEND (or bitset_del things from the
1467 * report_set) until we *know* that we can handoff the
1468 * result to dam_stabilize_map. If dam_stabilize_map
1469 * starts executing before we are complete, it will
1470 * block on the dam_lock mutex until we are ready.
1472 mapp
->dam_flags
|= DAM_SPEND
;
1475 * Copy the current active_set to the stable_set, then
1476 * add or remove stabilized report_set address from
1477 * the stable set (and delete them from the report_set).
1479 bitset_copy(&mapp
->dam_active_set
,
1480 &mapp
->dam_stable_set
);
1481 for (i
= 1; i
< mapp
->dam_high
; i
++) {
1482 if (!bitset_in_set(&mapp
->dam_report_set
, i
))
1485 passp
= ddi_get_soft_state(mapp
->dam_da
, i
);
1486 if (passp
->da_deadline
> ts
)
1487 continue; /* report not stabilized */
1489 /* report has stabilized */
1490 if (passp
->da_flags
& DA_RELE
)
1491 bitset_del(&mapp
->dam_stable_set
, i
);
1493 bitset_add(&mapp
->dam_stable_set
, i
);
1495 bitset_del(&mapp
->dam_report_set
, i
);
1498 DTRACE_PROBE2(damap__map__addr__stable__spendfail
,
1499 char *, mapp
->dam_name
, dam_t
*, mapp
);
1502 * Avoid waiting the entire stabalization
1503 * time again if taskq_diskpatch fails.
1506 delta_ticks
= drv_usectohz(
1507 damap_taskq_dispatch_retry_usec
);
1508 if (delta_ticks
< next_ticks
)
1509 next_ticks
= delta_ticks
;
1514 * reschedule the stabilization timer if there are reports
1518 DTRACE_PROBE2(damap__map__addr__stable__tpend
, char *,
1519 mapp
->dam_name
, dam_t
*, mapp
);
1520 dam_sched_timeout(dam_addr_stable_cb
, mapp
,
1521 (clock_t)next_ticks
);
1524 mutex_exit(&mapp
->dam_lock
);
1528 * fullset stabilization timeout callback
1531 dam_addrset_stable_cb(void *arg
)
1533 dam_t
*mapp
= (dam_t
*)arg
;
1535 mutex_enter(&mapp
->dam_lock
);
1536 if (mapp
->dam_tid
== 0) {
1537 mutex_exit(&mapp
->dam_lock
);
1538 DTRACE_PROBE2(damap__map__addrset__stable__cancelled
,
1539 char *, mapp
->dam_name
, dam_t
*, mapp
);
1545 * If map still underoing stabilization reschedule timeout,
1546 * else dispatch the task to configure the new stable set of
1549 if ((mapp
->dam_flags
& DAM_SPEND
) ||
1550 (taskq_dispatch(system_taskq
, dam_stabilize_map
, mapp
,
1551 TQ_NOSLEEP
| TQ_NOQUEUE
) == NULL
)) {
1552 DAM_INCR_STAT(mapp
, dam_overrun
);
1553 mapp
->dam_stable_overrun
++;
1554 dam_sched_timeout(dam_addrset_stable_cb
, mapp
,
1555 drv_usectohz(damap_taskq_dispatch_retry_usec
));
1557 DTRACE_PROBE2(damap__map__addrset__stable__overrun
,
1558 char *, mapp
->dam_name
, dam_t
*, mapp
);
1559 mutex_exit(&mapp
->dam_lock
);
1563 DAM_SET_STAT(mapp
, dam_overrun
, 0);
1564 mapp
->dam_stable_overrun
= 0;
1565 bitset_copy(&mapp
->dam_report_set
, &mapp
->dam_stable_set
);
1566 bitset_zero(&mapp
->dam_report_set
);
1567 mapp
->dam_flags
|= DAM_SPEND
;
1568 mapp
->dam_flags
&= ~DAM_SETADD
;
1569 /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1571 DTRACE_PROBE2(damap__map__addrset__stable__start
,
1572 char *, mapp
->dam_name
, dam_t
*, mapp
);
1573 mutex_exit(&mapp
->dam_lock
);
1577 * schedule map timeout in 'ticks' ticks
1578 * if map timer is currently running, cancel if ticks == 0
1581 dam_sched_timeout(void (*timeout_cb
)(), dam_t
*mapp
, clock_t ticks
)
1585 DTRACE_PROBE4(damap__sched__timeout
,
1586 char *, mapp
->dam_name
, dam_t
*, mapp
,
1587 int, ticks
, timeout_id_t
, mapp
->dam_tid
);
1589 ASSERT(mutex_owned(&mapp
->dam_lock
));
1590 if ((tid
= mapp
->dam_tid
) != 0) {
1593 mutex_exit(&mapp
->dam_lock
);
1594 (void) untimeout(tid
);
1595 mutex_enter(&mapp
->dam_lock
);
1598 if (timeout_cb
&& (ticks
!= 0))
1599 mapp
->dam_tid
= timeout(timeout_cb
, mapp
, ticks
);
1604 * report addition or removal of an address
1607 dam_addr_report(dam_t
*mapp
, dam_da_t
*passp
, id_t addrid
, int rpt_type
)
1609 char *addrstr
= damap_id2addr((damap_t
*)mapp
, addrid
);
1611 DTRACE_PROBE4(damap__addr__report
,
1612 char *, mapp
->dam_name
, dam_t
*, mapp
,
1613 char *, addrstr
, int, rpt_type
);
1615 ASSERT(mutex_owned(&mapp
->dam_lock
));
1616 ASSERT(!DAM_IN_REPORT(mapp
, addrid
));
1617 passp
->da_last_report
= gethrtime();
1618 mapp
->dam_last_update
= gethrtime();
1619 passp
->da_report_cnt
++;
1620 passp
->da_deadline
= ddi_get_lbolt64() + mapp
->dam_stable_ticks
;
1621 if (rpt_type
== RPT_ADDR_DEL
)
1622 passp
->da_flags
|= DA_RELE
;
1623 else if (rpt_type
== RPT_ADDR_ADD
)
1624 passp
->da_flags
&= ~DA_RELE
;
1625 bitset_add(&mapp
->dam_report_set
, addrid
);
1626 dam_sched_timeout(dam_addr_stable_cb
, mapp
, mapp
->dam_stable_ticks
);
1630 * release an address report
1633 dam_addr_report_release(dam_t
*mapp
, id_t addrid
)
1636 char *addrstr
= damap_id2addr((damap_t
*)mapp
, addrid
);
1638 DTRACE_PROBE3(damap__addr__report__release
,
1639 char *, mapp
->dam_name
, dam_t
*, mapp
,
1642 ASSERT(mutex_owned(&mapp
->dam_lock
));
1643 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
1646 * clear the report bit
1647 * if the address has a registered deactivation handler and
1648 * we are holding a private data pointer and the address has not
1649 * stabilized, deactivate the address (private data).
1651 bitset_del(&mapp
->dam_report_set
, addrid
);
1652 if (!DAM_IS_STABLE(mapp
, addrid
) && mapp
->dam_deactivate_cb
&&
1653 passp
->da_ppriv_rpt
) {
1654 mutex_exit(&mapp
->dam_lock
);
1655 (*mapp
->dam_deactivate_cb
)(mapp
->dam_activate_arg
,
1656 ddi_strid_id2str(mapp
->dam_addr_hash
, addrid
),
1657 addrid
, passp
->da_ppriv_rpt
, DAMAP_DEACT_RSN_UNSTBL
);
1658 mutex_enter(&mapp
->dam_lock
);
1660 passp
->da_ppriv_rpt
= NULL
;
1661 if (passp
->da_nvl_rpt
)
1662 nvlist_free(passp
->da_nvl_rpt
);
1666 * return the map ID of an address
1669 dam_get_addrid(dam_t
*mapp
, char *address
)
1674 ASSERT(mutex_owned(&mapp
->dam_lock
));
1675 if ((addrid
= ddi_strid_str2id(mapp
->dam_addr_hash
, address
)) == 0) {
1676 if ((addrid
= ddi_strid_alloc(mapp
->dam_addr_hash
,
1677 address
)) == (damap_id_t
)0) {
1680 if (ddi_soft_state_zalloc(mapp
->dam_da
, addrid
) !=
1682 ddi_strid_free(mapp
->dam_addr_hash
, addrid
);
1686 if (addrid
>= mapp
->dam_high
)
1687 mapp
->dam_high
= addrid
+ 1;
1690 * expand bitmaps if ID has outgrown old map size
1692 if (mapp
->dam_high
> mapp
->dam_size
) {
1693 mapp
->dam_size
= mapp
->dam_size
+ DAM_SIZE_BUMP
;
1694 bitset_resize(&mapp
->dam_active_set
, mapp
->dam_size
);
1695 bitset_resize(&mapp
->dam_stable_set
, mapp
->dam_size
);
1696 bitset_resize(&mapp
->dam_report_set
, mapp
->dam_size
);
1699 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
1701 passp
->da_addr
= ddi_strid_id2str(mapp
->dam_addr_hash
,
1702 addrid
); /* for mdb */
1708 * create and install map statistics
1711 dam_kstat_create(dam_t
*mapp
)
1714 struct dam_kstats
*statsp
;
1716 mapsp
= kstat_create("dam", 0, mapp
->dam_name
, "damap",
1718 sizeof (struct dam_kstats
) / sizeof (kstat_named_t
), 0);
1721 return (DDI_FAILURE
);
1723 statsp
= (struct dam_kstats
*)mapsp
->ks_data
;
1724 kstat_named_init(&statsp
->dam_cycles
, "cycles", KSTAT_DATA_UINT32
);
1725 kstat_named_init(&statsp
->dam_overrun
, "overrun", KSTAT_DATA_UINT32
);
1726 kstat_named_init(&statsp
->dam_jitter
, "jitter", KSTAT_DATA_UINT32
);
1727 kstat_named_init(&statsp
->dam_active
, "active", KSTAT_DATA_UINT32
);
1728 kstat_install(mapsp
);
1729 mapp
->dam_kstatsp
= mapsp
;
1730 return (DDI_SUCCESS
);