14c06356bSdh /*
24c06356bSdh * CDDL HEADER START
34c06356bSdh *
44c06356bSdh * The contents of this file are subject to the terms of the
54c06356bSdh * Common Development and Distribution License (the "License").
64c06356bSdh * You may not use this file except in compliance with the License.
74c06356bSdh *
84c06356bSdh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94c06356bSdh * or http://www.opensolaris.org/os/licensing.
104c06356bSdh * See the License for the specific language governing permissions
114c06356bSdh * and limitations under the License.
124c06356bSdh *
134c06356bSdh * When distributing Covered Code, include this CDDL HEADER in each
144c06356bSdh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154c06356bSdh * If applicable, add the following below this CDDL HEADER, with the
164c06356bSdh * fields enclosed by brackets "[]" replaced with your own identifying
174c06356bSdh * information: Portions Copyright [yyyy] [name of copyright owner]
184c06356bSdh *
194c06356bSdh * CDDL HEADER END
204c06356bSdh */
214c06356bSdh
224c06356bSdh /*
2360aabb4cSChris Horne * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2478427917SHans Rosenfeld * Copyright 2023 Racktop Systems, Inc.
254c06356bSdh */
264c06356bSdh
274c06356bSdh #include <sys/note.h>
284c06356bSdh #include <sys/types.h>
294c06356bSdh #include <sys/param.h>
304c06356bSdh #include <sys/systm.h>
314c06356bSdh #include <sys/buf.h>
324c06356bSdh #include <sys/kmem.h>
334c06356bSdh #include <sys/cmn_err.h>
344c06356bSdh #include <sys/debug.h>
354c06356bSdh #include <sys/sunndi.h>
364c06356bSdh #include <sys/kstat.h>
374c06356bSdh #include <sys/conf.h>
38a288e5a9SJoshua M. Clulow #include <sys/ddi_periodic.h>
394c06356bSdh #include <sys/devctl.h>
404c06356bSdh #include <sys/callb.h>
414c06356bSdh #include <sys/sysevent.h>
424c06356bSdh #include <sys/taskq.h>
434c06356bSdh #include <sys/ddi.h>
444c06356bSdh #include <sys/bitset.h>
454c06356bSdh #include <sys/damap.h>
464c06356bSdh #include <sys/damap_impl.h>
474c06356bSdh
484c06356bSdh #ifdef DEBUG
494c06356bSdh static int damap_debug = 0;
504c06356bSdh #endif /* DEBUG */
514c06356bSdh
521b115575SJohn Danielson extern taskq_t *system_taskq;
531b115575SJohn Danielson
544c06356bSdh static void dam_addrset_activate(dam_t *, bitset_t *);
551b115575SJohn Danielson static void dam_addrset_deactivate(dam_t *, bitset_t *);
561b115575SJohn Danielson static void dam_stabilize_map(void *);
574c06356bSdh static void dam_addr_stable_cb(void *);
581b115575SJohn Danielson static void dam_addrset_stable_cb(void *);
5960aabb4cSChris Horne static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
601b115575SJohn Danielson static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
611b115575SJohn Danielson static void dam_addr_release(dam_t *, id_t);
621b115575SJohn Danielson static void dam_addr_report_release(dam_t *, id_t);
631b115575SJohn Danielson static void dam_addr_deactivate(dam_t *, id_t);
64d189c170SReed static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
654c06356bSdh static id_t dam_get_addrid(dam_t *, char *);
664c06356bSdh static int dam_kstat_create(dam_t *);
671b115575SJohn Danielson static int dam_map_alloc(dam_t *);
684c06356bSdh
694c06356bSdh #define DAM_INCR_STAT(mapp, stat) \
704c06356bSdh if ((mapp)->dam_kstatsp) { \
714c06356bSdh struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
724c06356bSdh stp->stat.value.ui32++; \
734c06356bSdh }
744c06356bSdh
754c06356bSdh #define DAM_SET_STAT(mapp, stat, val) \
764c06356bSdh if ((mapp)->dam_kstatsp) { \
774c06356bSdh struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
784c06356bSdh stp->stat.value.ui32 = (val); \
794c06356bSdh }
804c06356bSdh
811b115575SJohn Danielson
821b115575SJohn Danielson /*
831b115575SJohn Danielson * increase damap size by 64 entries at a time
841b115575SJohn Danielson */
851b115575SJohn Danielson #define DAM_SIZE_BUMP 64
861b115575SJohn Danielson
8764109744SChris Horne int damap_taskq_dispatch_retry_usec = 1000;
8864109744SChris Horne
891b115575SJohn Danielson /*
901b115575SJohn Danielson * config/unconfig taskq data
911b115575SJohn Danielson */
921b115575SJohn Danielson typedef struct {
931b115575SJohn Danielson dam_t *tqd_mapp;
941b115575SJohn Danielson id_t tqd_id;
951b115575SJohn Danielson } cfg_tqd_t;
961b115575SJohn Danielson
971b115575SJohn Danielson extern pri_t maxclsyspri;
981b115575SJohn Danielson
994c06356bSdh /*
1004c06356bSdh * Create new device address map
1014c06356bSdh *
1021b115575SJohn Danielson * name: map name (kstat unique)
1034c06356bSdh * size: max # of map entries
1041b115575SJohn Danielson * mode: style of address reports: per-address or fullset
1054c06356bSdh * stable_usec: # of quiescent microseconds before report/map is stable
1064c06356bSdh *
1074c06356bSdh * activate_arg: address provider activation-callout private
1084c06356bSdh * activate_cb: address provider activation callback handler
1094c06356bSdh * deactivate_cb: address provider deactivation callback handler
1104c06356bSdh *
1114c06356bSdh * config_arg: configuration-callout private
1124c06356bSdh * config_cb: class configuration callout
1134c06356bSdh * unconfig_cb: class unconfiguration callout
1144c06356bSdh *
1154c06356bSdh * damapp: pointer to map handle (return)
1164c06356bSdh *
1174c06356bSdh * Returns: DAM_SUCCESS
1184c06356bSdh * DAM_EINVAL Invalid argument(s)
1194c06356bSdh * DAM_FAILURE General failure
1204c06356bSdh */
1214c06356bSdh 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)1221b115575SJohn Danielson damap_create(char *name, damap_rptmode_t mode, int map_opts,
12360aabb4cSChris Horne int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
1244c06356bSdh damap_deactivate_cb_t deactivate_cb,
1254c06356bSdh void *config_arg, damap_configure_cb_t configure_cb,
1264c06356bSdh damap_unconfig_cb_t unconfig_cb,
1274c06356bSdh damap_t **damapp)
1284c06356bSdh {
1294c06356bSdh dam_t *mapp;
1304c06356bSdh
1311b115575SJohn Danielson if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
1324c06356bSdh return (DAM_EINVAL);
1334c06356bSdh
1344c06356bSdh mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
1351b115575SJohn Danielson mapp->dam_options = map_opts;
13660aabb4cSChris Horne mapp->dam_stable_ticks = drv_usectohz(stable_usec);
1371b115575SJohn Danielson mapp->dam_size = 0;
1381b115575SJohn Danielson mapp->dam_rptmode = mode;
1394c06356bSdh mapp->dam_activate_arg = activate_arg;
1404c06356bSdh mapp->dam_activate_cb = (activate_cb_t)activate_cb;
1414c06356bSdh mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
1424c06356bSdh mapp->dam_config_arg = config_arg;
1434c06356bSdh mapp->dam_configure_cb = (configure_cb_t)configure_cb;
1444c06356bSdh mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
1451b115575SJohn Danielson mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
1461b115575SJohn Danielson mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
14760aabb4cSChris Horne cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
1484c06356bSdh bitset_init(&mapp->dam_active_set);
1494c06356bSdh bitset_init(&mapp->dam_stable_set);
1504c06356bSdh bitset_init(&mapp->dam_report_set);
1514c06356bSdh *damapp = (damap_t *)mapp;
1521b94a41bSChris Horne
1531b94a41bSChris Horne DTRACE_PROBE5(damap__create,
1541b94a41bSChris Horne char *, mapp->dam_name, damap_t *, mapp,
1551b94a41bSChris Horne damap_rptmode_t, mode, int, map_opts, int, stable_usec);
1561b94a41bSChris Horne
1571b115575SJohn Danielson return (DAM_SUCCESS);
1581b115575SJohn Danielson }
1591b115575SJohn Danielson
1601b115575SJohn Danielson /*
1611b115575SJohn Danielson * Allocate backing resources
1621b115575SJohn Danielson *
1631b115575SJohn Danielson * DAMs are lightly backed on create - major allocations occur
1641b115575SJohn Danielson * at the time a report is made to the map, and are extended on
1651b115575SJohn Danielson * a demand basis.
1661b115575SJohn Danielson */
1671b115575SJohn Danielson static int
dam_map_alloc(dam_t * mapp)1681b115575SJohn Danielson dam_map_alloc(dam_t *mapp)
1691b115575SJohn Danielson {
1701b115575SJohn Danielson void *softstate_p;
1711b115575SJohn Danielson
1721b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
1731b115575SJohn Danielson if (mapp->dam_flags & DAM_DESTROYPEND)
1741b115575SJohn Danielson return (DAM_FAILURE);
1751b115575SJohn Danielson
1761b115575SJohn Danielson /*
1771b115575SJohn Danielson * dam_high > 0 signals map allocation complete
1781b115575SJohn Danielson */
1791b115575SJohn Danielson if (mapp->dam_high)
1801b115575SJohn Danielson return (DAM_SUCCESS);
1811b115575SJohn Danielson
1821b115575SJohn Danielson mapp->dam_size = DAM_SIZE_BUMP;
1831b115575SJohn Danielson if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
1841b115575SJohn Danielson mapp->dam_size) != DDI_SUCCESS)
1851b115575SJohn Danielson return (DAM_FAILURE);
1861b115575SJohn Danielson
1871b115575SJohn Danielson if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
1881b115575SJohn Danielson DDI_SUCCESS) {
189*ccac1493SHans Rosenfeld ddi_soft_state_fini(&softstate_p);
1901b115575SJohn Danielson return (DAM_FAILURE);
1911b115575SJohn Danielson }
1924c06356bSdh if (dam_kstat_create(mapp) != DDI_SUCCESS) {
193*ccac1493SHans Rosenfeld ddi_soft_state_fini(&softstate_p);
1941b115575SJohn Danielson ddi_strid_fini(&mapp->dam_addr_hash);
1954c06356bSdh return (DAM_FAILURE);
1964c06356bSdh }
1971b115575SJohn Danielson mapp->dam_da = softstate_p;
1981b115575SJohn Danielson mapp->dam_high = 1;
1991b115575SJohn Danielson bitset_resize(&mapp->dam_active_set, mapp->dam_size);
2001b115575SJohn Danielson bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
2011b115575SJohn Danielson bitset_resize(&mapp->dam_report_set, mapp->dam_size);
2024c06356bSdh return (DAM_SUCCESS);
2034c06356bSdh }
2044c06356bSdh
2054c06356bSdh /*
2061b115575SJohn Danielson * Destroy address map
2074c06356bSdh *
2084c06356bSdh * damapp: address map
2094c06356bSdh *
2104c06356bSdh * Returns: DAM_SUCCESS
2114c06356bSdh * DAM_EINVAL Invalid argument(s)
2124c06356bSdh * DAM_FAILURE General failure
2134c06356bSdh */
2144c06356bSdh void
damap_destroy(damap_t * damapp)2154c06356bSdh damap_destroy(damap_t *damapp)
2164c06356bSdh {
2174c06356bSdh int i;
2184c06356bSdh dam_t *mapp = (dam_t *)damapp;
2194c06356bSdh
2204c06356bSdh ASSERT(mapp);
2214c06356bSdh
2221b94a41bSChris Horne DTRACE_PROBE2(damap__destroy,
2231b94a41bSChris Horne char *, mapp->dam_name, damap_t *, mapp);
2244c06356bSdh
2251b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
2264c06356bSdh
2274c06356bSdh /*
2281b115575SJohn Danielson * prevent new reports from being added to the map
2294c06356bSdh */
2301b115575SJohn Danielson mapp->dam_flags |= DAM_DESTROYPEND;
2314c06356bSdh
2321b115575SJohn Danielson if (mapp->dam_high) {
2331b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
2341b115575SJohn Danielson /*
2351b115575SJohn Danielson * wait for outstanding reports to stabilize and cancel
2361b115575SJohn Danielson * the timer for this map
2371b115575SJohn Danielson */
23860aabb4cSChris Horne (void) damap_sync(damapp, 0);
2391b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
24060aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
2411b115575SJohn Danielson
2421b115575SJohn Danielson /*
2431b115575SJohn Danielson * map is at full stop
2441b115575SJohn Danielson * release the contents of the map, invoking the
2451b115575SJohn Danielson * detactivation protocol as addresses are released
2461b115575SJohn Danielson */
2471b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
2481b115575SJohn Danielson for (i = 1; i < mapp->dam_high; i++) {
2491b115575SJohn Danielson if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
2501b115575SJohn Danielson continue;
2511b115575SJohn Danielson
2521b115575SJohn Danielson ASSERT(DAM_IN_REPORT(mapp, i) == 0);
2531b115575SJohn Danielson
2541b115575SJohn Danielson if (DAM_IS_STABLE(mapp, i)) {
2551b115575SJohn Danielson dam_addr_deactivate(mapp, i);
2561b115575SJohn Danielson } else {
2571b115575SJohn Danielson ddi_strid_free(mapp->dam_addr_hash, i);
2581b115575SJohn Danielson ddi_soft_state_free(mapp->dam_da, i);
2591b115575SJohn Danielson }
2601b115575SJohn Danielson }
2611b115575SJohn Danielson ddi_strid_fini(&mapp->dam_addr_hash);
2621b115575SJohn Danielson ddi_soft_state_fini(&mapp->dam_da);
2631b115575SJohn Danielson kstat_delete(mapp->dam_kstatsp);
26460aabb4cSChris Horne } else
26560aabb4cSChris Horne mutex_exit(&mapp->dam_lock);
26660aabb4cSChris Horne
2674c06356bSdh bitset_fini(&mapp->dam_active_set);
2684c06356bSdh bitset_fini(&mapp->dam_stable_set);
2694c06356bSdh bitset_fini(&mapp->dam_report_set);
2704c06356bSdh mutex_destroy(&mapp->dam_lock);
27160aabb4cSChris Horne cv_destroy(&mapp->dam_sync_cv);
2724c06356bSdh if (mapp->dam_name)
2734c06356bSdh kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
2744c06356bSdh kmem_free(mapp, sizeof (*mapp));
2754c06356bSdh }
2764c06356bSdh
2774c06356bSdh /*
27860aabb4cSChris Horne * Wait for map stability. If sync was successfull then return 1.
27960aabb4cSChris Horne * If called with a non-zero sync_usec, then a return value of 0 means a
28060aabb4cSChris Horne * timeout occurred prior to sync completion. NOTE: if sync_usec is
28160aabb4cSChris Horne * non-zero, it should be much longer than dam_stable_ticks.
2824c06356bSdh *
2834c06356bSdh * damapp: address map
28460aabb4cSChris Horne * sync_usec: micorseconds until we give up on sync completion.
2854c06356bSdh */
28660aabb4cSChris Horne #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
2874c06356bSdh int
damap_sync(damap_t * damapp,int sync_usec)28860aabb4cSChris Horne damap_sync(damap_t *damapp, int sync_usec)
2894c06356bSdh {
29060aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
29160aabb4cSChris Horne int rv;
2924c06356bSdh
2934c06356bSdh ASSERT(mapp);
2941b94a41bSChris Horne DTRACE_PROBE3(damap__map__sync__start,
2951b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
2961b94a41bSChris Horne int, sync_usec);
2974c06356bSdh
2981b115575SJohn Danielson /*
29960aabb4cSChris Horne * Block when waiting for
30060aabb4cSChris Horne * a) stabilization pending or a fullset update pending
30160aabb4cSChris Horne * b) the report set to finalize (bitset is null)
30260aabb4cSChris Horne * c) any scheduled timeouts to fire
3031b115575SJohn Danielson */
30460aabb4cSChris Horne rv = 1; /* return synced */
3054c06356bSdh mutex_enter(&mapp->dam_lock);
30660aabb4cSChris Horne again: while ((mapp->dam_flags & WAITFOR_FLAGS) ||
30760aabb4cSChris Horne (!bitset_is_null(&mapp->dam_report_set)) ||
30860aabb4cSChris Horne (mapp->dam_tid != 0)) {
3091b94a41bSChris Horne DTRACE_PROBE2(damap__map__sync__waiting,
3101b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
3114c06356bSdh
31260aabb4cSChris Horne /* Wait for condition relayed via timeout */
31360aabb4cSChris Horne if (sync_usec) {
31460aabb4cSChris Horne if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
31560aabb4cSChris Horne drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
31660aabb4cSChris Horne mapp->dam_sync_to_cnt++;
31760aabb4cSChris Horne rv = 0; /* return timeout */
31860aabb4cSChris Horne break;
31960aabb4cSChris Horne }
32060aabb4cSChris Horne } else
32160aabb4cSChris Horne cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
32260aabb4cSChris Horne }
3234c06356bSdh
32460aabb4cSChris Horne if (rv) {
32560aabb4cSChris Horne /*
32660aabb4cSChris Horne * Delay one stabilization time after the apparent sync above
32760aabb4cSChris Horne * and verify accuracy - resync if not accurate.
32860aabb4cSChris Horne */
32960aabb4cSChris Horne (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
33060aabb4cSChris Horne mapp->dam_stable_ticks, TR_MICROSEC);
33160aabb4cSChris Horne if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
33260aabb4cSChris Horne (!bitset_is_null(&mapp->dam_report_set)) ||
33360aabb4cSChris Horne (mapp->dam_tid != 0)))
33460aabb4cSChris Horne goto again;
33560aabb4cSChris Horne }
3364c06356bSdh mutex_exit(&mapp->dam_lock);
3374c06356bSdh
3381b94a41bSChris Horne DTRACE_PROBE3(damap__map__sync__end,
3391b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
3401b94a41bSChris Horne int, rv);
34160aabb4cSChris Horne return (rv);
34260aabb4cSChris Horne }
34360aabb4cSChris Horne
34460aabb4cSChris Horne /*
34560aabb4cSChris Horne * Return 1 if active set is empty
34660aabb4cSChris Horne */
34760aabb4cSChris Horne int
damap_is_empty(damap_t * damapp)34860aabb4cSChris Horne damap_is_empty(damap_t *damapp)
34960aabb4cSChris Horne {
35060aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
35160aabb4cSChris Horne int rv;
35260aabb4cSChris Horne
35360aabb4cSChris Horne mutex_enter(&mapp->dam_lock);
35460aabb4cSChris Horne rv = bitset_is_null(&mapp->dam_active_set);
35560aabb4cSChris Horne mutex_exit(&mapp->dam_lock);
35660aabb4cSChris Horne return (rv);
3574c06356bSdh }
3584c06356bSdh
3594c06356bSdh /*
3604c06356bSdh * Get the name of a device address map
3614c06356bSdh *
3624c06356bSdh * damapp: address map
3634c06356bSdh *
3644c06356bSdh * Returns: name
3654c06356bSdh */
3664c06356bSdh char *
damap_name(damap_t * damapp)3674c06356bSdh damap_name(damap_t *damapp)
3684c06356bSdh {
3694c06356bSdh dam_t *mapp = (dam_t *)damapp;
3704c06356bSdh
3714c06356bSdh return (mapp ? mapp->dam_name : "UNKNOWN_damap");
3724c06356bSdh }
3734c06356bSdh
37460aabb4cSChris Horne /*
37560aabb4cSChris Horne * Get the current size of the device address map
37660aabb4cSChris Horne *
37760aabb4cSChris Horne * damapp: address map
37860aabb4cSChris Horne *
37960aabb4cSChris Horne * Returns: size
38060aabb4cSChris Horne */
38160aabb4cSChris Horne int
damap_size(damap_t * damapp)38260aabb4cSChris Horne damap_size(damap_t *damapp)
38360aabb4cSChris Horne {
38460aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
38560aabb4cSChris Horne
38660aabb4cSChris Horne return (mapp->dam_size);
38760aabb4cSChris Horne }
38860aabb4cSChris Horne
3894c06356bSdh /*
3904c06356bSdh * Report an address to per-address report
3914c06356bSdh *
3924c06356bSdh * damapp: address map handle
3934c06356bSdh * address: address in ascii string representation
3941b115575SJohn Danielson * addridp: address ID
3954c06356bSdh * nvl: optional nvlist of configuration-private data
3964c06356bSdh * addr_priv: optional provider-private (passed to activate/deactivate cb)
3974c06356bSdh *
3984c06356bSdh * Returns: DAM_SUCCESS
3994c06356bSdh * DAM_EINVAL Invalid argument(s)
4004c06356bSdh * DAM_MAPFULL address map exhausted
4014c06356bSdh */
4024c06356bSdh int
damap_addr_add(damap_t * damapp,char * address,damap_id_t * addridp,nvlist_t * nvl,void * addr_priv)4031b115575SJohn Danielson damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
4041b115575SJohn Danielson nvlist_t *nvl, void *addr_priv)
4054c06356bSdh {
4064c06356bSdh dam_t *mapp = (dam_t *)damapp;
4074c06356bSdh id_t addrid;
4084c06356bSdh dam_da_t *passp;
4094c06356bSdh
4101b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
4114c06356bSdh return (DAM_EINVAL);
4124c06356bSdh
4131b94a41bSChris Horne DTRACE_PROBE3(damap__addr__add,
4141b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4151b94a41bSChris Horne char *, address);
4161b115575SJohn Danielson
4171b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
4181b115575SJohn Danielson if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
4191b115575SJohn Danielson ((addrid = dam_get_addrid(mapp, address)) == 0)) {
4201b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4214c06356bSdh return (DAM_MAPFULL);
4224c06356bSdh }
4234c06356bSdh
4244c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
4254c06356bSdh ASSERT(passp != NULL);
4264c06356bSdh
4274c06356bSdh /*
4284c06356bSdh * If re-reporting the same address (add or remove) clear
4294c06356bSdh * the existing report
4304c06356bSdh */
4314c06356bSdh if (DAM_IN_REPORT(mapp, addrid)) {
4321b94a41bSChris Horne DTRACE_PROBE3(damap__addr__add__jitter,
4331b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4341b94a41bSChris Horne char *, address);
4351b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_jitter);
4361b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
4374c06356bSdh passp->da_jitter++;
4384c06356bSdh }
43978427917SHans Rosenfeld passp->da_ppriv = addr_priv;
4404c06356bSdh if (nvl)
4414c06356bSdh (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
4424c06356bSdh
4431b115575SJohn Danielson dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
4441b115575SJohn Danielson if (addridp != NULL)
4451b115575SJohn Danielson *addridp = (damap_id_t)addrid;
4461b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4474c06356bSdh return (DAM_SUCCESS);
4484c06356bSdh }
4494c06356bSdh
4504c06356bSdh /*
4514c06356bSdh * Report removal of address from per-address report
4524c06356bSdh *
4534c06356bSdh * damapp: address map
4544c06356bSdh * address: address in ascii string representation
4554c06356bSdh *
4564c06356bSdh * Returns: DAM_SUCCESS
4574c06356bSdh * DAM_EINVAL Invalid argument(s)
4584c06356bSdh * DAM_FAILURE General failure
4594c06356bSdh */
4604c06356bSdh int
damap_addr_del(damap_t * damapp,char * address)4614c06356bSdh damap_addr_del(damap_t *damapp, char *address)
4624c06356bSdh {
4634c06356bSdh dam_t *mapp = (dam_t *)damapp;
4644c06356bSdh id_t addrid;
4654c06356bSdh dam_da_t *passp;
4664c06356bSdh
4671b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
4684c06356bSdh return (DAM_EINVAL);
4694c06356bSdh
4701b94a41bSChris Horne DTRACE_PROBE3(damap__addr__del,
4711b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4721b94a41bSChris Horne char *, address);
4731b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
4741b115575SJohn Danielson if (dam_map_alloc(mapp) != DAM_SUCCESS) {
4751b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4761b115575SJohn Danielson return (DAM_MAPFULL);
4771b115575SJohn Danielson }
4781b115575SJohn Danielson
4791b115575SJohn Danielson /*
4801b115575SJohn Danielson * if reporting the removal of an address which is not in the map
4811b115575SJohn Danielson * return success
4821b115575SJohn Danielson */
4834c06356bSdh if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
4841b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4854c06356bSdh return (DAM_SUCCESS);
4864c06356bSdh }
4874c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
4884c06356bSdh ASSERT(passp);
4894c06356bSdh if (DAM_IN_REPORT(mapp, addrid)) {
4901b94a41bSChris Horne DTRACE_PROBE3(damap__addr__del__jitter,
4911b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4921b94a41bSChris Horne char *, address);
4931b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_jitter);
4941b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
4954c06356bSdh passp->da_jitter++;
4964c06356bSdh }
4971b115575SJohn Danielson dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
4981b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4994c06356bSdh return (DAM_SUCCESS);
5004c06356bSdh }
5014c06356bSdh
5020b53804eSReed static int
damap_addrset_flush_locked(damap_t * damapp)5030b53804eSReed damap_addrset_flush_locked(damap_t *damapp)
5040b53804eSReed {
50560aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
5060b53804eSReed int idx;
5070b53804eSReed
5080b53804eSReed ASSERT(mapp);
5090b53804eSReed ASSERT(mutex_owned(&mapp->dam_lock));
5100b53804eSReed if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
5110b53804eSReed return (DAM_EINVAL);
5120b53804eSReed }
5130b53804eSReed
5141b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush__locked__enter,
5151b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5160b53804eSReed if (mapp->dam_flags & DAM_SETADD) {
5171b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush__locked__reset,
5181b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5190b53804eSReed
5200b53804eSReed /*
5210b53804eSReed * cancel stabilization timeout
5220b53804eSReed */
52360aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
5240b53804eSReed DAM_INCR_STAT(mapp, dam_jitter);
5250b53804eSReed
5260b53804eSReed /*
5270b53804eSReed * clear pending reports
5280b53804eSReed */
5290b53804eSReed for (idx = 1; idx < mapp->dam_high; idx++) {
5300b53804eSReed if (DAM_IN_REPORT(mapp, idx)) {
5310b53804eSReed dam_addr_report_release(mapp, idx);
5320b53804eSReed }
5330b53804eSReed }
5340b53804eSReed
5350b53804eSReed bitset_zero(&mapp->dam_report_set);
5360b53804eSReed mapp->dam_flags &= ~DAM_SETADD;
53760aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
5380b53804eSReed }
5390b53804eSReed
5400b53804eSReed return (DAM_SUCCESS);
5410b53804eSReed }
5420b53804eSReed
5434c06356bSdh /*
5444c06356bSdh * Initiate full-set report
5454c06356bSdh *
5464c06356bSdh * damapp: address map
5474c06356bSdh *
5484c06356bSdh * Returns: DAM_SUCCESS
5494c06356bSdh * DAM_EINVAL Invalid argument(s)
5504c06356bSdh */
5514c06356bSdh int
damap_addrset_begin(damap_t * damapp)5524c06356bSdh damap_addrset_begin(damap_t *damapp)
5534c06356bSdh {
5540b53804eSReed dam_t *mapp = (dam_t *)damapp;
5550b53804eSReed int rv;
5564c06356bSdh
5570b53804eSReed if (mapp == NULL) {
5584c06356bSdh return (DAM_EINVAL);
5590b53804eSReed }
5604c06356bSdh
5611b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__begin,
5621b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5630b53804eSReed
5641b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
5651b115575SJohn Danielson if (dam_map_alloc(mapp) != DAM_SUCCESS) {
5661b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
5670b53804eSReed
5681b115575SJohn Danielson return (DAM_MAPFULL);
5691b115575SJohn Danielson }
5701b115575SJohn Danielson
5710b53804eSReed rv = damap_addrset_flush_locked(damapp);
5720b53804eSReed if (rv == DAM_SUCCESS) {
5730b53804eSReed mapp->dam_flags |= DAM_SETADD;
5744c06356bSdh }
5751b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
5760b53804eSReed
5770b53804eSReed return (rv);
5780b53804eSReed }
5790b53804eSReed
5800b53804eSReed /*
5810b53804eSReed * Cancel full-set report
5820b53804eSReed *
58360aabb4cSChris Horne * damapp: address map
5840b53804eSReed *
58560aabb4cSChris Horne * Returns: DAM_SUCCESS
58660aabb4cSChris Horne * DAM_EINVAL Invalid argument(s)
5870b53804eSReed */
5880b53804eSReed int
damap_addrset_flush(damap_t * damapp)5890b53804eSReed damap_addrset_flush(damap_t *damapp)
5900b53804eSReed {
5910b53804eSReed int rv;
5920b53804eSReed dam_t *mapp = (dam_t *)damapp;
5930b53804eSReed
5940b53804eSReed if (mapp == NULL) {
5950b53804eSReed return (DAM_EINVAL);
5960b53804eSReed }
5970b53804eSReed
5981b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush,
5991b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
6000b53804eSReed
6010b53804eSReed mutex_enter(&mapp->dam_lock);
6020b53804eSReed rv = damap_addrset_flush_locked(damapp);
6030b53804eSReed mutex_exit(&mapp->dam_lock);
6040b53804eSReed
6050b53804eSReed return (rv);
6064c06356bSdh }
6074c06356bSdh
6084c06356bSdh /*
6094c06356bSdh * Report address to full-set report
6104c06356bSdh *
6114c06356bSdh * damapp: address map handle
6124c06356bSdh * address: address in ascii string representation
6134c06356bSdh * rindx: index if address stabilizes
6144c06356bSdh * nvl: optional nvlist of configuration-private data
6154c06356bSdh * addr_priv: optional provider-private data (passed to activate/release cb)
6164c06356bSdh *
6174c06356bSdh * Returns: DAM_SUCCESS
6184c06356bSdh * DAM_EINVAL Invalid argument(s)
6194c06356bSdh * DAM_MAPFULL address map exhausted
6204c06356bSdh * DAM_FAILURE General failure
6214c06356bSdh */
6224c06356bSdh int
damap_addrset_add(damap_t * damapp,char * address,damap_id_t * ridx,nvlist_t * nvl,void * addr_priv)6234c06356bSdh damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
6244c06356bSdh nvlist_t *nvl, void *addr_priv)
6254c06356bSdh {
6264c06356bSdh dam_t *mapp = (dam_t *)damapp;
6274c06356bSdh id_t addrid;
6284c06356bSdh dam_da_t *passp;
6294c06356bSdh
6301b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
6314c06356bSdh return (DAM_EINVAL);
6324c06356bSdh
6331b94a41bSChris Horne DTRACE_PROBE3(damap__addrset__add,
6341b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp, char *, address);
6351b115575SJohn Danielson
6361b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
6371b115575SJohn Danielson if (!(mapp->dam_flags & DAM_SETADD)) {
6381b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6394c06356bSdh return (DAM_FAILURE);
6401b115575SJohn Danielson }
6414c06356bSdh
6424c06356bSdh if ((addrid = dam_get_addrid(mapp, address)) == 0) {
6431b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6444c06356bSdh return (DAM_MAPFULL);
6454c06356bSdh }
6464c06356bSdh
6474c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
6484c06356bSdh ASSERT(passp);
6494c06356bSdh if (DAM_IN_REPORT(mapp, addrid)) {
6501b94a41bSChris Horne DTRACE_PROBE3(damap__addrset__add__jitter,
6511b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
6521b94a41bSChris Horne char *, address);
6531b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
6544c06356bSdh passp->da_jitter++;
6554c06356bSdh }
65678427917SHans Rosenfeld passp->da_ppriv = addr_priv;
6574c06356bSdh if (nvl)
6584c06356bSdh (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
6594c06356bSdh bitset_add(&mapp->dam_report_set, addrid);
6604c06356bSdh if (ridx)
6614c06356bSdh *ridx = (damap_id_t)addrid;
6621b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6634c06356bSdh return (DAM_SUCCESS);
6644c06356bSdh }
6654c06356bSdh
6664c06356bSdh /*
6674c06356bSdh * Commit full-set report for stabilization
6684c06356bSdh *
6694c06356bSdh * damapp: address map handle
6704c06356bSdh * flags: (currently 0)
6714c06356bSdh *
6724c06356bSdh * Returns: DAM_SUCCESS
6734c06356bSdh * DAM_EINVAL Invalid argument(s)
6744c06356bSdh * DAM_FAILURE General failure
6754c06356bSdh */
6764c06356bSdh int
damap_addrset_end(damap_t * damapp,int flags)6774c06356bSdh damap_addrset_end(damap_t *damapp, int flags)
6784c06356bSdh {
6794c06356bSdh dam_t *mapp = (dam_t *)damapp;
6804c06356bSdh int i;
6814c06356bSdh
6821b115575SJohn Danielson if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
6834c06356bSdh return (DAM_EINVAL);
6844c06356bSdh
6851b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__end,
6861b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
6871b115575SJohn Danielson
6881b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
6891b115575SJohn Danielson if (!(mapp->dam_flags & DAM_SETADD)) {
6901b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6914c06356bSdh return (DAM_FAILURE);
6921b115575SJohn Danielson }
6934c06356bSdh
6941b115575SJohn Danielson if (flags & DAMAP_END_RESET) {
6951b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__end__reset,
6961b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
69760aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
6984c06356bSdh for (i = 1; i < mapp->dam_high; i++)
6994c06356bSdh if (DAM_IN_REPORT(mapp, i))
7001b115575SJohn Danielson dam_addr_report_release(mapp, i);
7014c06356bSdh } else {
7024c06356bSdh mapp->dam_last_update = gethrtime();
70360aabb4cSChris Horne dam_sched_timeout(dam_addrset_stable_cb, mapp,
70460aabb4cSChris Horne mapp->dam_stable_ticks);
7054c06356bSdh }
7061b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
7074c06356bSdh return (DAM_SUCCESS);
7084c06356bSdh }
7094c06356bSdh
7104c06356bSdh /*
7114c06356bSdh * Return nvlist registered with reported address
7124c06356bSdh *
7134c06356bSdh * damapp: address map handle
7141b115575SJohn Danielson * addrid: address ID
7154c06356bSdh *
7164c06356bSdh * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
7174c06356bSdh * NULL
7184c06356bSdh */
7194c06356bSdh nvlist_t *
damap_id2nvlist(damap_t * damapp,damap_id_t addrid)7204c06356bSdh damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
7214c06356bSdh {
7224c06356bSdh dam_t *mapp = (dam_t *)damapp;
7234c06356bSdh dam_da_t *pass;
7244c06356bSdh
7251b115575SJohn Danielson if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
7261b115575SJohn Danielson if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
7274c06356bSdh return (pass->da_nvl);
7284c06356bSdh }
7294c06356bSdh return (NULL);
7304c06356bSdh }
7314c06356bSdh
7324c06356bSdh /*
7334c06356bSdh * Return address string
7344c06356bSdh *
7354c06356bSdh * damapp: address map handle
7361b115575SJohn Danielson * addrid: address ID
7374c06356bSdh *
7384c06356bSdh * Returns: char * Address string
7394c06356bSdh * NULL
7404c06356bSdh */
7414c06356bSdh char *
damap_id2addr(damap_t * damapp,damap_id_t addrid)7421b115575SJohn Danielson damap_id2addr(damap_t *damapp, damap_id_t addrid)
7434c06356bSdh {
7444c06356bSdh dam_t *mapp = (dam_t *)damapp;
7454c06356bSdh
7461b115575SJohn Danielson if (mapp->dam_high)
7471b115575SJohn Danielson return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
7481b115575SJohn Danielson else
7491b115575SJohn Danielson return (NULL);
7504c06356bSdh }
7514c06356bSdh
7524c06356bSdh /*
7531b115575SJohn Danielson * Release address reference in map
7544c06356bSdh *
7554c06356bSdh * damapp: address map handle
7561b115575SJohn Danielson * addrid: address ID
7574c06356bSdh */
7581b115575SJohn Danielson void
damap_id_rele(damap_t * damapp,damap_id_t addrid)7591b115575SJohn Danielson damap_id_rele(damap_t *damapp, damap_id_t addrid)
7604c06356bSdh {
7614c06356bSdh dam_t *mapp = (dam_t *)damapp;
7624c06356bSdh dam_da_t *passp;
7631b115575SJohn Danielson char *addr;
7644c06356bSdh
7651b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
7661b115575SJohn Danielson ASSERT(passp);
7674c06356bSdh
7681b115575SJohn Danielson addr = damap_id2addr(damapp, addrid);
7691b94a41bSChris Horne DTRACE_PROBE4(damap__id__rele,
7701b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
7711b94a41bSChris Horne char *, addr, int, passp->da_ref);
7724c06356bSdh
7731b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
7741b115575SJohn Danielson
7751b115575SJohn Danielson /*
7761b115575SJohn Danielson * teardown address if last outstanding reference
7771b115575SJohn Danielson */
7781b115575SJohn Danielson if (--passp->da_ref == 0)
7791b115575SJohn Danielson dam_addr_release(mapp, (id_t)addrid);
7804c06356bSdh
7811b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
7824c06356bSdh }
7834c06356bSdh
7844c06356bSdh /*
7854c06356bSdh * Return current reference count on address reference in map
7864c06356bSdh *
7874c06356bSdh * damapp: address map handle
7881b115575SJohn Danielson * addrid: address ID
7894c06356bSdh *
7904c06356bSdh * Returns: DAM_SUCCESS
7914c06356bSdh * DAM_FAILURE
7924c06356bSdh */
7934c06356bSdh int
damap_id_ref(damap_t * damapp,damap_id_t addrid)7941b115575SJohn Danielson damap_id_ref(damap_t *damapp, damap_id_t addrid)
7954c06356bSdh {
7964c06356bSdh dam_t *mapp = (dam_t *)damapp;
7974c06356bSdh dam_da_t *passp;
7984c06356bSdh int ref = -1;
7994c06356bSdh
8001b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8014c06356bSdh if (passp)
8024c06356bSdh ref = passp->da_ref;
8031b115575SJohn Danielson
8044c06356bSdh return (ref);
8054c06356bSdh }
8064c06356bSdh
8074c06356bSdh /*
8084c06356bSdh * Return next address ID in list
8094c06356bSdh *
8104c06356bSdh * damapp: address map handle
8114c06356bSdh * damap_list: address ID list passed to config|unconfig
8124c06356bSdh * returned by look by lookup_all
8134c06356bSdh * last: last ID returned, 0 is start of list
8144c06356bSdh *
8154c06356bSdh * Returns: addrid Next ID from the list
8164c06356bSdh * 0 End of the list
8174c06356bSdh */
8184c06356bSdh damap_id_t
damap_id_next(damap_t * damapp,damap_id_list_t damap_list,damap_id_t last)8194c06356bSdh damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
8204c06356bSdh {
8214c06356bSdh int i, start;
8224c06356bSdh dam_t *mapp = (dam_t *)damapp;
8234c06356bSdh bitset_t *dam_list = (bitset_t *)damap_list;
8244c06356bSdh
8254c06356bSdh if (!mapp || !dam_list)
8264c06356bSdh return ((damap_id_t)0);
8274c06356bSdh
8284c06356bSdh start = (int)last + 1;
8291b115575SJohn Danielson for (i = start; i < mapp->dam_high; i++) {
8301b115575SJohn Danielson if (bitset_in_set(dam_list, i)) {
8314c06356bSdh return ((damap_id_t)i);
8321b115575SJohn Danielson }
8331b115575SJohn Danielson }
8344c06356bSdh return ((damap_id_t)0);
8354c06356bSdh }
8364c06356bSdh
8374c06356bSdh /*
8384c06356bSdh * Set config private data
8394c06356bSdh *
8404c06356bSdh * damapp: address map handle
8411b115575SJohn Danielson * addrid: address ID
8424c06356bSdh * cfg_priv: configuration private data
8434c06356bSdh *
8444c06356bSdh */
8454c06356bSdh void
damap_id_priv_set(damap_t * damapp,damap_id_t addrid,void * cfg_priv)8461b115575SJohn Danielson damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
8474c06356bSdh {
8484c06356bSdh dam_t *mapp = (dam_t *)damapp;
8494c06356bSdh dam_da_t *passp;
8504c06356bSdh
8511b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
8521b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8534c06356bSdh if (!passp) {
8541b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8554c06356bSdh return;
8564c06356bSdh }
8574c06356bSdh passp->da_cfg_priv = cfg_priv;
8581b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8594c06356bSdh }
8604c06356bSdh
8614c06356bSdh /*
8624c06356bSdh * Get config private data
8634c06356bSdh *
8644c06356bSdh * damapp: address map handle
8651b115575SJohn Danielson * addrid: address ID
8664c06356bSdh *
8674c06356bSdh * Returns: configuration private data
8684c06356bSdh */
8694c06356bSdh void *
damap_id_priv_get(damap_t * damapp,damap_id_t addrid)8701b115575SJohn Danielson damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
8714c06356bSdh {
8724c06356bSdh dam_t *mapp = (dam_t *)damapp;
8734c06356bSdh dam_da_t *passp;
8744c06356bSdh void *rv;
8754c06356bSdh
8761b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
8771b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8784c06356bSdh if (!passp) {
8791b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8804c06356bSdh return (NULL);
8814c06356bSdh }
8824c06356bSdh rv = passp->da_cfg_priv;
8831b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8844c06356bSdh return (rv);
8854c06356bSdh }
8864c06356bSdh
8874c06356bSdh /*
8884c06356bSdh * Lookup a single address in the active address map
8894c06356bSdh *
8904c06356bSdh * damapp: address map handle
8914c06356bSdh * address: address string
8924c06356bSdh *
8934c06356bSdh * Returns: ID of active/stable address
8944c06356bSdh * 0 Address not in stable set
8954c06356bSdh *
8964c06356bSdh * Future: Allow the caller to wait for stabilize before returning not found.
8974c06356bSdh */
8984c06356bSdh damap_id_t
damap_lookup(damap_t * damapp,char * address)8994c06356bSdh damap_lookup(damap_t *damapp, char *address)
9004c06356bSdh {
9014c06356bSdh dam_t *mapp = (dam_t *)damapp;
9024c06356bSdh id_t addrid = 0;
9034c06356bSdh dam_da_t *passp = NULL;
9044c06356bSdh
9051b94a41bSChris Horne DTRACE_PROBE3(damap__lookup,
9061b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9071b94a41bSChris Horne char *, address);
9081b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
9091b115575SJohn Danielson if (!mapp->dam_high)
9101b115575SJohn Danielson addrid = 0;
9111b115575SJohn Danielson else
9121b115575SJohn Danielson addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
9134c06356bSdh if (addrid) {
9144c06356bSdh if (DAM_IS_STABLE(mapp, addrid)) {
9154c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
9164c06356bSdh ASSERT(passp);
9174c06356bSdh if (passp) {
9184c06356bSdh passp->da_ref++;
9194c06356bSdh } else {
9204c06356bSdh addrid = 0;
9214c06356bSdh }
9224c06356bSdh } else {
9234c06356bSdh addrid = 0;
9244c06356bSdh }
9254c06356bSdh }
9261b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9271b94a41bSChris Horne DTRACE_PROBE4(damap__lookup__return,
9281b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9291b94a41bSChris Horne char *, address, int, addrid);
9304c06356bSdh return ((damap_id_t)addrid);
9314c06356bSdh }
9324c06356bSdh
9334c06356bSdh
9344c06356bSdh /*
9354c06356bSdh * Return the list of stable addresses in the map
9364c06356bSdh *
9374c06356bSdh * damapp: address map handle
9384c06356bSdh * id_listp: pointer to list of address IDs in stable map (returned)
9394c06356bSdh *
9404c06356bSdh * Returns: # of entries returned in alist
9414c06356bSdh */
9424c06356bSdh int
damap_lookup_all(damap_t * damapp,damap_id_list_t * id_listp)9434c06356bSdh damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
9444c06356bSdh {
9454c06356bSdh dam_t *mapp = (dam_t *)damapp;
9464c06356bSdh int mapsz = mapp->dam_size;
9474c06356bSdh int n_ids, i;
9484c06356bSdh bitset_t *bsp;
9491b115575SJohn Danielson char *addrp;
9504c06356bSdh dam_da_t *passp;
9514c06356bSdh
9521b94a41bSChris Horne DTRACE_PROBE2(damap__lookup__all,
9531b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
9541b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
9551b115575SJohn Danielson if (!mapp->dam_high) {
9561b115575SJohn Danielson *id_listp = (damap_id_list_t)NULL;
9571b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9581b94a41bSChris Horne DTRACE_PROBE2(damap__lookup__all__nomap,
9591b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
9601b115575SJohn Danielson return (0);
9611b115575SJohn Danielson }
9624c06356bSdh bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
9634c06356bSdh bitset_init(bsp);
9644c06356bSdh bitset_resize(bsp, mapsz);
9654c06356bSdh bitset_copy(&mapp->dam_active_set, bsp);
9664c06356bSdh for (n_ids = 0, i = 1; i < mapsz; i++) {
9674c06356bSdh if (bitset_in_set(bsp, i)) {
9684c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, i);
9694c06356bSdh ASSERT(passp);
9704c06356bSdh if (passp) {
9711b115575SJohn Danielson addrp = damap_id2addr(damapp, i);
9721b94a41bSChris Horne DTRACE_PROBE3(damap__lookup__all__item,
9731b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9741b94a41bSChris Horne char *, addrp);
9754c06356bSdh passp->da_ref++;
9764c06356bSdh n_ids++;
9774c06356bSdh }
9784c06356bSdh }
9794c06356bSdh }
9804c06356bSdh if (n_ids) {
9814c06356bSdh *id_listp = (damap_id_list_t)bsp;
9821b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9834c06356bSdh return (n_ids);
9844c06356bSdh } else {
9854c06356bSdh *id_listp = (damap_id_list_t)NULL;
9864c06356bSdh bitset_fini(bsp);
9874c06356bSdh kmem_free(bsp, sizeof (*bsp));
9881b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9894c06356bSdh return (0);
9904c06356bSdh }
9914c06356bSdh }
9924c06356bSdh
9934c06356bSdh /*
9944c06356bSdh * Release the address list returned by damap_lookup_all()
9954c06356bSdh *
9964c06356bSdh * mapp: address map handle
9974c06356bSdh * id_list: list of address IDs returned in damap_lookup_all()
9984c06356bSdh */
9994c06356bSdh void
damap_id_list_rele(damap_t * damapp,damap_id_list_t id_list)10004c06356bSdh damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
10014c06356bSdh {
10024c06356bSdh dam_t *mapp = (dam_t *)damapp;
10034c06356bSdh int i;
10044c06356bSdh
10054c06356bSdh if (id_list == NULL)
10064c06356bSdh return;
10074c06356bSdh
10081b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10094c06356bSdh for (i = 1; i < mapp->dam_high; i++) {
10104c06356bSdh if (bitset_in_set((bitset_t *)id_list, i))
10111b115575SJohn Danielson (void) dam_addr_release(mapp, i);
10124c06356bSdh }
10131b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10144c06356bSdh bitset_fini((bitset_t *)id_list);
10154c06356bSdh kmem_free((void *)id_list, sizeof (bitset_t));
10164c06356bSdh }
10174c06356bSdh
10184c06356bSdh /*
10191b115575SJohn Danielson * activate an address that has passed the stabilization interval
10204c06356bSdh */
10214c06356bSdh static void
dam_addr_activate(dam_t * mapp,id_t addrid)10221b115575SJohn Danielson dam_addr_activate(dam_t *mapp, id_t addrid)
10234c06356bSdh {
10244c06356bSdh dam_da_t *passp;
10251b115575SJohn Danielson int config_rv;
10264c06356bSdh char *addrstr;
10274c06356bSdh
10281b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10291b115575SJohn Danielson bitset_add(&mapp->dam_active_set, addrid);
10301b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, addrid);
10311b115575SJohn Danielson ASSERT(passp);
10321b115575SJohn Danielson
10331b115575SJohn Danielson /*
10341b115575SJohn Danielson * copy the reported nvlist and provider private data
10351b115575SJohn Danielson */
10361b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
10371b94a41bSChris Horne DTRACE_PROBE3(damap__addr__activate__start,
10381b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10391b94a41bSChris Horne char *, addrstr);
10401b115575SJohn Danielson passp->da_nvl = passp->da_nvl_rpt;
10411b115575SJohn Danielson passp->da_nvl_rpt = NULL;
10421b115575SJohn Danielson passp->da_last_stable = gethrtime();
10431b115575SJohn Danielson passp->da_stable_cnt++;
10441b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10451b115575SJohn Danielson if (mapp->dam_activate_cb) {
10461b115575SJohn Danielson (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
104778427917SHans Rosenfeld addrid, &passp->da_ppriv);
10481b115575SJohn Danielson }
10491b115575SJohn Danielson
10501b115575SJohn Danielson /*
10511b115575SJohn Danielson * call the address-specific configuration action as part of
10521b115575SJohn Danielson * activation.
10531b115575SJohn Danielson */
10541b115575SJohn Danielson config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
10551b115575SJohn Danielson addrid);
10561b115575SJohn Danielson if (config_rv != DAM_SUCCESS) {
10571b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10581b115575SJohn Danielson passp->da_flags |= DA_FAILED_CONFIG;
10591b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10601b115575SJohn Danielson DTRACE_PROBE3(damap__addr__activate__config__failure,
10611b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10621b94a41bSChris Horne char *, addrstr);
1063d189c170SReed dam_deact_cleanup(mapp, addrid, addrstr,
1064d189c170SReed DAMAP_DEACT_RSN_CFG_FAIL);
1065d189c170SReed } else {
10661b94a41bSChris Horne DTRACE_PROBE3(damap__addr__activate__end,
10671b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10681b94a41bSChris Horne char *, addrstr);
10691b115575SJohn Danielson }
10701b115575SJohn Danielson }
10711b115575SJohn Danielson
10721b115575SJohn Danielson /*
10731b115575SJohn Danielson * deactivate a previously stable address
10741b115575SJohn Danielson */
10751b115575SJohn Danielson static void
dam_addr_deactivate(dam_t * mapp,id_t addrid)10761b115575SJohn Danielson dam_addr_deactivate(dam_t *mapp, id_t addrid)
10771b115575SJohn Danielson {
10781b115575SJohn Danielson char *addrstr;
10791b115575SJohn Danielson
10801b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
10811b94a41bSChris Horne DTRACE_PROBE3(damap__addr__deactivate__start,
10821b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10831b94a41bSChris Horne char *, addrstr);
10841b115575SJohn Danielson
10851b115575SJohn Danielson /*
10861b115575SJohn Danielson * call the unconfiguration callback
10871b115575SJohn Danielson */
10881b115575SJohn Danielson (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1089d189c170SReed dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1090d189c170SReed }
1091d189c170SReed
1092d189c170SReed static void
dam_deact_cleanup(dam_t * mapp,id_t addrid,char * addrstr,damap_deact_rsn_t deact_rsn)1093d189c170SReed dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1094d189c170SReed damap_deact_rsn_t deact_rsn)
1095d189c170SReed {
1096d189c170SReed dam_da_t *passp;
1097d189c170SReed
10981b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, addrid);
10991b115575SJohn Danielson ASSERT(passp);
11001b115575SJohn Danielson if (mapp->dam_deactivate_cb)
11011b115575SJohn Danielson (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
11021b115575SJohn Danielson ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1103d189c170SReed addrid, passp->da_ppriv, deact_rsn);
11041b115575SJohn Danielson
11051b115575SJohn Danielson /*
11061b115575SJohn Danielson * clear the active bit and free the backing info for
11071b115575SJohn Danielson * this address
11081b115575SJohn Danielson */
11091b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
11101b115575SJohn Danielson bitset_del(&mapp->dam_active_set, addrid);
11111b115575SJohn Danielson passp->da_ppriv = NULL;
1112aab83bb8SJosef 'Jeff' Sipek nvlist_free(passp->da_nvl);
11131b115575SJohn Danielson passp->da_nvl = NULL;
1114aab83bb8SJosef 'Jeff' Sipek nvlist_free(passp->da_nvl_rpt);
11151b115575SJohn Danielson passp->da_nvl_rpt = NULL;
11161b115575SJohn Danielson
11171b94a41bSChris Horne DTRACE_PROBE3(damap__addr__deactivate__end,
11181b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
11191b94a41bSChris Horne char *, addrstr);
11201b115575SJohn Danielson
11211b115575SJohn Danielson (void) dam_addr_release(mapp, addrid);
11221b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
11231b115575SJohn Danielson }
11241b115575SJohn Danielson
11251b115575SJohn Danielson /*
11261b115575SJohn Danielson * taskq callback for multi-thread activation
11271b115575SJohn Danielson */
11281b115575SJohn Danielson static void
dam_tq_config(void * arg)11291b115575SJohn Danielson dam_tq_config(void *arg)
11301b115575SJohn Danielson {
11311b115575SJohn Danielson cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
11321b115575SJohn Danielson
11331b115575SJohn Danielson dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
11341b115575SJohn Danielson kmem_free(tqd, sizeof (*tqd));
11351b115575SJohn Danielson }
11361b115575SJohn Danielson
11371b115575SJohn Danielson /*
11381b115575SJohn Danielson * taskq callback for multi-thread deactivation
11391b115575SJohn Danielson */
11401b115575SJohn Danielson static void
dam_tq_unconfig(void * arg)11411b115575SJohn Danielson dam_tq_unconfig(void *arg)
11421b115575SJohn Danielson {
11431b115575SJohn Danielson cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
11441b115575SJohn Danielson
11451b115575SJohn Danielson dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
11461b115575SJohn Danielson kmem_free(tqd, sizeof (*tqd));
11471b115575SJohn Danielson }
11481b115575SJohn Danielson
11491b115575SJohn Danielson /*
11501b115575SJohn Danielson * Activate a set of stabilized addresses
11511b115575SJohn Danielson */
11521b115575SJohn Danielson static void
dam_addrset_activate(dam_t * mapp,bitset_t * activate)11531b115575SJohn Danielson dam_addrset_activate(dam_t *mapp, bitset_t *activate)
11541b115575SJohn Danielson {
11551b115575SJohn Danielson
11561b115575SJohn Danielson int i, nset;
11571b115575SJohn Danielson taskq_t *tqp = NULL;
11581b115575SJohn Danielson cfg_tqd_t *tqd = NULL;
11591b115575SJohn Danielson char tqn[TASKQ_NAMELEN];
11601b115575SJohn Danielson extern pri_t maxclsyspri;
11611b115575SJohn Danielson
11621b115575SJohn Danielson if (mapp->dam_options & DAMAP_MTCONFIG) {
11634c06356bSdh /*
11641b115575SJohn Danielson * calculate the # of taskq threads to create
11654c06356bSdh */
11661b115575SJohn Danielson for (i = 1, nset = 0; i < mapp->dam_high; i++)
11671b115575SJohn Danielson if (bitset_in_set(activate, i))
11681b115575SJohn Danielson nset++;
11691b115575SJohn Danielson ASSERT(nset);
11701b115575SJohn Danielson (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
11711b115575SJohn Danielson tqp = taskq_create(tqn, nset, maxclsyspri, 1,
11721b115575SJohn Danielson INT_MAX, TASKQ_PREPOPULATE);
11731b115575SJohn Danielson }
11741b115575SJohn Danielson for (i = 1; i < mapp->dam_high; i++) {
11751b115575SJohn Danielson if (bitset_in_set(activate, i)) {
11761b115575SJohn Danielson if (!tqp)
11771b115575SJohn Danielson dam_addr_activate(mapp, i);
11781b115575SJohn Danielson else {
11791b115575SJohn Danielson /*
11801b115575SJohn Danielson * multi-threaded activation
11811b115575SJohn Danielson */
11821b115575SJohn Danielson tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
11831b115575SJohn Danielson tqd->tqd_mapp = mapp;
11841b115575SJohn Danielson tqd->tqd_id = i;
11851b115575SJohn Danielson (void) taskq_dispatch(tqp, dam_tq_config,
118664109744SChris Horne tqd, TQ_SLEEP);
11871b115575SJohn Danielson }
11881b115575SJohn Danielson }
11891b115575SJohn Danielson }
11901b115575SJohn Danielson if (tqp) {
11911b115575SJohn Danielson taskq_wait(tqp);
11921b115575SJohn Danielson taskq_destroy(tqp);
11934c06356bSdh }
11944c06356bSdh }
11954c06356bSdh
11964c06356bSdh /*
11971b115575SJohn Danielson * Deactivate a set of stabilized addresses
11984c06356bSdh */
11994c06356bSdh static void
dam_addrset_deactivate(dam_t * mapp,bitset_t * deactivate)12001b115575SJohn Danielson dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
12014c06356bSdh {
12021b115575SJohn Danielson int i, nset;
12031b115575SJohn Danielson taskq_t *tqp = NULL;
12041b115575SJohn Danielson cfg_tqd_t *tqd = NULL;
12051b115575SJohn Danielson char tqn[TASKQ_NAMELEN];
12061b115575SJohn Danielson
12071b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__deactivate,
12081b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
12094c06356bSdh
12101b115575SJohn Danielson if (mapp->dam_options & DAMAP_MTCONFIG) {
12111b115575SJohn Danielson /*
12121b115575SJohn Danielson * compute the # of taskq threads to dispatch
12131b115575SJohn Danielson */
12141b115575SJohn Danielson for (i = 1, nset = 0; i < mapp->dam_high; i++)
12151b115575SJohn Danielson if (bitset_in_set(deactivate, i))
12161b115575SJohn Danielson nset++;
12171b115575SJohn Danielson (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
12181b115575SJohn Danielson mapp->dam_name);
12191b115575SJohn Danielson tqp = taskq_create(tqn, nset, maxclsyspri, 1,
12201b115575SJohn Danielson INT_MAX, TASKQ_PREPOPULATE);
12211b115575SJohn Danielson }
12224c06356bSdh for (i = 1; i < mapp->dam_high; i++) {
12231b115575SJohn Danielson if (bitset_in_set(deactivate, i)) {
12241b115575SJohn Danielson if (!tqp) {
12251b115575SJohn Danielson dam_addr_deactivate(mapp, i);
12261b115575SJohn Danielson } else {
12271b115575SJohn Danielson tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
12281b115575SJohn Danielson tqd->tqd_mapp = mapp;
12291b115575SJohn Danielson tqd->tqd_id = i;
12301b115575SJohn Danielson (void) taskq_dispatch(tqp,
123164109744SChris Horne dam_tq_unconfig, tqd, TQ_SLEEP);
12321b115575SJohn Danielson }
12334c06356bSdh }
12344c06356bSdh }
12351b115575SJohn Danielson
12361b115575SJohn Danielson if (tqp) {
12371b115575SJohn Danielson taskq_wait(tqp);
12381b115575SJohn Danielson taskq_destroy(tqp);
12391b115575SJohn Danielson }
12404c06356bSdh }
12414c06356bSdh
12424c06356bSdh /*
12431b115575SJohn Danielson * Release a previously activated address
12444c06356bSdh */
12454c06356bSdh static void
dam_addr_release(dam_t * mapp,id_t addrid)12461b115575SJohn Danielson dam_addr_release(dam_t *mapp, id_t addrid)
12474c06356bSdh {
12484c06356bSdh dam_da_t *passp;
12491b115575SJohn Danielson char *addrstr;
12501b115575SJohn Danielson
12514c06356bSdh
12521b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
12534c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
12544c06356bSdh ASSERT(passp);
12554c06356bSdh
12561b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
12571b94a41bSChris Horne DTRACE_PROBE3(damap__addr__release,
12581b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12591b94a41bSChris Horne char *, addrstr);
12604c06356bSdh
12614c06356bSdh /*
12621b115575SJohn Danielson * defer releasing the address until outstanding references
12631b115575SJohn Danielson * are released
12644c06356bSdh */
12651b115575SJohn Danielson if (passp->da_ref > 1) {
12661b115575SJohn Danielson DTRACE_PROBE4(damap__addr__release__outstanding__refs,
12671b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12681b94a41bSChris Horne char *, addrstr, int, passp->da_ref);
12694c06356bSdh return;
12701b115575SJohn Danielson }
12714c06356bSdh
12724c06356bSdh /*
12731b115575SJohn Danielson * allow pending reports to stabilize
12744c06356bSdh */
12751b115575SJohn Danielson if (DAM_IN_REPORT(mapp, addrid)) {
12761b115575SJohn Danielson DTRACE_PROBE3(damap__addr__release__report__pending,
12771b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12781b94a41bSChris Horne char *, addrstr);
12794c06356bSdh return;
12804c06356bSdh }
12811b115575SJohn Danielson
12824c06356bSdh ddi_strid_free(mapp->dam_addr_hash, addrid);
12834c06356bSdh ddi_soft_state_free(mapp->dam_da, addrid);
12844c06356bSdh }
12854c06356bSdh
12864c06356bSdh /*
12874c06356bSdh * process stabilized address reports
12884c06356bSdh */
12894c06356bSdh static void
dam_stabilize_map(void * arg)12901b115575SJohn Danielson dam_stabilize_map(void *arg)
12914c06356bSdh {
12924c06356bSdh dam_t *mapp = (dam_t *)arg;
12934c06356bSdh bitset_t delta;
12944c06356bSdh bitset_t cfg;
12954c06356bSdh bitset_t uncfg;
12964c06356bSdh int has_cfg, has_uncfg;
12971b115575SJohn Danielson uint32_t i, n_active;
12981b115575SJohn Danielson
12991b94a41bSChris Horne DTRACE_PROBE2(damap__stabilize__map,
13001b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
13014c06356bSdh
13024c06356bSdh bitset_init(&delta);
13034c06356bSdh bitset_resize(&delta, mapp->dam_size);
13044c06356bSdh bitset_init(&cfg);
13054c06356bSdh bitset_resize(&cfg, mapp->dam_size);
13064c06356bSdh bitset_init(&uncfg);
13074c06356bSdh bitset_resize(&uncfg, mapp->dam_size);
13084c06356bSdh
13091b115575SJohn Danielson /*
13101b115575SJohn Danielson * determine which addresses have changed during
13111b115575SJohn Danielson * this stabilization cycle
13121b115575SJohn Danielson */
13131b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
13141b115575SJohn Danielson ASSERT(mapp->dam_flags & DAM_SPEND);
13154c06356bSdh if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
13164c06356bSdh &delta)) {
13171b115575SJohn Danielson /*
13181b115575SJohn Danielson * no difference
13191b115575SJohn Danielson */
13204c06356bSdh bitset_zero(&mapp->dam_stable_set);
132160aabb4cSChris Horne mapp->dam_flags &= ~DAM_SPEND;
132260aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
13231b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
132460aabb4cSChris Horne
13254c06356bSdh bitset_fini(&uncfg);
13264c06356bSdh bitset_fini(&cfg);
13274c06356bSdh bitset_fini(&delta);
13281b94a41bSChris Horne DTRACE_PROBE2(damap__stabilize__map__nochange,
13291b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
13304c06356bSdh return;
13314c06356bSdh }
13321b115575SJohn Danielson
13331b115575SJohn Danielson /*
13341b115575SJohn Danielson * compute the sets of addresses to be activated and deactivated
13351b115575SJohn Danielson */
13364c06356bSdh has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
13374c06356bSdh has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
13381b115575SJohn Danielson
13391b115575SJohn Danielson /*
13401b115575SJohn Danielson * drop map lock while invoking callouts
13411b115575SJohn Danielson */
13421b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
13431b115575SJohn Danielson
13441b115575SJohn Danielson /*
13451b115575SJohn Danielson * activate all newly stable addresss
13461b115575SJohn Danielson */
13471b115575SJohn Danielson if (has_cfg)
13484c06356bSdh dam_addrset_activate(mapp, &cfg);
13491b115575SJohn Danielson
13501b115575SJohn Danielson /*
13511b115575SJohn Danielson * deactivate addresss which are no longer in the map
13521b115575SJohn Danielson */
13531b115575SJohn Danielson if (has_uncfg)
13541b115575SJohn Danielson dam_addrset_deactivate(mapp, &uncfg);
13551b115575SJohn Danielson
13561b115575SJohn Danielson
13571b115575SJohn Danielson /*
13581b115575SJohn Danielson * timestamp the last stable time and increment the kstat keeping
13591b115575SJohn Danielson * the # of of stable cycles for the map
13601b115575SJohn Danielson */
13611b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
13624c06356bSdh bitset_zero(&mapp->dam_stable_set);
13634c06356bSdh mapp->dam_last_stable = gethrtime();
13644c06356bSdh mapp->dam_stable_cnt++;
13651b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_cycles);
13661b115575SJohn Danielson
13671b115575SJohn Danielson /*
13681b115575SJohn Danielson * determine the number of stable addresses
13691b115575SJohn Danielson * and update the n_active kstat for this map
13701b115575SJohn Danielson */
13711b115575SJohn Danielson for (i = 1, n_active = 0; i < mapp->dam_high; i++)
13721b115575SJohn Danielson if (bitset_in_set(&mapp->dam_active_set, i))
13731b115575SJohn Danielson n_active++;
13741b115575SJohn Danielson DAM_SET_STAT(mapp, dam_active, n_active);
13751b115575SJohn Danielson
13761b94a41bSChris Horne DTRACE_PROBE3(damap__map__stable__end,
13771b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
13781b94a41bSChris Horne int, n_active);
13791b115575SJohn Danielson
138060aabb4cSChris Horne mapp->dam_flags &= ~DAM_SPEND;
138160aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
13821b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
138360aabb4cSChris Horne
13844c06356bSdh bitset_fini(&uncfg);
13854c06356bSdh bitset_fini(&cfg);
13864c06356bSdh bitset_fini(&delta);
13874c06356bSdh }
13884c06356bSdh
13894c06356bSdh /*
13904c06356bSdh * per-address stabilization timeout
13914c06356bSdh */
13924c06356bSdh static void
dam_addr_stable_cb(void * arg)13934c06356bSdh dam_addr_stable_cb(void *arg)
13944c06356bSdh {
13954c06356bSdh dam_t *mapp = (dam_t *)arg;
13964c06356bSdh int i;
13974c06356bSdh dam_da_t *passp;
13984c06356bSdh int spend = 0;
13994c06356bSdh int tpend = 0;
140060aabb4cSChris Horne int64_t ts, next_ticks, delta_ticks;
14014c06356bSdh
14021b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
14034c06356bSdh if (mapp->dam_tid == 0) {
14041b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__cancelled,
14051b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
14061b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
14074c06356bSdh return;
14084c06356bSdh }
14094c06356bSdh mapp->dam_tid = 0;
14101b115575SJohn Danielson
14114c06356bSdh /*
14124c06356bSdh * If still under stabilization, reschedule timeout,
14131b115575SJohn Danielson * otherwise dispatch the task to activate and deactivate the
14141b115575SJohn Danielson * new stable address
14154c06356bSdh */
14164c06356bSdh if (mapp->dam_flags & DAM_SPEND) {
14171b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_overrun);
14184c06356bSdh mapp->dam_stable_overrun++;
14191b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__overrun,
14201b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
142160aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp,
142260aabb4cSChris Horne mapp->dam_stable_ticks);
14231b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
14244c06356bSdh return;
14254c06356bSdh }
14264c06356bSdh
14271b115575SJohn Danielson DAM_SET_STAT(mapp, dam_overrun, 0);
14281b115575SJohn Danielson mapp->dam_stable_overrun = 0;
14291b115575SJohn Danielson
14301b94a41bSChris Horne /* See if any reports stabalized and compute next timeout. */
143160aabb4cSChris Horne ts = ddi_get_lbolt64();
143260aabb4cSChris Horne next_ticks = mapp->dam_stable_ticks;
14334c06356bSdh for (i = 1; i < mapp->dam_high; i++) {
14341b94a41bSChris Horne if (bitset_in_set(&mapp->dam_report_set, i)) {
14351b94a41bSChris Horne passp = ddi_get_soft_state(mapp->dam_da, i);
14361b94a41bSChris Horne ASSERT(passp);
14374c06356bSdh
14381b94a41bSChris Horne if (passp->da_deadline <= ts)
14391b94a41bSChris Horne spend++; /* report has stabilized */
14401b94a41bSChris Horne else {
14411b94a41bSChris Horne /* not stabilized, determine next map timeout */
14421b94a41bSChris Horne tpend++;
14431b94a41bSChris Horne delta_ticks = passp->da_deadline - ts;
14441b94a41bSChris Horne if (delta_ticks < next_ticks)
14451b94a41bSChris Horne next_ticks = delta_ticks;
14461b94a41bSChris Horne }
14471b94a41bSChris Horne }
14484c06356bSdh }
14494c06356bSdh
14504c06356bSdh /*
14511b115575SJohn Danielson * schedule system_taskq activation of stabilized reports
14524c06356bSdh */
14534c06356bSdh if (spend) {
14541b115575SJohn Danielson if (taskq_dispatch(system_taskq, dam_stabilize_map,
1455fc8ae2ecSToomas Soome mapp, TQ_NOSLEEP | TQ_NOQUEUE) != TASKQID_INVALID) {
14561b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__start,
14571b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
14581b94a41bSChris Horne
14591b94a41bSChris Horne /*
14601b94a41bSChris Horne * The stable_set we compute below stays pending until
14611b94a41bSChris Horne * processed by dam_stabilize_map. We can't set
14621b94a41bSChris Horne * DAM_SPEND (or bitset_del things from the
14631b94a41bSChris Horne * report_set) until we *know* that we can handoff the
14641b94a41bSChris Horne * result to dam_stabilize_map. If dam_stabilize_map
14651b94a41bSChris Horne * starts executing before we are complete, it will
14661b94a41bSChris Horne * block on the dam_lock mutex until we are ready.
14671b94a41bSChris Horne */
146860aabb4cSChris Horne mapp->dam_flags |= DAM_SPEND;
14691b94a41bSChris Horne
14701b94a41bSChris Horne /*
14711b94a41bSChris Horne * Copy the current active_set to the stable_set, then
14721b94a41bSChris Horne * add or remove stabilized report_set address from
14731b94a41bSChris Horne * the stable set (and delete them from the report_set).
14741b94a41bSChris Horne */
14751b94a41bSChris Horne bitset_copy(&mapp->dam_active_set,
14761b94a41bSChris Horne &mapp->dam_stable_set);
14771b94a41bSChris Horne for (i = 1; i < mapp->dam_high; i++) {
14781b94a41bSChris Horne if (!bitset_in_set(&mapp->dam_report_set, i))
14791b94a41bSChris Horne continue;
14801b94a41bSChris Horne
14811b94a41bSChris Horne passp = ddi_get_soft_state(mapp->dam_da, i);
14821b94a41bSChris Horne if (passp->da_deadline > ts)
14831b94a41bSChris Horne continue; /* report not stabilized */
14841b94a41bSChris Horne
14851b94a41bSChris Horne /* report has stabilized */
14861b94a41bSChris Horne if (passp->da_flags & DA_RELE)
14871b94a41bSChris Horne bitset_del(&mapp->dam_stable_set, i);
14881b94a41bSChris Horne else
14891b94a41bSChris Horne bitset_add(&mapp->dam_stable_set, i);
14901b94a41bSChris Horne
14911b94a41bSChris Horne bitset_del(&mapp->dam_report_set, i);
14921b94a41bSChris Horne }
14931b115575SJohn Danielson } else {
14941b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__spendfail,
14951b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
149664109744SChris Horne
149764109744SChris Horne /*
149864109744SChris Horne * Avoid waiting the entire stabalization
149964109744SChris Horne * time again if taskq_diskpatch fails.
150064109744SChris Horne */
15011b94a41bSChris Horne tpend++;
150260aabb4cSChris Horne delta_ticks = drv_usectohz(
150364109744SChris Horne damap_taskq_dispatch_retry_usec);
150460aabb4cSChris Horne if (delta_ticks < next_ticks)
150560aabb4cSChris Horne next_ticks = delta_ticks;
15061b115575SJohn Danielson }
15074c06356bSdh }
15084c06356bSdh
15094c06356bSdh /*
15101b115575SJohn Danielson * reschedule the stabilization timer if there are reports
15111b115575SJohn Danielson * still pending
15124c06356bSdh */
15131b94a41bSChris Horne if (tpend) {
15141b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
15151b94a41bSChris Horne mapp->dam_name, dam_t *, mapp);
151660aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp,
151760aabb4cSChris Horne (clock_t)next_ticks);
15181b94a41bSChris Horne }
15191b115575SJohn Danielson
15201b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15214c06356bSdh }
15224c06356bSdh
15234c06356bSdh /*
15241b115575SJohn Danielson * fullset stabilization timeout callback
15254c06356bSdh */
15264c06356bSdh static void
dam_addrset_stable_cb(void * arg)15271b115575SJohn Danielson dam_addrset_stable_cb(void *arg)
15284c06356bSdh {
15294c06356bSdh dam_t *mapp = (dam_t *)arg;
15304c06356bSdh
15311b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
15324c06356bSdh if (mapp->dam_tid == 0) {
15331b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15341b115575SJohn Danielson DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
15351b115575SJohn Danielson char *, mapp->dam_name, dam_t *, mapp);
15364c06356bSdh return;
15374c06356bSdh }
15384c06356bSdh mapp->dam_tid = 0;
15394c06356bSdh
15404c06356bSdh /*
15411b115575SJohn Danielson * If map still underoing stabilization reschedule timeout,
15421b115575SJohn Danielson * else dispatch the task to configure the new stable set of
15431b115575SJohn Danielson * addresses.
15444c06356bSdh */
154564109744SChris Horne if ((mapp->dam_flags & DAM_SPEND) ||
154664109744SChris Horne (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1547fc8ae2ecSToomas Soome TQ_NOSLEEP | TQ_NOQUEUE) == TASKQID_INVALID)) {
15481b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_overrun);
15494c06356bSdh mapp->dam_stable_overrun++;
155060aabb4cSChris Horne dam_sched_timeout(dam_addrset_stable_cb, mapp,
155160aabb4cSChris Horne drv_usectohz(damap_taskq_dispatch_retry_usec));
155264109744SChris Horne
15531b94a41bSChris Horne DTRACE_PROBE2(damap__map__addrset__stable__overrun,
15541b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
15551b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15561b115575SJohn Danielson return;
15574c06356bSdh }
15581b115575SJohn Danielson
15591b115575SJohn Danielson DAM_SET_STAT(mapp, dam_overrun, 0);
15601b115575SJohn Danielson mapp->dam_stable_overrun = 0;
15611b115575SJohn Danielson bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
15621b115575SJohn Danielson bitset_zero(&mapp->dam_report_set);
15631b115575SJohn Danielson mapp->dam_flags |= DAM_SPEND;
15641b115575SJohn Danielson mapp->dam_flags &= ~DAM_SETADD;
156560aabb4cSChris Horne /* NOTE: don't need cv_signal since DAM_SPEND is still set */
156660aabb4cSChris Horne
15671b94a41bSChris Horne DTRACE_PROBE2(damap__map__addrset__stable__start,
15681b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
15691b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15704c06356bSdh }
15714c06356bSdh
15724c06356bSdh /*
157360aabb4cSChris Horne * schedule map timeout in 'ticks' ticks
157460aabb4cSChris Horne * if map timer is currently running, cancel if ticks == 0
15754c06356bSdh */
15764c06356bSdh static void
dam_sched_timeout(void (* timeout_cb)(),dam_t * mapp,clock_t ticks)157760aabb4cSChris Horne dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
15784c06356bSdh {
15794c06356bSdh timeout_id_t tid;
15804c06356bSdh
15811b94a41bSChris Horne DTRACE_PROBE4(damap__sched__timeout,
15821b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
15831b94a41bSChris Horne int, ticks, timeout_id_t, mapp->dam_tid);
15841b115575SJohn Danielson
15851b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
15864c06356bSdh if ((tid = mapp->dam_tid) != 0) {
158760aabb4cSChris Horne if (ticks == 0) {
15881b115575SJohn Danielson mapp->dam_tid = 0;
15891b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15901b115575SJohn Danielson (void) untimeout(tid);
15911b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
15921b115575SJohn Danielson }
15931b115575SJohn Danielson } else {
159460aabb4cSChris Horne if (timeout_cb && (ticks != 0))
159560aabb4cSChris Horne mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
15964c06356bSdh }
15974c06356bSdh }
15984c06356bSdh
15994c06356bSdh /*
16001b115575SJohn Danielson * report addition or removal of an address
16014c06356bSdh */
16024c06356bSdh static void
dam_addr_report(dam_t * mapp,dam_da_t * passp,id_t addrid,int rpt_type)16031b115575SJohn Danielson dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
16044c06356bSdh {
16051b115575SJohn Danielson char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
16061b115575SJohn Danielson
16071b94a41bSChris Horne DTRACE_PROBE4(damap__addr__report,
16081b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
16091b94a41bSChris Horne char *, addrstr, int, rpt_type);
16101b115575SJohn Danielson
16111b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16124c06356bSdh ASSERT(!DAM_IN_REPORT(mapp, addrid));
16134c06356bSdh passp->da_last_report = gethrtime();
16144c06356bSdh mapp->dam_last_update = gethrtime();
16154c06356bSdh passp->da_report_cnt++;
161660aabb4cSChris Horne passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
16171b115575SJohn Danielson if (rpt_type == RPT_ADDR_DEL)
16184c06356bSdh passp->da_flags |= DA_RELE;
16191b115575SJohn Danielson else if (rpt_type == RPT_ADDR_ADD)
16204c06356bSdh passp->da_flags &= ~DA_RELE;
16214c06356bSdh bitset_add(&mapp->dam_report_set, addrid);
162260aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
16234c06356bSdh }
16244c06356bSdh
16254c06356bSdh /*
16264c06356bSdh * release an address report
16274c06356bSdh */
16284c06356bSdh static void
dam_addr_report_release(dam_t * mapp,id_t addrid)16291b115575SJohn Danielson dam_addr_report_release(dam_t *mapp, id_t addrid)
16304c06356bSdh {
16314c06356bSdh dam_da_t *passp;
16321b115575SJohn Danielson char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
16334c06356bSdh
16341b94a41bSChris Horne DTRACE_PROBE3(damap__addr__report__release,
16351b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
16361b94a41bSChris Horne char *, addrstr);
16371b115575SJohn Danielson
16381b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16394c06356bSdh passp = ddi_get_soft_state(mapp->dam_da, addrid);
16404c06356bSdh ASSERT(passp);
16411b115575SJohn Danielson /*
16421b115575SJohn Danielson * clear the report bit
16431b115575SJohn Danielson * if the address has a registered deactivation handler and
16449aed1621SDavid Hollister * we are holding a private data pointer and the address has not
16459aed1621SDavid Hollister * stabilized, deactivate the address (private data).
16461b115575SJohn Danielson */
16471b115575SJohn Danielson bitset_del(&mapp->dam_report_set, addrid);
16489aed1621SDavid Hollister if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
164978427917SHans Rosenfeld passp->da_ppriv) {
16501b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
16511b115575SJohn Danielson (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
16521b115575SJohn Danielson ddi_strid_id2str(mapp->dam_addr_hash, addrid),
165378427917SHans Rosenfeld addrid, passp->da_ppriv, DAMAP_DEACT_RSN_UNSTBL);
16541b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
16551b115575SJohn Danielson }
165678427917SHans Rosenfeld passp->da_ppriv = NULL;
1657aab83bb8SJosef 'Jeff' Sipek nvlist_free(passp->da_nvl_rpt);
16584c06356bSdh }
16594c06356bSdh
16604c06356bSdh /*
16614c06356bSdh * return the map ID of an address
16624c06356bSdh */
16634c06356bSdh static id_t
dam_get_addrid(dam_t * mapp,char * address)16644c06356bSdh dam_get_addrid(dam_t *mapp, char *address)
16654c06356bSdh {
16664c06356bSdh damap_id_t addrid;
16674c06356bSdh dam_da_t *passp;
16684c06356bSdh
16691b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16704c06356bSdh if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
16711b115575SJohn Danielson if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
16724c06356bSdh address)) == (damap_id_t)0) {
16734c06356bSdh return (0);
16744c06356bSdh }
16754c06356bSdh if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
16764c06356bSdh DDI_SUCCESS) {
16774c06356bSdh ddi_strid_free(mapp->dam_addr_hash, addrid);
16784c06356bSdh return (0);
16794c06356bSdh }
16801b115575SJohn Danielson
16814c06356bSdh if (addrid >= mapp->dam_high)
16824c06356bSdh mapp->dam_high = addrid + 1;
16831b115575SJohn Danielson
16841b115575SJohn Danielson /*
16851b115575SJohn Danielson * expand bitmaps if ID has outgrown old map size
16861b115575SJohn Danielson */
16871b115575SJohn Danielson if (mapp->dam_high > mapp->dam_size) {
16881b115575SJohn Danielson mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
16891b115575SJohn Danielson bitset_resize(&mapp->dam_active_set, mapp->dam_size);
16901b115575SJohn Danielson bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
16911b115575SJohn Danielson bitset_resize(&mapp->dam_report_set, mapp->dam_size);
16921b115575SJohn Danielson }
16931b115575SJohn Danielson
16941b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, addrid);
16951b115575SJohn Danielson passp->da_ref = 1;
16961b115575SJohn Danielson passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
16971b115575SJohn Danielson addrid); /* for mdb */
16984c06356bSdh }
16994c06356bSdh return (addrid);
17004c06356bSdh }
17014c06356bSdh
17024c06356bSdh /*
17034c06356bSdh * create and install map statistics
17044c06356bSdh */
17054c06356bSdh static int
dam_kstat_create(dam_t * mapp)17064c06356bSdh dam_kstat_create(dam_t *mapp)
17074c06356bSdh {
17084c06356bSdh kstat_t *mapsp;
17094c06356bSdh struct dam_kstats *statsp;
17104c06356bSdh
17114c06356bSdh mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
17124c06356bSdh KSTAT_TYPE_NAMED,
17134c06356bSdh sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
17141b115575SJohn Danielson
17151b115575SJohn Danielson if (mapsp == NULL)
17164c06356bSdh return (DDI_FAILURE);
17174c06356bSdh
17184c06356bSdh statsp = (struct dam_kstats *)mapsp->ks_data;
17191b115575SJohn Danielson kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
17201b115575SJohn Danielson kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
17211b115575SJohn Danielson kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
17221b115575SJohn Danielson kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
17234c06356bSdh kstat_install(mapsp);
17244c06356bSdh mapp->dam_kstatsp = mapsp;
17254c06356bSdh return (DDI_SUCCESS);
17264c06356bSdh }
1727