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 /* 234c06356bSdh142964 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 244c06356bSdh142964 * Use is subject to license terms. 254c06356bSdh142964 */ 264c06356bSdh142964 274c06356bSdh142964 #include <sys/note.h> 284c06356bSdh142964 #include <sys/types.h> 294c06356bSdh142964 #include <sys/param.h> 304c06356bSdh142964 #include <sys/systm.h> 314c06356bSdh142964 #include <sys/buf.h> 324c06356bSdh142964 #include <sys/kmem.h> 334c06356bSdh142964 #include <sys/cmn_err.h> 344c06356bSdh142964 #include <sys/debug.h> 354c06356bSdh142964 #include <sys/sunndi.h> 364c06356bSdh142964 #include <sys/kstat.h> 374c06356bSdh142964 #include <sys/conf.h> 384c06356bSdh142964 #include <sys/ddi_timer.h> 394c06356bSdh142964 #include <sys/devctl.h> 404c06356bSdh142964 #include <sys/callb.h> 414c06356bSdh142964 #include <sys/sysevent.h> 424c06356bSdh142964 #include <sys/taskq.h> 434c06356bSdh142964 #include <sys/ddi.h> 444c06356bSdh142964 #include <sys/bitset.h> 454c06356bSdh142964 #include <sys/damap.h> 464c06356bSdh142964 #include <sys/damap_impl.h> 474c06356bSdh142964 484c06356bSdh142964 #ifdef DEBUG 494c06356bSdh142964 static int damap_debug = 0; 504c06356bSdh142964 #endif /* DEBUG */ 514c06356bSdh142964 524c06356bSdh142964 static void dam_addrset_activate(dam_t *, bitset_t *); 534c06356bSdh142964 static void dam_addrset_release(dam_t *, bitset_t *); 544c06356bSdh142964 static void dam_activate_taskq(void *); 554c06356bSdh142964 static void dam_addr_stable_cb(void *); 564c06356bSdh142964 static void dam_set_stable_cb(void *); 574c06356bSdh142964 static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)()); 584c06356bSdh142964 static void dam_add_report(dam_t *, dam_da_t *, id_t, int); 594c06356bSdh142964 static void dam_release(dam_t *, id_t); 604c06356bSdh142964 static void dam_release_report(dam_t *, id_t); 614c06356bSdh142964 static void dam_deactivate_addr(dam_t *, id_t); 624c06356bSdh142964 static id_t dam_get_addrid(dam_t *, char *); 634c06356bSdh142964 static int dam_kstat_create(dam_t *); 644c06356bSdh142964 static void dam_kstat_destroy(dam_t *); 654c06356bSdh142964 664c06356bSdh142964 #define DAM_INCR_STAT(mapp, stat) \ 674c06356bSdh142964 if ((mapp)->dam_kstatsp) { \ 684c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 694c06356bSdh142964 stp->stat.value.ui32++; \ 704c06356bSdh142964 } 714c06356bSdh142964 724c06356bSdh142964 #define DAM_SET_STAT(mapp, stat, val) \ 734c06356bSdh142964 if ((mapp)->dam_kstatsp) { \ 744c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 754c06356bSdh142964 stp->stat.value.ui32 = (val); \ 764c06356bSdh142964 } 774c06356bSdh142964 784c06356bSdh142964 /* 794c06356bSdh142964 * Create new device address map 804c06356bSdh142964 * 814c06356bSdh142964 * ident: map name (kstat) 824c06356bSdh142964 * size: max # of map entries 834c06356bSdh142964 * rptmode: type or mode of reporting 844c06356bSdh142964 * stable_usec: # of quiescent microseconds before report/map is stable 854c06356bSdh142964 * 864c06356bSdh142964 * activate_arg: address provider activation-callout private 874c06356bSdh142964 * activate_cb: address provider activation callback handler 884c06356bSdh142964 * deactivate_cb: address provider deactivation callback handler 894c06356bSdh142964 * 904c06356bSdh142964 * config_arg: configuration-callout private 914c06356bSdh142964 * config_cb: class configuration callout 924c06356bSdh142964 * unconfig_cb: class unconfiguration callout 934c06356bSdh142964 * 944c06356bSdh142964 * damapp: pointer to map handle (return) 954c06356bSdh142964 * 964c06356bSdh142964 * Returns: DAM_SUCCESS 974c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 984c06356bSdh142964 * DAM_FAILURE General failure 994c06356bSdh142964 */ 1004c06356bSdh142964 int 1014c06356bSdh142964 damap_create(char *ident, size_t size, damap_rptmode_t rptmode, 1024c06356bSdh142964 clock_t stable_usec, 1034c06356bSdh142964 void *activate_arg, damap_activate_cb_t activate_cb, 1044c06356bSdh142964 damap_deactivate_cb_t deactivate_cb, 1054c06356bSdh142964 void *config_arg, damap_configure_cb_t configure_cb, 1064c06356bSdh142964 damap_unconfig_cb_t unconfig_cb, 1074c06356bSdh142964 damap_t **damapp) 1084c06356bSdh142964 { 1094c06356bSdh142964 dam_t *mapp; 1104c06356bSdh142964 void *softstate_p; 1114c06356bSdh142964 1124c06356bSdh142964 DTRACE_PROBE1(damap__create__entry, char *, ident); 1134c06356bSdh142964 if ((configure_cb == NULL) || (unconfig_cb == NULL)) 1144c06356bSdh142964 return (DAM_EINVAL); 1154c06356bSdh142964 1164c06356bSdh142964 if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) != 1174c06356bSdh142964 DDI_SUCCESS) 1184c06356bSdh142964 return (DAM_FAILURE); 1194c06356bSdh142964 1204c06356bSdh142964 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); 1214c06356bSdh142964 if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) { 1224c06356bSdh142964 ddi_soft_state_fini(&softstate_p); 1234c06356bSdh142964 kmem_free(mapp, sizeof (*mapp)); 1244c06356bSdh142964 return (DAM_FAILURE); 1254c06356bSdh142964 } 1264c06356bSdh142964 1274c06356bSdh142964 mapp->dam_da = softstate_p; 1284c06356bSdh142964 mapp->dam_stabletmo = drv_usectohz(stable_usec); 1294c06356bSdh142964 mapp->dam_size = size; 1304c06356bSdh142964 mapp->dam_high = 1; 1314c06356bSdh142964 mapp->dam_rptmode = rptmode; 1324c06356bSdh142964 1334c06356bSdh142964 mapp->dam_activate_arg = activate_arg; 1344c06356bSdh142964 mapp->dam_activate_cb = (activate_cb_t)activate_cb; 1354c06356bSdh142964 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; 1364c06356bSdh142964 1374c06356bSdh142964 mapp->dam_config_arg = config_arg; 1384c06356bSdh142964 mapp->dam_configure_cb = (configure_cb_t)configure_cb; 1394c06356bSdh142964 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; 1404c06356bSdh142964 1414c06356bSdh142964 if (ident) 1424c06356bSdh142964 mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP); 1434c06356bSdh142964 1444c06356bSdh142964 bitset_init(&mapp->dam_active_set); 1454c06356bSdh142964 bitset_resize(&mapp->dam_active_set, size); 1464c06356bSdh142964 bitset_init(&mapp->dam_stable_set); 1474c06356bSdh142964 bitset_resize(&mapp->dam_stable_set, size); 1484c06356bSdh142964 bitset_init(&mapp->dam_report_set); 1494c06356bSdh142964 bitset_resize(&mapp->dam_report_set, size); 1504c06356bSdh142964 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); 1514c06356bSdh142964 cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL); 1524c06356bSdh142964 mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI, 1534c06356bSdh142964 0); 1544c06356bSdh142964 *damapp = (damap_t *)mapp; 1554c06356bSdh142964 if (dam_kstat_create(mapp) != DDI_SUCCESS) { 1564c06356bSdh142964 damap_destroy((damap_t *)mapp); 1574c06356bSdh142964 return (DAM_FAILURE); 1584c06356bSdh142964 } 1594c06356bSdh142964 1604c06356bSdh142964 DTRACE_PROBE1(damap__create__exit, dam_t *, mapp); 1614c06356bSdh142964 return (DAM_SUCCESS); 1624c06356bSdh142964 } 1634c06356bSdh142964 1644c06356bSdh142964 /* 1654c06356bSdh142964 * Destroy device address map 1664c06356bSdh142964 * 1674c06356bSdh142964 * damapp: address map 1684c06356bSdh142964 * 1694c06356bSdh142964 * Returns: DAM_SUCCESS 1704c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 1714c06356bSdh142964 * DAM_FAILURE General failure 1724c06356bSdh142964 */ 1734c06356bSdh142964 void 1744c06356bSdh142964 damap_destroy(damap_t *damapp) 1754c06356bSdh142964 { 1764c06356bSdh142964 int i; 1774c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 1784c06356bSdh142964 1794c06356bSdh142964 ASSERT(mapp); 1804c06356bSdh142964 1814c06356bSdh142964 DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *, 1824c06356bSdh142964 mapp->dam_name); 1834c06356bSdh142964 1844c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_DESTROYPEND); 1854c06356bSdh142964 (void) damap_sync(damapp); 1864c06356bSdh142964 1874c06356bSdh142964 /* 1884c06356bSdh142964 * cancel pending timeouts and kill off the taskq 1894c06356bSdh142964 */ 1904c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 1914c06356bSdh142964 ddi_taskq_wait(mapp->dam_taskqp); 1924c06356bSdh142964 ddi_taskq_destroy(mapp->dam_taskqp); 1934c06356bSdh142964 1944c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 1954c06356bSdh142964 if (ddi_get_soft_state(mapp->dam_da, i) == NULL) 1964c06356bSdh142964 continue; 1974c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 1984c06356bSdh142964 dam_release_report(mapp, i); 1994c06356bSdh142964 if (DAM_IS_STABLE(mapp, i)) 2004c06356bSdh142964 dam_deactivate_addr(mapp, i); 2014c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, i); 2024c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, i); 2034c06356bSdh142964 } 2044c06356bSdh142964 ddi_strid_fini(&mapp->dam_addr_hash); 2054c06356bSdh142964 ddi_soft_state_fini(&mapp->dam_da); 2064c06356bSdh142964 bitset_fini(&mapp->dam_active_set); 2074c06356bSdh142964 bitset_fini(&mapp->dam_stable_set); 2084c06356bSdh142964 bitset_fini(&mapp->dam_report_set); 2094c06356bSdh142964 dam_kstat_destroy(mapp); 2104c06356bSdh142964 mutex_destroy(&mapp->dam_lock); 2114c06356bSdh142964 cv_destroy(&mapp->dam_cv); 2124c06356bSdh142964 if (mapp->dam_name) 2134c06356bSdh142964 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); 2144c06356bSdh142964 kmem_free(mapp, sizeof (*mapp)); 2154c06356bSdh142964 DTRACE_PROBE(damap__destroy__exit); 2164c06356bSdh142964 } 2174c06356bSdh142964 2184c06356bSdh142964 /* 2194c06356bSdh142964 * Wait for map stability. 2204c06356bSdh142964 * 2214c06356bSdh142964 * damapp: address map 2224c06356bSdh142964 */ 2234c06356bSdh142964 int 2244c06356bSdh142964 damap_sync(damap_t *damapp) 2254c06356bSdh142964 { 2264c06356bSdh142964 2274c06356bSdh142964 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK) 2284c06356bSdh142964 2294c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 2304c06356bSdh142964 int none_active; 2314c06356bSdh142964 2324c06356bSdh142964 ASSERT(mapp); 2334c06356bSdh142964 2344c06356bSdh142964 DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp); 2354c06356bSdh142964 2364c06356bSdh142964 mutex_enter(&mapp->dam_lock); 2374c06356bSdh142964 while ((mapp->dam_flags & WAITFOR_FLAGS) || 2384c06356bSdh142964 (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) { 2394c06356bSdh142964 cv_wait(&mapp->dam_cv, &mapp->dam_lock); 2404c06356bSdh142964 } 2414c06356bSdh142964 2424c06356bSdh142964 none_active = bitset_is_null(&mapp->dam_active_set); 2434c06356bSdh142964 2444c06356bSdh142964 mutex_exit(&mapp->dam_lock); 2454c06356bSdh142964 DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active); 2464c06356bSdh142964 2474c06356bSdh142964 return (none_active); 2484c06356bSdh142964 } 2494c06356bSdh142964 2504c06356bSdh142964 /* 2514c06356bSdh142964 * Get the name of a device address map 2524c06356bSdh142964 * 2534c06356bSdh142964 * damapp: address map 2544c06356bSdh142964 * 2554c06356bSdh142964 * Returns: name 2564c06356bSdh142964 */ 2574c06356bSdh142964 char * 2584c06356bSdh142964 damap_name(damap_t *damapp) 2594c06356bSdh142964 { 2604c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 2614c06356bSdh142964 2624c06356bSdh142964 return (mapp ? mapp->dam_name : "UNKNOWN_damap"); 2634c06356bSdh142964 } 2644c06356bSdh142964 2654c06356bSdh142964 /* 2664c06356bSdh142964 * Report an address to per-address report 2674c06356bSdh142964 * 2684c06356bSdh142964 * damapp: address map handle 2694c06356bSdh142964 * address: address in ascii string representation 2704c06356bSdh142964 * rindx: index if address stabilizes 2714c06356bSdh142964 * nvl: optional nvlist of configuration-private data 2724c06356bSdh142964 * addr_priv: optional provider-private (passed to activate/deactivate cb) 2734c06356bSdh142964 * 2744c06356bSdh142964 * Returns: DAM_SUCCESS 2754c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 2764c06356bSdh142964 * DAM_MAPFULL address map exhausted 2774c06356bSdh142964 */ 2784c06356bSdh142964 int 2794c06356bSdh142964 damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl, 2804c06356bSdh142964 void *addr_priv) 2814c06356bSdh142964 { 2824c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 2834c06356bSdh142964 id_t addrid; 2844c06356bSdh142964 dam_da_t *passp; 2854c06356bSdh142964 2864c06356bSdh142964 DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp, 2874c06356bSdh142964 char *, address); 2884c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 2894c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 2904c06356bSdh142964 return (DAM_EINVAL); 2914c06356bSdh142964 2924c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 2934c06356bSdh142964 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 2944c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 2954c06356bSdh142964 return (DAM_MAPFULL); 2964c06356bSdh142964 } 2974c06356bSdh142964 2984c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 2994c06356bSdh142964 ASSERT(passp != NULL); 3004c06356bSdh142964 3014c06356bSdh142964 /* 3024c06356bSdh142964 * If re-reporting the same address (add or remove) clear 3034c06356bSdh142964 * the existing report 3044c06356bSdh142964 */ 3054c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 3064c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 3074c06356bSdh142964 dam_release_report(mapp, addrid); 3084c06356bSdh142964 passp->da_jitter++; 3094c06356bSdh142964 } 3104c06356bSdh142964 passp->da_ppriv_rpt = addr_priv; 3114c06356bSdh142964 if (nvl) 3124c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 3134c06356bSdh142964 3144c06356bSdh142964 dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD); 3154c06356bSdh142964 if (ridx != NULL) 3164c06356bSdh142964 *ridx = (damap_id_t)addrid; 3174c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 3184c06356bSdh142964 DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *, 3194c06356bSdh142964 address, int, addrid); 3204c06356bSdh142964 return (DAM_SUCCESS); 3214c06356bSdh142964 } 3224c06356bSdh142964 3234c06356bSdh142964 /* 3244c06356bSdh142964 * Report removal of address from per-address report 3254c06356bSdh142964 * 3264c06356bSdh142964 * damapp: address map 3274c06356bSdh142964 * address: address in ascii string representation 3284c06356bSdh142964 * 3294c06356bSdh142964 * Returns: DAM_SUCCESS 3304c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 3314c06356bSdh142964 * DAM_FAILURE General failure 3324c06356bSdh142964 */ 3334c06356bSdh142964 int 3344c06356bSdh142964 damap_addr_del(damap_t *damapp, char *address) 3354c06356bSdh142964 { 3364c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 3374c06356bSdh142964 id_t addrid; 3384c06356bSdh142964 dam_da_t *passp; 3394c06356bSdh142964 3404c06356bSdh142964 DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp, 3414c06356bSdh142964 char *, address); 3424c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 3434c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 3444c06356bSdh142964 return (DAM_EINVAL); 3454c06356bSdh142964 3464c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 3474c06356bSdh142964 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { 3484c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 3494c06356bSdh142964 return (DAM_SUCCESS); 3504c06356bSdh142964 } 3514c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 3524c06356bSdh142964 ASSERT(passp); 3534c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 3544c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 3554c06356bSdh142964 dam_release_report(mapp, addrid); 3564c06356bSdh142964 passp->da_jitter++; 3574c06356bSdh142964 } 3584c06356bSdh142964 dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL); 3594c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 3604c06356bSdh142964 DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp, 3614c06356bSdh142964 char *, address, int, addrid); 3624c06356bSdh142964 return (DAM_SUCCESS); 3634c06356bSdh142964 } 3644c06356bSdh142964 3654c06356bSdh142964 /* 3664c06356bSdh142964 * Initiate full-set report 3674c06356bSdh142964 * 3684c06356bSdh142964 * damapp: address map 3694c06356bSdh142964 * 3704c06356bSdh142964 * Returns: DAM_SUCCESS 3714c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 3724c06356bSdh142964 */ 3734c06356bSdh142964 int 3744c06356bSdh142964 damap_addrset_begin(damap_t *damapp) 3754c06356bSdh142964 { 3764c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 3774c06356bSdh142964 int i; 3784c06356bSdh142964 3794c06356bSdh142964 DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp); 3804c06356bSdh142964 3814c06356bSdh142964 if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 3824c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 3834c06356bSdh142964 return (DAM_EINVAL); 3844c06356bSdh142964 3854c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 3864c06356bSdh142964 /* 3874c06356bSdh142964 * reset any pending reports 3884c06356bSdh142964 */ 3894c06356bSdh142964 if (mapp->dam_flags & DAM_SETADD) { 3904c06356bSdh142964 /* 3914c06356bSdh142964 * cancel stabilization timeout 3924c06356bSdh142964 */ 3934c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 3944c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 3954c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 3964c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 3974c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 3984c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 3994c06356bSdh142964 dam_release_report(mapp, i); 4004c06356bSdh142964 } 4014c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 4024c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 4034c06356bSdh142964 } 4044c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SETADD); 4054c06356bSdh142964 bitset_zero(&mapp->dam_report_set); 4064c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 4074c06356bSdh142964 DTRACE_PROBE(damap__addrset__begin__exit); 4084c06356bSdh142964 return (DAM_SUCCESS); 4094c06356bSdh142964 } 4104c06356bSdh142964 4114c06356bSdh142964 /* 4124c06356bSdh142964 * Report address to full-set report 4134c06356bSdh142964 * 4144c06356bSdh142964 * damapp: address map handle 4154c06356bSdh142964 * address: address in ascii string representation 4164c06356bSdh142964 * rindx: index if address stabilizes 4174c06356bSdh142964 * nvl: optional nvlist of configuration-private data 4184c06356bSdh142964 * addr_priv: optional provider-private data (passed to activate/release cb) 4194c06356bSdh142964 * 4204c06356bSdh142964 * Returns: DAM_SUCCESS 4214c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 4224c06356bSdh142964 * DAM_MAPFULL address map exhausted 4234c06356bSdh142964 * DAM_FAILURE General failure 4244c06356bSdh142964 */ 4254c06356bSdh142964 int 4264c06356bSdh142964 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx, 4274c06356bSdh142964 nvlist_t *nvl, void *addr_priv) 4284c06356bSdh142964 { 4294c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 4304c06356bSdh142964 id_t addrid; 4314c06356bSdh142964 dam_da_t *passp; 4324c06356bSdh142964 4334c06356bSdh142964 DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp, 4344c06356bSdh142964 char *, address); 4354c06356bSdh142964 4364c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 4374c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 4384c06356bSdh142964 return (DAM_EINVAL); 4394c06356bSdh142964 4404c06356bSdh142964 if (!(mapp->dam_flags & DAM_SETADD)) 4414c06356bSdh142964 return (DAM_FAILURE); 4424c06356bSdh142964 4434c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 4444c06356bSdh142964 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 4454c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 4464c06356bSdh142964 return (DAM_MAPFULL); 4474c06356bSdh142964 } 4484c06356bSdh142964 4494c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 4504c06356bSdh142964 ASSERT(passp); 4514c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 4524c06356bSdh142964 dam_release_report(mapp, addrid); 4534c06356bSdh142964 passp->da_jitter++; 4544c06356bSdh142964 } 4554c06356bSdh142964 passp->da_ppriv_rpt = addr_priv; 4564c06356bSdh142964 if (nvl) 4574c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 4584c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 4594c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid); 4604c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 4614c06356bSdh142964 if (ridx) 4624c06356bSdh142964 *ridx = (damap_id_t)addrid; 4634c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 4644c06356bSdh142964 DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *, 4654c06356bSdh142964 address, int, addrid); 4664c06356bSdh142964 return (DAM_SUCCESS); 4674c06356bSdh142964 } 4684c06356bSdh142964 4694c06356bSdh142964 /* 4704c06356bSdh142964 * Commit full-set report for stabilization 4714c06356bSdh142964 * 4724c06356bSdh142964 * damapp: address map handle 4734c06356bSdh142964 * flags: (currently 0) 4744c06356bSdh142964 * 4754c06356bSdh142964 * Returns: DAM_SUCCESS 4764c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 4774c06356bSdh142964 * DAM_FAILURE General failure 4784c06356bSdh142964 */ 4794c06356bSdh142964 int 4804c06356bSdh142964 damap_addrset_end(damap_t *damapp, int flags) 4814c06356bSdh142964 { 4824c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 4834c06356bSdh142964 int i; 4844c06356bSdh142964 4854c06356bSdh142964 DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp); 4864c06356bSdh142964 4874c06356bSdh142964 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 4884c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 4894c06356bSdh142964 return (DAM_EINVAL); 4904c06356bSdh142964 4914c06356bSdh142964 if (!(mapp->dam_flags & DAM_SETADD)) 4924c06356bSdh142964 return (DAM_FAILURE); 4934c06356bSdh142964 4944c06356bSdh142964 if (flags & DAMAP_RESET) { 4954c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 4964c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 4974c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 4984c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 4994c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) 5004c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 5014c06356bSdh142964 dam_release_report(mapp, i); 5024c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 5034c06356bSdh142964 } else { 5044c06356bSdh142964 mapp->dam_last_update = gethrtime(); 5054c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 5064c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 5074c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 5084c06356bSdh142964 } 5094c06356bSdh142964 DTRACE_PROBE(damap__addrset__end__exit); 5104c06356bSdh142964 return (DAM_SUCCESS); 5114c06356bSdh142964 } 5124c06356bSdh142964 5134c06356bSdh142964 /* 5144c06356bSdh142964 * Return nvlist registered with reported address 5154c06356bSdh142964 * 5164c06356bSdh142964 * damapp: address map handle 5174c06356bSdh142964 * aid: address ID 5184c06356bSdh142964 * 5194c06356bSdh142964 * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) 5204c06356bSdh142964 * NULL 5214c06356bSdh142964 */ 5224c06356bSdh142964 nvlist_t * 5234c06356bSdh142964 damap_id2nvlist(damap_t *damapp, damap_id_t addrid) 5244c06356bSdh142964 { 5254c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 5264c06356bSdh142964 id_t aid = (id_t)addrid; 5274c06356bSdh142964 dam_da_t *pass; 5284c06356bSdh142964 5294c06356bSdh142964 if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) { 5304c06356bSdh142964 if (pass = ddi_get_soft_state(mapp->dam_da, aid)) 5314c06356bSdh142964 return (pass->da_nvl); 5324c06356bSdh142964 } 5334c06356bSdh142964 return (NULL); 5344c06356bSdh142964 } 5354c06356bSdh142964 5364c06356bSdh142964 /* 5374c06356bSdh142964 * Return address string 5384c06356bSdh142964 * 5394c06356bSdh142964 * damapp: address map handle 5404c06356bSdh142964 * aid: address ID 5414c06356bSdh142964 * 5424c06356bSdh142964 * Returns: char * Address string 5434c06356bSdh142964 * NULL 5444c06356bSdh142964 */ 5454c06356bSdh142964 char * 5464c06356bSdh142964 damap_id2addr(damap_t *damapp, damap_id_t aid) 5474c06356bSdh142964 { 5484c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 5494c06356bSdh142964 5504c06356bSdh142964 return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid)); 5514c06356bSdh142964 } 5524c06356bSdh142964 5534c06356bSdh142964 /* 5544c06356bSdh142964 * Hold address reference in map 5554c06356bSdh142964 * 5564c06356bSdh142964 * damapp: address map handle 5574c06356bSdh142964 * aid: address ID 5584c06356bSdh142964 * 5594c06356bSdh142964 * Returns: DAM_SUCCESS 5604c06356bSdh142964 * DAM_FAILURE 5614c06356bSdh142964 */ 5624c06356bSdh142964 int 5634c06356bSdh142964 damap_id_hold(damap_t *damapp, damap_id_t aid) 5644c06356bSdh142964 { 5654c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 5664c06356bSdh142964 dam_da_t *passp; 5674c06356bSdh142964 5684c06356bSdh142964 5694c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 5704c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 5714c06356bSdh142964 if (!passp) { 5724c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 5734c06356bSdh142964 return (DAM_FAILURE); 5744c06356bSdh142964 } 5754c06356bSdh142964 passp->da_ref++; 5764c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 5774c06356bSdh142964 return (DAM_SUCCESS); 5784c06356bSdh142964 } 5794c06356bSdh142964 5804c06356bSdh142964 /* 5814c06356bSdh142964 * Release address reference in map 5824c06356bSdh142964 * 5834c06356bSdh142964 * damapp: address map handle 5844c06356bSdh142964 * aid: address ID 5854c06356bSdh142964 */ 5864c06356bSdh142964 void 5874c06356bSdh142964 damap_id_rele(damap_t *damapp, damap_id_t addrid) 5884c06356bSdh142964 { 5894c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 5904c06356bSdh142964 5914c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 5924c06356bSdh142964 dam_release(mapp, (id_t)addrid); 5934c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 5944c06356bSdh142964 } 5954c06356bSdh142964 5964c06356bSdh142964 /* 5974c06356bSdh142964 * Return current reference count on address reference in map 5984c06356bSdh142964 * 5994c06356bSdh142964 * damapp: address map handle 6004c06356bSdh142964 * aid: address ID 6014c06356bSdh142964 * 6024c06356bSdh142964 * Returns: DAM_SUCCESS 6034c06356bSdh142964 * DAM_FAILURE 6044c06356bSdh142964 */ 6054c06356bSdh142964 int 6064c06356bSdh142964 damap_id_ref(damap_t *damapp, damap_id_t aid) 6074c06356bSdh142964 { 6084c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 6094c06356bSdh142964 dam_da_t *passp; 6104c06356bSdh142964 int ref = -1; 6114c06356bSdh142964 6124c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 6134c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 6144c06356bSdh142964 if (passp) 6154c06356bSdh142964 ref = passp->da_ref; 6164c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 6174c06356bSdh142964 return (ref); 6184c06356bSdh142964 } 6194c06356bSdh142964 6204c06356bSdh142964 /* 6214c06356bSdh142964 * Return next address ID in list 6224c06356bSdh142964 * 6234c06356bSdh142964 * damapp: address map handle 6244c06356bSdh142964 * damap_list: address ID list passed to config|unconfig 6254c06356bSdh142964 * returned by look by lookup_all 6264c06356bSdh142964 * last: last ID returned, 0 is start of list 6274c06356bSdh142964 * 6284c06356bSdh142964 * Returns: addrid Next ID from the list 6294c06356bSdh142964 * 0 End of the list 6304c06356bSdh142964 */ 6314c06356bSdh142964 damap_id_t 6324c06356bSdh142964 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last) 6334c06356bSdh142964 { 6344c06356bSdh142964 int i, start; 6354c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 6364c06356bSdh142964 bitset_t *dam_list = (bitset_t *)damap_list; 6374c06356bSdh142964 6384c06356bSdh142964 if (!mapp || !dam_list) 6394c06356bSdh142964 return ((damap_id_t)0); 6404c06356bSdh142964 6414c06356bSdh142964 start = (int)last + 1; 6424c06356bSdh142964 for (i = start; i < mapp->dam_high; i++) 6434c06356bSdh142964 if (bitset_in_set(dam_list, i)) 6444c06356bSdh142964 return ((damap_id_t)i); 6454c06356bSdh142964 return ((damap_id_t)0); 6464c06356bSdh142964 } 6474c06356bSdh142964 6484c06356bSdh142964 /* 6494c06356bSdh142964 * Set config private data 6504c06356bSdh142964 * 6514c06356bSdh142964 * damapp: address map handle 6524c06356bSdh142964 * aid: address ID 6534c06356bSdh142964 * cfg_priv: configuration private data 6544c06356bSdh142964 * 6554c06356bSdh142964 */ 6564c06356bSdh142964 void 6574c06356bSdh142964 damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv) 6584c06356bSdh142964 { 6594c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 6604c06356bSdh142964 dam_da_t *passp; 6614c06356bSdh142964 6624c06356bSdh142964 6634c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 6644c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 6654c06356bSdh142964 if (!passp) { 6664c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 6674c06356bSdh142964 return; 6684c06356bSdh142964 } 6694c06356bSdh142964 passp->da_cfg_priv = cfg_priv; 6704c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 6714c06356bSdh142964 } 6724c06356bSdh142964 6734c06356bSdh142964 /* 6744c06356bSdh142964 * Get config private data 6754c06356bSdh142964 * 6764c06356bSdh142964 * damapp: address map handle 6774c06356bSdh142964 * aid: address ID 6784c06356bSdh142964 * 6794c06356bSdh142964 * Returns: configuration private data 6804c06356bSdh142964 */ 6814c06356bSdh142964 void * 6824c06356bSdh142964 damap_id_priv_get(damap_t *damapp, damap_id_t aid) 6834c06356bSdh142964 { 6844c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 6854c06356bSdh142964 dam_da_t *passp; 6864c06356bSdh142964 void *rv; 6874c06356bSdh142964 6884c06356bSdh142964 6894c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 6904c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 6914c06356bSdh142964 if (!passp) { 6924c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 6934c06356bSdh142964 return (NULL); 6944c06356bSdh142964 } 6954c06356bSdh142964 rv = passp->da_cfg_priv; 6964c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 6974c06356bSdh142964 return (rv); 6984c06356bSdh142964 } 6994c06356bSdh142964 7004c06356bSdh142964 /* 7014c06356bSdh142964 * Lookup a single address in the active address map 7024c06356bSdh142964 * 7034c06356bSdh142964 * damapp: address map handle 7044c06356bSdh142964 * address: address string 7054c06356bSdh142964 * 7064c06356bSdh142964 * Returns: ID of active/stable address 7074c06356bSdh142964 * 0 Address not in stable set 7084c06356bSdh142964 * 7094c06356bSdh142964 * Future: Allow the caller to wait for stabilize before returning not found. 7104c06356bSdh142964 */ 7114c06356bSdh142964 damap_id_t 7124c06356bSdh142964 damap_lookup(damap_t *damapp, char *address) 7134c06356bSdh142964 { 7144c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 7154c06356bSdh142964 id_t addrid = 0; 7164c06356bSdh142964 dam_da_t *passp = NULL; 7174c06356bSdh142964 7184c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 7194c06356bSdh142964 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); 7204c06356bSdh142964 if (addrid) { 7214c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 7224c06356bSdh142964 if (DAM_IS_STABLE(mapp, addrid)) { 7234c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 7244c06356bSdh142964 ASSERT(passp); 7254c06356bSdh142964 if (passp) { 7264c06356bSdh142964 passp->da_ref++; 7274c06356bSdh142964 } else { 7284c06356bSdh142964 addrid = 0; 7294c06356bSdh142964 } 7304c06356bSdh142964 } else { 7314c06356bSdh142964 addrid = 0; 7324c06356bSdh142964 } 7334c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 7344c06356bSdh142964 } 7354c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 7364c06356bSdh142964 return ((damap_id_t)addrid); 7374c06356bSdh142964 } 7384c06356bSdh142964 7394c06356bSdh142964 7404c06356bSdh142964 /* 7414c06356bSdh142964 * Return the list of stable addresses in the map 7424c06356bSdh142964 * 7434c06356bSdh142964 * damapp: address map handle 7444c06356bSdh142964 * id_listp: pointer to list of address IDs in stable map (returned) 7454c06356bSdh142964 * 7464c06356bSdh142964 * Returns: # of entries returned in alist 7474c06356bSdh142964 */ 7484c06356bSdh142964 int 7494c06356bSdh142964 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp) 7504c06356bSdh142964 { 7514c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 7524c06356bSdh142964 int mapsz = mapp->dam_size; 7534c06356bSdh142964 int n_ids, i; 7544c06356bSdh142964 bitset_t *bsp; 7554c06356bSdh142964 dam_da_t *passp; 7564c06356bSdh142964 7574c06356bSdh142964 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); 7584c06356bSdh142964 bitset_init(bsp); 7594c06356bSdh142964 bitset_resize(bsp, mapsz); 7604c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 7614c06356bSdh142964 bitset_copy(&mapp->dam_active_set, bsp); 7624c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 7634c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 7644c06356bSdh142964 for (n_ids = 0, i = 1; i < mapsz; i++) { 7654c06356bSdh142964 if (bitset_in_set(bsp, i)) { 7664c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 7674c06356bSdh142964 ASSERT(passp); 7684c06356bSdh142964 if (passp) { 7694c06356bSdh142964 passp->da_ref++; 7704c06356bSdh142964 n_ids++; 7714c06356bSdh142964 } 7724c06356bSdh142964 } 7734c06356bSdh142964 } 7744c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 7754c06356bSdh142964 if (n_ids) { 7764c06356bSdh142964 *id_listp = (damap_id_list_t)bsp; 7774c06356bSdh142964 return (n_ids); 7784c06356bSdh142964 } else { 7794c06356bSdh142964 *id_listp = (damap_id_list_t)NULL; 7804c06356bSdh142964 bitset_fini(bsp); 7814c06356bSdh142964 kmem_free(bsp, sizeof (*bsp)); 7824c06356bSdh142964 return (0); 7834c06356bSdh142964 } 7844c06356bSdh142964 } 7854c06356bSdh142964 7864c06356bSdh142964 /* 7874c06356bSdh142964 * Release the address list returned by damap_lookup_all() 7884c06356bSdh142964 * 7894c06356bSdh142964 * mapp: address map handle 7904c06356bSdh142964 * id_list: list of address IDs returned in damap_lookup_all() 7914c06356bSdh142964 */ 7924c06356bSdh142964 void 7934c06356bSdh142964 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list) 7944c06356bSdh142964 { 7954c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 7964c06356bSdh142964 int i; 7974c06356bSdh142964 7984c06356bSdh142964 if (id_list == NULL) 7994c06356bSdh142964 return; 8004c06356bSdh142964 8014c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 8024c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 8034c06356bSdh142964 if (bitset_in_set((bitset_t *)id_list, i)) 8044c06356bSdh142964 (void) dam_release(mapp, i); 8054c06356bSdh142964 } 8064c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 8074c06356bSdh142964 bitset_fini((bitset_t *)id_list); 8084c06356bSdh142964 kmem_free((void *)id_list, sizeof (bitset_t)); 8094c06356bSdh142964 } 8104c06356bSdh142964 8114c06356bSdh142964 /* 8124c06356bSdh142964 * Activate a set of stabilized addresses 8134c06356bSdh142964 */ 8144c06356bSdh142964 static void 8154c06356bSdh142964 dam_addrset_activate(dam_t *mapp, bitset_t *active_set) 8164c06356bSdh142964 { 8174c06356bSdh142964 dam_da_t *passp; 8184c06356bSdh142964 char *addrstr; 8194c06356bSdh142964 int i; 8204c06356bSdh142964 uint32_t n_active = 0; 8214c06356bSdh142964 8224c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 8234c06356bSdh142964 if (bitset_in_set(&mapp->dam_active_set, i)) 8244c06356bSdh142964 n_active++; 8254c06356bSdh142964 if (!bitset_in_set(active_set, i)) 8264c06356bSdh142964 continue; 8274c06356bSdh142964 n_active++; 8284c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 8294c06356bSdh142964 ASSERT(passp); 8304c06356bSdh142964 if (mapp->dam_activate_cb) { 8314c06356bSdh142964 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i); 8324c06356bSdh142964 (*mapp->dam_activate_cb)( 8334c06356bSdh142964 mapp->dam_activate_arg, addrstr, i, 8344c06356bSdh142964 &passp->da_ppriv_rpt); 8354c06356bSdh142964 } 8364c06356bSdh142964 DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i); 8374c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 8384c06356bSdh142964 bitset_add(&mapp->dam_active_set, i); 8394c06356bSdh142964 /* 8404c06356bSdh142964 * copy the reported nvlist and provider private data 8414c06356bSdh142964 */ 8424c06356bSdh142964 passp->da_nvl = passp->da_nvl_rpt; 8434c06356bSdh142964 passp->da_ppriv = passp->da_ppriv_rpt; 8444c06356bSdh142964 passp->da_ppriv_rpt = NULL; 8454c06356bSdh142964 passp->da_nvl_rpt = NULL; 8464c06356bSdh142964 passp->da_last_stable = gethrtime(); 8474c06356bSdh142964 passp->da_stable_cnt++; 8484c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 8494c06356bSdh142964 DAM_SET_STAT(mapp, dam_numstable, n_active); 8504c06356bSdh142964 } 8514c06356bSdh142964 } 8524c06356bSdh142964 8534c06356bSdh142964 /* 8544c06356bSdh142964 * Release a set of stabilized addresses 8554c06356bSdh142964 */ 8564c06356bSdh142964 static void 8574c06356bSdh142964 dam_addrset_release(dam_t *mapp, bitset_t *release_set) 8584c06356bSdh142964 { 8594c06356bSdh142964 int i; 8604c06356bSdh142964 8614c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 8624c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 8634c06356bSdh142964 if (bitset_in_set(release_set, i)) { 8644c06356bSdh142964 DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp, 8654c06356bSdh142964 int, i); 8664c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 8674c06356bSdh142964 bitset_del(&mapp->dam_active_set, i); 8684c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 8694c06356bSdh142964 (void) dam_release(mapp, i); 8704c06356bSdh142964 } 8714c06356bSdh142964 } 8724c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 8734c06356bSdh142964 } 8744c06356bSdh142964 8754c06356bSdh142964 /* 8764c06356bSdh142964 * release a previously activated address 8774c06356bSdh142964 */ 8784c06356bSdh142964 static void 8794c06356bSdh142964 dam_release(dam_t *mapp, id_t addrid) 8804c06356bSdh142964 { 8814c06356bSdh142964 dam_da_t *passp; 8824c06356bSdh142964 8834c06356bSdh142964 DAM_ASSERT_LOCKED(mapp, ADDR_LOCK); 8844c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 8854c06356bSdh142964 ASSERT(passp); 8864c06356bSdh142964 8874c06356bSdh142964 /* 8884c06356bSdh142964 * invoke the deactivation callback to notify 8894c06356bSdh142964 * this address is no longer active 8904c06356bSdh142964 */ 8914c06356bSdh142964 dam_deactivate_addr(mapp, addrid); 8924c06356bSdh142964 8934c06356bSdh142964 /* 8944c06356bSdh142964 * allow pending reports for this address to stabilize 8954c06356bSdh142964 */ 8964c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) 8974c06356bSdh142964 return; 8984c06356bSdh142964 8994c06356bSdh142964 /* 9004c06356bSdh142964 * defer teardown until outstanding references are released 9014c06356bSdh142964 */ 9024c06356bSdh142964 if (--passp->da_ref) { 9034c06356bSdh142964 passp->da_flags |= DA_RELE; 9044c06356bSdh142964 return; 9054c06356bSdh142964 } 9064c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid); 9074c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, addrid); 9084c06356bSdh142964 } 9094c06356bSdh142964 9104c06356bSdh142964 /* 9114c06356bSdh142964 * process stabilized address reports 9124c06356bSdh142964 */ 9134c06356bSdh142964 static void 9144c06356bSdh142964 dam_activate_taskq(void *arg) 9154c06356bSdh142964 { 9164c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 9174c06356bSdh142964 bitset_t delta; 9184c06356bSdh142964 bitset_t cfg; 9194c06356bSdh142964 bitset_t uncfg; 9204c06356bSdh142964 int has_cfg, has_uncfg; 9214c06356bSdh142964 9224c06356bSdh142964 bitset_init(&delta); 9234c06356bSdh142964 bitset_resize(&delta, mapp->dam_size); 9244c06356bSdh142964 bitset_init(&cfg); 9254c06356bSdh142964 bitset_resize(&cfg, mapp->dam_size); 9264c06356bSdh142964 bitset_init(&uncfg); 9274c06356bSdh142964 bitset_resize(&uncfg, mapp->dam_size); 9284c06356bSdh142964 9294c06356bSdh142964 DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp); 9304c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 9314c06356bSdh142964 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, 9324c06356bSdh142964 &delta)) { 9334c06356bSdh142964 bitset_zero(&mapp->dam_stable_set); 9344c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SPEND); 9354c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 9364c06356bSdh142964 bitset_fini(&uncfg); 9374c06356bSdh142964 bitset_fini(&cfg); 9384c06356bSdh142964 bitset_fini(&delta); 9394c06356bSdh142964 return; 9404c06356bSdh142964 } 9414c06356bSdh142964 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); 9424c06356bSdh142964 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); 9434c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 9444c06356bSdh142964 if (has_cfg) { 9454c06356bSdh142964 dam_addrset_activate(mapp, &cfg); 9464c06356bSdh142964 (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg); 9474c06356bSdh142964 } 9484c06356bSdh142964 if (has_uncfg) { 9494c06356bSdh142964 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg); 9504c06356bSdh142964 dam_addrset_release(mapp, &uncfg); 9514c06356bSdh142964 } 9524c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 9534c06356bSdh142964 bitset_zero(&mapp->dam_stable_set); 9544c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SPEND); 9554c06356bSdh142964 mapp->dam_last_stable = gethrtime(); 9564c06356bSdh142964 mapp->dam_stable_cnt++; 9574c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable); 9584c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 9594c06356bSdh142964 bitset_fini(&uncfg); 9604c06356bSdh142964 bitset_fini(&cfg); 9614c06356bSdh142964 bitset_fini(&delta); 9624c06356bSdh142964 DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp); 9634c06356bSdh142964 } 9644c06356bSdh142964 9654c06356bSdh142964 /* 9664c06356bSdh142964 * per-address stabilization timeout 9674c06356bSdh142964 */ 9684c06356bSdh142964 static void 9694c06356bSdh142964 dam_addr_stable_cb(void *arg) 9704c06356bSdh142964 { 9714c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 9724c06356bSdh142964 int i; 9734c06356bSdh142964 dam_da_t *passp; 9744c06356bSdh142964 int spend = 0; 9754c06356bSdh142964 int tpend = 0; 9764c06356bSdh142964 int64_t next_tmov = mapp->dam_stabletmo; 9774c06356bSdh142964 int64_t tmo_delta; 978*d3d50737SRafael Vanoni int64_t ts = ddi_get_lbolt64(); 9794c06356bSdh142964 9804c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp); 9814c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 9824c06356bSdh142964 if (mapp->dam_tid == 0) { 9834c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 9844c06356bSdh142964 return; 9854c06356bSdh142964 } 9864c06356bSdh142964 mapp->dam_tid = 0; 9874c06356bSdh142964 /* 9884c06356bSdh142964 * If still under stabilization, reschedule timeout, 9894c06356bSdh142964 * else dispatch the task to activate & deactivate the stable 9904c06356bSdh142964 * set. 9914c06356bSdh142964 */ 9924c06356bSdh142964 if (mapp->dam_flags & DAM_SPEND) { 9934c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable_blocked); 9944c06356bSdh142964 mapp->dam_stable_overrun++; 9954c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 9964c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 9974c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__overrun, 9984c06356bSdh142964 dam_t *, mapp); 9994c06356bSdh142964 return; 10004c06356bSdh142964 } 10014c06356bSdh142964 10024c06356bSdh142964 bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); 10034c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 10044c06356bSdh142964 if (!bitset_in_set(&mapp->dam_report_set, i)) 10054c06356bSdh142964 continue; 10064c06356bSdh142964 /* 10074c06356bSdh142964 * Stabilize each address 10084c06356bSdh142964 */ 10094c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 10104c06356bSdh142964 ASSERT(passp); 10114c06356bSdh142964 if (!passp) { 10124c06356bSdh142964 cmn_err(CE_WARN, "Clearing report no softstate %d", i); 10134c06356bSdh142964 bitset_del(&mapp->dam_report_set, i); 10144c06356bSdh142964 continue; 10154c06356bSdh142964 } 10164c06356bSdh142964 10174c06356bSdh142964 /* report has stabilized */ 10184c06356bSdh142964 if (passp->da_deadline <= ts) { 10194c06356bSdh142964 bitset_del(&mapp->dam_report_set, i); 10204c06356bSdh142964 if (passp->da_flags & DA_RELE) { 10214c06356bSdh142964 DTRACE_PROBE2(damap__addr__stable__del, 10224c06356bSdh142964 dam_t *, mapp, int, i); 10234c06356bSdh142964 bitset_del(&mapp->dam_stable_set, i); 10244c06356bSdh142964 } else { 10254c06356bSdh142964 DTRACE_PROBE2(damap__addr__stable__add, 10264c06356bSdh142964 dam_t *, mapp, int, i); 10274c06356bSdh142964 bitset_add(&mapp->dam_stable_set, i); 10284c06356bSdh142964 } 10294c06356bSdh142964 spend++; 10304c06356bSdh142964 continue; 10314c06356bSdh142964 } 10324c06356bSdh142964 10334c06356bSdh142964 /* 10344c06356bSdh142964 * not stabilized, determine next (future) map timeout 10354c06356bSdh142964 */ 10364c06356bSdh142964 tpend++; 10374c06356bSdh142964 tmo_delta = passp->da_deadline - ts; 10384c06356bSdh142964 if (tmo_delta < next_tmov) 10394c06356bSdh142964 next_tmov = tmo_delta; 10404c06356bSdh142964 } 10414c06356bSdh142964 10424c06356bSdh142964 /* 10434c06356bSdh142964 * schedule taskq activation of stabilized reports 10444c06356bSdh142964 */ 10454c06356bSdh142964 if (spend) { 10464c06356bSdh142964 if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 10474c06356bSdh142964 mapp, DDI_NOSLEEP) == DDI_SUCCESS) { 10484c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SPEND); 10494c06356bSdh142964 } else 10504c06356bSdh142964 tpend++; 10514c06356bSdh142964 } 10524c06356bSdh142964 10534c06356bSdh142964 /* 10544c06356bSdh142964 * schedule timeout to handle future stabalization of active reports 10554c06356bSdh142964 */ 10564c06356bSdh142964 if (tpend) 10574c06356bSdh142964 dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb); 10584c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 10594c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp); 10604c06356bSdh142964 } 10614c06356bSdh142964 10624c06356bSdh142964 /* 10634c06356bSdh142964 * fullset stabilization timeout 10644c06356bSdh142964 */ 10654c06356bSdh142964 static void 10664c06356bSdh142964 dam_set_stable_cb(void *arg) 10674c06356bSdh142964 { 10684c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 10694c06356bSdh142964 10704c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp); 10714c06356bSdh142964 10724c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 10734c06356bSdh142964 if (mapp->dam_tid == 0) { 10744c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 10754c06356bSdh142964 return; 10764c06356bSdh142964 } 10774c06356bSdh142964 mapp->dam_tid = 0; 10784c06356bSdh142964 10794c06356bSdh142964 /* 10804c06356bSdh142964 * If still under stabilization, reschedule timeout, 10814c06356bSdh142964 * else dispatch the task to activate & deactivate the stable 10824c06356bSdh142964 * set. 10834c06356bSdh142964 */ 10844c06356bSdh142964 if (mapp->dam_flags & DAM_SPEND) { 10854c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable_blocked); 10864c06356bSdh142964 mapp->dam_stable_overrun++; 10874c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 10884c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__overrun, 10894c06356bSdh142964 dam_t *, mapp); 10904c06356bSdh142964 } else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 10914c06356bSdh142964 mapp, DDI_NOSLEEP) == DDI_FAILURE) { 10924c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 10934c06356bSdh142964 } else { 10944c06356bSdh142964 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); 10954c06356bSdh142964 bitset_zero(&mapp->dam_report_set); 10964c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SETADD); 10974c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SPEND); 10984c06356bSdh142964 } 10994c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 11004c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp); 11014c06356bSdh142964 } 11024c06356bSdh142964 11034c06356bSdh142964 /* 11044c06356bSdh142964 * reschedule map timeout 'tmo_ms' ticks 11054c06356bSdh142964 */ 11064c06356bSdh142964 static void 11074c06356bSdh142964 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)()) 11084c06356bSdh142964 { 11094c06356bSdh142964 timeout_id_t tid; 11104c06356bSdh142964 11114c06356bSdh142964 if ((tid = mapp->dam_tid) != 0) { 11124c06356bSdh142964 mapp->dam_tid = 0; 11134c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 11144c06356bSdh142964 (void) untimeout(tid); 11154c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 11164c06356bSdh142964 } 11174c06356bSdh142964 11184c06356bSdh142964 if (tmo_cb && (tmo_ms != 0)) 11194c06356bSdh142964 mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); 11204c06356bSdh142964 } 11214c06356bSdh142964 11224c06356bSdh142964 /* 11234c06356bSdh142964 * record report addition or removal of an address 11244c06356bSdh142964 */ 11254c06356bSdh142964 static void 11264c06356bSdh142964 dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report) 11274c06356bSdh142964 { 11284c06356bSdh142964 ASSERT(!DAM_IN_REPORT(mapp, addrid)); 11294c06356bSdh142964 passp->da_last_report = gethrtime(); 11304c06356bSdh142964 mapp->dam_last_update = gethrtime(); 11314c06356bSdh142964 passp->da_report_cnt++; 1132*d3d50737SRafael Vanoni passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo; 11334c06356bSdh142964 if (report == RPT_ADDR_DEL) 11344c06356bSdh142964 passp->da_flags |= DA_RELE; 11354c06356bSdh142964 else if (report == RPT_ADDR_ADD) 11364c06356bSdh142964 passp->da_flags &= ~DA_RELE; 11374c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 11384c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid); 11394c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 11404c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 11414c06356bSdh142964 11424c06356bSdh142964 } 11434c06356bSdh142964 11444c06356bSdh142964 /* 11454c06356bSdh142964 * release an address report 11464c06356bSdh142964 */ 11474c06356bSdh142964 static void 11484c06356bSdh142964 dam_release_report(dam_t *mapp, id_t addrid) 11494c06356bSdh142964 { 11504c06356bSdh142964 dam_da_t *passp; 11514c06356bSdh142964 11524c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 11534c06356bSdh142964 ASSERT(passp); 11544c06356bSdh142964 passp->da_ppriv_rpt = NULL; 11554c06356bSdh142964 if (passp->da_nvl_rpt) 11564c06356bSdh142964 nvlist_free(passp->da_nvl_rpt); 11574c06356bSdh142964 passp->da_nvl_rpt = NULL; 11584c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 11594c06356bSdh142964 bitset_del(&mapp->dam_report_set, addrid); 11604c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 11614c06356bSdh142964 } 11624c06356bSdh142964 11634c06356bSdh142964 /* 11644c06356bSdh142964 * deactivate a previously stable address 11654c06356bSdh142964 */ 11664c06356bSdh142964 static void 11674c06356bSdh142964 dam_deactivate_addr(dam_t *mapp, id_t addrid) 11684c06356bSdh142964 { 11694c06356bSdh142964 dam_da_t *passp; 11704c06356bSdh142964 11714c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 11724c06356bSdh142964 ASSERT(passp); 11734c06356bSdh142964 if (passp == NULL) 11744c06356bSdh142964 return; 11754c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 11764c06356bSdh142964 if (mapp->dam_deactivate_cb) 11774c06356bSdh142964 (*mapp->dam_deactivate_cb)( 11784c06356bSdh142964 mapp->dam_activate_arg, 11794c06356bSdh142964 ddi_strid_id2str(mapp->dam_addr_hash, 11804c06356bSdh142964 addrid), addrid, passp->da_ppriv); 11814c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 11824c06356bSdh142964 passp->da_ppriv = NULL; 11834c06356bSdh142964 if (passp->da_nvl) 11844c06356bSdh142964 nvlist_free(passp->da_nvl); 11854c06356bSdh142964 passp->da_nvl = NULL; 11864c06356bSdh142964 } 11874c06356bSdh142964 11884c06356bSdh142964 /* 11894c06356bSdh142964 * return the map ID of an address 11904c06356bSdh142964 */ 11914c06356bSdh142964 static id_t 11924c06356bSdh142964 dam_get_addrid(dam_t *mapp, char *address) 11934c06356bSdh142964 { 11944c06356bSdh142964 damap_id_t addrid; 11954c06356bSdh142964 dam_da_t *passp; 11964c06356bSdh142964 11974c06356bSdh142964 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { 11984c06356bSdh142964 if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash, 11994c06356bSdh142964 address)) == (damap_id_t)0) { 12004c06356bSdh142964 return (0); 12014c06356bSdh142964 } 12024c06356bSdh142964 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) != 12034c06356bSdh142964 DDI_SUCCESS) { 12044c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid); 12054c06356bSdh142964 return (0); 12064c06356bSdh142964 } 12074c06356bSdh142964 if (addrid >= mapp->dam_high) 12084c06356bSdh142964 mapp->dam_high = addrid + 1; 12094c06356bSdh142964 } 12104c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 12114c06356bSdh142964 if (passp == NULL) 12124c06356bSdh142964 return (0); 12134c06356bSdh142964 passp->da_ref++; 12144c06356bSdh142964 if (passp->da_addr == NULL) 12154c06356bSdh142964 passp->da_addr = ddi_strid_id2str( 12164c06356bSdh142964 mapp->dam_addr_hash, addrid); /* for mdb */ 12174c06356bSdh142964 return (addrid); 12184c06356bSdh142964 } 12194c06356bSdh142964 12204c06356bSdh142964 /* 12214c06356bSdh142964 * create and install map statistics 12224c06356bSdh142964 */ 12234c06356bSdh142964 static int 12244c06356bSdh142964 dam_kstat_create(dam_t *mapp) 12254c06356bSdh142964 { 12264c06356bSdh142964 kstat_t *mapsp; 12274c06356bSdh142964 struct dam_kstats *statsp; 12284c06356bSdh142964 12294c06356bSdh142964 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", 12304c06356bSdh142964 KSTAT_TYPE_NAMED, 12314c06356bSdh142964 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); 12324c06356bSdh142964 if (mapsp == NULL) { 12334c06356bSdh142964 return (DDI_FAILURE); 12344c06356bSdh142964 } 12354c06356bSdh142964 12364c06356bSdh142964 statsp = (struct dam_kstats *)mapsp->ks_data; 12374c06356bSdh142964 kstat_named_init(&statsp->dam_stable, "stable cycles", 12384c06356bSdh142964 KSTAT_DATA_UINT32); 12394c06356bSdh142964 kstat_named_init(&statsp->dam_stable_blocked, 12404c06356bSdh142964 "stable cycle overrun", KSTAT_DATA_UINT32); 12414c06356bSdh142964 kstat_named_init(&statsp->dam_rereport, 12424c06356bSdh142964 "restarted reports", KSTAT_DATA_UINT32); 12434c06356bSdh142964 kstat_named_init(&statsp->dam_numstable, 12444c06356bSdh142964 "# of stable map entries", KSTAT_DATA_UINT32); 12454c06356bSdh142964 kstat_install(mapsp); 12464c06356bSdh142964 mapp->dam_kstatsp = mapsp; 12474c06356bSdh142964 return (DDI_SUCCESS); 12484c06356bSdh142964 } 12494c06356bSdh142964 12504c06356bSdh142964 /* 12514c06356bSdh142964 * destroy map stats 12524c06356bSdh142964 */ 12534c06356bSdh142964 static void 12544c06356bSdh142964 dam_kstat_destroy(dam_t *mapp) 12554c06356bSdh142964 { 12564c06356bSdh142964 12574c06356bSdh142964 kstat_delete(mapp->dam_kstatsp); 12584c06356bSdh142964 } 1259