14c06356bSdh142964 /*
24c06356bSdh142964 * CDDL HEADER START
34c06356bSdh142964 *
44c06356bSdh142964 * The contents of this file are subject to the terms of the
54c06356bSdh142964 * Common Development and Distribution License (the "License").
64c06356bSdh142964 * You may not use this file except in compliance with the License.
74c06356bSdh142964 *
84c06356bSdh142964 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94c06356bSdh142964 * or http://www.opensolaris.org/os/licensing.
104c06356bSdh142964 * See the License for the specific language governing permissions
114c06356bSdh142964 * and limitations under the License.
124c06356bSdh142964 *
134c06356bSdh142964 * When distributing Covered Code, include this CDDL HEADER in each
144c06356bSdh142964 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154c06356bSdh142964 * If applicable, add the following below this CDDL HEADER, with the
164c06356bSdh142964 * fields enclosed by brackets "[]" replaced with your own identifying
174c06356bSdh142964 * information: Portions Copyright [yyyy] [name of copyright owner]
184c06356bSdh142964 *
194c06356bSdh142964 * CDDL HEADER END
204c06356bSdh142964 */
214c06356bSdh142964
224c06356bSdh142964 /*
2360aabb4cSChris Horne * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
244c06356bSdh142964 */
254c06356bSdh142964
264c06356bSdh142964 #include <sys/note.h>
274c06356bSdh142964 #include <sys/types.h>
284c06356bSdh142964 #include <sys/param.h>
294c06356bSdh142964 #include <sys/systm.h>
304c06356bSdh142964 #include <sys/buf.h>
314c06356bSdh142964 #include <sys/kmem.h>
324c06356bSdh142964 #include <sys/cmn_err.h>
334c06356bSdh142964 #include <sys/debug.h>
344c06356bSdh142964 #include <sys/sunndi.h>
354c06356bSdh142964 #include <sys/kstat.h>
364c06356bSdh142964 #include <sys/conf.h>
37*a288e5a9SJoshua M. Clulow #include <sys/ddi_periodic.h>
384c06356bSdh142964 #include <sys/devctl.h>
394c06356bSdh142964 #include <sys/callb.h>
404c06356bSdh142964 #include <sys/sysevent.h>
414c06356bSdh142964 #include <sys/taskq.h>
424c06356bSdh142964 #include <sys/ddi.h>
434c06356bSdh142964 #include <sys/bitset.h>
444c06356bSdh142964 #include <sys/damap.h>
454c06356bSdh142964 #include <sys/damap_impl.h>
464c06356bSdh142964
474c06356bSdh142964 #ifdef DEBUG
484c06356bSdh142964 static int damap_debug = 0;
494c06356bSdh142964 #endif /* DEBUG */
504c06356bSdh142964
511b115575SJohn Danielson extern taskq_t *system_taskq;
521b115575SJohn Danielson
534c06356bSdh142964 static void dam_addrset_activate(dam_t *, bitset_t *);
541b115575SJohn Danielson static void dam_addrset_deactivate(dam_t *, bitset_t *);
551b115575SJohn Danielson static void dam_stabilize_map(void *);
564c06356bSdh142964 static void dam_addr_stable_cb(void *);
571b115575SJohn Danielson static void dam_addrset_stable_cb(void *);
5860aabb4cSChris Horne static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
591b115575SJohn Danielson static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
601b115575SJohn Danielson static void dam_addr_release(dam_t *, id_t);
611b115575SJohn Danielson static void dam_addr_report_release(dam_t *, id_t);
621b115575SJohn Danielson static void dam_addr_deactivate(dam_t *, id_t);
63d189c170SReed static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
644c06356bSdh142964 static id_t dam_get_addrid(dam_t *, char *);
654c06356bSdh142964 static int dam_kstat_create(dam_t *);
661b115575SJohn Danielson static int dam_map_alloc(dam_t *);
674c06356bSdh142964
684c06356bSdh142964 #define DAM_INCR_STAT(mapp, stat) \
694c06356bSdh142964 if ((mapp)->dam_kstatsp) { \
704c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
714c06356bSdh142964 stp->stat.value.ui32++; \
724c06356bSdh142964 }
734c06356bSdh142964
744c06356bSdh142964 #define DAM_SET_STAT(mapp, stat, val) \
754c06356bSdh142964 if ((mapp)->dam_kstatsp) { \
764c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
774c06356bSdh142964 stp->stat.value.ui32 = (val); \
784c06356bSdh142964 }
794c06356bSdh142964
801b115575SJohn Danielson
811b115575SJohn Danielson /*
821b115575SJohn Danielson * increase damap size by 64 entries at a time
831b115575SJohn Danielson */
841b115575SJohn Danielson #define DAM_SIZE_BUMP 64
851b115575SJohn Danielson
8664109744SChris Horne int damap_taskq_dispatch_retry_usec = 1000;
8764109744SChris Horne
881b115575SJohn Danielson /*
891b115575SJohn Danielson * config/unconfig taskq data
901b115575SJohn Danielson */
911b115575SJohn Danielson typedef struct {
921b115575SJohn Danielson dam_t *tqd_mapp;
931b115575SJohn Danielson id_t tqd_id;
941b115575SJohn Danielson } cfg_tqd_t;
951b115575SJohn Danielson
961b115575SJohn Danielson extern pri_t maxclsyspri;
971b115575SJohn Danielson
984c06356bSdh142964 /*
994c06356bSdh142964 * Create new device address map
1004c06356bSdh142964 *
1011b115575SJohn Danielson * name: map name (kstat unique)
1024c06356bSdh142964 * size: max # of map entries
1031b115575SJohn Danielson * mode: style of address reports: per-address or fullset
1044c06356bSdh142964 * stable_usec: # of quiescent microseconds before report/map is stable
1054c06356bSdh142964 *
1064c06356bSdh142964 * activate_arg: address provider activation-callout private
1074c06356bSdh142964 * activate_cb: address provider activation callback handler
1084c06356bSdh142964 * deactivate_cb: address provider deactivation callback handler
1094c06356bSdh142964 *
1104c06356bSdh142964 * config_arg: configuration-callout private
1114c06356bSdh142964 * config_cb: class configuration callout
1124c06356bSdh142964 * unconfig_cb: class unconfiguration callout
1134c06356bSdh142964 *
1144c06356bSdh142964 * damapp: pointer to map handle (return)
1154c06356bSdh142964 *
1164c06356bSdh142964 * Returns: DAM_SUCCESS
1174c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
1184c06356bSdh142964 * DAM_FAILURE General failure
1194c06356bSdh142964 */
1204c06356bSdh142964 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)1211b115575SJohn Danielson damap_create(char *name, damap_rptmode_t mode, int map_opts,
12260aabb4cSChris Horne int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
1234c06356bSdh142964 damap_deactivate_cb_t deactivate_cb,
1244c06356bSdh142964 void *config_arg, damap_configure_cb_t configure_cb,
1254c06356bSdh142964 damap_unconfig_cb_t unconfig_cb,
1264c06356bSdh142964 damap_t **damapp)
1274c06356bSdh142964 {
1284c06356bSdh142964 dam_t *mapp;
1294c06356bSdh142964
1301b115575SJohn Danielson if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
1314c06356bSdh142964 return (DAM_EINVAL);
1324c06356bSdh142964
1334c06356bSdh142964 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
1341b115575SJohn Danielson mapp->dam_options = map_opts;
13560aabb4cSChris Horne mapp->dam_stable_ticks = drv_usectohz(stable_usec);
1361b115575SJohn Danielson mapp->dam_size = 0;
1371b115575SJohn Danielson mapp->dam_rptmode = mode;
1384c06356bSdh142964 mapp->dam_activate_arg = activate_arg;
1394c06356bSdh142964 mapp->dam_activate_cb = (activate_cb_t)activate_cb;
1404c06356bSdh142964 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
1414c06356bSdh142964 mapp->dam_config_arg = config_arg;
1424c06356bSdh142964 mapp->dam_configure_cb = (configure_cb_t)configure_cb;
1434c06356bSdh142964 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
1441b115575SJohn Danielson mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
1454c06356bSdh142964 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
14660aabb4cSChris Horne cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
1471b115575SJohn Danielson bitset_init(&mapp->dam_active_set);
1481b115575SJohn Danielson bitset_init(&mapp->dam_stable_set);
1491b115575SJohn Danielson bitset_init(&mapp->dam_report_set);
1504c06356bSdh142964 *damapp = (damap_t *)mapp;
1511b94a41bSChris Horne
1521b94a41bSChris Horne DTRACE_PROBE5(damap__create,
1531b94a41bSChris Horne char *, mapp->dam_name, damap_t *, mapp,
1541b94a41bSChris Horne damap_rptmode_t, mode, int, map_opts, int, stable_usec);
1551b94a41bSChris Horne
1564c06356bSdh142964 return (DAM_SUCCESS);
1574c06356bSdh142964 }
1584c06356bSdh142964
1594c06356bSdh142964 /*
1601b115575SJohn Danielson * Allocate backing resources
1611b115575SJohn Danielson *
1621b115575SJohn Danielson * DAMs are lightly backed on create - major allocations occur
1631b115575SJohn Danielson * at the time a report is made to the map, and are extended on
1641b115575SJohn Danielson * a demand basis.
1651b115575SJohn Danielson */
1661b115575SJohn Danielson static int
dam_map_alloc(dam_t * mapp)1671b115575SJohn Danielson dam_map_alloc(dam_t *mapp)
1681b115575SJohn Danielson {
1691b115575SJohn Danielson void *softstate_p;
1701b115575SJohn Danielson
1711b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
1721b115575SJohn Danielson if (mapp->dam_flags & DAM_DESTROYPEND)
1731b115575SJohn Danielson return (DAM_FAILURE);
1741b115575SJohn Danielson
1751b115575SJohn Danielson /*
1761b115575SJohn Danielson * dam_high > 0 signals map allocation complete
1771b115575SJohn Danielson */
1781b115575SJohn Danielson if (mapp->dam_high)
1791b115575SJohn Danielson return (DAM_SUCCESS);
1801b115575SJohn Danielson
1811b115575SJohn Danielson mapp->dam_size = DAM_SIZE_BUMP;
1821b115575SJohn Danielson if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
1831b115575SJohn Danielson mapp->dam_size) != DDI_SUCCESS)
1841b115575SJohn Danielson return (DAM_FAILURE);
1851b115575SJohn Danielson
1861b115575SJohn Danielson if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
1871b115575SJohn Danielson DDI_SUCCESS) {
1881b115575SJohn Danielson ddi_soft_state_fini(softstate_p);
1891b115575SJohn Danielson return (DAM_FAILURE);
1901b115575SJohn Danielson }
1911b115575SJohn Danielson if (dam_kstat_create(mapp) != DDI_SUCCESS) {
1921b115575SJohn Danielson ddi_soft_state_fini(softstate_p);
1931b115575SJohn Danielson ddi_strid_fini(&mapp->dam_addr_hash);
1941b115575SJohn Danielson return (DAM_FAILURE);
1951b115575SJohn Danielson }
1961b115575SJohn Danielson mapp->dam_da = softstate_p;
1971b115575SJohn Danielson mapp->dam_high = 1;
1981b115575SJohn Danielson bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1991b115575SJohn Danielson bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
2001b115575SJohn Danielson bitset_resize(&mapp->dam_report_set, mapp->dam_size);
2011b115575SJohn Danielson return (DAM_SUCCESS);
2021b115575SJohn Danielson }
2031b115575SJohn Danielson
2041b115575SJohn Danielson /*
2051b115575SJohn Danielson * Destroy address map
2064c06356bSdh142964 *
2074c06356bSdh142964 * damapp: address map
2084c06356bSdh142964 *
2094c06356bSdh142964 * Returns: DAM_SUCCESS
2104c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
2114c06356bSdh142964 * DAM_FAILURE General failure
2124c06356bSdh142964 */
2134c06356bSdh142964 void
damap_destroy(damap_t * damapp)2144c06356bSdh142964 damap_destroy(damap_t *damapp)
2154c06356bSdh142964 {
2164c06356bSdh142964 int i;
2174c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
2184c06356bSdh142964
2194c06356bSdh142964 ASSERT(mapp);
2204c06356bSdh142964
2211b94a41bSChris Horne DTRACE_PROBE2(damap__destroy,
2221b94a41bSChris Horne char *, mapp->dam_name, damap_t *, mapp);
2234c06356bSdh142964
2241b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
2254c06356bSdh142964
2264c06356bSdh142964 /*
2271b115575SJohn Danielson * prevent new reports from being added to the map
2284c06356bSdh142964 */
2291b115575SJohn Danielson mapp->dam_flags |= DAM_DESTROYPEND;
2304c06356bSdh142964
2311b115575SJohn Danielson if (mapp->dam_high) {
2321b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
2331b115575SJohn Danielson /*
2341b115575SJohn Danielson * wait for outstanding reports to stabilize and cancel
2351b115575SJohn Danielson * the timer for this map
2361b115575SJohn Danielson */
23760aabb4cSChris Horne (void) damap_sync(damapp, 0);
2381b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
23960aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
2401b115575SJohn Danielson
2411b115575SJohn Danielson /*
2421b115575SJohn Danielson * map is at full stop
2431b115575SJohn Danielson * release the contents of the map, invoking the
2441b115575SJohn Danielson * detactivation protocol as addresses are released
2451b115575SJohn Danielson */
2461b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
2474c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) {
2484c06356bSdh142964 if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
2494c06356bSdh142964 continue;
2501b115575SJohn Danielson
2511b115575SJohn Danielson ASSERT(DAM_IN_REPORT(mapp, i) == 0);
2521b115575SJohn Danielson
2531b115575SJohn Danielson if (DAM_IS_STABLE(mapp, i)) {
2541b115575SJohn Danielson dam_addr_deactivate(mapp, i);
2551b115575SJohn Danielson } else {
2564c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, i);
2574c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, i);
2584c06356bSdh142964 }
2591b115575SJohn Danielson }
2604c06356bSdh142964 ddi_strid_fini(&mapp->dam_addr_hash);
2614c06356bSdh142964 ddi_soft_state_fini(&mapp->dam_da);
2621b115575SJohn Danielson kstat_delete(mapp->dam_kstatsp);
26360aabb4cSChris Horne } else
26460aabb4cSChris Horne mutex_exit(&mapp->dam_lock);
26560aabb4cSChris Horne
2664c06356bSdh142964 bitset_fini(&mapp->dam_active_set);
2674c06356bSdh142964 bitset_fini(&mapp->dam_stable_set);
2684c06356bSdh142964 bitset_fini(&mapp->dam_report_set);
2694c06356bSdh142964 mutex_destroy(&mapp->dam_lock);
27060aabb4cSChris Horne cv_destroy(&mapp->dam_sync_cv);
2714c06356bSdh142964 if (mapp->dam_name)
2724c06356bSdh142964 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
2734c06356bSdh142964 kmem_free(mapp, sizeof (*mapp));
2744c06356bSdh142964 }
2754c06356bSdh142964
2764c06356bSdh142964 /*
27760aabb4cSChris Horne * Wait for map stability. If sync was successfull then return 1.
27860aabb4cSChris Horne * If called with a non-zero sync_usec, then a return value of 0 means a
27960aabb4cSChris Horne * timeout occurred prior to sync completion. NOTE: if sync_usec is
28060aabb4cSChris Horne * non-zero, it should be much longer than dam_stable_ticks.
2814c06356bSdh142964 *
2824c06356bSdh142964 * damapp: address map
28360aabb4cSChris Horne * sync_usec: micorseconds until we give up on sync completion.
2844c06356bSdh142964 */
2851b115575SJohn Danielson #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
28660aabb4cSChris Horne int
damap_sync(damap_t * damapp,int sync_usec)28760aabb4cSChris Horne damap_sync(damap_t *damapp, int sync_usec)
28860aabb4cSChris Horne {
2894c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
29060aabb4cSChris Horne int rv;
2914c06356bSdh142964
2924c06356bSdh142964 ASSERT(mapp);
2931b94a41bSChris Horne DTRACE_PROBE3(damap__map__sync__start,
2941b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
2951b94a41bSChris Horne int, sync_usec);
2964c06356bSdh142964
2971b115575SJohn Danielson /*
29860aabb4cSChris Horne * Block when waiting for
2991b115575SJohn Danielson * a) stabilization pending or a fullset update pending
30060aabb4cSChris Horne * b) the report set to finalize (bitset is null)
30160aabb4cSChris Horne * c) any scheduled timeouts to fire
3021b115575SJohn Danielson */
30360aabb4cSChris Horne rv = 1; /* return synced */
3044c06356bSdh142964 mutex_enter(&mapp->dam_lock);
30560aabb4cSChris Horne again: while ((mapp->dam_flags & WAITFOR_FLAGS) ||
30660aabb4cSChris Horne (!bitset_is_null(&mapp->dam_report_set)) ||
30760aabb4cSChris Horne (mapp->dam_tid != 0)) {
3081b94a41bSChris Horne DTRACE_PROBE2(damap__map__sync__waiting,
3091b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
31060aabb4cSChris Horne
31160aabb4cSChris Horne /* Wait for condition relayed via timeout */
31260aabb4cSChris Horne if (sync_usec) {
31360aabb4cSChris Horne if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
31460aabb4cSChris Horne drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
31560aabb4cSChris Horne mapp->dam_sync_to_cnt++;
31660aabb4cSChris Horne rv = 0; /* return timeout */
31760aabb4cSChris Horne break;
31860aabb4cSChris Horne }
31960aabb4cSChris Horne } else
32060aabb4cSChris Horne cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
3214c06356bSdh142964 }
3224c06356bSdh142964
32360aabb4cSChris Horne if (rv) {
32460aabb4cSChris Horne /*
32560aabb4cSChris Horne * Delay one stabilization time after the apparent sync above
32660aabb4cSChris Horne * and verify accuracy - resync if not accurate.
32760aabb4cSChris Horne */
32860aabb4cSChris Horne (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
32960aabb4cSChris Horne mapp->dam_stable_ticks, TR_MICROSEC);
33060aabb4cSChris Horne if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
33160aabb4cSChris Horne (!bitset_is_null(&mapp->dam_report_set)) ||
33260aabb4cSChris Horne (mapp->dam_tid != 0)))
33360aabb4cSChris Horne goto again;
33460aabb4cSChris Horne }
3354c06356bSdh142964 mutex_exit(&mapp->dam_lock);
3364c06356bSdh142964
3371b94a41bSChris Horne DTRACE_PROBE3(damap__map__sync__end,
3381b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
3391b94a41bSChris Horne int, rv);
34060aabb4cSChris Horne return (rv);
34160aabb4cSChris Horne }
34260aabb4cSChris Horne
34360aabb4cSChris Horne /*
34460aabb4cSChris Horne * Return 1 if active set is empty
34560aabb4cSChris Horne */
34660aabb4cSChris Horne int
damap_is_empty(damap_t * damapp)34760aabb4cSChris Horne damap_is_empty(damap_t *damapp)
34860aabb4cSChris Horne {
34960aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
35060aabb4cSChris Horne int rv;
35160aabb4cSChris Horne
35260aabb4cSChris Horne mutex_enter(&mapp->dam_lock);
35360aabb4cSChris Horne rv = bitset_is_null(&mapp->dam_active_set);
35460aabb4cSChris Horne mutex_exit(&mapp->dam_lock);
35560aabb4cSChris Horne return (rv);
3564c06356bSdh142964 }
3574c06356bSdh142964
3584c06356bSdh142964 /*
3594c06356bSdh142964 * Get the name of a device address map
3604c06356bSdh142964 *
3614c06356bSdh142964 * damapp: address map
3624c06356bSdh142964 *
3634c06356bSdh142964 * Returns: name
3644c06356bSdh142964 */
3654c06356bSdh142964 char *
damap_name(damap_t * damapp)3664c06356bSdh142964 damap_name(damap_t *damapp)
3674c06356bSdh142964 {
3684c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
3694c06356bSdh142964
3704c06356bSdh142964 return (mapp ? mapp->dam_name : "UNKNOWN_damap");
3714c06356bSdh142964 }
3724c06356bSdh142964
3734c06356bSdh142964 /*
37460aabb4cSChris Horne * Get the current size of the device address map
37560aabb4cSChris Horne *
37660aabb4cSChris Horne * damapp: address map
37760aabb4cSChris Horne *
37860aabb4cSChris Horne * Returns: size
37960aabb4cSChris Horne */
38060aabb4cSChris Horne int
damap_size(damap_t * damapp)38160aabb4cSChris Horne damap_size(damap_t *damapp)
38260aabb4cSChris Horne {
38360aabb4cSChris Horne dam_t *mapp = (dam_t *)damapp;
38460aabb4cSChris Horne
38560aabb4cSChris Horne return (mapp->dam_size);
38660aabb4cSChris Horne }
38760aabb4cSChris Horne
38860aabb4cSChris Horne /*
3894c06356bSdh142964 * Report an address to per-address report
3904c06356bSdh142964 *
3914c06356bSdh142964 * damapp: address map handle
3924c06356bSdh142964 * address: address in ascii string representation
3931b115575SJohn Danielson * addridp: address ID
3944c06356bSdh142964 * nvl: optional nvlist of configuration-private data
3954c06356bSdh142964 * addr_priv: optional provider-private (passed to activate/deactivate cb)
3964c06356bSdh142964 *
3974c06356bSdh142964 * Returns: DAM_SUCCESS
3984c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
3994c06356bSdh142964 * DAM_MAPFULL address map exhausted
4004c06356bSdh142964 */
4014c06356bSdh142964 int
damap_addr_add(damap_t * damapp,char * address,damap_id_t * addridp,nvlist_t * nvl,void * addr_priv)4021b115575SJohn Danielson damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
4031b115575SJohn Danielson nvlist_t *nvl, void *addr_priv)
4044c06356bSdh142964 {
4054c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
4064c06356bSdh142964 id_t addrid;
4074c06356bSdh142964 dam_da_t *passp;
4084c06356bSdh142964
4091b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
4104c06356bSdh142964 return (DAM_EINVAL);
4114c06356bSdh142964
4121b94a41bSChris Horne DTRACE_PROBE3(damap__addr__add,
4131b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4141b94a41bSChris Horne char *, address);
4151b115575SJohn Danielson
4161b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
4171b115575SJohn Danielson if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
4181b115575SJohn Danielson ((addrid = dam_get_addrid(mapp, address)) == 0)) {
4191b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4204c06356bSdh142964 return (DAM_MAPFULL);
4214c06356bSdh142964 }
4224c06356bSdh142964
4234c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
4244c06356bSdh142964 ASSERT(passp != NULL);
4254c06356bSdh142964
4264c06356bSdh142964 /*
4274c06356bSdh142964 * If re-reporting the same address (add or remove) clear
4284c06356bSdh142964 * the existing report
4294c06356bSdh142964 */
4304c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) {
4311b94a41bSChris Horne DTRACE_PROBE3(damap__addr__add__jitter,
4321b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4331b94a41bSChris Horne char *, address);
4341b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_jitter);
4351b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
4364c06356bSdh142964 passp->da_jitter++;
4374c06356bSdh142964 }
4384c06356bSdh142964 passp->da_ppriv_rpt = addr_priv;
4394c06356bSdh142964 if (nvl)
4404c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
4414c06356bSdh142964
4421b115575SJohn Danielson dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
4431b115575SJohn Danielson if (addridp != NULL)
4441b115575SJohn Danielson *addridp = (damap_id_t)addrid;
4451b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4464c06356bSdh142964 return (DAM_SUCCESS);
4474c06356bSdh142964 }
4484c06356bSdh142964
4494c06356bSdh142964 /*
4504c06356bSdh142964 * Report removal of address from per-address report
4514c06356bSdh142964 *
4524c06356bSdh142964 * damapp: address map
4534c06356bSdh142964 * address: address in ascii string representation
4544c06356bSdh142964 *
4554c06356bSdh142964 * Returns: DAM_SUCCESS
4564c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
4574c06356bSdh142964 * DAM_FAILURE General failure
4584c06356bSdh142964 */
4594c06356bSdh142964 int
damap_addr_del(damap_t * damapp,char * address)4604c06356bSdh142964 damap_addr_del(damap_t *damapp, char *address)
4614c06356bSdh142964 {
4624c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
4634c06356bSdh142964 id_t addrid;
4644c06356bSdh142964 dam_da_t *passp;
4654c06356bSdh142964
4661b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
4674c06356bSdh142964 return (DAM_EINVAL);
4684c06356bSdh142964
4691b94a41bSChris Horne DTRACE_PROBE3(damap__addr__del,
4701b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4711b94a41bSChris Horne char *, address);
4721b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
4731b115575SJohn Danielson if (dam_map_alloc(mapp) != DAM_SUCCESS) {
4741b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4751b115575SJohn Danielson return (DAM_MAPFULL);
4761b115575SJohn Danielson }
4771b115575SJohn Danielson
4781b115575SJohn Danielson /*
4791b115575SJohn Danielson * if reporting the removal of an address which is not in the map
4801b115575SJohn Danielson * return success
4811b115575SJohn Danielson */
4824c06356bSdh142964 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
4831b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4844c06356bSdh142964 return (DAM_SUCCESS);
4854c06356bSdh142964 }
4864c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
4874c06356bSdh142964 ASSERT(passp);
4884c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) {
4891b94a41bSChris Horne DTRACE_PROBE3(damap__addr__del__jitter,
4901b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
4911b94a41bSChris Horne char *, address);
4921b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_jitter);
4931b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
4944c06356bSdh142964 passp->da_jitter++;
4954c06356bSdh142964 }
4961b115575SJohn Danielson dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
4971b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
4984c06356bSdh142964 return (DAM_SUCCESS);
4994c06356bSdh142964 }
5004c06356bSdh142964
5010b53804eSReed static int
damap_addrset_flush_locked(damap_t * damapp)5020b53804eSReed damap_addrset_flush_locked(damap_t *damapp)
5030b53804eSReed {
5040b53804eSReed dam_t *mapp = (dam_t *)damapp;
5050b53804eSReed int idx;
5060b53804eSReed
5070b53804eSReed ASSERT(mapp);
5080b53804eSReed ASSERT(mutex_owned(&mapp->dam_lock));
5090b53804eSReed if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
5100b53804eSReed return (DAM_EINVAL);
5110b53804eSReed }
5120b53804eSReed
5131b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush__locked__enter,
5141b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5150b53804eSReed if (mapp->dam_flags & DAM_SETADD) {
5161b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush__locked__reset,
5171b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5180b53804eSReed
5190b53804eSReed /*
5200b53804eSReed * cancel stabilization timeout
5210b53804eSReed */
52260aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
5230b53804eSReed DAM_INCR_STAT(mapp, dam_jitter);
5240b53804eSReed
5250b53804eSReed /*
5260b53804eSReed * clear pending reports
5270b53804eSReed */
5280b53804eSReed for (idx = 1; idx < mapp->dam_high; idx++) {
5290b53804eSReed if (DAM_IN_REPORT(mapp, idx)) {
5300b53804eSReed dam_addr_report_release(mapp, idx);
5310b53804eSReed }
5320b53804eSReed }
5330b53804eSReed
5340b53804eSReed bitset_zero(&mapp->dam_report_set);
5350b53804eSReed mapp->dam_flags &= ~DAM_SETADD;
53660aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
5370b53804eSReed }
5380b53804eSReed
5390b53804eSReed return (DAM_SUCCESS);
5400b53804eSReed }
5410b53804eSReed
5424c06356bSdh142964 /*
5434c06356bSdh142964 * Initiate full-set report
5444c06356bSdh142964 *
5454c06356bSdh142964 * damapp: address map
5464c06356bSdh142964 *
5474c06356bSdh142964 * Returns: DAM_SUCCESS
5484c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
5494c06356bSdh142964 */
5504c06356bSdh142964 int
damap_addrset_begin(damap_t * damapp)5514c06356bSdh142964 damap_addrset_begin(damap_t *damapp)
5524c06356bSdh142964 {
5534c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
5540b53804eSReed int rv;
5554c06356bSdh142964
5560b53804eSReed if (mapp == NULL) {
5574c06356bSdh142964 return (DAM_EINVAL);
5580b53804eSReed }
5594c06356bSdh142964
5601b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__begin,
5611b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5620b53804eSReed
5631b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
5641b115575SJohn Danielson if (dam_map_alloc(mapp) != DAM_SUCCESS) {
5651b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
5660b53804eSReed
5671b115575SJohn Danielson return (DAM_MAPFULL);
5681b115575SJohn Danielson }
5690b53804eSReed
5700b53804eSReed rv = damap_addrset_flush_locked(damapp);
5710b53804eSReed if (rv == DAM_SUCCESS) {
5720b53804eSReed mapp->dam_flags |= DAM_SETADD;
5730b53804eSReed }
5740b53804eSReed mutex_exit(&mapp->dam_lock);
5750b53804eSReed
5760b53804eSReed return (rv);
5770b53804eSReed }
5781b115575SJohn Danielson
5791b115575SJohn Danielson /*
5800b53804eSReed * Cancel full-set report
5810b53804eSReed *
5820b53804eSReed * damapp: address map
5830b53804eSReed *
5840b53804eSReed * Returns: DAM_SUCCESS
5850b53804eSReed * DAM_EINVAL Invalid argument(s)
5861b115575SJohn Danielson */
5870b53804eSReed int
damap_addrset_flush(damap_t * damapp)5880b53804eSReed damap_addrset_flush(damap_t *damapp)
5890b53804eSReed {
5900b53804eSReed int rv;
5910b53804eSReed dam_t *mapp = (dam_t *)damapp;
5920b53804eSReed
5930b53804eSReed if (mapp == NULL) {
5940b53804eSReed return (DAM_EINVAL);
5954c06356bSdh142964 }
5960b53804eSReed
5971b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__flush,
5981b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
5990b53804eSReed
6000b53804eSReed mutex_enter(&mapp->dam_lock);
6010b53804eSReed rv = damap_addrset_flush_locked(damapp);
6021b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6030b53804eSReed
6040b53804eSReed return (rv);
6054c06356bSdh142964 }
6064c06356bSdh142964
6074c06356bSdh142964 /*
6084c06356bSdh142964 * Report address to full-set report
6094c06356bSdh142964 *
6104c06356bSdh142964 * damapp: address map handle
6114c06356bSdh142964 * address: address in ascii string representation
6124c06356bSdh142964 * rindx: index if address stabilizes
6134c06356bSdh142964 * nvl: optional nvlist of configuration-private data
6144c06356bSdh142964 * addr_priv: optional provider-private data (passed to activate/release cb)
6154c06356bSdh142964 *
6164c06356bSdh142964 * Returns: DAM_SUCCESS
6174c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
6184c06356bSdh142964 * DAM_MAPFULL address map exhausted
6194c06356bSdh142964 * DAM_FAILURE General failure
6204c06356bSdh142964 */
6214c06356bSdh142964 int
damap_addrset_add(damap_t * damapp,char * address,damap_id_t * ridx,nvlist_t * nvl,void * addr_priv)6224c06356bSdh142964 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
6234c06356bSdh142964 nvlist_t *nvl, void *addr_priv)
6244c06356bSdh142964 {
6254c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
6264c06356bSdh142964 id_t addrid;
6274c06356bSdh142964 dam_da_t *passp;
6284c06356bSdh142964
6291b115575SJohn Danielson if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
6304c06356bSdh142964 return (DAM_EINVAL);
6314c06356bSdh142964
6321b94a41bSChris Horne DTRACE_PROBE3(damap__addrset__add,
6331b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp, char *, address);
6344c06356bSdh142964
6351b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
6361b115575SJohn Danielson if (!(mapp->dam_flags & DAM_SETADD)) {
6371b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6381b115575SJohn Danielson return (DAM_FAILURE);
6391b115575SJohn Danielson }
6401b115575SJohn Danielson
6414c06356bSdh142964 if ((addrid = dam_get_addrid(mapp, address)) == 0) {
6421b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6434c06356bSdh142964 return (DAM_MAPFULL);
6444c06356bSdh142964 }
6454c06356bSdh142964
6464c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
6474c06356bSdh142964 ASSERT(passp);
6484c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) {
6491b94a41bSChris Horne DTRACE_PROBE3(damap__addrset__add__jitter,
6501b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
6511b94a41bSChris Horne char *, address);
6521b115575SJohn Danielson dam_addr_report_release(mapp, addrid);
6534c06356bSdh142964 passp->da_jitter++;
6544c06356bSdh142964 }
6554c06356bSdh142964 passp->da_ppriv_rpt = addr_priv;
6564c06356bSdh142964 if (nvl)
6574c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
6584c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid);
6594c06356bSdh142964 if (ridx)
6604c06356bSdh142964 *ridx = (damap_id_t)addrid;
6611b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6624c06356bSdh142964 return (DAM_SUCCESS);
6634c06356bSdh142964 }
6644c06356bSdh142964
6654c06356bSdh142964 /*
6664c06356bSdh142964 * Commit full-set report for stabilization
6674c06356bSdh142964 *
6684c06356bSdh142964 * damapp: address map handle
6694c06356bSdh142964 * flags: (currently 0)
6704c06356bSdh142964 *
6714c06356bSdh142964 * Returns: DAM_SUCCESS
6724c06356bSdh142964 * DAM_EINVAL Invalid argument(s)
6734c06356bSdh142964 * DAM_FAILURE General failure
6744c06356bSdh142964 */
6754c06356bSdh142964 int
damap_addrset_end(damap_t * damapp,int flags)6764c06356bSdh142964 damap_addrset_end(damap_t *damapp, int flags)
6774c06356bSdh142964 {
6784c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
6794c06356bSdh142964 int i;
6804c06356bSdh142964
6811b115575SJohn Danielson if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
6824c06356bSdh142964 return (DAM_EINVAL);
6834c06356bSdh142964
6841b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__end,
6851b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
6864c06356bSdh142964
6871b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
6881b115575SJohn Danielson if (!(mapp->dam_flags & DAM_SETADD)) {
6891b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
6901b115575SJohn Danielson return (DAM_FAILURE);
6911b115575SJohn Danielson }
6921b115575SJohn Danielson
6931b115575SJohn Danielson if (flags & DAMAP_END_RESET) {
6941b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__end__reset,
6951b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
69660aabb4cSChris Horne dam_sched_timeout(NULL, mapp, 0);
6974c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++)
6984c06356bSdh142964 if (DAM_IN_REPORT(mapp, i))
6991b115575SJohn Danielson dam_addr_report_release(mapp, i);
7004c06356bSdh142964 } else {
7014c06356bSdh142964 mapp->dam_last_update = gethrtime();
70260aabb4cSChris Horne dam_sched_timeout(dam_addrset_stable_cb, mapp,
70360aabb4cSChris Horne mapp->dam_stable_ticks);
7044c06356bSdh142964 }
7051b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
7064c06356bSdh142964 return (DAM_SUCCESS);
7074c06356bSdh142964 }
7084c06356bSdh142964
7094c06356bSdh142964 /*
7104c06356bSdh142964 * Return nvlist registered with reported address
7114c06356bSdh142964 *
7124c06356bSdh142964 * damapp: address map handle
7131b115575SJohn Danielson * addrid: address ID
7144c06356bSdh142964 *
7154c06356bSdh142964 * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
7164c06356bSdh142964 * NULL
7174c06356bSdh142964 */
7184c06356bSdh142964 nvlist_t *
damap_id2nvlist(damap_t * damapp,damap_id_t addrid)7194c06356bSdh142964 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
7204c06356bSdh142964 {
7214c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
7224c06356bSdh142964 dam_da_t *pass;
7234c06356bSdh142964
7241b115575SJohn Danielson if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
7251b115575SJohn Danielson if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
7264c06356bSdh142964 return (pass->da_nvl);
7274c06356bSdh142964 }
7284c06356bSdh142964 return (NULL);
7294c06356bSdh142964 }
7304c06356bSdh142964
7314c06356bSdh142964 /*
7324c06356bSdh142964 * Return address string
7334c06356bSdh142964 *
7344c06356bSdh142964 * damapp: address map handle
7351b115575SJohn Danielson * addrid: address ID
7364c06356bSdh142964 *
7374c06356bSdh142964 * Returns: char * Address string
7384c06356bSdh142964 * NULL
7394c06356bSdh142964 */
7404c06356bSdh142964 char *
damap_id2addr(damap_t * damapp,damap_id_t addrid)7411b115575SJohn Danielson damap_id2addr(damap_t *damapp, damap_id_t addrid)
7424c06356bSdh142964 {
7434c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
7444c06356bSdh142964
7451b115575SJohn Danielson if (mapp->dam_high)
7461b115575SJohn Danielson return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
7471b115575SJohn Danielson else
7481b115575SJohn Danielson return (NULL);
7494c06356bSdh142964 }
7504c06356bSdh142964
7514c06356bSdh142964 /*
7524c06356bSdh142964 * Release address reference in map
7534c06356bSdh142964 *
7544c06356bSdh142964 * damapp: address map handle
7551b115575SJohn Danielson * addrid: address ID
7564c06356bSdh142964 */
7574c06356bSdh142964 void
damap_id_rele(damap_t * damapp,damap_id_t addrid)7584c06356bSdh142964 damap_id_rele(damap_t *damapp, damap_id_t addrid)
7594c06356bSdh142964 {
7604c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
7611b115575SJohn Danielson dam_da_t *passp;
7621b115575SJohn Danielson char *addr;
7634c06356bSdh142964
7641b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
7651b115575SJohn Danielson ASSERT(passp);
7661b115575SJohn Danielson
7671b115575SJohn Danielson addr = damap_id2addr(damapp, addrid);
7681b94a41bSChris Horne DTRACE_PROBE4(damap__id__rele,
7691b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
7701b94a41bSChris Horne char *, addr, int, passp->da_ref);
7711b115575SJohn Danielson
7721b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
7731b115575SJohn Danielson
7741b115575SJohn Danielson /*
7751b115575SJohn Danielson * teardown address if last outstanding reference
7761b115575SJohn Danielson */
7771b115575SJohn Danielson if (--passp->da_ref == 0)
7781b115575SJohn Danielson dam_addr_release(mapp, (id_t)addrid);
7791b115575SJohn Danielson
7801b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
7814c06356bSdh142964 }
7824c06356bSdh142964
7834c06356bSdh142964 /*
7844c06356bSdh142964 * Return current reference count on address reference in map
7854c06356bSdh142964 *
7864c06356bSdh142964 * damapp: address map handle
7871b115575SJohn Danielson * addrid: address ID
7884c06356bSdh142964 *
7894c06356bSdh142964 * Returns: DAM_SUCCESS
7904c06356bSdh142964 * DAM_FAILURE
7914c06356bSdh142964 */
7924c06356bSdh142964 int
damap_id_ref(damap_t * damapp,damap_id_t addrid)7931b115575SJohn Danielson damap_id_ref(damap_t *damapp, damap_id_t addrid)
7944c06356bSdh142964 {
7954c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
7964c06356bSdh142964 dam_da_t *passp;
7974c06356bSdh142964 int ref = -1;
7984c06356bSdh142964
7991b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8004c06356bSdh142964 if (passp)
8014c06356bSdh142964 ref = passp->da_ref;
8021b115575SJohn Danielson
8034c06356bSdh142964 return (ref);
8044c06356bSdh142964 }
8054c06356bSdh142964
8064c06356bSdh142964 /*
8074c06356bSdh142964 * Return next address ID in list
8084c06356bSdh142964 *
8094c06356bSdh142964 * damapp: address map handle
8104c06356bSdh142964 * damap_list: address ID list passed to config|unconfig
8114c06356bSdh142964 * returned by look by lookup_all
8124c06356bSdh142964 * last: last ID returned, 0 is start of list
8134c06356bSdh142964 *
8144c06356bSdh142964 * Returns: addrid Next ID from the list
8154c06356bSdh142964 * 0 End of the list
8164c06356bSdh142964 */
8174c06356bSdh142964 damap_id_t
damap_id_next(damap_t * damapp,damap_id_list_t damap_list,damap_id_t last)8184c06356bSdh142964 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
8194c06356bSdh142964 {
8204c06356bSdh142964 int i, start;
8214c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
8224c06356bSdh142964 bitset_t *dam_list = (bitset_t *)damap_list;
8234c06356bSdh142964
8244c06356bSdh142964 if (!mapp || !dam_list)
8254c06356bSdh142964 return ((damap_id_t)0);
8264c06356bSdh142964
8274c06356bSdh142964 start = (int)last + 1;
8281b115575SJohn Danielson for (i = start; i < mapp->dam_high; i++) {
8291b115575SJohn Danielson if (bitset_in_set(dam_list, i)) {
8304c06356bSdh142964 return ((damap_id_t)i);
8311b115575SJohn Danielson }
8321b115575SJohn Danielson }
8334c06356bSdh142964 return ((damap_id_t)0);
8344c06356bSdh142964 }
8354c06356bSdh142964
8364c06356bSdh142964 /*
8374c06356bSdh142964 * Set config private data
8384c06356bSdh142964 *
8394c06356bSdh142964 * damapp: address map handle
8401b115575SJohn Danielson * addrid: address ID
8414c06356bSdh142964 * cfg_priv: configuration private data
8424c06356bSdh142964 *
8434c06356bSdh142964 */
8444c06356bSdh142964 void
damap_id_priv_set(damap_t * damapp,damap_id_t addrid,void * cfg_priv)8451b115575SJohn Danielson damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
8464c06356bSdh142964 {
8474c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
8484c06356bSdh142964 dam_da_t *passp;
8494c06356bSdh142964
8501b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
8511b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8524c06356bSdh142964 if (!passp) {
8531b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8544c06356bSdh142964 return;
8554c06356bSdh142964 }
8564c06356bSdh142964 passp->da_cfg_priv = cfg_priv;
8571b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8584c06356bSdh142964 }
8594c06356bSdh142964
8604c06356bSdh142964 /*
8614c06356bSdh142964 * Get config private data
8624c06356bSdh142964 *
8634c06356bSdh142964 * damapp: address map handle
8641b115575SJohn Danielson * addrid: address ID
8654c06356bSdh142964 *
8664c06356bSdh142964 * Returns: configuration private data
8674c06356bSdh142964 */
8684c06356bSdh142964 void *
damap_id_priv_get(damap_t * damapp,damap_id_t addrid)8691b115575SJohn Danielson damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
8704c06356bSdh142964 {
8714c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
8724c06356bSdh142964 dam_da_t *passp;
8734c06356bSdh142964 void *rv;
8744c06356bSdh142964
8751b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
8761b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
8774c06356bSdh142964 if (!passp) {
8781b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8794c06356bSdh142964 return (NULL);
8804c06356bSdh142964 }
8814c06356bSdh142964 rv = passp->da_cfg_priv;
8821b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
8834c06356bSdh142964 return (rv);
8844c06356bSdh142964 }
8854c06356bSdh142964
8864c06356bSdh142964 /*
8874c06356bSdh142964 * Lookup a single address in the active address map
8884c06356bSdh142964 *
8894c06356bSdh142964 * damapp: address map handle
8904c06356bSdh142964 * address: address string
8914c06356bSdh142964 *
8924c06356bSdh142964 * Returns: ID of active/stable address
8934c06356bSdh142964 * 0 Address not in stable set
8944c06356bSdh142964 *
8954c06356bSdh142964 * Future: Allow the caller to wait for stabilize before returning not found.
8964c06356bSdh142964 */
8974c06356bSdh142964 damap_id_t
damap_lookup(damap_t * damapp,char * address)8984c06356bSdh142964 damap_lookup(damap_t *damapp, char *address)
8994c06356bSdh142964 {
9004c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
9014c06356bSdh142964 id_t addrid = 0;
9024c06356bSdh142964 dam_da_t *passp = NULL;
9034c06356bSdh142964
9041b94a41bSChris Horne DTRACE_PROBE3(damap__lookup,
9051b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9061b94a41bSChris Horne char *, address);
9071b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
9081b115575SJohn Danielson if (!mapp->dam_high)
9091b115575SJohn Danielson addrid = 0;
9101b115575SJohn Danielson else
9114c06356bSdh142964 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
9124c06356bSdh142964 if (addrid) {
9134c06356bSdh142964 if (DAM_IS_STABLE(mapp, addrid)) {
9144c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
9154c06356bSdh142964 ASSERT(passp);
9164c06356bSdh142964 if (passp) {
9174c06356bSdh142964 passp->da_ref++;
9184c06356bSdh142964 } else {
9194c06356bSdh142964 addrid = 0;
9204c06356bSdh142964 }
9214c06356bSdh142964 } else {
9224c06356bSdh142964 addrid = 0;
9234c06356bSdh142964 }
9244c06356bSdh142964 }
9251b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9261b94a41bSChris Horne DTRACE_PROBE4(damap__lookup__return,
9271b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9281b94a41bSChris Horne char *, address, int, addrid);
9294c06356bSdh142964 return ((damap_id_t)addrid);
9304c06356bSdh142964 }
9314c06356bSdh142964
9324c06356bSdh142964
9334c06356bSdh142964 /*
9344c06356bSdh142964 * Return the list of stable addresses in the map
9354c06356bSdh142964 *
9364c06356bSdh142964 * damapp: address map handle
9374c06356bSdh142964 * id_listp: pointer to list of address IDs in stable map (returned)
9384c06356bSdh142964 *
9394c06356bSdh142964 * Returns: # of entries returned in alist
9404c06356bSdh142964 */
9414c06356bSdh142964 int
damap_lookup_all(damap_t * damapp,damap_id_list_t * id_listp)9424c06356bSdh142964 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
9434c06356bSdh142964 {
9444c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
9454c06356bSdh142964 int mapsz = mapp->dam_size;
9464c06356bSdh142964 int n_ids, i;
9474c06356bSdh142964 bitset_t *bsp;
9481b115575SJohn Danielson char *addrp;
9494c06356bSdh142964 dam_da_t *passp;
9504c06356bSdh142964
9511b94a41bSChris Horne DTRACE_PROBE2(damap__lookup__all,
9521b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
9531b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
9541b115575SJohn Danielson if (!mapp->dam_high) {
9551b115575SJohn Danielson *id_listp = (damap_id_list_t)NULL;
9561b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9571b94a41bSChris Horne DTRACE_PROBE2(damap__lookup__all__nomap,
9581b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
9591b115575SJohn Danielson return (0);
9601b115575SJohn Danielson }
9614c06356bSdh142964 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
9624c06356bSdh142964 bitset_init(bsp);
9634c06356bSdh142964 bitset_resize(bsp, mapsz);
9644c06356bSdh142964 bitset_copy(&mapp->dam_active_set, bsp);
9654c06356bSdh142964 for (n_ids = 0, i = 1; i < mapsz; i++) {
9664c06356bSdh142964 if (bitset_in_set(bsp, i)) {
9674c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i);
9684c06356bSdh142964 ASSERT(passp);
9694c06356bSdh142964 if (passp) {
9701b115575SJohn Danielson addrp = damap_id2addr(damapp, i);
9711b94a41bSChris Horne DTRACE_PROBE3(damap__lookup__all__item,
9721b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
9731b94a41bSChris Horne char *, addrp);
9744c06356bSdh142964 passp->da_ref++;
9754c06356bSdh142964 n_ids++;
9764c06356bSdh142964 }
9774c06356bSdh142964 }
9784c06356bSdh142964 }
9794c06356bSdh142964 if (n_ids) {
9804c06356bSdh142964 *id_listp = (damap_id_list_t)bsp;
9811b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9824c06356bSdh142964 return (n_ids);
9834c06356bSdh142964 } else {
9844c06356bSdh142964 *id_listp = (damap_id_list_t)NULL;
9854c06356bSdh142964 bitset_fini(bsp);
9864c06356bSdh142964 kmem_free(bsp, sizeof (*bsp));
9871b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
9884c06356bSdh142964 return (0);
9894c06356bSdh142964 }
9904c06356bSdh142964 }
9914c06356bSdh142964
9924c06356bSdh142964 /*
9934c06356bSdh142964 * Release the address list returned by damap_lookup_all()
9944c06356bSdh142964 *
9954c06356bSdh142964 * mapp: address map handle
9964c06356bSdh142964 * id_list: list of address IDs returned in damap_lookup_all()
9974c06356bSdh142964 */
9984c06356bSdh142964 void
damap_id_list_rele(damap_t * damapp,damap_id_list_t id_list)9994c06356bSdh142964 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
10004c06356bSdh142964 {
10014c06356bSdh142964 dam_t *mapp = (dam_t *)damapp;
10024c06356bSdh142964 int i;
10034c06356bSdh142964
10044c06356bSdh142964 if (id_list == NULL)
10054c06356bSdh142964 return;
10064c06356bSdh142964
10071b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10084c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) {
10094c06356bSdh142964 if (bitset_in_set((bitset_t *)id_list, i))
10101b115575SJohn Danielson (void) dam_addr_release(mapp, i);
10114c06356bSdh142964 }
10121b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10134c06356bSdh142964 bitset_fini((bitset_t *)id_list);
10144c06356bSdh142964 kmem_free((void *)id_list, sizeof (bitset_t));
10154c06356bSdh142964 }
10164c06356bSdh142964
10174c06356bSdh142964 /*
10181b115575SJohn Danielson * activate an address that has passed the stabilization interval
10194c06356bSdh142964 */
10204c06356bSdh142964 static void
dam_addr_activate(dam_t * mapp,id_t addrid)10211b115575SJohn Danielson dam_addr_activate(dam_t *mapp, id_t addrid)
10224c06356bSdh142964 {
10234c06356bSdh142964 dam_da_t *passp;
10241b115575SJohn Danielson int config_rv;
10254c06356bSdh142964 char *addrstr;
10264c06356bSdh142964
10271b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10281b115575SJohn Danielson bitset_add(&mapp->dam_active_set, addrid);
10291b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, addrid);
10304c06356bSdh142964 ASSERT(passp);
10311b115575SJohn Danielson
10324c06356bSdh142964 /*
10334c06356bSdh142964 * copy the reported nvlist and provider private data
10344c06356bSdh142964 */
10351b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
10361b94a41bSChris Horne DTRACE_PROBE3(damap__addr__activate__start,
10371b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10381b94a41bSChris Horne char *, addrstr);
10394c06356bSdh142964 passp->da_nvl = passp->da_nvl_rpt;
10404c06356bSdh142964 passp->da_ppriv = passp->da_ppriv_rpt;
10414c06356bSdh142964 passp->da_ppriv_rpt = NULL;
10424c06356bSdh142964 passp->da_nvl_rpt = NULL;
10434c06356bSdh142964 passp->da_last_stable = gethrtime();
10444c06356bSdh142964 passp->da_stable_cnt++;
10451b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10461b115575SJohn Danielson if (mapp->dam_activate_cb) {
10471b115575SJohn Danielson (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
10481b115575SJohn Danielson addrid, &passp->da_ppriv_rpt);
10494c06356bSdh142964 }
10504c06356bSdh142964
10514c06356bSdh142964 /*
10521b115575SJohn Danielson * call the address-specific configuration action as part of
10531b115575SJohn Danielson * activation.
10544c06356bSdh142964 */
10551b115575SJohn Danielson config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
10561b115575SJohn Danielson addrid);
10571b115575SJohn Danielson if (config_rv != DAM_SUCCESS) {
10581b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
10591b115575SJohn Danielson passp->da_flags |= DA_FAILED_CONFIG;
10601b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
10611b115575SJohn Danielson DTRACE_PROBE3(damap__addr__activate__config__failure,
10621b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10631b94a41bSChris Horne char *, addrstr);
1064d189c170SReed dam_deact_cleanup(mapp, addrid, addrstr,
1065d189c170SReed DAMAP_DEACT_RSN_CFG_FAIL);
1066d189c170SReed } else {
10671b94a41bSChris Horne DTRACE_PROBE3(damap__addr__activate__end,
10681b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10691b94a41bSChris Horne char *, addrstr);
10704c06356bSdh142964 }
10714c06356bSdh142964 }
10724c06356bSdh142964
10734c06356bSdh142964 /*
10741b115575SJohn Danielson * deactivate a previously stable address
10754c06356bSdh142964 */
10764c06356bSdh142964 static void
dam_addr_deactivate(dam_t * mapp,id_t addrid)10771b115575SJohn Danielson dam_addr_deactivate(dam_t *mapp, id_t addrid)
10784c06356bSdh142964 {
10791b115575SJohn Danielson char *addrstr;
10804c06356bSdh142964
10811b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
10821b94a41bSChris Horne DTRACE_PROBE3(damap__addr__deactivate__start,
10831b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
10841b94a41bSChris Horne char *, addrstr);
10851b115575SJohn Danielson
10861b115575SJohn Danielson /*
10871b115575SJohn Danielson * call the unconfiguration callback
10881b115575SJohn Danielson */
10891b115575SJohn Danielson (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1090d189c170SReed dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1091d189c170SReed }
1092d189c170SReed
1093d189c170SReed static void
dam_deact_cleanup(dam_t * mapp,id_t addrid,char * addrstr,damap_deact_rsn_t deact_rsn)1094d189c170SReed dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1095d189c170SReed damap_deact_rsn_t deact_rsn)
1096d189c170SReed {
1097d189c170SReed dam_da_t *passp;
1098d189c170SReed
10991b115575SJohn Danielson passp = ddi_get_soft_state(mapp->dam_da, addrid);
11001b115575SJohn Danielson ASSERT(passp);
11011b115575SJohn Danielson if (mapp->dam_deactivate_cb)
11021b115575SJohn Danielson (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
11031b115575SJohn Danielson ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1104d189c170SReed addrid, passp->da_ppriv, deact_rsn);
11051b115575SJohn Danielson
11061b115575SJohn Danielson /*
11071b115575SJohn Danielson * clear the active bit and free the backing info for
11081b115575SJohn Danielson * this address
11091b115575SJohn Danielson */
11101b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
11111b115575SJohn Danielson bitset_del(&mapp->dam_active_set, addrid);
11121b115575SJohn Danielson passp->da_ppriv = NULL;
11131b115575SJohn Danielson nvlist_free(passp->da_nvl);
11141b115575SJohn Danielson passp->da_nvl = NULL;
11151b115575SJohn Danielson passp->da_ppriv_rpt = NULL;
11161b115575SJohn Danielson nvlist_free(passp->da_nvl_rpt);
11171b115575SJohn Danielson passp->da_nvl_rpt = NULL;
11181b115575SJohn Danielson
11191b94a41bSChris Horne DTRACE_PROBE3(damap__addr__deactivate__end,
11201b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
11211b94a41bSChris Horne char *, addrstr);
11221b115575SJohn Danielson
11231b115575SJohn Danielson (void) dam_addr_release(mapp, addrid);
11241b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
11251b115575SJohn Danielson }
11261b115575SJohn Danielson
11271b115575SJohn Danielson /*
11281b115575SJohn Danielson * taskq callback for multi-thread activation
11291b115575SJohn Danielson */
11301b115575SJohn Danielson static void
dam_tq_config(void * arg)11311b115575SJohn Danielson dam_tq_config(void *arg)
11321b115575SJohn Danielson {
11331b115575SJohn Danielson cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
11341b115575SJohn Danielson
11351b115575SJohn Danielson dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
11361b115575SJohn Danielson kmem_free(tqd, sizeof (*tqd));
11371b115575SJohn Danielson }
11381b115575SJohn Danielson
11391b115575SJohn Danielson /*
11401b115575SJohn Danielson * taskq callback for multi-thread deactivation
11411b115575SJohn Danielson */
11421b115575SJohn Danielson static void
dam_tq_unconfig(void * arg)11431b115575SJohn Danielson dam_tq_unconfig(void *arg)
11441b115575SJohn Danielson {
11451b115575SJohn Danielson cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
11461b115575SJohn Danielson
11471b115575SJohn Danielson dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
11481b115575SJohn Danielson kmem_free(tqd, sizeof (*tqd));
11491b115575SJohn Danielson }
11501b115575SJohn Danielson
11511b115575SJohn Danielson /*
11521b115575SJohn Danielson * Activate a set of stabilized addresses
11531b115575SJohn Danielson */
11541b115575SJohn Danielson static void
dam_addrset_activate(dam_t * mapp,bitset_t * activate)11551b115575SJohn Danielson dam_addrset_activate(dam_t *mapp, bitset_t *activate)
11561b115575SJohn Danielson {
11571b115575SJohn Danielson
11581b115575SJohn Danielson int i, nset;
11591b115575SJohn Danielson taskq_t *tqp = NULL;
11601b115575SJohn Danielson cfg_tqd_t *tqd = NULL;
11611b115575SJohn Danielson char tqn[TASKQ_NAMELEN];
11621b115575SJohn Danielson extern pri_t maxclsyspri;
11631b115575SJohn Danielson
11641b115575SJohn Danielson if (mapp->dam_options & DAMAP_MTCONFIG) {
11651b115575SJohn Danielson /*
11661b115575SJohn Danielson * calculate the # of taskq threads to create
11671b115575SJohn Danielson */
11681b115575SJohn Danielson for (i = 1, nset = 0; i < mapp->dam_high; i++)
11691b115575SJohn Danielson if (bitset_in_set(activate, i))
11701b115575SJohn Danielson nset++;
11711b115575SJohn Danielson ASSERT(nset);
11721b115575SJohn Danielson (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
11731b115575SJohn Danielson tqp = taskq_create(tqn, nset, maxclsyspri, 1,
11741b115575SJohn Danielson INT_MAX, TASKQ_PREPOPULATE);
11751b115575SJohn Danielson }
11761b115575SJohn Danielson for (i = 1; i < mapp->dam_high; i++) {
11771b115575SJohn Danielson if (bitset_in_set(activate, i)) {
11781b115575SJohn Danielson if (!tqp)
11791b115575SJohn Danielson dam_addr_activate(mapp, i);
11801b115575SJohn Danielson else {
11811b115575SJohn Danielson /*
11821b115575SJohn Danielson * multi-threaded activation
11831b115575SJohn Danielson */
11841b115575SJohn Danielson tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
11851b115575SJohn Danielson tqd->tqd_mapp = mapp;
11861b115575SJohn Danielson tqd->tqd_id = i;
11871b115575SJohn Danielson (void) taskq_dispatch(tqp, dam_tq_config,
118864109744SChris Horne tqd, TQ_SLEEP);
11891b115575SJohn Danielson }
11901b115575SJohn Danielson }
11911b115575SJohn Danielson }
11921b115575SJohn Danielson if (tqp) {
11931b115575SJohn Danielson taskq_wait(tqp);
11941b115575SJohn Danielson taskq_destroy(tqp);
11951b115575SJohn Danielson }
11961b115575SJohn Danielson }
11971b115575SJohn Danielson
11981b115575SJohn Danielson /*
11991b115575SJohn Danielson * Deactivate a set of stabilized addresses
12001b115575SJohn Danielson */
12011b115575SJohn Danielson static void
dam_addrset_deactivate(dam_t * mapp,bitset_t * deactivate)12021b115575SJohn Danielson dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
12031b115575SJohn Danielson {
12041b115575SJohn Danielson int i, nset;
12051b115575SJohn Danielson taskq_t *tqp = NULL;
12061b115575SJohn Danielson cfg_tqd_t *tqd = NULL;
12071b115575SJohn Danielson char tqn[TASKQ_NAMELEN];
12081b115575SJohn Danielson
12091b94a41bSChris Horne DTRACE_PROBE2(damap__addrset__deactivate,
12101b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
12111b115575SJohn Danielson
12121b115575SJohn Danielson if (mapp->dam_options & DAMAP_MTCONFIG) {
12131b115575SJohn Danielson /*
12141b115575SJohn Danielson * compute the # of taskq threads to dispatch
12151b115575SJohn Danielson */
12161b115575SJohn Danielson for (i = 1, nset = 0; i < mapp->dam_high; i++)
12171b115575SJohn Danielson if (bitset_in_set(deactivate, i))
12181b115575SJohn Danielson nset++;
12191b115575SJohn Danielson (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
12201b115575SJohn Danielson mapp->dam_name);
12211b115575SJohn Danielson tqp = taskq_create(tqn, nset, maxclsyspri, 1,
12221b115575SJohn Danielson INT_MAX, TASKQ_PREPOPULATE);
12231b115575SJohn Danielson }
12241b115575SJohn Danielson for (i = 1; i < mapp->dam_high; i++) {
12251b115575SJohn Danielson if (bitset_in_set(deactivate, i)) {
12261b115575SJohn Danielson if (!tqp) {
12271b115575SJohn Danielson dam_addr_deactivate(mapp, i);
12281b115575SJohn Danielson } else {
12291b115575SJohn Danielson tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
12301b115575SJohn Danielson tqd->tqd_mapp = mapp;
12311b115575SJohn Danielson tqd->tqd_id = i;
12321b115575SJohn Danielson (void) taskq_dispatch(tqp,
123364109744SChris Horne dam_tq_unconfig, tqd, TQ_SLEEP);
12341b115575SJohn Danielson }
12351b115575SJohn Danielson }
12361b115575SJohn Danielson }
12371b115575SJohn Danielson
12381b115575SJohn Danielson if (tqp) {
12391b115575SJohn Danielson taskq_wait(tqp);
12401b115575SJohn Danielson taskq_destroy(tqp);
12411b115575SJohn Danielson }
12421b115575SJohn Danielson }
12431b115575SJohn Danielson
12441b115575SJohn Danielson /*
12451b115575SJohn Danielson * Release a previously activated address
12461b115575SJohn Danielson */
12471b115575SJohn Danielson static void
dam_addr_release(dam_t * mapp,id_t addrid)12481b115575SJohn Danielson dam_addr_release(dam_t *mapp, id_t addrid)
12491b115575SJohn Danielson {
12501b115575SJohn Danielson dam_da_t *passp;
12511b115575SJohn Danielson char *addrstr;
12521b115575SJohn Danielson
12531b115575SJohn Danielson
12541b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
12554c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
12564c06356bSdh142964 ASSERT(passp);
12574c06356bSdh142964
12581b115575SJohn Danielson addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
12591b94a41bSChris Horne DTRACE_PROBE3(damap__addr__release,
12601b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12611b94a41bSChris Horne char *, addrstr);
12624c06356bSdh142964
12634c06356bSdh142964 /*
12641b115575SJohn Danielson * defer releasing the address until outstanding references
12651b115575SJohn Danielson * are released
12664c06356bSdh142964 */
12671b115575SJohn Danielson if (passp->da_ref > 1) {
12681b115575SJohn Danielson DTRACE_PROBE4(damap__addr__release__outstanding__refs,
12691b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12701b94a41bSChris Horne char *, addrstr, int, passp->da_ref);
12714c06356bSdh142964 return;
12724c06356bSdh142964 }
12731b115575SJohn Danielson
12741b115575SJohn Danielson /*
12751b115575SJohn Danielson * allow pending reports to stabilize
12761b115575SJohn Danielson */
12771b115575SJohn Danielson if (DAM_IN_REPORT(mapp, addrid)) {
12781b115575SJohn Danielson DTRACE_PROBE3(damap__addr__release__report__pending,
12791b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
12801b94a41bSChris Horne char *, addrstr);
12811b115575SJohn Danielson return;
12821b115575SJohn Danielson }
12831b115575SJohn Danielson
12844c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid);
12854c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, addrid);
12864c06356bSdh142964 }
12874c06356bSdh142964
12884c06356bSdh142964 /*
12894c06356bSdh142964 * process stabilized address reports
12904c06356bSdh142964 */
12914c06356bSdh142964 static void
dam_stabilize_map(void * arg)12921b115575SJohn Danielson dam_stabilize_map(void *arg)
12934c06356bSdh142964 {
12944c06356bSdh142964 dam_t *mapp = (dam_t *)arg;
12954c06356bSdh142964 bitset_t delta;
12964c06356bSdh142964 bitset_t cfg;
12974c06356bSdh142964 bitset_t uncfg;
12984c06356bSdh142964 int has_cfg, has_uncfg;
12991b115575SJohn Danielson uint32_t i, n_active;
13001b115575SJohn Danielson
13011b94a41bSChris Horne DTRACE_PROBE2(damap__stabilize__map,
13021b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
13034c06356bSdh142964
13044c06356bSdh142964 bitset_init(&delta);
13054c06356bSdh142964 bitset_resize(&delta, mapp->dam_size);
13064c06356bSdh142964 bitset_init(&cfg);
13074c06356bSdh142964 bitset_resize(&cfg, mapp->dam_size);
13084c06356bSdh142964 bitset_init(&uncfg);
13094c06356bSdh142964 bitset_resize(&uncfg, mapp->dam_size);
13104c06356bSdh142964
13111b115575SJohn Danielson /*
13121b115575SJohn Danielson * determine which addresses have changed during
13131b115575SJohn Danielson * this stabilization cycle
13141b115575SJohn Danielson */
13151b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
13161b115575SJohn Danielson ASSERT(mapp->dam_flags & DAM_SPEND);
13174c06356bSdh142964 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
13184c06356bSdh142964 &delta)) {
13191b115575SJohn Danielson /*
13201b115575SJohn Danielson * no difference
13211b115575SJohn Danielson */
13224c06356bSdh142964 bitset_zero(&mapp->dam_stable_set);
13231b115575SJohn Danielson mapp->dam_flags &= ~DAM_SPEND;
132460aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
13251b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
132660aabb4cSChris Horne
13274c06356bSdh142964 bitset_fini(&uncfg);
13284c06356bSdh142964 bitset_fini(&cfg);
13294c06356bSdh142964 bitset_fini(&delta);
13301b94a41bSChris Horne DTRACE_PROBE2(damap__stabilize__map__nochange,
13311b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
13324c06356bSdh142964 return;
13334c06356bSdh142964 }
13341b115575SJohn Danielson
13351b115575SJohn Danielson /*
13361b115575SJohn Danielson * compute the sets of addresses to be activated and deactivated
13371b115575SJohn Danielson */
13384c06356bSdh142964 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
13394c06356bSdh142964 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
13401b115575SJohn Danielson
13411b115575SJohn Danielson /*
13421b115575SJohn Danielson * drop map lock while invoking callouts
13431b115575SJohn Danielson */
13441b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
13451b115575SJohn Danielson
13461b115575SJohn Danielson /*
13471b115575SJohn Danielson * activate all newly stable addresss
13481b115575SJohn Danielson */
13491b115575SJohn Danielson if (has_cfg)
13504c06356bSdh142964 dam_addrset_activate(mapp, &cfg);
13511b115575SJohn Danielson
13521b115575SJohn Danielson /*
13531b115575SJohn Danielson * deactivate addresss which are no longer in the map
13541b115575SJohn Danielson */
13551b115575SJohn Danielson if (has_uncfg)
13561b115575SJohn Danielson dam_addrset_deactivate(mapp, &uncfg);
13571b115575SJohn Danielson
13581b115575SJohn Danielson
13591b115575SJohn Danielson /*
13601b115575SJohn Danielson * timestamp the last stable time and increment the kstat keeping
13611b115575SJohn Danielson * the # of of stable cycles for the map
13621b115575SJohn Danielson */
13631b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
13644c06356bSdh142964 bitset_zero(&mapp->dam_stable_set);
13654c06356bSdh142964 mapp->dam_last_stable = gethrtime();
13664c06356bSdh142964 mapp->dam_stable_cnt++;
13671b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_cycles);
13681b115575SJohn Danielson
13691b115575SJohn Danielson /*
13701b115575SJohn Danielson * determine the number of stable addresses
13711b115575SJohn Danielson * and update the n_active kstat for this map
13721b115575SJohn Danielson */
13731b115575SJohn Danielson for (i = 1, n_active = 0; i < mapp->dam_high; i++)
13741b115575SJohn Danielson if (bitset_in_set(&mapp->dam_active_set, i))
13751b115575SJohn Danielson n_active++;
13761b115575SJohn Danielson DAM_SET_STAT(mapp, dam_active, n_active);
13771b115575SJohn Danielson
13781b94a41bSChris Horne DTRACE_PROBE3(damap__map__stable__end,
13791b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
13801b94a41bSChris Horne int, n_active);
13811b115575SJohn Danielson
13821b115575SJohn Danielson mapp->dam_flags &= ~DAM_SPEND;
138360aabb4cSChris Horne cv_signal(&mapp->dam_sync_cv);
13841b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
138560aabb4cSChris Horne
13864c06356bSdh142964 bitset_fini(&uncfg);
13874c06356bSdh142964 bitset_fini(&cfg);
13884c06356bSdh142964 bitset_fini(&delta);
13894c06356bSdh142964 }
13904c06356bSdh142964
13914c06356bSdh142964 /*
13924c06356bSdh142964 * per-address stabilization timeout
13934c06356bSdh142964 */
13944c06356bSdh142964 static void
dam_addr_stable_cb(void * arg)13954c06356bSdh142964 dam_addr_stable_cb(void *arg)
13964c06356bSdh142964 {
13974c06356bSdh142964 dam_t *mapp = (dam_t *)arg;
13984c06356bSdh142964 int i;
13994c06356bSdh142964 dam_da_t *passp;
14004c06356bSdh142964 int spend = 0;
14014c06356bSdh142964 int tpend = 0;
140260aabb4cSChris Horne int64_t ts, next_ticks, delta_ticks;
14034c06356bSdh142964
14041b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
14054c06356bSdh142964 if (mapp->dam_tid == 0) {
14061b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__cancelled,
14071b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
14081b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
14094c06356bSdh142964 return;
14104c06356bSdh142964 }
14114c06356bSdh142964 mapp->dam_tid = 0;
14121b115575SJohn Danielson
14134c06356bSdh142964 /*
14144c06356bSdh142964 * If still under stabilization, reschedule timeout,
14151b115575SJohn Danielson * otherwise dispatch the task to activate and deactivate the
14161b115575SJohn Danielson * new stable address
14174c06356bSdh142964 */
14184c06356bSdh142964 if (mapp->dam_flags & DAM_SPEND) {
14191b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_overrun);
14204c06356bSdh142964 mapp->dam_stable_overrun++;
14211b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__overrun,
14221b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
142360aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp,
142460aabb4cSChris Horne mapp->dam_stable_ticks);
14251b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
14264c06356bSdh142964 return;
14274c06356bSdh142964 }
14284c06356bSdh142964
14291b115575SJohn Danielson DAM_SET_STAT(mapp, dam_overrun, 0);
14301b115575SJohn Danielson mapp->dam_stable_overrun = 0;
14311b115575SJohn Danielson
14321b94a41bSChris Horne /* See if any reports stabalized and compute next timeout. */
143360aabb4cSChris Horne ts = ddi_get_lbolt64();
143460aabb4cSChris Horne next_ticks = mapp->dam_stable_ticks;
14354c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) {
14361b94a41bSChris Horne if (bitset_in_set(&mapp->dam_report_set, i)) {
14374c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i);
14384c06356bSdh142964 ASSERT(passp);
14394c06356bSdh142964
14401b94a41bSChris Horne if (passp->da_deadline <= ts)
14411b94a41bSChris Horne spend++; /* report has stabilized */
14421b94a41bSChris Horne else {
14431b94a41bSChris Horne /* not stabilized, determine next map timeout */
14444c06356bSdh142964 tpend++;
144560aabb4cSChris Horne delta_ticks = passp->da_deadline - ts;
144660aabb4cSChris Horne if (delta_ticks < next_ticks)
144760aabb4cSChris Horne next_ticks = delta_ticks;
14484c06356bSdh142964 }
14491b94a41bSChris Horne }
14501b94a41bSChris Horne }
14514c06356bSdh142964
14524c06356bSdh142964 /*
14531b115575SJohn Danielson * schedule system_taskq activation of stabilized reports
14544c06356bSdh142964 */
14554c06356bSdh142964 if (spend) {
14561b115575SJohn Danielson if (taskq_dispatch(system_taskq, dam_stabilize_map,
145764109744SChris Horne mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
14581b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__start,
14591b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
14601b94a41bSChris Horne
14611b94a41bSChris Horne /*
14621b94a41bSChris Horne * The stable_set we compute below stays pending until
14631b94a41bSChris Horne * processed by dam_stabilize_map. We can't set
14641b94a41bSChris Horne * DAM_SPEND (or bitset_del things from the
14651b94a41bSChris Horne * report_set) until we *know* that we can handoff the
14661b94a41bSChris Horne * result to dam_stabilize_map. If dam_stabilize_map
14671b94a41bSChris Horne * starts executing before we are complete, it will
14681b94a41bSChris Horne * block on the dam_lock mutex until we are ready.
14691b94a41bSChris Horne */
14701b115575SJohn Danielson mapp->dam_flags |= DAM_SPEND;
14711b94a41bSChris Horne
14721b94a41bSChris Horne /*
14731b94a41bSChris Horne * Copy the current active_set to the stable_set, then
14741b94a41bSChris Horne * add or remove stabilized report_set address from
14751b94a41bSChris Horne * the stable set (and delete them from the report_set).
14761b94a41bSChris Horne */
14771b94a41bSChris Horne bitset_copy(&mapp->dam_active_set,
14781b94a41bSChris Horne &mapp->dam_stable_set);
14791b94a41bSChris Horne for (i = 1; i < mapp->dam_high; i++) {
14801b94a41bSChris Horne if (!bitset_in_set(&mapp->dam_report_set, i))
14811b94a41bSChris Horne continue;
14821b94a41bSChris Horne
14831b94a41bSChris Horne passp = ddi_get_soft_state(mapp->dam_da, i);
14841b94a41bSChris Horne if (passp->da_deadline > ts)
14851b94a41bSChris Horne continue; /* report not stabilized */
14861b94a41bSChris Horne
14871b94a41bSChris Horne /* report has stabilized */
14881b94a41bSChris Horne if (passp->da_flags & DA_RELE)
14891b94a41bSChris Horne bitset_del(&mapp->dam_stable_set, i);
14901b94a41bSChris Horne else
14911b94a41bSChris Horne bitset_add(&mapp->dam_stable_set, i);
14921b94a41bSChris Horne
14931b94a41bSChris Horne bitset_del(&mapp->dam_report_set, i);
14941b94a41bSChris Horne }
14951b115575SJohn Danielson } else {
14961b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__spendfail,
14971b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
149864109744SChris Horne
149964109744SChris Horne /*
150064109744SChris Horne * Avoid waiting the entire stabalization
150164109744SChris Horne * time again if taskq_diskpatch fails.
150264109744SChris Horne */
15031b94a41bSChris Horne tpend++;
150460aabb4cSChris Horne delta_ticks = drv_usectohz(
150564109744SChris Horne damap_taskq_dispatch_retry_usec);
150660aabb4cSChris Horne if (delta_ticks < next_ticks)
150760aabb4cSChris Horne next_ticks = delta_ticks;
15084c06356bSdh142964 }
15091b115575SJohn Danielson }
15104c06356bSdh142964
15114c06356bSdh142964 /*
15121b115575SJohn Danielson * reschedule the stabilization timer if there are reports
15131b115575SJohn Danielson * still pending
15144c06356bSdh142964 */
15151b94a41bSChris Horne if (tpend) {
15161b94a41bSChris Horne DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
15171b94a41bSChris Horne mapp->dam_name, dam_t *, mapp);
151860aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp,
151960aabb4cSChris Horne (clock_t)next_ticks);
15201b94a41bSChris Horne }
15211b115575SJohn Danielson
15221b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15234c06356bSdh142964 }
15244c06356bSdh142964
15254c06356bSdh142964 /*
15261b115575SJohn Danielson * fullset stabilization timeout callback
15274c06356bSdh142964 */
15284c06356bSdh142964 static void
dam_addrset_stable_cb(void * arg)15291b115575SJohn Danielson dam_addrset_stable_cb(void *arg)
15304c06356bSdh142964 {
15314c06356bSdh142964 dam_t *mapp = (dam_t *)arg;
15324c06356bSdh142964
15331b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
15344c06356bSdh142964 if (mapp->dam_tid == 0) {
15351b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15361b115575SJohn Danielson DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
15371b115575SJohn Danielson char *, mapp->dam_name, dam_t *, mapp);
15384c06356bSdh142964 return;
15394c06356bSdh142964 }
15404c06356bSdh142964 mapp->dam_tid = 0;
15414c06356bSdh142964
15424c06356bSdh142964 /*
15431b115575SJohn Danielson * If map still underoing stabilization reschedule timeout,
15441b115575SJohn Danielson * else dispatch the task to configure the new stable set of
15451b115575SJohn Danielson * addresses.
15464c06356bSdh142964 */
154764109744SChris Horne if ((mapp->dam_flags & DAM_SPEND) ||
154864109744SChris Horne (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
154964109744SChris Horne TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
15501b115575SJohn Danielson DAM_INCR_STAT(mapp, dam_overrun);
15514c06356bSdh142964 mapp->dam_stable_overrun++;
155260aabb4cSChris Horne dam_sched_timeout(dam_addrset_stable_cb, mapp,
155360aabb4cSChris Horne drv_usectohz(damap_taskq_dispatch_retry_usec));
155464109744SChris Horne
15551b94a41bSChris Horne DTRACE_PROBE2(damap__map__addrset__stable__overrun,
15561b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
15571b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15581b115575SJohn Danielson return;
15591b115575SJohn Danielson }
15601b115575SJohn Danielson
15611b115575SJohn Danielson DAM_SET_STAT(mapp, dam_overrun, 0);
15621b115575SJohn Danielson mapp->dam_stable_overrun = 0;
15634c06356bSdh142964 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
15644c06356bSdh142964 bitset_zero(&mapp->dam_report_set);
15651b115575SJohn Danielson mapp->dam_flags |= DAM_SPEND;
15661b115575SJohn Danielson mapp->dam_flags &= ~DAM_SETADD;
156760aabb4cSChris Horne /* NOTE: don't need cv_signal since DAM_SPEND is still set */
156860aabb4cSChris Horne
15691b94a41bSChris Horne DTRACE_PROBE2(damap__map__addrset__stable__start,
15701b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp);
15711b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15724c06356bSdh142964 }
15734c06356bSdh142964
15744c06356bSdh142964 /*
157560aabb4cSChris Horne * schedule map timeout in 'ticks' ticks
157660aabb4cSChris Horne * if map timer is currently running, cancel if ticks == 0
15774c06356bSdh142964 */
15784c06356bSdh142964 static void
dam_sched_timeout(void (* timeout_cb)(),dam_t * mapp,clock_t ticks)157960aabb4cSChris Horne dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
15804c06356bSdh142964 {
15814c06356bSdh142964 timeout_id_t tid;
15824c06356bSdh142964
15831b94a41bSChris Horne DTRACE_PROBE4(damap__sched__timeout,
15841b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
15851b94a41bSChris Horne int, ticks, timeout_id_t, mapp->dam_tid);
15864c06356bSdh142964
15871b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
15881b115575SJohn Danielson if ((tid = mapp->dam_tid) != 0) {
158960aabb4cSChris Horne if (ticks == 0) {
15901b115575SJohn Danielson mapp->dam_tid = 0;
15911b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
15921b115575SJohn Danielson (void) untimeout(tid);
15931b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
15941b115575SJohn Danielson }
15951b115575SJohn Danielson } else {
159660aabb4cSChris Horne if (timeout_cb && (ticks != 0))
159760aabb4cSChris Horne mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
15984c06356bSdh142964 }
15991b115575SJohn Danielson }
16004c06356bSdh142964
16014c06356bSdh142964 /*
16021b115575SJohn Danielson * report addition or removal of an address
16034c06356bSdh142964 */
16044c06356bSdh142964 static void
dam_addr_report(dam_t * mapp,dam_da_t * passp,id_t addrid,int rpt_type)16051b115575SJohn Danielson dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
16064c06356bSdh142964 {
16071b115575SJohn Danielson char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
16081b115575SJohn Danielson
16091b94a41bSChris Horne DTRACE_PROBE4(damap__addr__report,
16101b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
16111b94a41bSChris Horne char *, addrstr, int, rpt_type);
16121b115575SJohn Danielson
16131b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16144c06356bSdh142964 ASSERT(!DAM_IN_REPORT(mapp, addrid));
16154c06356bSdh142964 passp->da_last_report = gethrtime();
16164c06356bSdh142964 mapp->dam_last_update = gethrtime();
16174c06356bSdh142964 passp->da_report_cnt++;
161860aabb4cSChris Horne passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
16191b115575SJohn Danielson if (rpt_type == RPT_ADDR_DEL)
16204c06356bSdh142964 passp->da_flags |= DA_RELE;
16211b115575SJohn Danielson else if (rpt_type == RPT_ADDR_ADD)
16224c06356bSdh142964 passp->da_flags &= ~DA_RELE;
16234c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid);
162460aabb4cSChris Horne dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
16254c06356bSdh142964 }
16264c06356bSdh142964
16274c06356bSdh142964 /*
16284c06356bSdh142964 * release an address report
16294c06356bSdh142964 */
16304c06356bSdh142964 static void
dam_addr_report_release(dam_t * mapp,id_t addrid)16311b115575SJohn Danielson dam_addr_report_release(dam_t *mapp, id_t addrid)
16324c06356bSdh142964 {
16334c06356bSdh142964 dam_da_t *passp;
16341b115575SJohn Danielson char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
16354c06356bSdh142964
16361b94a41bSChris Horne DTRACE_PROBE3(damap__addr__report__release,
16371b94a41bSChris Horne char *, mapp->dam_name, dam_t *, mapp,
16381b94a41bSChris Horne char *, addrstr);
16391b115575SJohn Danielson
16401b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16414c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
16424c06356bSdh142964 ASSERT(passp);
16431b115575SJohn Danielson /*
16441b115575SJohn Danielson * clear the report bit
16451b115575SJohn Danielson * if the address has a registered deactivation handler and
16469aed1621SDavid Hollister * we are holding a private data pointer and the address has not
16479aed1621SDavid Hollister * stabilized, deactivate the address (private data).
16481b115575SJohn Danielson */
16491b115575SJohn Danielson bitset_del(&mapp->dam_report_set, addrid);
16509aed1621SDavid Hollister if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
16519aed1621SDavid Hollister passp->da_ppriv_rpt) {
16521b115575SJohn Danielson mutex_exit(&mapp->dam_lock);
16531b115575SJohn Danielson (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
16541b115575SJohn Danielson ddi_strid_id2str(mapp->dam_addr_hash, addrid),
16559aed1621SDavid Hollister addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
16561b115575SJohn Danielson mutex_enter(&mapp->dam_lock);
16571b115575SJohn Danielson }
16584c06356bSdh142964 passp->da_ppriv_rpt = NULL;
16594c06356bSdh142964 nvlist_free(passp->da_nvl_rpt);
16604c06356bSdh142964 }
16614c06356bSdh142964
16624c06356bSdh142964 /*
16634c06356bSdh142964 * return the map ID of an address
16644c06356bSdh142964 */
16654c06356bSdh142964 static id_t
dam_get_addrid(dam_t * mapp,char * address)16664c06356bSdh142964 dam_get_addrid(dam_t *mapp, char *address)
16674c06356bSdh142964 {
16684c06356bSdh142964 damap_id_t addrid;
16694c06356bSdh142964 dam_da_t *passp;
16704c06356bSdh142964
16711b115575SJohn Danielson ASSERT(mutex_owned(&mapp->dam_lock));
16724c06356bSdh142964 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
16731b115575SJohn Danielson if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
16744c06356bSdh142964 address)) == (damap_id_t)0) {
16754c06356bSdh142964 return (0);
16764c06356bSdh142964 }
16774c06356bSdh142964 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
16784c06356bSdh142964 DDI_SUCCESS) {
16794c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid);
16804c06356bSdh142964 return (0);
16814c06356bSdh142964 }
16821b115575SJohn Danielson
16834c06356bSdh142964 if (addrid >= mapp->dam_high)
16844c06356bSdh142964 mapp->dam_high = addrid + 1;
16851b115575SJohn Danielson
16861b115575SJohn Danielson /*
16871b115575SJohn Danielson * expand bitmaps if ID has outgrown old map size
16881b115575SJohn Danielson */
16891b115575SJohn Danielson if (mapp->dam_high > mapp->dam_size) {
16901b115575SJohn Danielson mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
16911b115575SJohn Danielson bitset_resize(&mapp->dam_active_set, mapp->dam_size);
16921b115575SJohn Danielson bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
16931b115575SJohn Danielson bitset_resize(&mapp->dam_report_set, mapp->dam_size);
16944c06356bSdh142964 }
16951b115575SJohn Danielson
16964c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid);
16971b115575SJohn Danielson passp->da_ref = 1;
16981b115575SJohn Danielson passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
16991b115575SJohn Danielson addrid); /* for mdb */
17001b115575SJohn Danielson }
17014c06356bSdh142964 return (addrid);
17024c06356bSdh142964 }
17034c06356bSdh142964
17044c06356bSdh142964 /*
17054c06356bSdh142964 * create and install map statistics
17064c06356bSdh142964 */
17074c06356bSdh142964 static int
dam_kstat_create(dam_t * mapp)17084c06356bSdh142964 dam_kstat_create(dam_t *mapp)
17094c06356bSdh142964 {
17104c06356bSdh142964 kstat_t *mapsp;
17114c06356bSdh142964 struct dam_kstats *statsp;
17124c06356bSdh142964
17134c06356bSdh142964 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
17144c06356bSdh142964 KSTAT_TYPE_NAMED,
17154c06356bSdh142964 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
17161b115575SJohn Danielson
17171b115575SJohn Danielson if (mapsp == NULL)
17184c06356bSdh142964 return (DDI_FAILURE);
17194c06356bSdh142964
17204c06356bSdh142964 statsp = (struct dam_kstats *)mapsp->ks_data;
17211b115575SJohn Danielson kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
17221b115575SJohn Danielson kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
17231b115575SJohn Danielson kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
17241b115575SJohn Danielson kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
17254c06356bSdh142964 kstat_install(mapsp);
17264c06356bSdh142964 mapp->dam_kstatsp = mapsp;
17274c06356bSdh142964 return (DDI_SUCCESS);
17284c06356bSdh142964 }
1729