110696SDavid.Hollister@Sun.COM /*
210696SDavid.Hollister@Sun.COM * CDDL HEADER START
310696SDavid.Hollister@Sun.COM *
410696SDavid.Hollister@Sun.COM * The contents of this file are subject to the terms of the
510696SDavid.Hollister@Sun.COM * Common Development and Distribution License (the "License").
610696SDavid.Hollister@Sun.COM * You may not use this file except in compliance with the License.
710696SDavid.Hollister@Sun.COM *
810696SDavid.Hollister@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910696SDavid.Hollister@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010696SDavid.Hollister@Sun.COM * See the License for the specific language governing permissions
1110696SDavid.Hollister@Sun.COM * and limitations under the License.
1210696SDavid.Hollister@Sun.COM *
1310696SDavid.Hollister@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410696SDavid.Hollister@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510696SDavid.Hollister@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610696SDavid.Hollister@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710696SDavid.Hollister@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810696SDavid.Hollister@Sun.COM *
1910696SDavid.Hollister@Sun.COM * CDDL HEADER END
2010696SDavid.Hollister@Sun.COM */
2110696SDavid.Hollister@Sun.COM
2210696SDavid.Hollister@Sun.COM /*
2312207SChris.Horne@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410696SDavid.Hollister@Sun.COM */
2510696SDavid.Hollister@Sun.COM
2610696SDavid.Hollister@Sun.COM #include <sys/note.h>
2710696SDavid.Hollister@Sun.COM #include <sys/types.h>
2810696SDavid.Hollister@Sun.COM #include <sys/param.h>
2910696SDavid.Hollister@Sun.COM #include <sys/systm.h>
3010696SDavid.Hollister@Sun.COM #include <sys/buf.h>
3110696SDavid.Hollister@Sun.COM #include <sys/kmem.h>
3210696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h>
3310696SDavid.Hollister@Sun.COM #include <sys/debug.h>
3410696SDavid.Hollister@Sun.COM #include <sys/sunndi.h>
3510696SDavid.Hollister@Sun.COM #include <sys/kstat.h>
3610696SDavid.Hollister@Sun.COM #include <sys/conf.h>
3710696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h>
3810696SDavid.Hollister@Sun.COM #include <sys/devctl.h>
3910696SDavid.Hollister@Sun.COM #include <sys/callb.h>
4010696SDavid.Hollister@Sun.COM #include <sys/sysevent.h>
4110696SDavid.Hollister@Sun.COM #include <sys/taskq.h>
4210696SDavid.Hollister@Sun.COM #include <sys/ddi.h>
4310696SDavid.Hollister@Sun.COM #include <sys/bitset.h>
4410696SDavid.Hollister@Sun.COM #include <sys/damap.h>
4510696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h>
4610696SDavid.Hollister@Sun.COM
4710696SDavid.Hollister@Sun.COM #ifdef DEBUG
4810696SDavid.Hollister@Sun.COM static int damap_debug = 0;
4910696SDavid.Hollister@Sun.COM #endif /* DEBUG */
5010696SDavid.Hollister@Sun.COM
5111068SJohn.Danielson@Sun.COM extern taskq_t *system_taskq;
5211068SJohn.Danielson@Sun.COM
5310696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *);
5411068SJohn.Danielson@Sun.COM static void dam_addrset_deactivate(dam_t *, bitset_t *);
5511068SJohn.Danielson@Sun.COM static void dam_stabilize_map(void *);
5610696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *);
5711068SJohn.Danielson@Sun.COM static void dam_addrset_stable_cb(void *);
5812207SChris.Horne@Sun.COM static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
5911068SJohn.Danielson@Sun.COM static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
6011068SJohn.Danielson@Sun.COM static void dam_addr_release(dam_t *, id_t);
6111068SJohn.Danielson@Sun.COM static void dam_addr_report_release(dam_t *, id_t);
6211068SJohn.Danielson@Sun.COM static void dam_addr_deactivate(dam_t *, id_t);
6311363SReed.Liu@Sun.COM static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
6410696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *);
6510696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *);
6611068SJohn.Danielson@Sun.COM static int dam_map_alloc(dam_t *);
6710696SDavid.Hollister@Sun.COM
6810696SDavid.Hollister@Sun.COM #define DAM_INCR_STAT(mapp, stat) \
6910696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \
7010696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
7110696SDavid.Hollister@Sun.COM stp->stat.value.ui32++; \
7210696SDavid.Hollister@Sun.COM }
7310696SDavid.Hollister@Sun.COM
7410696SDavid.Hollister@Sun.COM #define DAM_SET_STAT(mapp, stat, val) \
7510696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \
7610696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
7710696SDavid.Hollister@Sun.COM stp->stat.value.ui32 = (val); \
7810696SDavid.Hollister@Sun.COM }
7910696SDavid.Hollister@Sun.COM
8011068SJohn.Danielson@Sun.COM
8111068SJohn.Danielson@Sun.COM /*
8211068SJohn.Danielson@Sun.COM * increase damap size by 64 entries at a time
8311068SJohn.Danielson@Sun.COM */
8411068SJohn.Danielson@Sun.COM #define DAM_SIZE_BUMP 64
8511068SJohn.Danielson@Sun.COM
8611854SChris.Horne@Sun.COM int damap_taskq_dispatch_retry_usec = 1000;
8711854SChris.Horne@Sun.COM
8811068SJohn.Danielson@Sun.COM /*
8911068SJohn.Danielson@Sun.COM * config/unconfig taskq data
9011068SJohn.Danielson@Sun.COM */
9111068SJohn.Danielson@Sun.COM typedef struct {
9211068SJohn.Danielson@Sun.COM dam_t *tqd_mapp;
9311068SJohn.Danielson@Sun.COM id_t tqd_id;
9411068SJohn.Danielson@Sun.COM } cfg_tqd_t;
9511068SJohn.Danielson@Sun.COM
9611068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri;
9711068SJohn.Danielson@Sun.COM
9810696SDavid.Hollister@Sun.COM /*
9910696SDavid.Hollister@Sun.COM * Create new device address map
10010696SDavid.Hollister@Sun.COM *
10111068SJohn.Danielson@Sun.COM * name: map name (kstat unique)
10210696SDavid.Hollister@Sun.COM * size: max # of map entries
10311068SJohn.Danielson@Sun.COM * mode: style of address reports: per-address or fullset
10410696SDavid.Hollister@Sun.COM * stable_usec: # of quiescent microseconds before report/map is stable
10510696SDavid.Hollister@Sun.COM *
10610696SDavid.Hollister@Sun.COM * activate_arg: address provider activation-callout private
10710696SDavid.Hollister@Sun.COM * activate_cb: address provider activation callback handler
10810696SDavid.Hollister@Sun.COM * deactivate_cb: address provider deactivation callback handler
10910696SDavid.Hollister@Sun.COM *
11010696SDavid.Hollister@Sun.COM * config_arg: configuration-callout private
11110696SDavid.Hollister@Sun.COM * config_cb: class configuration callout
11210696SDavid.Hollister@Sun.COM * unconfig_cb: class unconfiguration callout
11310696SDavid.Hollister@Sun.COM *
11410696SDavid.Hollister@Sun.COM * damapp: pointer to map handle (return)
11510696SDavid.Hollister@Sun.COM *
11610696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
11710696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
11810696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure
11910696SDavid.Hollister@Sun.COM */
12010696SDavid.Hollister@Sun.COM int
damap_create(char * name,damap_rptmode_t mode,int map_opts,int stable_usec,void * activate_arg,damap_activate_cb_t activate_cb,damap_deactivate_cb_t deactivate_cb,void * config_arg,damap_configure_cb_t configure_cb,damap_unconfig_cb_t unconfig_cb,damap_t ** damapp)12111068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts,
12212207SChris.Horne@Sun.COM int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
12310696SDavid.Hollister@Sun.COM damap_deactivate_cb_t deactivate_cb,
12410696SDavid.Hollister@Sun.COM void *config_arg, damap_configure_cb_t configure_cb,
12510696SDavid.Hollister@Sun.COM damap_unconfig_cb_t unconfig_cb,
12610696SDavid.Hollister@Sun.COM damap_t **damapp)
12710696SDavid.Hollister@Sun.COM {
12810696SDavid.Hollister@Sun.COM dam_t *mapp;
12910696SDavid.Hollister@Sun.COM
13011068SJohn.Danielson@Sun.COM if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
13110696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
13210696SDavid.Hollister@Sun.COM
13310696SDavid.Hollister@Sun.COM mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
13411068SJohn.Danielson@Sun.COM mapp->dam_options = map_opts;
13512207SChris.Horne@Sun.COM mapp->dam_stable_ticks = drv_usectohz(stable_usec);
13611068SJohn.Danielson@Sun.COM mapp->dam_size = 0;
13711068SJohn.Danielson@Sun.COM mapp->dam_rptmode = mode;
13810696SDavid.Hollister@Sun.COM mapp->dam_activate_arg = activate_arg;
13910696SDavid.Hollister@Sun.COM mapp->dam_activate_cb = (activate_cb_t)activate_cb;
14010696SDavid.Hollister@Sun.COM mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
14110696SDavid.Hollister@Sun.COM mapp->dam_config_arg = config_arg;
14210696SDavid.Hollister@Sun.COM mapp->dam_configure_cb = (configure_cb_t)configure_cb;
14310696SDavid.Hollister@Sun.COM mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
14411068SJohn.Danielson@Sun.COM mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
14510696SDavid.Hollister@Sun.COM mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
14612207SChris.Horne@Sun.COM cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
14711068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_active_set);
14811068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_stable_set);
14911068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_report_set);
15010696SDavid.Hollister@Sun.COM *damapp = (damap_t *)mapp;
151*12399SChris.Horne@Sun.COM
152*12399SChris.Horne@Sun.COM DTRACE_PROBE5(damap__create,
153*12399SChris.Horne@Sun.COM char *, mapp->dam_name, damap_t *, mapp,
154*12399SChris.Horne@Sun.COM damap_rptmode_t, mode, int, map_opts, int, stable_usec);
155*12399SChris.Horne@Sun.COM
15610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
15710696SDavid.Hollister@Sun.COM }
15810696SDavid.Hollister@Sun.COM
15910696SDavid.Hollister@Sun.COM /*
16011068SJohn.Danielson@Sun.COM * Allocate backing resources
16111068SJohn.Danielson@Sun.COM *
16211068SJohn.Danielson@Sun.COM * DAMs are lightly backed on create - major allocations occur
16311068SJohn.Danielson@Sun.COM * at the time a report is made to the map, and are extended on
16411068SJohn.Danielson@Sun.COM * a demand basis.
16511068SJohn.Danielson@Sun.COM */
16611068SJohn.Danielson@Sun.COM static int
dam_map_alloc(dam_t * mapp)16711068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp)
16811068SJohn.Danielson@Sun.COM {
16911068SJohn.Danielson@Sun.COM void *softstate_p;
17011068SJohn.Danielson@Sun.COM
17111068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
17211068SJohn.Danielson@Sun.COM if (mapp->dam_flags & DAM_DESTROYPEND)
17311068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
17411068SJohn.Danielson@Sun.COM
17511068SJohn.Danielson@Sun.COM /*
17611068SJohn.Danielson@Sun.COM * dam_high > 0 signals map allocation complete
17711068SJohn.Danielson@Sun.COM */
17811068SJohn.Danielson@Sun.COM if (mapp->dam_high)
17911068SJohn.Danielson@Sun.COM return (DAM_SUCCESS);
18011068SJohn.Danielson@Sun.COM
18111068SJohn.Danielson@Sun.COM mapp->dam_size = DAM_SIZE_BUMP;
18211068SJohn.Danielson@Sun.COM if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
18311068SJohn.Danielson@Sun.COM mapp->dam_size) != DDI_SUCCESS)
18411068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
18511068SJohn.Danielson@Sun.COM
18611068SJohn.Danielson@Sun.COM if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
18711068SJohn.Danielson@Sun.COM DDI_SUCCESS) {
18811068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p);
18911068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
19011068SJohn.Danielson@Sun.COM }
19111068SJohn.Danielson@Sun.COM if (dam_kstat_create(mapp) != DDI_SUCCESS) {
19211068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p);
19311068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash);
19411068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
19511068SJohn.Danielson@Sun.COM }
19611068SJohn.Danielson@Sun.COM mapp->dam_da = softstate_p;
19711068SJohn.Danielson@Sun.COM mapp->dam_high = 1;
19811068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size);
19911068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
20011068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size);
20111068SJohn.Danielson@Sun.COM return (DAM_SUCCESS);
20211068SJohn.Danielson@Sun.COM }
20311068SJohn.Danielson@Sun.COM
20411068SJohn.Danielson@Sun.COM /*
20511068SJohn.Danielson@Sun.COM * Destroy address map
20610696SDavid.Hollister@Sun.COM *
20710696SDavid.Hollister@Sun.COM * damapp: address map
20810696SDavid.Hollister@Sun.COM *
20910696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
21010696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
21110696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure
21210696SDavid.Hollister@Sun.COM */
21310696SDavid.Hollister@Sun.COM void
damap_destroy(damap_t * damapp)21410696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp)
21510696SDavid.Hollister@Sun.COM {
21610696SDavid.Hollister@Sun.COM int i;
21710696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
21810696SDavid.Hollister@Sun.COM
21910696SDavid.Hollister@Sun.COM ASSERT(mapp);
22010696SDavid.Hollister@Sun.COM
221*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__destroy,
222*12399SChris.Horne@Sun.COM char *, mapp->dam_name, damap_t *, mapp);
22310696SDavid.Hollister@Sun.COM
22411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
22510696SDavid.Hollister@Sun.COM
22610696SDavid.Hollister@Sun.COM /*
22711068SJohn.Danielson@Sun.COM * prevent new reports from being added to the map
22810696SDavid.Hollister@Sun.COM */
22911068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_DESTROYPEND;
23011068SJohn.Danielson@Sun.COM
23111068SJohn.Danielson@Sun.COM if (mapp->dam_high) {
23211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
23311068SJohn.Danielson@Sun.COM /*
23411068SJohn.Danielson@Sun.COM * wait for outstanding reports to stabilize and cancel
23511068SJohn.Danielson@Sun.COM * the timer for this map
23611068SJohn.Danielson@Sun.COM */
23712207SChris.Horne@Sun.COM (void) damap_sync(damapp, 0);
23811068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
23912207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0);
24010696SDavid.Hollister@Sun.COM
24111068SJohn.Danielson@Sun.COM /*
24211068SJohn.Danielson@Sun.COM * map is at full stop
24311068SJohn.Danielson@Sun.COM * release the contents of the map, invoking the
24411068SJohn.Danielson@Sun.COM * detactivation protocol as addresses are released
24511068SJohn.Danielson@Sun.COM */
24611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
24711068SJohn.Danielson@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
24811068SJohn.Danielson@Sun.COM if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
24911068SJohn.Danielson@Sun.COM continue;
25011068SJohn.Danielson@Sun.COM
25111068SJohn.Danielson@Sun.COM ASSERT(DAM_IN_REPORT(mapp, i) == 0);
25211068SJohn.Danielson@Sun.COM
25311068SJohn.Danielson@Sun.COM if (DAM_IS_STABLE(mapp, i)) {
25411068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i);
25511068SJohn.Danielson@Sun.COM } else {
25611068SJohn.Danielson@Sun.COM ddi_strid_free(mapp->dam_addr_hash, i);
25711068SJohn.Danielson@Sun.COM ddi_soft_state_free(mapp->dam_da, i);
25811068SJohn.Danielson@Sun.COM }
25911068SJohn.Danielson@Sun.COM }
26011068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash);
26111068SJohn.Danielson@Sun.COM ddi_soft_state_fini(&mapp->dam_da);
26211068SJohn.Danielson@Sun.COM kstat_delete(mapp->dam_kstatsp);
26312207SChris.Horne@Sun.COM } else
26412207SChris.Horne@Sun.COM mutex_exit(&mapp->dam_lock);
26512207SChris.Horne@Sun.COM
26610696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_active_set);
26710696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_stable_set);
26810696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_report_set);
26910696SDavid.Hollister@Sun.COM mutex_destroy(&mapp->dam_lock);
27012207SChris.Horne@Sun.COM cv_destroy(&mapp->dam_sync_cv);
27110696SDavid.Hollister@Sun.COM if (mapp->dam_name)
27210696SDavid.Hollister@Sun.COM kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
27310696SDavid.Hollister@Sun.COM kmem_free(mapp, sizeof (*mapp));
27410696SDavid.Hollister@Sun.COM }
27510696SDavid.Hollister@Sun.COM
27610696SDavid.Hollister@Sun.COM /*
27712207SChris.Horne@Sun.COM * Wait for map stability. If sync was successfull then return 1.
27812207SChris.Horne@Sun.COM * If called with a non-zero sync_usec, then a return value of 0 means a
27912207SChris.Horne@Sun.COM * timeout occurred prior to sync completion. NOTE: if sync_usec is
28012207SChris.Horne@Sun.COM * non-zero, it should be much longer than dam_stable_ticks.
28110696SDavid.Hollister@Sun.COM *
28210696SDavid.Hollister@Sun.COM * damapp: address map
28312207SChris.Horne@Sun.COM * sync_usec: micorseconds until we give up on sync completion.
28410696SDavid.Hollister@Sun.COM */
28512207SChris.Horne@Sun.COM #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
28610696SDavid.Hollister@Sun.COM int
damap_sync(damap_t * damapp,int sync_usec)28712207SChris.Horne@Sun.COM damap_sync(damap_t *damapp, int sync_usec)
28810696SDavid.Hollister@Sun.COM {
28912207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp;
29012207SChris.Horne@Sun.COM int rv;
29110696SDavid.Hollister@Sun.COM
29210696SDavid.Hollister@Sun.COM ASSERT(mapp);
293*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__map__sync__start,
294*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
295*12399SChris.Horne@Sun.COM int, sync_usec);
29610696SDavid.Hollister@Sun.COM
29711068SJohn.Danielson@Sun.COM /*
29812207SChris.Horne@Sun.COM * Block when waiting for
29912207SChris.Horne@Sun.COM * a) stabilization pending or a fullset update pending
30012207SChris.Horne@Sun.COM * b) the report set to finalize (bitset is null)
30112207SChris.Horne@Sun.COM * c) any scheduled timeouts to fire
30211068SJohn.Danielson@Sun.COM */
30312207SChris.Horne@Sun.COM rv = 1; /* return synced */
30410696SDavid.Hollister@Sun.COM mutex_enter(&mapp->dam_lock);
30512207SChris.Horne@Sun.COM again: while ((mapp->dam_flags & WAITFOR_FLAGS) ||
30612207SChris.Horne@Sun.COM (!bitset_is_null(&mapp->dam_report_set)) ||
30712207SChris.Horne@Sun.COM (mapp->dam_tid != 0)) {
308*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__sync__waiting,
309*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
31012207SChris.Horne@Sun.COM
31112207SChris.Horne@Sun.COM /* Wait for condition relayed via timeout */
31212207SChris.Horne@Sun.COM if (sync_usec) {
31312207SChris.Horne@Sun.COM if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
31412207SChris.Horne@Sun.COM drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
31512207SChris.Horne@Sun.COM mapp->dam_sync_to_cnt++;
31612207SChris.Horne@Sun.COM rv = 0; /* return timeout */
31712207SChris.Horne@Sun.COM break;
31812207SChris.Horne@Sun.COM }
31912207SChris.Horne@Sun.COM } else
32012207SChris.Horne@Sun.COM cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
32110696SDavid.Hollister@Sun.COM }
32210696SDavid.Hollister@Sun.COM
32312207SChris.Horne@Sun.COM if (rv) {
32412207SChris.Horne@Sun.COM /*
32512207SChris.Horne@Sun.COM * Delay one stabilization time after the apparent sync above
32612207SChris.Horne@Sun.COM * and verify accuracy - resync if not accurate.
32712207SChris.Horne@Sun.COM */
32812207SChris.Horne@Sun.COM (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
32912207SChris.Horne@Sun.COM mapp->dam_stable_ticks, TR_MICROSEC);
33012207SChris.Horne@Sun.COM if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
33112207SChris.Horne@Sun.COM (!bitset_is_null(&mapp->dam_report_set)) ||
33212207SChris.Horne@Sun.COM (mapp->dam_tid != 0)))
33312207SChris.Horne@Sun.COM goto again;
33412207SChris.Horne@Sun.COM }
33510696SDavid.Hollister@Sun.COM mutex_exit(&mapp->dam_lock);
33612207SChris.Horne@Sun.COM
337*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__map__sync__end,
338*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
339*12399SChris.Horne@Sun.COM int, rv);
34012207SChris.Horne@Sun.COM return (rv);
34112207SChris.Horne@Sun.COM }
34210696SDavid.Hollister@Sun.COM
34312207SChris.Horne@Sun.COM /*
34412207SChris.Horne@Sun.COM * Return 1 if active set is empty
34512207SChris.Horne@Sun.COM */
34612207SChris.Horne@Sun.COM int
damap_is_empty(damap_t * damapp)34712207SChris.Horne@Sun.COM damap_is_empty(damap_t *damapp)
34812207SChris.Horne@Sun.COM {
34912207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp;
35012207SChris.Horne@Sun.COM int rv;
35112207SChris.Horne@Sun.COM
35212207SChris.Horne@Sun.COM mutex_enter(&mapp->dam_lock);
35312207SChris.Horne@Sun.COM rv = bitset_is_null(&mapp->dam_active_set);
35412207SChris.Horne@Sun.COM mutex_exit(&mapp->dam_lock);
35512207SChris.Horne@Sun.COM return (rv);
35610696SDavid.Hollister@Sun.COM }
35710696SDavid.Hollister@Sun.COM
35810696SDavid.Hollister@Sun.COM /*
35910696SDavid.Hollister@Sun.COM * Get the name of a device address map
36010696SDavid.Hollister@Sun.COM *
36110696SDavid.Hollister@Sun.COM * damapp: address map
36210696SDavid.Hollister@Sun.COM *
36310696SDavid.Hollister@Sun.COM * Returns: name
36410696SDavid.Hollister@Sun.COM */
36510696SDavid.Hollister@Sun.COM char *
damap_name(damap_t * damapp)36610696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp)
36710696SDavid.Hollister@Sun.COM {
36810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
36910696SDavid.Hollister@Sun.COM
37010696SDavid.Hollister@Sun.COM return (mapp ? mapp->dam_name : "UNKNOWN_damap");
37110696SDavid.Hollister@Sun.COM }
37210696SDavid.Hollister@Sun.COM
37310696SDavid.Hollister@Sun.COM /*
37412207SChris.Horne@Sun.COM * Get the current size of the device address map
37512207SChris.Horne@Sun.COM *
37612207SChris.Horne@Sun.COM * damapp: address map
37712207SChris.Horne@Sun.COM *
37812207SChris.Horne@Sun.COM * Returns: size
37912207SChris.Horne@Sun.COM */
38012207SChris.Horne@Sun.COM int
damap_size(damap_t * damapp)38112207SChris.Horne@Sun.COM damap_size(damap_t *damapp)
38212207SChris.Horne@Sun.COM {
38312207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp;
38412207SChris.Horne@Sun.COM
38512207SChris.Horne@Sun.COM return (mapp->dam_size);
38612207SChris.Horne@Sun.COM }
38712207SChris.Horne@Sun.COM
38812207SChris.Horne@Sun.COM /*
38910696SDavid.Hollister@Sun.COM * Report an address to per-address report
39010696SDavid.Hollister@Sun.COM *
39110696SDavid.Hollister@Sun.COM * damapp: address map handle
39210696SDavid.Hollister@Sun.COM * address: address in ascii string representation
39311068SJohn.Danielson@Sun.COM * addridp: address ID
39410696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data
39510696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private (passed to activate/deactivate cb)
39610696SDavid.Hollister@Sun.COM *
39710696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
39810696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
39910696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted
40010696SDavid.Hollister@Sun.COM */
40110696SDavid.Hollister@Sun.COM int
damap_addr_add(damap_t * damapp,char * address,damap_id_t * addridp,nvlist_t * nvl,void * addr_priv)40211068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
40311068SJohn.Danielson@Sun.COM nvlist_t *nvl, void *addr_priv)
40410696SDavid.Hollister@Sun.COM {
40510696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
40610696SDavid.Hollister@Sun.COM id_t addrid;
40710696SDavid.Hollister@Sun.COM dam_da_t *passp;
40810696SDavid.Hollister@Sun.COM
40911068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
41010696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
41110696SDavid.Hollister@Sun.COM
412*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__add,
413*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
414*12399SChris.Horne@Sun.COM char *, address);
41511068SJohn.Danielson@Sun.COM
41611068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
41711068SJohn.Danielson@Sun.COM if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
41811068SJohn.Danielson@Sun.COM ((addrid = dam_get_addrid(mapp, address)) == 0)) {
41911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
42010696SDavid.Hollister@Sun.COM return (DAM_MAPFULL);
42110696SDavid.Hollister@Sun.COM }
42210696SDavid.Hollister@Sun.COM
42310696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
42410696SDavid.Hollister@Sun.COM ASSERT(passp != NULL);
42510696SDavid.Hollister@Sun.COM
42610696SDavid.Hollister@Sun.COM /*
42710696SDavid.Hollister@Sun.COM * If re-reporting the same address (add or remove) clear
42810696SDavid.Hollister@Sun.COM * the existing report
42910696SDavid.Hollister@Sun.COM */
43010696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) {
431*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__add__jitter,
432*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
433*12399SChris.Horne@Sun.COM char *, address);
43411068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter);
43511068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid);
43610696SDavid.Hollister@Sun.COM passp->da_jitter++;
43710696SDavid.Hollister@Sun.COM }
43810696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv;
43910696SDavid.Hollister@Sun.COM if (nvl)
44010696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
44110696SDavid.Hollister@Sun.COM
44211068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
44311068SJohn.Danielson@Sun.COM if (addridp != NULL)
44411068SJohn.Danielson@Sun.COM *addridp = (damap_id_t)addrid;
44511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
44610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
44710696SDavid.Hollister@Sun.COM }
44810696SDavid.Hollister@Sun.COM
44910696SDavid.Hollister@Sun.COM /*
45010696SDavid.Hollister@Sun.COM * Report removal of address from per-address report
45110696SDavid.Hollister@Sun.COM *
45210696SDavid.Hollister@Sun.COM * damapp: address map
45310696SDavid.Hollister@Sun.COM * address: address in ascii string representation
45410696SDavid.Hollister@Sun.COM *
45510696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
45610696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
45710696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure
45810696SDavid.Hollister@Sun.COM */
45910696SDavid.Hollister@Sun.COM int
damap_addr_del(damap_t * damapp,char * address)46010696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address)
46110696SDavid.Hollister@Sun.COM {
46210696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
46310696SDavid.Hollister@Sun.COM id_t addrid;
46410696SDavid.Hollister@Sun.COM dam_da_t *passp;
46510696SDavid.Hollister@Sun.COM
46611068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
46710696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
46810696SDavid.Hollister@Sun.COM
469*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__del,
470*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
471*12399SChris.Horne@Sun.COM char *, address);
47211068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
47311068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) {
47411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
47511068SJohn.Danielson@Sun.COM return (DAM_MAPFULL);
47611068SJohn.Danielson@Sun.COM }
47711068SJohn.Danielson@Sun.COM
47811068SJohn.Danielson@Sun.COM /*
47911068SJohn.Danielson@Sun.COM * if reporting the removal of an address which is not in the map
48011068SJohn.Danielson@Sun.COM * return success
48111068SJohn.Danielson@Sun.COM */
48210696SDavid.Hollister@Sun.COM if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
48311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
48410696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
48510696SDavid.Hollister@Sun.COM }
48610696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
48710696SDavid.Hollister@Sun.COM ASSERT(passp);
48810696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) {
489*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__del__jitter,
490*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
491*12399SChris.Horne@Sun.COM char *, address);
49211068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter);
49311068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid);
49410696SDavid.Hollister@Sun.COM passp->da_jitter++;
49510696SDavid.Hollister@Sun.COM }
49611068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
49711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
49810696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
49910696SDavid.Hollister@Sun.COM }
50010696SDavid.Hollister@Sun.COM
50112000SReed.Liu@Sun.COM static int
damap_addrset_flush_locked(damap_t * damapp)50212000SReed.Liu@Sun.COM damap_addrset_flush_locked(damap_t *damapp)
50312000SReed.Liu@Sun.COM {
50412207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp;
50512000SReed.Liu@Sun.COM int idx;
50612000SReed.Liu@Sun.COM
50712000SReed.Liu@Sun.COM ASSERT(mapp);
50812000SReed.Liu@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
50912000SReed.Liu@Sun.COM if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
51012000SReed.Liu@Sun.COM return (DAM_EINVAL);
51112000SReed.Liu@Sun.COM }
51212000SReed.Liu@Sun.COM
513*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__flush__locked__enter,
514*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
51512000SReed.Liu@Sun.COM if (mapp->dam_flags & DAM_SETADD) {
516*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__flush__locked__reset,
517*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
51812000SReed.Liu@Sun.COM
51912000SReed.Liu@Sun.COM /*
52012000SReed.Liu@Sun.COM * cancel stabilization timeout
52112000SReed.Liu@Sun.COM */
52212207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0);
52312000SReed.Liu@Sun.COM DAM_INCR_STAT(mapp, dam_jitter);
52412000SReed.Liu@Sun.COM
52512000SReed.Liu@Sun.COM /*
52612000SReed.Liu@Sun.COM * clear pending reports
52712000SReed.Liu@Sun.COM */
52812000SReed.Liu@Sun.COM for (idx = 1; idx < mapp->dam_high; idx++) {
52912000SReed.Liu@Sun.COM if (DAM_IN_REPORT(mapp, idx)) {
53012000SReed.Liu@Sun.COM dam_addr_report_release(mapp, idx);
53112000SReed.Liu@Sun.COM }
53212000SReed.Liu@Sun.COM }
53312000SReed.Liu@Sun.COM
53412000SReed.Liu@Sun.COM bitset_zero(&mapp->dam_report_set);
53512000SReed.Liu@Sun.COM mapp->dam_flags &= ~DAM_SETADD;
53612207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv);
53712000SReed.Liu@Sun.COM }
53812000SReed.Liu@Sun.COM
53912000SReed.Liu@Sun.COM return (DAM_SUCCESS);
54012000SReed.Liu@Sun.COM }
54112000SReed.Liu@Sun.COM
54210696SDavid.Hollister@Sun.COM /*
54310696SDavid.Hollister@Sun.COM * Initiate full-set report
54410696SDavid.Hollister@Sun.COM *
54510696SDavid.Hollister@Sun.COM * damapp: address map
54610696SDavid.Hollister@Sun.COM *
54710696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
54810696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
54910696SDavid.Hollister@Sun.COM */
55010696SDavid.Hollister@Sun.COM int
damap_addrset_begin(damap_t * damapp)55110696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp)
55210696SDavid.Hollister@Sun.COM {
55312000SReed.Liu@Sun.COM dam_t *mapp = (dam_t *)damapp;
55412000SReed.Liu@Sun.COM int rv;
55510696SDavid.Hollister@Sun.COM
55612000SReed.Liu@Sun.COM if (mapp == NULL) {
55710696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
55812000SReed.Liu@Sun.COM }
55910696SDavid.Hollister@Sun.COM
560*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__begin,
561*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
56212000SReed.Liu@Sun.COM
56311068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
56411068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) {
56511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
56612000SReed.Liu@Sun.COM
56711068SJohn.Danielson@Sun.COM return (DAM_MAPFULL);
56811068SJohn.Danielson@Sun.COM }
56912000SReed.Liu@Sun.COM
57012000SReed.Liu@Sun.COM rv = damap_addrset_flush_locked(damapp);
57112000SReed.Liu@Sun.COM if (rv == DAM_SUCCESS) {
57212000SReed.Liu@Sun.COM mapp->dam_flags |= DAM_SETADD;
57312000SReed.Liu@Sun.COM }
57412000SReed.Liu@Sun.COM mutex_exit(&mapp->dam_lock);
57512000SReed.Liu@Sun.COM
57612000SReed.Liu@Sun.COM return (rv);
57712000SReed.Liu@Sun.COM }
57811068SJohn.Danielson@Sun.COM
57912000SReed.Liu@Sun.COM /*
58012000SReed.Liu@Sun.COM * Cancel full-set report
58112000SReed.Liu@Sun.COM *
58212207SChris.Horne@Sun.COM * damapp: address map
58312000SReed.Liu@Sun.COM *
58412207SChris.Horne@Sun.COM * Returns: DAM_SUCCESS
58512207SChris.Horne@Sun.COM * DAM_EINVAL Invalid argument(s)
58612000SReed.Liu@Sun.COM */
58712000SReed.Liu@Sun.COM int
damap_addrset_flush(damap_t * damapp)58812000SReed.Liu@Sun.COM damap_addrset_flush(damap_t *damapp)
58912000SReed.Liu@Sun.COM {
59012000SReed.Liu@Sun.COM int rv;
59112000SReed.Liu@Sun.COM dam_t *mapp = (dam_t *)damapp;
59212000SReed.Liu@Sun.COM
59312000SReed.Liu@Sun.COM if (mapp == NULL) {
59412000SReed.Liu@Sun.COM return (DAM_EINVAL);
59510696SDavid.Hollister@Sun.COM }
59612000SReed.Liu@Sun.COM
597*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__flush,
598*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
59912000SReed.Liu@Sun.COM
60012000SReed.Liu@Sun.COM mutex_enter(&mapp->dam_lock);
60112000SReed.Liu@Sun.COM rv = damap_addrset_flush_locked(damapp);
60211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
60312000SReed.Liu@Sun.COM
60412000SReed.Liu@Sun.COM return (rv);
60510696SDavid.Hollister@Sun.COM }
60610696SDavid.Hollister@Sun.COM
60710696SDavid.Hollister@Sun.COM /*
60810696SDavid.Hollister@Sun.COM * Report address to full-set report
60910696SDavid.Hollister@Sun.COM *
61010696SDavid.Hollister@Sun.COM * damapp: address map handle
61110696SDavid.Hollister@Sun.COM * address: address in ascii string representation
61210696SDavid.Hollister@Sun.COM * rindx: index if address stabilizes
61310696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data
61410696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private data (passed to activate/release cb)
61510696SDavid.Hollister@Sun.COM *
61610696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
61710696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
61810696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted
61910696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure
62010696SDavid.Hollister@Sun.COM */
62110696SDavid.Hollister@Sun.COM int
damap_addrset_add(damap_t * damapp,char * address,damap_id_t * ridx,nvlist_t * nvl,void * addr_priv)62210696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
62310696SDavid.Hollister@Sun.COM nvlist_t *nvl, void *addr_priv)
62410696SDavid.Hollister@Sun.COM {
62510696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
62610696SDavid.Hollister@Sun.COM id_t addrid;
62710696SDavid.Hollister@Sun.COM dam_da_t *passp;
62810696SDavid.Hollister@Sun.COM
62911068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
63010696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
63110696SDavid.Hollister@Sun.COM
632*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addrset__add,
633*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp, char *, address);
63410696SDavid.Hollister@Sun.COM
63511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
63611068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) {
63711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
63811068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
63911068SJohn.Danielson@Sun.COM }
64011068SJohn.Danielson@Sun.COM
64110696SDavid.Hollister@Sun.COM if ((addrid = dam_get_addrid(mapp, address)) == 0) {
64211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
64310696SDavid.Hollister@Sun.COM return (DAM_MAPFULL);
64410696SDavid.Hollister@Sun.COM }
64510696SDavid.Hollister@Sun.COM
64610696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
64710696SDavid.Hollister@Sun.COM ASSERT(passp);
64810696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) {
649*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addrset__add__jitter,
650*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
651*12399SChris.Horne@Sun.COM char *, address);
65211068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid);
65310696SDavid.Hollister@Sun.COM passp->da_jitter++;
65410696SDavid.Hollister@Sun.COM }
65510696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv;
65610696SDavid.Hollister@Sun.COM if (nvl)
65710696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
65810696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid);
65910696SDavid.Hollister@Sun.COM if (ridx)
66010696SDavid.Hollister@Sun.COM *ridx = (damap_id_t)addrid;
66111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
66210696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
66310696SDavid.Hollister@Sun.COM }
66410696SDavid.Hollister@Sun.COM
66510696SDavid.Hollister@Sun.COM /*
66610696SDavid.Hollister@Sun.COM * Commit full-set report for stabilization
66710696SDavid.Hollister@Sun.COM *
66810696SDavid.Hollister@Sun.COM * damapp: address map handle
66910696SDavid.Hollister@Sun.COM * flags: (currently 0)
67010696SDavid.Hollister@Sun.COM *
67110696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
67210696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s)
67310696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure
67410696SDavid.Hollister@Sun.COM */
67510696SDavid.Hollister@Sun.COM int
damap_addrset_end(damap_t * damapp,int flags)67610696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags)
67710696SDavid.Hollister@Sun.COM {
67810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
67910696SDavid.Hollister@Sun.COM int i;
68010696SDavid.Hollister@Sun.COM
68111068SJohn.Danielson@Sun.COM if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
68210696SDavid.Hollister@Sun.COM return (DAM_EINVAL);
68310696SDavid.Hollister@Sun.COM
684*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__end,
685*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
68610696SDavid.Hollister@Sun.COM
68711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
68811068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) {
68911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
69011068SJohn.Danielson@Sun.COM return (DAM_FAILURE);
69111068SJohn.Danielson@Sun.COM }
69211068SJohn.Danielson@Sun.COM
69311068SJohn.Danielson@Sun.COM if (flags & DAMAP_END_RESET) {
694*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__end__reset,
695*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
69612207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0);
69710696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++)
69810696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, i))
69911068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, i);
70010696SDavid.Hollister@Sun.COM } else {
70110696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime();
70212207SChris.Horne@Sun.COM dam_sched_timeout(dam_addrset_stable_cb, mapp,
70312207SChris.Horne@Sun.COM mapp->dam_stable_ticks);
70410696SDavid.Hollister@Sun.COM }
70511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
70610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS);
70710696SDavid.Hollister@Sun.COM }
70810696SDavid.Hollister@Sun.COM
70910696SDavid.Hollister@Sun.COM /*
71010696SDavid.Hollister@Sun.COM * Return nvlist registered with reported address
71110696SDavid.Hollister@Sun.COM *
71210696SDavid.Hollister@Sun.COM * damapp: address map handle
71311068SJohn.Danielson@Sun.COM * addrid: address ID
71410696SDavid.Hollister@Sun.COM *
71510696SDavid.Hollister@Sun.COM * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
71610696SDavid.Hollister@Sun.COM * NULL
71710696SDavid.Hollister@Sun.COM */
71810696SDavid.Hollister@Sun.COM nvlist_t *
damap_id2nvlist(damap_t * damapp,damap_id_t addrid)71910696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
72010696SDavid.Hollister@Sun.COM {
72110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
72210696SDavid.Hollister@Sun.COM dam_da_t *pass;
72310696SDavid.Hollister@Sun.COM
72411068SJohn.Danielson@Sun.COM if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
72511068SJohn.Danielson@Sun.COM if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
72610696SDavid.Hollister@Sun.COM return (pass->da_nvl);
72710696SDavid.Hollister@Sun.COM }
72810696SDavid.Hollister@Sun.COM return (NULL);
72910696SDavid.Hollister@Sun.COM }
73010696SDavid.Hollister@Sun.COM
73110696SDavid.Hollister@Sun.COM /*
73210696SDavid.Hollister@Sun.COM * Return address string
73310696SDavid.Hollister@Sun.COM *
73410696SDavid.Hollister@Sun.COM * damapp: address map handle
73511068SJohn.Danielson@Sun.COM * addrid: address ID
73610696SDavid.Hollister@Sun.COM *
73710696SDavid.Hollister@Sun.COM * Returns: char * Address string
73810696SDavid.Hollister@Sun.COM * NULL
73910696SDavid.Hollister@Sun.COM */
74010696SDavid.Hollister@Sun.COM char *
damap_id2addr(damap_t * damapp,damap_id_t addrid)74111068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid)
74210696SDavid.Hollister@Sun.COM {
74310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
74410696SDavid.Hollister@Sun.COM
74511068SJohn.Danielson@Sun.COM if (mapp->dam_high)
74611068SJohn.Danielson@Sun.COM return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
74711068SJohn.Danielson@Sun.COM else
74811068SJohn.Danielson@Sun.COM return (NULL);
74910696SDavid.Hollister@Sun.COM }
75010696SDavid.Hollister@Sun.COM
75110696SDavid.Hollister@Sun.COM /*
75210696SDavid.Hollister@Sun.COM * Release address reference in map
75310696SDavid.Hollister@Sun.COM *
75410696SDavid.Hollister@Sun.COM * damapp: address map handle
75511068SJohn.Danielson@Sun.COM * addrid: address ID
75610696SDavid.Hollister@Sun.COM */
75710696SDavid.Hollister@Sun.COM void
damap_id_rele(damap_t * damapp,damap_id_t addrid)75810696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid)
75910696SDavid.Hollister@Sun.COM {
76010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
76111068SJohn.Danielson@Sun.COM dam_da_t *passp;
76211068SJohn.Danielson@Sun.COM char *addr;
76310696SDavid.Hollister@Sun.COM
76411068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
76511068SJohn.Danielson@Sun.COM ASSERT(passp);
76611068SJohn.Danielson@Sun.COM
76711068SJohn.Danielson@Sun.COM addr = damap_id2addr(damapp, addrid);
768*12399SChris.Horne@Sun.COM DTRACE_PROBE4(damap__id__rele,
769*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
770*12399SChris.Horne@Sun.COM char *, addr, int, passp->da_ref);
77111068SJohn.Danielson@Sun.COM
77211068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
77311068SJohn.Danielson@Sun.COM
77411068SJohn.Danielson@Sun.COM /*
77511068SJohn.Danielson@Sun.COM * teardown address if last outstanding reference
77611068SJohn.Danielson@Sun.COM */
77711068SJohn.Danielson@Sun.COM if (--passp->da_ref == 0)
77811068SJohn.Danielson@Sun.COM dam_addr_release(mapp, (id_t)addrid);
77911068SJohn.Danielson@Sun.COM
78011068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
78110696SDavid.Hollister@Sun.COM }
78210696SDavid.Hollister@Sun.COM
78310696SDavid.Hollister@Sun.COM /*
78410696SDavid.Hollister@Sun.COM * Return current reference count on address reference in map
78510696SDavid.Hollister@Sun.COM *
78610696SDavid.Hollister@Sun.COM * damapp: address map handle
78711068SJohn.Danielson@Sun.COM * addrid: address ID
78810696SDavid.Hollister@Sun.COM *
78910696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS
79010696SDavid.Hollister@Sun.COM * DAM_FAILURE
79110696SDavid.Hollister@Sun.COM */
79210696SDavid.Hollister@Sun.COM int
damap_id_ref(damap_t * damapp,damap_id_t addrid)79311068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid)
79410696SDavid.Hollister@Sun.COM {
79510696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
79610696SDavid.Hollister@Sun.COM dam_da_t *passp;
79710696SDavid.Hollister@Sun.COM int ref = -1;
79810696SDavid.Hollister@Sun.COM
79911068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
80010696SDavid.Hollister@Sun.COM if (passp)
80110696SDavid.Hollister@Sun.COM ref = passp->da_ref;
80211068SJohn.Danielson@Sun.COM
80310696SDavid.Hollister@Sun.COM return (ref);
80410696SDavid.Hollister@Sun.COM }
80510696SDavid.Hollister@Sun.COM
80610696SDavid.Hollister@Sun.COM /*
80710696SDavid.Hollister@Sun.COM * Return next address ID in list
80810696SDavid.Hollister@Sun.COM *
80910696SDavid.Hollister@Sun.COM * damapp: address map handle
81010696SDavid.Hollister@Sun.COM * damap_list: address ID list passed to config|unconfig
81110696SDavid.Hollister@Sun.COM * returned by look by lookup_all
81210696SDavid.Hollister@Sun.COM * last: last ID returned, 0 is start of list
81310696SDavid.Hollister@Sun.COM *
81410696SDavid.Hollister@Sun.COM * Returns: addrid Next ID from the list
81510696SDavid.Hollister@Sun.COM * 0 End of the list
81610696SDavid.Hollister@Sun.COM */
81710696SDavid.Hollister@Sun.COM damap_id_t
damap_id_next(damap_t * damapp,damap_id_list_t damap_list,damap_id_t last)81810696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
81910696SDavid.Hollister@Sun.COM {
82010696SDavid.Hollister@Sun.COM int i, start;
82110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
82210696SDavid.Hollister@Sun.COM bitset_t *dam_list = (bitset_t *)damap_list;
82310696SDavid.Hollister@Sun.COM
82410696SDavid.Hollister@Sun.COM if (!mapp || !dam_list)
82510696SDavid.Hollister@Sun.COM return ((damap_id_t)0);
82610696SDavid.Hollister@Sun.COM
82710696SDavid.Hollister@Sun.COM start = (int)last + 1;
82811068SJohn.Danielson@Sun.COM for (i = start; i < mapp->dam_high; i++) {
82911068SJohn.Danielson@Sun.COM if (bitset_in_set(dam_list, i)) {
83010696SDavid.Hollister@Sun.COM return ((damap_id_t)i);
83111068SJohn.Danielson@Sun.COM }
83211068SJohn.Danielson@Sun.COM }
83310696SDavid.Hollister@Sun.COM return ((damap_id_t)0);
83410696SDavid.Hollister@Sun.COM }
83510696SDavid.Hollister@Sun.COM
83610696SDavid.Hollister@Sun.COM /*
83710696SDavid.Hollister@Sun.COM * Set config private data
83810696SDavid.Hollister@Sun.COM *
83910696SDavid.Hollister@Sun.COM * damapp: address map handle
84011068SJohn.Danielson@Sun.COM * addrid: address ID
84110696SDavid.Hollister@Sun.COM * cfg_priv: configuration private data
84210696SDavid.Hollister@Sun.COM *
84310696SDavid.Hollister@Sun.COM */
84410696SDavid.Hollister@Sun.COM void
damap_id_priv_set(damap_t * damapp,damap_id_t addrid,void * cfg_priv)84511068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
84610696SDavid.Hollister@Sun.COM {
84710696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
84810696SDavid.Hollister@Sun.COM dam_da_t *passp;
84910696SDavid.Hollister@Sun.COM
85011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
85111068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
85210696SDavid.Hollister@Sun.COM if (!passp) {
85311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
85410696SDavid.Hollister@Sun.COM return;
85510696SDavid.Hollister@Sun.COM }
85610696SDavid.Hollister@Sun.COM passp->da_cfg_priv = cfg_priv;
85711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
85810696SDavid.Hollister@Sun.COM }
85910696SDavid.Hollister@Sun.COM
86010696SDavid.Hollister@Sun.COM /*
86110696SDavid.Hollister@Sun.COM * Get config private data
86210696SDavid.Hollister@Sun.COM *
86310696SDavid.Hollister@Sun.COM * damapp: address map handle
86411068SJohn.Danielson@Sun.COM * addrid: address ID
86510696SDavid.Hollister@Sun.COM *
86610696SDavid.Hollister@Sun.COM * Returns: configuration private data
86710696SDavid.Hollister@Sun.COM */
86810696SDavid.Hollister@Sun.COM void *
damap_id_priv_get(damap_t * damapp,damap_id_t addrid)86911068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
87010696SDavid.Hollister@Sun.COM {
87110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
87210696SDavid.Hollister@Sun.COM dam_da_t *passp;
87310696SDavid.Hollister@Sun.COM void *rv;
87410696SDavid.Hollister@Sun.COM
87511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
87611068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
87710696SDavid.Hollister@Sun.COM if (!passp) {
87811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
87910696SDavid.Hollister@Sun.COM return (NULL);
88010696SDavid.Hollister@Sun.COM }
88110696SDavid.Hollister@Sun.COM rv = passp->da_cfg_priv;
88211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
88310696SDavid.Hollister@Sun.COM return (rv);
88410696SDavid.Hollister@Sun.COM }
88510696SDavid.Hollister@Sun.COM
88610696SDavid.Hollister@Sun.COM /*
88710696SDavid.Hollister@Sun.COM * Lookup a single address in the active address map
88810696SDavid.Hollister@Sun.COM *
88910696SDavid.Hollister@Sun.COM * damapp: address map handle
89010696SDavid.Hollister@Sun.COM * address: address string
89110696SDavid.Hollister@Sun.COM *
89210696SDavid.Hollister@Sun.COM * Returns: ID of active/stable address
89310696SDavid.Hollister@Sun.COM * 0 Address not in stable set
89410696SDavid.Hollister@Sun.COM *
89510696SDavid.Hollister@Sun.COM * Future: Allow the caller to wait for stabilize before returning not found.
89610696SDavid.Hollister@Sun.COM */
89710696SDavid.Hollister@Sun.COM damap_id_t
damap_lookup(damap_t * damapp,char * address)89810696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address)
89910696SDavid.Hollister@Sun.COM {
90010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
90110696SDavid.Hollister@Sun.COM id_t addrid = 0;
90210696SDavid.Hollister@Sun.COM dam_da_t *passp = NULL;
90310696SDavid.Hollister@Sun.COM
904*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__lookup,
905*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
906*12399SChris.Horne@Sun.COM char *, address);
90711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
90811068SJohn.Danielson@Sun.COM if (!mapp->dam_high)
90911068SJohn.Danielson@Sun.COM addrid = 0;
91011068SJohn.Danielson@Sun.COM else
91111068SJohn.Danielson@Sun.COM addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
91210696SDavid.Hollister@Sun.COM if (addrid) {
91310696SDavid.Hollister@Sun.COM if (DAM_IS_STABLE(mapp, addrid)) {
91410696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
91510696SDavid.Hollister@Sun.COM ASSERT(passp);
91610696SDavid.Hollister@Sun.COM if (passp) {
91710696SDavid.Hollister@Sun.COM passp->da_ref++;
91810696SDavid.Hollister@Sun.COM } else {
91910696SDavid.Hollister@Sun.COM addrid = 0;
92010696SDavid.Hollister@Sun.COM }
92110696SDavid.Hollister@Sun.COM } else {
92210696SDavid.Hollister@Sun.COM addrid = 0;
92310696SDavid.Hollister@Sun.COM }
92410696SDavid.Hollister@Sun.COM }
92511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
926*12399SChris.Horne@Sun.COM DTRACE_PROBE4(damap__lookup__return,
927*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
928*12399SChris.Horne@Sun.COM char *, address, int, addrid);
92910696SDavid.Hollister@Sun.COM return ((damap_id_t)addrid);
93010696SDavid.Hollister@Sun.COM }
93110696SDavid.Hollister@Sun.COM
93210696SDavid.Hollister@Sun.COM
93310696SDavid.Hollister@Sun.COM /*
93410696SDavid.Hollister@Sun.COM * Return the list of stable addresses in the map
93510696SDavid.Hollister@Sun.COM *
93610696SDavid.Hollister@Sun.COM * damapp: address map handle
93710696SDavid.Hollister@Sun.COM * id_listp: pointer to list of address IDs in stable map (returned)
93810696SDavid.Hollister@Sun.COM *
93910696SDavid.Hollister@Sun.COM * Returns: # of entries returned in alist
94010696SDavid.Hollister@Sun.COM */
94110696SDavid.Hollister@Sun.COM int
damap_lookup_all(damap_t * damapp,damap_id_list_t * id_listp)94210696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
94310696SDavid.Hollister@Sun.COM {
94410696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
94510696SDavid.Hollister@Sun.COM int mapsz = mapp->dam_size;
94610696SDavid.Hollister@Sun.COM int n_ids, i;
94710696SDavid.Hollister@Sun.COM bitset_t *bsp;
94811068SJohn.Danielson@Sun.COM char *addrp;
94910696SDavid.Hollister@Sun.COM dam_da_t *passp;
95010696SDavid.Hollister@Sun.COM
951*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__lookup__all,
952*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
95311068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
95411068SJohn.Danielson@Sun.COM if (!mapp->dam_high) {
95511068SJohn.Danielson@Sun.COM *id_listp = (damap_id_list_t)NULL;
95611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
957*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__lookup__all__nomap,
958*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
95911068SJohn.Danielson@Sun.COM return (0);
96011068SJohn.Danielson@Sun.COM }
96110696SDavid.Hollister@Sun.COM bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
96210696SDavid.Hollister@Sun.COM bitset_init(bsp);
96310696SDavid.Hollister@Sun.COM bitset_resize(bsp, mapsz);
96410696SDavid.Hollister@Sun.COM bitset_copy(&mapp->dam_active_set, bsp);
96510696SDavid.Hollister@Sun.COM for (n_ids = 0, i = 1; i < mapsz; i++) {
96610696SDavid.Hollister@Sun.COM if (bitset_in_set(bsp, i)) {
96710696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i);
96810696SDavid.Hollister@Sun.COM ASSERT(passp);
96910696SDavid.Hollister@Sun.COM if (passp) {
97011068SJohn.Danielson@Sun.COM addrp = damap_id2addr(damapp, i);
971*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__lookup__all__item,
972*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
973*12399SChris.Horne@Sun.COM char *, addrp);
97410696SDavid.Hollister@Sun.COM passp->da_ref++;
97510696SDavid.Hollister@Sun.COM n_ids++;
97610696SDavid.Hollister@Sun.COM }
97710696SDavid.Hollister@Sun.COM }
97810696SDavid.Hollister@Sun.COM }
97910696SDavid.Hollister@Sun.COM if (n_ids) {
98010696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)bsp;
98111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
98210696SDavid.Hollister@Sun.COM return (n_ids);
98310696SDavid.Hollister@Sun.COM } else {
98410696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)NULL;
98510696SDavid.Hollister@Sun.COM bitset_fini(bsp);
98610696SDavid.Hollister@Sun.COM kmem_free(bsp, sizeof (*bsp));
98711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
98810696SDavid.Hollister@Sun.COM return (0);
98910696SDavid.Hollister@Sun.COM }
99010696SDavid.Hollister@Sun.COM }
99110696SDavid.Hollister@Sun.COM
99210696SDavid.Hollister@Sun.COM /*
99310696SDavid.Hollister@Sun.COM * Release the address list returned by damap_lookup_all()
99410696SDavid.Hollister@Sun.COM *
99510696SDavid.Hollister@Sun.COM * mapp: address map handle
99610696SDavid.Hollister@Sun.COM * id_list: list of address IDs returned in damap_lookup_all()
99710696SDavid.Hollister@Sun.COM */
99810696SDavid.Hollister@Sun.COM void
damap_id_list_rele(damap_t * damapp,damap_id_list_t id_list)99910696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
100010696SDavid.Hollister@Sun.COM {
100110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp;
100210696SDavid.Hollister@Sun.COM int i;
100310696SDavid.Hollister@Sun.COM
100410696SDavid.Hollister@Sun.COM if (id_list == NULL)
100510696SDavid.Hollister@Sun.COM return;
100610696SDavid.Hollister@Sun.COM
100711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
100810696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
100910696SDavid.Hollister@Sun.COM if (bitset_in_set((bitset_t *)id_list, i))
101011068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, i);
101110696SDavid.Hollister@Sun.COM }
101211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
101310696SDavid.Hollister@Sun.COM bitset_fini((bitset_t *)id_list);
101410696SDavid.Hollister@Sun.COM kmem_free((void *)id_list, sizeof (bitset_t));
101510696SDavid.Hollister@Sun.COM }
101610696SDavid.Hollister@Sun.COM
101710696SDavid.Hollister@Sun.COM /*
101811068SJohn.Danielson@Sun.COM * activate an address that has passed the stabilization interval
101911068SJohn.Danielson@Sun.COM */
102011068SJohn.Danielson@Sun.COM static void
dam_addr_activate(dam_t * mapp,id_t addrid)102111068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid)
102211068SJohn.Danielson@Sun.COM {
102311068SJohn.Danielson@Sun.COM dam_da_t *passp;
102411068SJohn.Danielson@Sun.COM int config_rv;
102511068SJohn.Danielson@Sun.COM char *addrstr;
102611068SJohn.Danielson@Sun.COM
102711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
102811068SJohn.Danielson@Sun.COM bitset_add(&mapp->dam_active_set, addrid);
102911068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
103011068SJohn.Danielson@Sun.COM ASSERT(passp);
103111068SJohn.Danielson@Sun.COM
103211068SJohn.Danielson@Sun.COM /*
103311068SJohn.Danielson@Sun.COM * copy the reported nvlist and provider private data
103411068SJohn.Danielson@Sun.COM */
103511068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1036*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__activate__start,
1037*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1038*12399SChris.Horne@Sun.COM char *, addrstr);
103911068SJohn.Danielson@Sun.COM passp->da_nvl = passp->da_nvl_rpt;
104011068SJohn.Danielson@Sun.COM passp->da_ppriv = passp->da_ppriv_rpt;
104111068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL;
104211068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL;
104311068SJohn.Danielson@Sun.COM passp->da_last_stable = gethrtime();
104411068SJohn.Danielson@Sun.COM passp->da_stable_cnt++;
104511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
104611068SJohn.Danielson@Sun.COM if (mapp->dam_activate_cb) {
104711068SJohn.Danielson@Sun.COM (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
104811068SJohn.Danielson@Sun.COM addrid, &passp->da_ppriv_rpt);
104911068SJohn.Danielson@Sun.COM }
105011068SJohn.Danielson@Sun.COM
105111068SJohn.Danielson@Sun.COM /*
105211068SJohn.Danielson@Sun.COM * call the address-specific configuration action as part of
105311068SJohn.Danielson@Sun.COM * activation.
105411068SJohn.Danielson@Sun.COM */
105511068SJohn.Danielson@Sun.COM config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
105611068SJohn.Danielson@Sun.COM addrid);
105711068SJohn.Danielson@Sun.COM if (config_rv != DAM_SUCCESS) {
105811068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
105911068SJohn.Danielson@Sun.COM passp->da_flags |= DA_FAILED_CONFIG;
106011068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
106111068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__activate__config__failure,
1062*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1063*12399SChris.Horne@Sun.COM char *, addrstr);
106411363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr,
106511363SReed.Liu@Sun.COM DAMAP_DEACT_RSN_CFG_FAIL);
106611363SReed.Liu@Sun.COM } else {
1067*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__activate__end,
1068*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1069*12399SChris.Horne@Sun.COM char *, addrstr);
107011068SJohn.Danielson@Sun.COM }
107111068SJohn.Danielson@Sun.COM }
107211068SJohn.Danielson@Sun.COM
107311068SJohn.Danielson@Sun.COM /*
107411068SJohn.Danielson@Sun.COM * deactivate a previously stable address
107511068SJohn.Danielson@Sun.COM */
107611068SJohn.Danielson@Sun.COM static void
dam_addr_deactivate(dam_t * mapp,id_t addrid)107711068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid)
107811068SJohn.Danielson@Sun.COM {
107911068SJohn.Danielson@Sun.COM char *addrstr;
108011068SJohn.Danielson@Sun.COM
108111068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1082*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__start,
1083*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1084*12399SChris.Horne@Sun.COM char *, addrstr);
108511068SJohn.Danielson@Sun.COM
108611068SJohn.Danielson@Sun.COM /*
108711068SJohn.Danielson@Sun.COM * call the unconfiguration callback
108811068SJohn.Danielson@Sun.COM */
108911068SJohn.Danielson@Sun.COM (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
109011363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
109111363SReed.Liu@Sun.COM }
109211363SReed.Liu@Sun.COM
109311363SReed.Liu@Sun.COM static void
dam_deact_cleanup(dam_t * mapp,id_t addrid,char * addrstr,damap_deact_rsn_t deact_rsn)109411363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
109511363SReed.Liu@Sun.COM damap_deact_rsn_t deact_rsn)
109611363SReed.Liu@Sun.COM {
109711363SReed.Liu@Sun.COM dam_da_t *passp;
109811363SReed.Liu@Sun.COM
109911068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
110011068SJohn.Danielson@Sun.COM ASSERT(passp);
110111068SJohn.Danielson@Sun.COM if (mapp->dam_deactivate_cb)
110211068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
110311068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid),
110411363SReed.Liu@Sun.COM addrid, passp->da_ppriv, deact_rsn);
110511068SJohn.Danielson@Sun.COM
110611068SJohn.Danielson@Sun.COM /*
110711068SJohn.Danielson@Sun.COM * clear the active bit and free the backing info for
110811068SJohn.Danielson@Sun.COM * this address
110911068SJohn.Danielson@Sun.COM */
111011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
111111068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_active_set, addrid);
111211068SJohn.Danielson@Sun.COM passp->da_ppriv = NULL;
111311068SJohn.Danielson@Sun.COM if (passp->da_nvl)
111411068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl);
111511068SJohn.Danielson@Sun.COM passp->da_nvl = NULL;
111611068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL;
111711068SJohn.Danielson@Sun.COM if (passp->da_nvl_rpt)
111811068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl_rpt);
111911068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL;
112011068SJohn.Danielson@Sun.COM
1121*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__end,
1122*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1123*12399SChris.Horne@Sun.COM char *, addrstr);
112411068SJohn.Danielson@Sun.COM
112511068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, addrid);
112611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
112711068SJohn.Danielson@Sun.COM }
112811068SJohn.Danielson@Sun.COM
112911068SJohn.Danielson@Sun.COM /*
113011068SJohn.Danielson@Sun.COM * taskq callback for multi-thread activation
113111068SJohn.Danielson@Sun.COM */
113211068SJohn.Danielson@Sun.COM static void
dam_tq_config(void * arg)113311068SJohn.Danielson@Sun.COM dam_tq_config(void *arg)
113411068SJohn.Danielson@Sun.COM {
113511068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
113611068SJohn.Danielson@Sun.COM
113711068SJohn.Danielson@Sun.COM dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
113811068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd));
113911068SJohn.Danielson@Sun.COM }
114011068SJohn.Danielson@Sun.COM
114111068SJohn.Danielson@Sun.COM /*
114211068SJohn.Danielson@Sun.COM * taskq callback for multi-thread deactivation
114311068SJohn.Danielson@Sun.COM */
114411068SJohn.Danielson@Sun.COM static void
dam_tq_unconfig(void * arg)114511068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg)
114611068SJohn.Danielson@Sun.COM {
114711068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
114811068SJohn.Danielson@Sun.COM
114911068SJohn.Danielson@Sun.COM dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
115011068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd));
115111068SJohn.Danielson@Sun.COM }
115211068SJohn.Danielson@Sun.COM
115311068SJohn.Danielson@Sun.COM /*
115410696SDavid.Hollister@Sun.COM * Activate a set of stabilized addresses
115510696SDavid.Hollister@Sun.COM */
115610696SDavid.Hollister@Sun.COM static void
dam_addrset_activate(dam_t * mapp,bitset_t * activate)115711068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate)
115810696SDavid.Hollister@Sun.COM {
115911068SJohn.Danielson@Sun.COM
116011068SJohn.Danielson@Sun.COM int i, nset;
116111068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL;
116211068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL;
116311068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN];
116411068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri;
116510696SDavid.Hollister@Sun.COM
116611068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) {
116711068SJohn.Danielson@Sun.COM /*
116811068SJohn.Danielson@Sun.COM * calculate the # of taskq threads to create
116911068SJohn.Danielson@Sun.COM */
117011068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++)
117111068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i))
117211068SJohn.Danielson@Sun.COM nset++;
117311068SJohn.Danielson@Sun.COM ASSERT(nset);
117411068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
117511068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1,
117611068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE);
117711068SJohn.Danielson@Sun.COM }
117810696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
117911068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i)) {
118011068SJohn.Danielson@Sun.COM if (!tqp)
118111068SJohn.Danielson@Sun.COM dam_addr_activate(mapp, i);
118211068SJohn.Danielson@Sun.COM else {
118311068SJohn.Danielson@Sun.COM /*
118411068SJohn.Danielson@Sun.COM * multi-threaded activation
118511068SJohn.Danielson@Sun.COM */
118611068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
118711068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp;
118811068SJohn.Danielson@Sun.COM tqd->tqd_id = i;
118911068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp, dam_tq_config,
119011854SChris.Horne@Sun.COM tqd, TQ_SLEEP);
119111068SJohn.Danielson@Sun.COM }
119210696SDavid.Hollister@Sun.COM }
119311068SJohn.Danielson@Sun.COM }
119411068SJohn.Danielson@Sun.COM if (tqp) {
119511068SJohn.Danielson@Sun.COM taskq_wait(tqp);
119611068SJohn.Danielson@Sun.COM taskq_destroy(tqp);
119710696SDavid.Hollister@Sun.COM }
119810696SDavid.Hollister@Sun.COM }
119910696SDavid.Hollister@Sun.COM
120010696SDavid.Hollister@Sun.COM /*
120111068SJohn.Danielson@Sun.COM * Deactivate a set of stabilized addresses
120210696SDavid.Hollister@Sun.COM */
120310696SDavid.Hollister@Sun.COM static void
dam_addrset_deactivate(dam_t * mapp,bitset_t * deactivate)120411068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
120510696SDavid.Hollister@Sun.COM {
120611068SJohn.Danielson@Sun.COM int i, nset;
120711068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL;
120811068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL;
120911068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN];
121011068SJohn.Danielson@Sun.COM
1211*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__addrset__deactivate,
1212*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
121310696SDavid.Hollister@Sun.COM
121411068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) {
121511068SJohn.Danielson@Sun.COM /*
121611068SJohn.Danielson@Sun.COM * compute the # of taskq threads to dispatch
121711068SJohn.Danielson@Sun.COM */
121811068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++)
121911068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i))
122011068SJohn.Danielson@Sun.COM nset++;
122111068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
122211068SJohn.Danielson@Sun.COM mapp->dam_name);
122311068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1,
122411068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE);
122511068SJohn.Danielson@Sun.COM }
122610696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
122711068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i)) {
122811068SJohn.Danielson@Sun.COM if (!tqp) {
122911068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i);
123011068SJohn.Danielson@Sun.COM } else {
123111068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
123211068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp;
123311068SJohn.Danielson@Sun.COM tqd->tqd_id = i;
123411068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp,
123511854SChris.Horne@Sun.COM dam_tq_unconfig, tqd, TQ_SLEEP);
123611068SJohn.Danielson@Sun.COM }
123710696SDavid.Hollister@Sun.COM }
123810696SDavid.Hollister@Sun.COM }
123911068SJohn.Danielson@Sun.COM
124011068SJohn.Danielson@Sun.COM if (tqp) {
124111068SJohn.Danielson@Sun.COM taskq_wait(tqp);
124211068SJohn.Danielson@Sun.COM taskq_destroy(tqp);
124311068SJohn.Danielson@Sun.COM }
124410696SDavid.Hollister@Sun.COM }
124510696SDavid.Hollister@Sun.COM
124610696SDavid.Hollister@Sun.COM /*
124711068SJohn.Danielson@Sun.COM * Release a previously activated address
124810696SDavid.Hollister@Sun.COM */
124910696SDavid.Hollister@Sun.COM static void
dam_addr_release(dam_t * mapp,id_t addrid)125011068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid)
125110696SDavid.Hollister@Sun.COM {
125210696SDavid.Hollister@Sun.COM dam_da_t *passp;
125311068SJohn.Danielson@Sun.COM char *addrstr;
125410696SDavid.Hollister@Sun.COM
125511068SJohn.Danielson@Sun.COM
125611068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
125710696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
125810696SDavid.Hollister@Sun.COM ASSERT(passp);
125910696SDavid.Hollister@Sun.COM
126011068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1261*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__release,
1262*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1263*12399SChris.Horne@Sun.COM char *, addrstr);
126410696SDavid.Hollister@Sun.COM
126510696SDavid.Hollister@Sun.COM /*
126611068SJohn.Danielson@Sun.COM * defer releasing the address until outstanding references
126711068SJohn.Danielson@Sun.COM * are released
126810696SDavid.Hollister@Sun.COM */
126911068SJohn.Danielson@Sun.COM if (passp->da_ref > 1) {
127011068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1271*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1272*12399SChris.Horne@Sun.COM char *, addrstr, int, passp->da_ref);
127310696SDavid.Hollister@Sun.COM return;
127411068SJohn.Danielson@Sun.COM }
127510696SDavid.Hollister@Sun.COM
127610696SDavid.Hollister@Sun.COM /*
127711068SJohn.Danielson@Sun.COM * allow pending reports to stabilize
127810696SDavid.Hollister@Sun.COM */
127911068SJohn.Danielson@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) {
128011068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__release__report__pending,
1281*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1282*12399SChris.Horne@Sun.COM char *, addrstr);
128310696SDavid.Hollister@Sun.COM return;
128410696SDavid.Hollister@Sun.COM }
128511068SJohn.Danielson@Sun.COM
128610696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid);
128710696SDavid.Hollister@Sun.COM ddi_soft_state_free(mapp->dam_da, addrid);
128810696SDavid.Hollister@Sun.COM }
128910696SDavid.Hollister@Sun.COM
129010696SDavid.Hollister@Sun.COM /*
129110696SDavid.Hollister@Sun.COM * process stabilized address reports
129210696SDavid.Hollister@Sun.COM */
129310696SDavid.Hollister@Sun.COM static void
dam_stabilize_map(void * arg)129411068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg)
129510696SDavid.Hollister@Sun.COM {
129610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg;
129710696SDavid.Hollister@Sun.COM bitset_t delta;
129810696SDavid.Hollister@Sun.COM bitset_t cfg;
129910696SDavid.Hollister@Sun.COM bitset_t uncfg;
130010696SDavid.Hollister@Sun.COM int has_cfg, has_uncfg;
130111068SJohn.Danielson@Sun.COM uint32_t i, n_active;
130211068SJohn.Danielson@Sun.COM
1303*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__stabilize__map,
1304*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
130510696SDavid.Hollister@Sun.COM
130610696SDavid.Hollister@Sun.COM bitset_init(&delta);
130710696SDavid.Hollister@Sun.COM bitset_resize(&delta, mapp->dam_size);
130810696SDavid.Hollister@Sun.COM bitset_init(&cfg);
130910696SDavid.Hollister@Sun.COM bitset_resize(&cfg, mapp->dam_size);
131010696SDavid.Hollister@Sun.COM bitset_init(&uncfg);
131110696SDavid.Hollister@Sun.COM bitset_resize(&uncfg, mapp->dam_size);
131210696SDavid.Hollister@Sun.COM
131311068SJohn.Danielson@Sun.COM /*
131411068SJohn.Danielson@Sun.COM * determine which addresses have changed during
131511068SJohn.Danielson@Sun.COM * this stabilization cycle
131611068SJohn.Danielson@Sun.COM */
131711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
131811068SJohn.Danielson@Sun.COM ASSERT(mapp->dam_flags & DAM_SPEND);
131910696SDavid.Hollister@Sun.COM if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
132010696SDavid.Hollister@Sun.COM &delta)) {
132111068SJohn.Danielson@Sun.COM /*
132211068SJohn.Danielson@Sun.COM * no difference
132311068SJohn.Danielson@Sun.COM */
132410696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set);
132512207SChris.Horne@Sun.COM mapp->dam_flags &= ~DAM_SPEND;
132612207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv);
132711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
132812207SChris.Horne@Sun.COM
132910696SDavid.Hollister@Sun.COM bitset_fini(&uncfg);
133010696SDavid.Hollister@Sun.COM bitset_fini(&cfg);
133110696SDavid.Hollister@Sun.COM bitset_fini(&delta);
1332*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__stabilize__map__nochange,
1333*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
133410696SDavid.Hollister@Sun.COM return;
133510696SDavid.Hollister@Sun.COM }
133611068SJohn.Danielson@Sun.COM
133711068SJohn.Danielson@Sun.COM /*
133811068SJohn.Danielson@Sun.COM * compute the sets of addresses to be activated and deactivated
133911068SJohn.Danielson@Sun.COM */
134010696SDavid.Hollister@Sun.COM has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
134110696SDavid.Hollister@Sun.COM has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
134211068SJohn.Danielson@Sun.COM
134311068SJohn.Danielson@Sun.COM /*
134411068SJohn.Danielson@Sun.COM * drop map lock while invoking callouts
134511068SJohn.Danielson@Sun.COM */
134611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
134711068SJohn.Danielson@Sun.COM
134811068SJohn.Danielson@Sun.COM /*
134911068SJohn.Danielson@Sun.COM * activate all newly stable addresss
135011068SJohn.Danielson@Sun.COM */
135111068SJohn.Danielson@Sun.COM if (has_cfg)
135210696SDavid.Hollister@Sun.COM dam_addrset_activate(mapp, &cfg);
135311068SJohn.Danielson@Sun.COM
135411068SJohn.Danielson@Sun.COM /*
135511068SJohn.Danielson@Sun.COM * deactivate addresss which are no longer in the map
135611068SJohn.Danielson@Sun.COM */
135711068SJohn.Danielson@Sun.COM if (has_uncfg)
135811068SJohn.Danielson@Sun.COM dam_addrset_deactivate(mapp, &uncfg);
135911068SJohn.Danielson@Sun.COM
136011068SJohn.Danielson@Sun.COM
136111068SJohn.Danielson@Sun.COM /*
136211068SJohn.Danielson@Sun.COM * timestamp the last stable time and increment the kstat keeping
136311068SJohn.Danielson@Sun.COM * the # of of stable cycles for the map
136411068SJohn.Danielson@Sun.COM */
136511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
136610696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set);
136710696SDavid.Hollister@Sun.COM mapp->dam_last_stable = gethrtime();
136810696SDavid.Hollister@Sun.COM mapp->dam_stable_cnt++;
136911068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_cycles);
137011068SJohn.Danielson@Sun.COM
137111068SJohn.Danielson@Sun.COM /*
137211068SJohn.Danielson@Sun.COM * determine the number of stable addresses
137311068SJohn.Danielson@Sun.COM * and update the n_active kstat for this map
137411068SJohn.Danielson@Sun.COM */
137511068SJohn.Danielson@Sun.COM for (i = 1, n_active = 0; i < mapp->dam_high; i++)
137611068SJohn.Danielson@Sun.COM if (bitset_in_set(&mapp->dam_active_set, i))
137711068SJohn.Danielson@Sun.COM n_active++;
137811068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_active, n_active);
137911068SJohn.Danielson@Sun.COM
1380*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__map__stable__end,
1381*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1382*12399SChris.Horne@Sun.COM int, n_active);
138311068SJohn.Danielson@Sun.COM
138412207SChris.Horne@Sun.COM mapp->dam_flags &= ~DAM_SPEND;
138512207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv);
138611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
138712207SChris.Horne@Sun.COM
138810696SDavid.Hollister@Sun.COM bitset_fini(&uncfg);
138910696SDavid.Hollister@Sun.COM bitset_fini(&cfg);
139010696SDavid.Hollister@Sun.COM bitset_fini(&delta);
139110696SDavid.Hollister@Sun.COM }
139210696SDavid.Hollister@Sun.COM
139310696SDavid.Hollister@Sun.COM /*
139410696SDavid.Hollister@Sun.COM * per-address stabilization timeout
139510696SDavid.Hollister@Sun.COM */
139610696SDavid.Hollister@Sun.COM static void
dam_addr_stable_cb(void * arg)139710696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg)
139810696SDavid.Hollister@Sun.COM {
139910696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg;
140010696SDavid.Hollister@Sun.COM int i;
140110696SDavid.Hollister@Sun.COM dam_da_t *passp;
140210696SDavid.Hollister@Sun.COM int spend = 0;
140310696SDavid.Hollister@Sun.COM int tpend = 0;
140412207SChris.Horne@Sun.COM int64_t ts, next_ticks, delta_ticks;
140510696SDavid.Hollister@Sun.COM
140611068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
140710696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) {
1408*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1409*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
141011068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
141110696SDavid.Hollister@Sun.COM return;
141210696SDavid.Hollister@Sun.COM }
141310696SDavid.Hollister@Sun.COM mapp->dam_tid = 0;
141411068SJohn.Danielson@Sun.COM
141510696SDavid.Hollister@Sun.COM /*
141610696SDavid.Hollister@Sun.COM * If still under stabilization, reschedule timeout,
141711068SJohn.Danielson@Sun.COM * otherwise dispatch the task to activate and deactivate the
141811068SJohn.Danielson@Sun.COM * new stable address
141910696SDavid.Hollister@Sun.COM */
142010696SDavid.Hollister@Sun.COM if (mapp->dam_flags & DAM_SPEND) {
142111068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun);
142210696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++;
1423*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__overrun,
1424*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
142512207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp,
142612207SChris.Horne@Sun.COM mapp->dam_stable_ticks);
142711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
142810696SDavid.Hollister@Sun.COM return;
142910696SDavid.Hollister@Sun.COM }
143010696SDavid.Hollister@Sun.COM
143111068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0);
143211068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0;
143311068SJohn.Danielson@Sun.COM
1434*12399SChris.Horne@Sun.COM /* See if any reports stabalized and compute next timeout. */
143512207SChris.Horne@Sun.COM ts = ddi_get_lbolt64();
143612207SChris.Horne@Sun.COM next_ticks = mapp->dam_stable_ticks;
143710696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
1438*12399SChris.Horne@Sun.COM if (bitset_in_set(&mapp->dam_report_set, i)) {
1439*12399SChris.Horne@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i);
1440*12399SChris.Horne@Sun.COM ASSERT(passp);
144110696SDavid.Hollister@Sun.COM
1442*12399SChris.Horne@Sun.COM if (passp->da_deadline <= ts)
1443*12399SChris.Horne@Sun.COM spend++; /* report has stabilized */
1444*12399SChris.Horne@Sun.COM else {
1445*12399SChris.Horne@Sun.COM /* not stabilized, determine next map timeout */
1446*12399SChris.Horne@Sun.COM tpend++;
1447*12399SChris.Horne@Sun.COM delta_ticks = passp->da_deadline - ts;
1448*12399SChris.Horne@Sun.COM if (delta_ticks < next_ticks)
1449*12399SChris.Horne@Sun.COM next_ticks = delta_ticks;
1450*12399SChris.Horne@Sun.COM }
145110696SDavid.Hollister@Sun.COM }
145210696SDavid.Hollister@Sun.COM }
145310696SDavid.Hollister@Sun.COM
145410696SDavid.Hollister@Sun.COM /*
145511068SJohn.Danielson@Sun.COM * schedule system_taskq activation of stabilized reports
145610696SDavid.Hollister@Sun.COM */
145710696SDavid.Hollister@Sun.COM if (spend) {
145811068SJohn.Danielson@Sun.COM if (taskq_dispatch(system_taskq, dam_stabilize_map,
145911854SChris.Horne@Sun.COM mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1460*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__start,
1461*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
1462*12399SChris.Horne@Sun.COM
1463*12399SChris.Horne@Sun.COM /*
1464*12399SChris.Horne@Sun.COM * The stable_set we compute below stays pending until
1465*12399SChris.Horne@Sun.COM * processed by dam_stabilize_map. We can't set
1466*12399SChris.Horne@Sun.COM * DAM_SPEND (or bitset_del things from the
1467*12399SChris.Horne@Sun.COM * report_set) until we *know* that we can handoff the
1468*12399SChris.Horne@Sun.COM * result to dam_stabilize_map. If dam_stabilize_map
1469*12399SChris.Horne@Sun.COM * starts executing before we are complete, it will
1470*12399SChris.Horne@Sun.COM * block on the dam_lock mutex until we are ready.
1471*12399SChris.Horne@Sun.COM */
147212207SChris.Horne@Sun.COM mapp->dam_flags |= DAM_SPEND;
1473*12399SChris.Horne@Sun.COM
1474*12399SChris.Horne@Sun.COM /*
1475*12399SChris.Horne@Sun.COM * Copy the current active_set to the stable_set, then
1476*12399SChris.Horne@Sun.COM * add or remove stabilized report_set address from
1477*12399SChris.Horne@Sun.COM * the stable set (and delete them from the report_set).
1478*12399SChris.Horne@Sun.COM */
1479*12399SChris.Horne@Sun.COM bitset_copy(&mapp->dam_active_set,
1480*12399SChris.Horne@Sun.COM &mapp->dam_stable_set);
1481*12399SChris.Horne@Sun.COM for (i = 1; i < mapp->dam_high; i++) {
1482*12399SChris.Horne@Sun.COM if (!bitset_in_set(&mapp->dam_report_set, i))
1483*12399SChris.Horne@Sun.COM continue;
1484*12399SChris.Horne@Sun.COM
1485*12399SChris.Horne@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i);
1486*12399SChris.Horne@Sun.COM if (passp->da_deadline > ts)
1487*12399SChris.Horne@Sun.COM continue; /* report not stabilized */
1488*12399SChris.Horne@Sun.COM
1489*12399SChris.Horne@Sun.COM /* report has stabilized */
1490*12399SChris.Horne@Sun.COM if (passp->da_flags & DA_RELE)
1491*12399SChris.Horne@Sun.COM bitset_del(&mapp->dam_stable_set, i);
1492*12399SChris.Horne@Sun.COM else
1493*12399SChris.Horne@Sun.COM bitset_add(&mapp->dam_stable_set, i);
1494*12399SChris.Horne@Sun.COM
1495*12399SChris.Horne@Sun.COM bitset_del(&mapp->dam_report_set, i);
1496*12399SChris.Horne@Sun.COM }
149711068SJohn.Danielson@Sun.COM } else {
1498*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1499*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
150011854SChris.Horne@Sun.COM
150111854SChris.Horne@Sun.COM /*
150211854SChris.Horne@Sun.COM * Avoid waiting the entire stabalization
150311854SChris.Horne@Sun.COM * time again if taskq_diskpatch fails.
150411854SChris.Horne@Sun.COM */
1505*12399SChris.Horne@Sun.COM tpend++;
150612207SChris.Horne@Sun.COM delta_ticks = drv_usectohz(
150711854SChris.Horne@Sun.COM damap_taskq_dispatch_retry_usec);
150812207SChris.Horne@Sun.COM if (delta_ticks < next_ticks)
150912207SChris.Horne@Sun.COM next_ticks = delta_ticks;
151011068SJohn.Danielson@Sun.COM }
151110696SDavid.Hollister@Sun.COM }
151210696SDavid.Hollister@Sun.COM
151310696SDavid.Hollister@Sun.COM /*
151411068SJohn.Danielson@Sun.COM * reschedule the stabilization timer if there are reports
151511068SJohn.Danielson@Sun.COM * still pending
151610696SDavid.Hollister@Sun.COM */
1517*12399SChris.Horne@Sun.COM if (tpend) {
1518*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1519*12399SChris.Horne@Sun.COM mapp->dam_name, dam_t *, mapp);
152012207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp,
152112207SChris.Horne@Sun.COM (clock_t)next_ticks);
1522*12399SChris.Horne@Sun.COM }
152311068SJohn.Danielson@Sun.COM
152411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
152510696SDavid.Hollister@Sun.COM }
152610696SDavid.Hollister@Sun.COM
152710696SDavid.Hollister@Sun.COM /*
152811068SJohn.Danielson@Sun.COM * fullset stabilization timeout callback
152910696SDavid.Hollister@Sun.COM */
153010696SDavid.Hollister@Sun.COM static void
dam_addrset_stable_cb(void * arg)153111068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg)
153210696SDavid.Hollister@Sun.COM {
153310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg;
153410696SDavid.Hollister@Sun.COM
153511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
153610696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) {
153711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
153811068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
153911068SJohn.Danielson@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
154010696SDavid.Hollister@Sun.COM return;
154110696SDavid.Hollister@Sun.COM }
154210696SDavid.Hollister@Sun.COM mapp->dam_tid = 0;
154310696SDavid.Hollister@Sun.COM
154410696SDavid.Hollister@Sun.COM /*
154511068SJohn.Danielson@Sun.COM * If map still underoing stabilization reschedule timeout,
154611068SJohn.Danielson@Sun.COM * else dispatch the task to configure the new stable set of
154711068SJohn.Danielson@Sun.COM * addresses.
154810696SDavid.Hollister@Sun.COM */
154911854SChris.Horne@Sun.COM if ((mapp->dam_flags & DAM_SPEND) ||
155011854SChris.Horne@Sun.COM (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
155111854SChris.Horne@Sun.COM TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
155211068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun);
155310696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++;
155412207SChris.Horne@Sun.COM dam_sched_timeout(dam_addrset_stable_cb, mapp,
155512207SChris.Horne@Sun.COM drv_usectohz(damap_taskq_dispatch_retry_usec));
155611854SChris.Horne@Sun.COM
1557*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1558*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
155911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
156011068SJohn.Danielson@Sun.COM return;
156110696SDavid.Hollister@Sun.COM }
156211068SJohn.Danielson@Sun.COM
156311068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0);
156411068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0;
156511068SJohn.Danielson@Sun.COM bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
156611068SJohn.Danielson@Sun.COM bitset_zero(&mapp->dam_report_set);
156711068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_SPEND;
156811068SJohn.Danielson@Sun.COM mapp->dam_flags &= ~DAM_SETADD;
156912207SChris.Horne@Sun.COM /* NOTE: don't need cv_signal since DAM_SPEND is still set */
157012207SChris.Horne@Sun.COM
1571*12399SChris.Horne@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__start,
1572*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp);
157311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
157410696SDavid.Hollister@Sun.COM }
157510696SDavid.Hollister@Sun.COM
157610696SDavid.Hollister@Sun.COM /*
157712207SChris.Horne@Sun.COM * schedule map timeout in 'ticks' ticks
157812207SChris.Horne@Sun.COM * if map timer is currently running, cancel if ticks == 0
157910696SDavid.Hollister@Sun.COM */
158010696SDavid.Hollister@Sun.COM static void
dam_sched_timeout(void (* timeout_cb)(),dam_t * mapp,clock_t ticks)158112207SChris.Horne@Sun.COM dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
158210696SDavid.Hollister@Sun.COM {
158310696SDavid.Hollister@Sun.COM timeout_id_t tid;
158410696SDavid.Hollister@Sun.COM
1585*12399SChris.Horne@Sun.COM DTRACE_PROBE4(damap__sched__timeout,
1586*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1587*12399SChris.Horne@Sun.COM int, ticks, timeout_id_t, mapp->dam_tid);
158811068SJohn.Danielson@Sun.COM
158911068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
159010696SDavid.Hollister@Sun.COM if ((tid = mapp->dam_tid) != 0) {
159112207SChris.Horne@Sun.COM if (ticks == 0) {
159211068SJohn.Danielson@Sun.COM mapp->dam_tid = 0;
159311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
159411068SJohn.Danielson@Sun.COM (void) untimeout(tid);
159511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
159611068SJohn.Danielson@Sun.COM }
159711068SJohn.Danielson@Sun.COM } else {
159812207SChris.Horne@Sun.COM if (timeout_cb && (ticks != 0))
159912207SChris.Horne@Sun.COM mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
160010696SDavid.Hollister@Sun.COM }
160110696SDavid.Hollister@Sun.COM }
160210696SDavid.Hollister@Sun.COM
160310696SDavid.Hollister@Sun.COM /*
160411068SJohn.Danielson@Sun.COM * report addition or removal of an address
160510696SDavid.Hollister@Sun.COM */
160610696SDavid.Hollister@Sun.COM static void
dam_addr_report(dam_t * mapp,dam_da_t * passp,id_t addrid,int rpt_type)160711068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
160810696SDavid.Hollister@Sun.COM {
160911068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
161011068SJohn.Danielson@Sun.COM
1611*12399SChris.Horne@Sun.COM DTRACE_PROBE4(damap__addr__report,
1612*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1613*12399SChris.Horne@Sun.COM char *, addrstr, int, rpt_type);
161411068SJohn.Danielson@Sun.COM
161511068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
161610696SDavid.Hollister@Sun.COM ASSERT(!DAM_IN_REPORT(mapp, addrid));
161710696SDavid.Hollister@Sun.COM passp->da_last_report = gethrtime();
161810696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime();
161910696SDavid.Hollister@Sun.COM passp->da_report_cnt++;
162012207SChris.Horne@Sun.COM passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
162111068SJohn.Danielson@Sun.COM if (rpt_type == RPT_ADDR_DEL)
162210696SDavid.Hollister@Sun.COM passp->da_flags |= DA_RELE;
162311068SJohn.Danielson@Sun.COM else if (rpt_type == RPT_ADDR_ADD)
162410696SDavid.Hollister@Sun.COM passp->da_flags &= ~DA_RELE;
162510696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid);
162612207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
162710696SDavid.Hollister@Sun.COM }
162810696SDavid.Hollister@Sun.COM
162910696SDavid.Hollister@Sun.COM /*
163010696SDavid.Hollister@Sun.COM * release an address report
163110696SDavid.Hollister@Sun.COM */
163210696SDavid.Hollister@Sun.COM static void
dam_addr_report_release(dam_t * mapp,id_t addrid)163311068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid)
163410696SDavid.Hollister@Sun.COM {
163510696SDavid.Hollister@Sun.COM dam_da_t *passp;
163611068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
163710696SDavid.Hollister@Sun.COM
1638*12399SChris.Horne@Sun.COM DTRACE_PROBE3(damap__addr__report__release,
1639*12399SChris.Horne@Sun.COM char *, mapp->dam_name, dam_t *, mapp,
1640*12399SChris.Horne@Sun.COM char *, addrstr);
164111068SJohn.Danielson@Sun.COM
164211068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
164310696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
164410696SDavid.Hollister@Sun.COM ASSERT(passp);
164511068SJohn.Danielson@Sun.COM /*
164611068SJohn.Danielson@Sun.COM * clear the report bit
164711068SJohn.Danielson@Sun.COM * if the address has a registered deactivation handler and
164811601SDavid.Hollister@Sun.COM * we are holding a private data pointer and the address has not
164911601SDavid.Hollister@Sun.COM * stabilized, deactivate the address (private data).
165011068SJohn.Danielson@Sun.COM */
165111068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_report_set, addrid);
165211601SDavid.Hollister@Sun.COM if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
165311601SDavid.Hollister@Sun.COM passp->da_ppriv_rpt) {
165411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock);
165511068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
165611068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid),
165711601SDavid.Hollister@Sun.COM addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
165811068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock);
165911068SJohn.Danielson@Sun.COM }
166010696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = NULL;
166110696SDavid.Hollister@Sun.COM if (passp->da_nvl_rpt)
166210696SDavid.Hollister@Sun.COM nvlist_free(passp->da_nvl_rpt);
166310696SDavid.Hollister@Sun.COM }
166410696SDavid.Hollister@Sun.COM
166510696SDavid.Hollister@Sun.COM /*
166610696SDavid.Hollister@Sun.COM * return the map ID of an address
166710696SDavid.Hollister@Sun.COM */
166810696SDavid.Hollister@Sun.COM static id_t
dam_get_addrid(dam_t * mapp,char * address)166910696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address)
167010696SDavid.Hollister@Sun.COM {
167110696SDavid.Hollister@Sun.COM damap_id_t addrid;
167210696SDavid.Hollister@Sun.COM dam_da_t *passp;
167310696SDavid.Hollister@Sun.COM
167411068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock));
167510696SDavid.Hollister@Sun.COM if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
167611068SJohn.Danielson@Sun.COM if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
167710696SDavid.Hollister@Sun.COM address)) == (damap_id_t)0) {
167810696SDavid.Hollister@Sun.COM return (0);
167910696SDavid.Hollister@Sun.COM }
168010696SDavid.Hollister@Sun.COM if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
168110696SDavid.Hollister@Sun.COM DDI_SUCCESS) {
168210696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid);
168310696SDavid.Hollister@Sun.COM return (0);
168410696SDavid.Hollister@Sun.COM }
168511068SJohn.Danielson@Sun.COM
168610696SDavid.Hollister@Sun.COM if (addrid >= mapp->dam_high)
168710696SDavid.Hollister@Sun.COM mapp->dam_high = addrid + 1;
168811068SJohn.Danielson@Sun.COM
168911068SJohn.Danielson@Sun.COM /*
169011068SJohn.Danielson@Sun.COM * expand bitmaps if ID has outgrown old map size
169111068SJohn.Danielson@Sun.COM */
169211068SJohn.Danielson@Sun.COM if (mapp->dam_high > mapp->dam_size) {
169311068SJohn.Danielson@Sun.COM mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
169411068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size);
169511068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
169611068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size);
169711068SJohn.Danielson@Sun.COM }
169811068SJohn.Danielson@Sun.COM
169911068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid);
170011068SJohn.Danielson@Sun.COM passp->da_ref = 1;
170111068SJohn.Danielson@Sun.COM passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
170211068SJohn.Danielson@Sun.COM addrid); /* for mdb */
170310696SDavid.Hollister@Sun.COM }
170410696SDavid.Hollister@Sun.COM return (addrid);
170510696SDavid.Hollister@Sun.COM }
170610696SDavid.Hollister@Sun.COM
170710696SDavid.Hollister@Sun.COM /*
170810696SDavid.Hollister@Sun.COM * create and install map statistics
170910696SDavid.Hollister@Sun.COM */
171010696SDavid.Hollister@Sun.COM static int
dam_kstat_create(dam_t * mapp)171110696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp)
171210696SDavid.Hollister@Sun.COM {
171310696SDavid.Hollister@Sun.COM kstat_t *mapsp;
171410696SDavid.Hollister@Sun.COM struct dam_kstats *statsp;
171510696SDavid.Hollister@Sun.COM
171610696SDavid.Hollister@Sun.COM mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
171710696SDavid.Hollister@Sun.COM KSTAT_TYPE_NAMED,
171810696SDavid.Hollister@Sun.COM sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
171911068SJohn.Danielson@Sun.COM
172011068SJohn.Danielson@Sun.COM if (mapsp == NULL)
172110696SDavid.Hollister@Sun.COM return (DDI_FAILURE);
172210696SDavid.Hollister@Sun.COM
172310696SDavid.Hollister@Sun.COM statsp = (struct dam_kstats *)mapsp->ks_data;
172411068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
172511068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
172611068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
172711068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
172810696SDavid.Hollister@Sun.COM kstat_install(mapsp);
172910696SDavid.Hollister@Sun.COM mapp->dam_kstatsp = mapsp;
173010696SDavid.Hollister@Sun.COM return (DDI_SUCCESS);
173110696SDavid.Hollister@Sun.COM }
1732