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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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