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
;
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
,
1123 (void) dam_addr_release(mapp
, addrid
);
1124 mutex_exit(&mapp
->dam_lock
);
1128 * taskq callback for multi-thread activation
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
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
1155 dam_addrset_activate(dam_t
*mapp
, bitset_t
*activate
)
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
))
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
)) {
1179 dam_addr_activate(mapp
, i
);
1182 * multi-threaded activation
1184 tqd
= kmem_alloc(sizeof (*tqd
), KM_SLEEP
);
1185 tqd
->tqd_mapp
= mapp
;
1187 (void) taskq_dispatch(tqp
, dam_tq_config
,
1199 * Deactivate a set of stabilized addresses
1202 dam_addrset_deactivate(dam_t
*mapp
, bitset_t
*deactivate
)
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
))
1219 (void) snprintf(tqn
, sizeof (tqn
), "deactv-%s",
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
)) {
1227 dam_addr_deactivate(mapp
, i
);
1229 tqd
= kmem_alloc(sizeof (*tqd
), KM_SLEEP
);
1230 tqd
->tqd_mapp
= mapp
;
1232 (void) taskq_dispatch(tqp
,
1233 dam_tq_unconfig
, tqd
, TQ_SLEEP
);
1245 * Release a previously activated address
1248 dam_addr_release(dam_t
*mapp
, id_t addrid
)
1254 ASSERT(mutex_owned(&mapp
->dam_lock
));
1255 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
1258 addrstr
= ddi_strid_id2str(mapp
->dam_addr_hash
, addrid
);
1259 DTRACE_PROBE3(damap__addr__release
,
1260 char *, mapp
->dam_name
, dam_t
*, mapp
,
1264 * defer releasing the address until outstanding references
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
);
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
,
1284 ddi_strid_free(mapp
->dam_addr_hash
, addrid
);
1285 ddi_soft_state_free(mapp
->dam_da
, addrid
);
1289 * process stabilized address reports
1292 dam_stabilize_map(void *arg
)
1294 dam_t
*mapp
= (dam_t
*)arg
;
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
);
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
,
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
);
1329 bitset_fini(&delta
);
1330 DTRACE_PROBE2(damap__stabilize__map__nochange
,
1331 char *, mapp
->dam_name
, dam_t
*, mapp
);
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
1350 dam_addrset_activate(mapp
, &cfg
);
1353 * deactivate addresss which are no longer in the map
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
))
1376 DAM_SET_STAT(mapp
, dam_active
, n_active
);
1378 DTRACE_PROBE3(damap__map__stable__end
,
1379 char *, mapp
->dam_name
, dam_t
*, mapp
,
1382 mapp
->dam_flags
&= ~DAM_SPEND
;
1383 cv_signal(&mapp
->dam_sync_cv
);
1384 mutex_exit(&mapp
->dam_lock
);
1386 bitset_fini(&uncfg
);
1388 bitset_fini(&delta
);
1392 * per-address stabilization timeout
1395 dam_addr_stable_cb(void *arg
)
1397 dam_t
*mapp
= (dam_t
*)arg
;
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
);
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
);
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
);
1440 if (passp
->da_deadline
<= ts
)
1441 spend
++; /* report has stabilized */
1443 /* not stabilized, determine next map timeout */
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
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
))
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
);
1491 bitset_add(&mapp
->dam_stable_set
, i
);
1493 bitset_del(&mapp
->dam_report_set
, i
);
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.
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
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
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
);
1543 * If map still underoing stabilization reschedule timeout,
1544 * else dispatch the task to configure the new stable set of
1547 if ((mapp
->dam_flags
& DAM_SPEND
) ||
1548 (taskq_dispatch(system_taskq
, dam_stabilize_map
, mapp
,
1549 TQ_NOSLEEP
| TQ_NOQUEUE
) == NULL
)) {
1550 DAM_INCR_STAT(mapp
, dam_overrun
);
1551 mapp
->dam_stable_overrun
++;
1552 dam_sched_timeout(dam_addrset_stable_cb
, mapp
,
1553 drv_usectohz(damap_taskq_dispatch_retry_usec
));
1555 DTRACE_PROBE2(damap__map__addrset__stable__overrun
,
1556 char *, mapp
->dam_name
, dam_t
*, mapp
);
1557 mutex_exit(&mapp
->dam_lock
);
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
1579 dam_sched_timeout(void (*timeout_cb
)(), dam_t
*mapp
, clock_t ticks
)
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) {
1591 mutex_exit(&mapp
->dam_lock
);
1592 (void) untimeout(tid
);
1593 mutex_enter(&mapp
->dam_lock
);
1596 if (timeout_cb
&& (ticks
!= 0))
1597 mapp
->dam_tid
= timeout(timeout_cb
, mapp
, ticks
);
1602 * report addition or removal of an address
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
1631 dam_addr_report_release(dam_t
*mapp
, id_t addrid
)
1634 char *addrstr
= damap_id2addr((damap_t
*)mapp
, addrid
);
1636 DTRACE_PROBE3(damap__addr__report__release
,
1637 char *, mapp
->dam_name
, dam_t
*, mapp
,
1640 ASSERT(mutex_owned(&mapp
->dam_lock
));
1641 passp
= ddi_get_soft_state(mapp
->dam_da
, addrid
);
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
1666 dam_get_addrid(dam_t
*mapp
, char *address
)
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) {
1677 if (ddi_soft_state_zalloc(mapp
->dam_da
, addrid
) !=
1679 ddi_strid_free(mapp
->dam_addr_hash
, addrid
);
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
);
1698 passp
->da_addr
= ddi_strid_id2str(mapp
->dam_addr_hash
,
1699 addrid
); /* for mdb */
1705 * create and install map statistics
1708 dam_kstat_create(dam_t
*mapp
)
1711 struct dam_kstats
*statsp
;
1713 mapsp
= kstat_create("dam", 0, mapp
->dam_name
, "damap",
1715 sizeof (struct dam_kstats
) / sizeof (kstat_named_t
), 0);
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
);