110696SDavid.Hollister@Sun.COM /* 210696SDavid.Hollister@Sun.COM * CDDL HEADER START 310696SDavid.Hollister@Sun.COM * 410696SDavid.Hollister@Sun.COM * The contents of this file are subject to the terms of the 510696SDavid.Hollister@Sun.COM * Common Development and Distribution License (the "License"). 610696SDavid.Hollister@Sun.COM * You may not use this file except in compliance with the License. 710696SDavid.Hollister@Sun.COM * 810696SDavid.Hollister@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 910696SDavid.Hollister@Sun.COM * or http://www.opensolaris.org/os/licensing. 1010696SDavid.Hollister@Sun.COM * See the License for the specific language governing permissions 1110696SDavid.Hollister@Sun.COM * and limitations under the License. 1210696SDavid.Hollister@Sun.COM * 1310696SDavid.Hollister@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1410696SDavid.Hollister@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1510696SDavid.Hollister@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1610696SDavid.Hollister@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1710696SDavid.Hollister@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1810696SDavid.Hollister@Sun.COM * 1910696SDavid.Hollister@Sun.COM * CDDL HEADER END 2010696SDavid.Hollister@Sun.COM */ 2110696SDavid.Hollister@Sun.COM 2210696SDavid.Hollister@Sun.COM /* 23*12207SChris.Horne@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2410696SDavid.Hollister@Sun.COM */ 2510696SDavid.Hollister@Sun.COM 2610696SDavid.Hollister@Sun.COM #include <sys/note.h> 2710696SDavid.Hollister@Sun.COM #include <sys/types.h> 2810696SDavid.Hollister@Sun.COM #include <sys/param.h> 2910696SDavid.Hollister@Sun.COM #include <sys/systm.h> 3010696SDavid.Hollister@Sun.COM #include <sys/buf.h> 3110696SDavid.Hollister@Sun.COM #include <sys/kmem.h> 3210696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h> 3310696SDavid.Hollister@Sun.COM #include <sys/debug.h> 3410696SDavid.Hollister@Sun.COM #include <sys/sunndi.h> 3510696SDavid.Hollister@Sun.COM #include <sys/kstat.h> 3610696SDavid.Hollister@Sun.COM #include <sys/conf.h> 3710696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h> 3810696SDavid.Hollister@Sun.COM #include <sys/devctl.h> 3910696SDavid.Hollister@Sun.COM #include <sys/callb.h> 4010696SDavid.Hollister@Sun.COM #include <sys/sysevent.h> 4110696SDavid.Hollister@Sun.COM #include <sys/taskq.h> 4210696SDavid.Hollister@Sun.COM #include <sys/ddi.h> 4310696SDavid.Hollister@Sun.COM #include <sys/bitset.h> 4410696SDavid.Hollister@Sun.COM #include <sys/damap.h> 4510696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h> 4610696SDavid.Hollister@Sun.COM 4710696SDavid.Hollister@Sun.COM #ifdef DEBUG 4810696SDavid.Hollister@Sun.COM static int damap_debug = 0; 4910696SDavid.Hollister@Sun.COM #endif /* DEBUG */ 5010696SDavid.Hollister@Sun.COM 5111068SJohn.Danielson@Sun.COM extern taskq_t *system_taskq; 5211068SJohn.Danielson@Sun.COM 5310696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *); 5411068SJohn.Danielson@Sun.COM static void dam_addrset_deactivate(dam_t *, bitset_t *); 5511068SJohn.Danielson@Sun.COM static void dam_stabilize_map(void *); 5610696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *); 5711068SJohn.Danielson@Sun.COM static void dam_addrset_stable_cb(void *); 58*12207SChris.Horne@Sun.COM static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t); 5911068SJohn.Danielson@Sun.COM static void dam_addr_report(dam_t *, dam_da_t *, id_t, int); 6011068SJohn.Danielson@Sun.COM static void dam_addr_release(dam_t *, id_t); 6111068SJohn.Danielson@Sun.COM static void dam_addr_report_release(dam_t *, id_t); 6211068SJohn.Danielson@Sun.COM static void dam_addr_deactivate(dam_t *, id_t); 6311363SReed.Liu@Sun.COM static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t); 6410696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *); 6510696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *); 6611068SJohn.Danielson@Sun.COM static int dam_map_alloc(dam_t *); 6710696SDavid.Hollister@Sun.COM 6810696SDavid.Hollister@Sun.COM #define DAM_INCR_STAT(mapp, stat) \ 6910696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \ 7010696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 7110696SDavid.Hollister@Sun.COM stp->stat.value.ui32++; \ 7210696SDavid.Hollister@Sun.COM } 7310696SDavid.Hollister@Sun.COM 7410696SDavid.Hollister@Sun.COM #define DAM_SET_STAT(mapp, stat, val) \ 7510696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \ 7610696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 7710696SDavid.Hollister@Sun.COM stp->stat.value.ui32 = (val); \ 7810696SDavid.Hollister@Sun.COM } 7910696SDavid.Hollister@Sun.COM 8011068SJohn.Danielson@Sun.COM 8111068SJohn.Danielson@Sun.COM /* 8211068SJohn.Danielson@Sun.COM * increase damap size by 64 entries at a time 8311068SJohn.Danielson@Sun.COM */ 8411068SJohn.Danielson@Sun.COM #define DAM_SIZE_BUMP 64 8511068SJohn.Danielson@Sun.COM 8611854SChris.Horne@Sun.COM int damap_taskq_dispatch_retry_usec = 1000; 8711854SChris.Horne@Sun.COM 8811068SJohn.Danielson@Sun.COM /* 8911068SJohn.Danielson@Sun.COM * config/unconfig taskq data 9011068SJohn.Danielson@Sun.COM */ 9111068SJohn.Danielson@Sun.COM typedef struct { 9211068SJohn.Danielson@Sun.COM dam_t *tqd_mapp; 9311068SJohn.Danielson@Sun.COM id_t tqd_id; 9411068SJohn.Danielson@Sun.COM } cfg_tqd_t; 9511068SJohn.Danielson@Sun.COM 9611068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri; 9711068SJohn.Danielson@Sun.COM 9810696SDavid.Hollister@Sun.COM /* 9910696SDavid.Hollister@Sun.COM * Create new device address map 10010696SDavid.Hollister@Sun.COM * 10111068SJohn.Danielson@Sun.COM * name: map name (kstat unique) 10210696SDavid.Hollister@Sun.COM * size: max # of map entries 10311068SJohn.Danielson@Sun.COM * mode: style of address reports: per-address or fullset 10410696SDavid.Hollister@Sun.COM * stable_usec: # of quiescent microseconds before report/map is stable 10510696SDavid.Hollister@Sun.COM * 10610696SDavid.Hollister@Sun.COM * activate_arg: address provider activation-callout private 10710696SDavid.Hollister@Sun.COM * activate_cb: address provider activation callback handler 10810696SDavid.Hollister@Sun.COM * deactivate_cb: address provider deactivation callback handler 10910696SDavid.Hollister@Sun.COM * 11010696SDavid.Hollister@Sun.COM * config_arg: configuration-callout private 11110696SDavid.Hollister@Sun.COM * config_cb: class configuration callout 11210696SDavid.Hollister@Sun.COM * unconfig_cb: class unconfiguration callout 11310696SDavid.Hollister@Sun.COM * 11410696SDavid.Hollister@Sun.COM * damapp: pointer to map handle (return) 11510696SDavid.Hollister@Sun.COM * 11610696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 11710696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 11810696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 11910696SDavid.Hollister@Sun.COM */ 12010696SDavid.Hollister@Sun.COM int 12111068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts, 122*12207SChris.Horne@Sun.COM int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb, 12310696SDavid.Hollister@Sun.COM damap_deactivate_cb_t deactivate_cb, 12410696SDavid.Hollister@Sun.COM void *config_arg, damap_configure_cb_t configure_cb, 12510696SDavid.Hollister@Sun.COM damap_unconfig_cb_t unconfig_cb, 12610696SDavid.Hollister@Sun.COM damap_t **damapp) 12710696SDavid.Hollister@Sun.COM { 12810696SDavid.Hollister@Sun.COM dam_t *mapp; 12910696SDavid.Hollister@Sun.COM 13011068SJohn.Danielson@Sun.COM if (configure_cb == NULL || unconfig_cb == NULL || name == NULL) 13110696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 13210696SDavid.Hollister@Sun.COM 13311068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__create, char *, name, 134*12207SChris.Horne@Sun.COM damap_rptmode_t, mode, int, stable_usec); 13510696SDavid.Hollister@Sun.COM 13610696SDavid.Hollister@Sun.COM mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); 13711068SJohn.Danielson@Sun.COM mapp->dam_options = map_opts; 138*12207SChris.Horne@Sun.COM mapp->dam_stable_ticks = drv_usectohz(stable_usec); 13911068SJohn.Danielson@Sun.COM mapp->dam_size = 0; 14011068SJohn.Danielson@Sun.COM mapp->dam_rptmode = mode; 14110696SDavid.Hollister@Sun.COM mapp->dam_activate_arg = activate_arg; 14210696SDavid.Hollister@Sun.COM mapp->dam_activate_cb = (activate_cb_t)activate_cb; 14310696SDavid.Hollister@Sun.COM mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; 14410696SDavid.Hollister@Sun.COM mapp->dam_config_arg = config_arg; 14510696SDavid.Hollister@Sun.COM mapp->dam_configure_cb = (configure_cb_t)configure_cb; 14610696SDavid.Hollister@Sun.COM mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; 14711068SJohn.Danielson@Sun.COM mapp->dam_name = i_ddi_strdup(name, KM_SLEEP); 14810696SDavid.Hollister@Sun.COM mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); 149*12207SChris.Horne@Sun.COM cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL); 15011068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_active_set); 15111068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_stable_set); 15211068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_report_set); 15310696SDavid.Hollister@Sun.COM *damapp = (damap_t *)mapp; 15410696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 15510696SDavid.Hollister@Sun.COM } 15610696SDavid.Hollister@Sun.COM 15710696SDavid.Hollister@Sun.COM /* 15811068SJohn.Danielson@Sun.COM * Allocate backing resources 15911068SJohn.Danielson@Sun.COM * 16011068SJohn.Danielson@Sun.COM * DAMs are lightly backed on create - major allocations occur 16111068SJohn.Danielson@Sun.COM * at the time a report is made to the map, and are extended on 16211068SJohn.Danielson@Sun.COM * a demand basis. 16311068SJohn.Danielson@Sun.COM */ 16411068SJohn.Danielson@Sun.COM static int 16511068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp) 16611068SJohn.Danielson@Sun.COM { 16711068SJohn.Danielson@Sun.COM void *softstate_p; 16811068SJohn.Danielson@Sun.COM 16911068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 17011068SJohn.Danielson@Sun.COM if (mapp->dam_flags & DAM_DESTROYPEND) 17111068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 17211068SJohn.Danielson@Sun.COM 17311068SJohn.Danielson@Sun.COM /* 17411068SJohn.Danielson@Sun.COM * dam_high > 0 signals map allocation complete 17511068SJohn.Danielson@Sun.COM */ 17611068SJohn.Danielson@Sun.COM if (mapp->dam_high) 17711068SJohn.Danielson@Sun.COM return (DAM_SUCCESS); 17811068SJohn.Danielson@Sun.COM 17911068SJohn.Danielson@Sun.COM mapp->dam_size = DAM_SIZE_BUMP; 18011068SJohn.Danielson@Sun.COM if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), 18111068SJohn.Danielson@Sun.COM mapp->dam_size) != DDI_SUCCESS) 18211068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 18311068SJohn.Danielson@Sun.COM 18411068SJohn.Danielson@Sun.COM if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) != 18511068SJohn.Danielson@Sun.COM DDI_SUCCESS) { 18611068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p); 18711068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 18811068SJohn.Danielson@Sun.COM } 18911068SJohn.Danielson@Sun.COM if (dam_kstat_create(mapp) != DDI_SUCCESS) { 19011068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p); 19111068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash); 19211068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 19311068SJohn.Danielson@Sun.COM } 19411068SJohn.Danielson@Sun.COM mapp->dam_da = softstate_p; 19511068SJohn.Danielson@Sun.COM mapp->dam_high = 1; 19611068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size); 19711068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size); 19811068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size); 19911068SJohn.Danielson@Sun.COM return (DAM_SUCCESS); 20011068SJohn.Danielson@Sun.COM } 20111068SJohn.Danielson@Sun.COM 20211068SJohn.Danielson@Sun.COM /* 20311068SJohn.Danielson@Sun.COM * Destroy address map 20410696SDavid.Hollister@Sun.COM * 20510696SDavid.Hollister@Sun.COM * damapp: address map 20610696SDavid.Hollister@Sun.COM * 20710696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 20810696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 20910696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 21010696SDavid.Hollister@Sun.COM */ 21110696SDavid.Hollister@Sun.COM void 21210696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp) 21310696SDavid.Hollister@Sun.COM { 21410696SDavid.Hollister@Sun.COM int i; 21510696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 21610696SDavid.Hollister@Sun.COM 21710696SDavid.Hollister@Sun.COM ASSERT(mapp); 21810696SDavid.Hollister@Sun.COM 21911068SJohn.Danielson@Sun.COM DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name); 22010696SDavid.Hollister@Sun.COM 22111068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 22210696SDavid.Hollister@Sun.COM 22310696SDavid.Hollister@Sun.COM /* 22411068SJohn.Danielson@Sun.COM * prevent new reports from being added to the map 22510696SDavid.Hollister@Sun.COM */ 22611068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_DESTROYPEND; 22711068SJohn.Danielson@Sun.COM 22811068SJohn.Danielson@Sun.COM if (mapp->dam_high) { 22911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 23011068SJohn.Danielson@Sun.COM /* 23111068SJohn.Danielson@Sun.COM * wait for outstanding reports to stabilize and cancel 23211068SJohn.Danielson@Sun.COM * the timer for this map 23311068SJohn.Danielson@Sun.COM */ 234*12207SChris.Horne@Sun.COM (void) damap_sync(damapp, 0); 23511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 236*12207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0); 23710696SDavid.Hollister@Sun.COM 23811068SJohn.Danielson@Sun.COM /* 23911068SJohn.Danielson@Sun.COM * map is at full stop 24011068SJohn.Danielson@Sun.COM * release the contents of the map, invoking the 24111068SJohn.Danielson@Sun.COM * detactivation protocol as addresses are released 24211068SJohn.Danielson@Sun.COM */ 24311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 24411068SJohn.Danielson@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 24511068SJohn.Danielson@Sun.COM if (ddi_get_soft_state(mapp->dam_da, i) == NULL) 24611068SJohn.Danielson@Sun.COM continue; 24711068SJohn.Danielson@Sun.COM 24811068SJohn.Danielson@Sun.COM ASSERT(DAM_IN_REPORT(mapp, i) == 0); 24911068SJohn.Danielson@Sun.COM 25011068SJohn.Danielson@Sun.COM if (DAM_IS_STABLE(mapp, i)) { 25111068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i); 25211068SJohn.Danielson@Sun.COM } else { 25311068SJohn.Danielson@Sun.COM ddi_strid_free(mapp->dam_addr_hash, i); 25411068SJohn.Danielson@Sun.COM ddi_soft_state_free(mapp->dam_da, i); 25511068SJohn.Danielson@Sun.COM } 25611068SJohn.Danielson@Sun.COM } 25711068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash); 25811068SJohn.Danielson@Sun.COM ddi_soft_state_fini(&mapp->dam_da); 25911068SJohn.Danielson@Sun.COM kstat_delete(mapp->dam_kstatsp); 260*12207SChris.Horne@Sun.COM } else 261*12207SChris.Horne@Sun.COM mutex_exit(&mapp->dam_lock); 262*12207SChris.Horne@Sun.COM 26310696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_active_set); 26410696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_stable_set); 26510696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_report_set); 26610696SDavid.Hollister@Sun.COM mutex_destroy(&mapp->dam_lock); 267*12207SChris.Horne@Sun.COM cv_destroy(&mapp->dam_sync_cv); 26810696SDavid.Hollister@Sun.COM if (mapp->dam_name) 26910696SDavid.Hollister@Sun.COM kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); 27010696SDavid.Hollister@Sun.COM kmem_free(mapp, sizeof (*mapp)); 27110696SDavid.Hollister@Sun.COM } 27210696SDavid.Hollister@Sun.COM 27310696SDavid.Hollister@Sun.COM /* 274*12207SChris.Horne@Sun.COM * Wait for map stability. If sync was successfull then return 1. 275*12207SChris.Horne@Sun.COM * If called with a non-zero sync_usec, then a return value of 0 means a 276*12207SChris.Horne@Sun.COM * timeout occurred prior to sync completion. NOTE: if sync_usec is 277*12207SChris.Horne@Sun.COM * non-zero, it should be much longer than dam_stable_ticks. 27810696SDavid.Hollister@Sun.COM * 27910696SDavid.Hollister@Sun.COM * damapp: address map 280*12207SChris.Horne@Sun.COM * sync_usec: micorseconds until we give up on sync completion. 28110696SDavid.Hollister@Sun.COM */ 282*12207SChris.Horne@Sun.COM #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND) 28310696SDavid.Hollister@Sun.COM int 284*12207SChris.Horne@Sun.COM damap_sync(damap_t *damapp, int sync_usec) 28510696SDavid.Hollister@Sun.COM { 286*12207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp; 287*12207SChris.Horne@Sun.COM int rv; 28810696SDavid.Hollister@Sun.COM 28910696SDavid.Hollister@Sun.COM ASSERT(mapp); 29011068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name, 29111068SJohn.Danielson@Sun.COM dam_t *, mapp); 29210696SDavid.Hollister@Sun.COM 29311068SJohn.Danielson@Sun.COM /* 294*12207SChris.Horne@Sun.COM * Block when waiting for 295*12207SChris.Horne@Sun.COM * a) stabilization pending or a fullset update pending 296*12207SChris.Horne@Sun.COM * b) the report set to finalize (bitset is null) 297*12207SChris.Horne@Sun.COM * c) any scheduled timeouts to fire 29811068SJohn.Danielson@Sun.COM */ 299*12207SChris.Horne@Sun.COM rv = 1; /* return synced */ 30010696SDavid.Hollister@Sun.COM mutex_enter(&mapp->dam_lock); 301*12207SChris.Horne@Sun.COM again: while ((mapp->dam_flags & WAITFOR_FLAGS) || 302*12207SChris.Horne@Sun.COM (!bitset_is_null(&mapp->dam_report_set)) || 303*12207SChris.Horne@Sun.COM (mapp->dam_tid != 0)) { 30411068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name, 30511068SJohn.Danielson@Sun.COM dam_t *, mapp); 306*12207SChris.Horne@Sun.COM 307*12207SChris.Horne@Sun.COM /* Wait for condition relayed via timeout */ 308*12207SChris.Horne@Sun.COM if (sync_usec) { 309*12207SChris.Horne@Sun.COM if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock, 310*12207SChris.Horne@Sun.COM drv_usectohz(sync_usec), TR_MICROSEC) == -1) { 311*12207SChris.Horne@Sun.COM mapp->dam_sync_to_cnt++; 312*12207SChris.Horne@Sun.COM rv = 0; /* return timeout */ 313*12207SChris.Horne@Sun.COM break; 314*12207SChris.Horne@Sun.COM } 315*12207SChris.Horne@Sun.COM } else 316*12207SChris.Horne@Sun.COM cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock); 31710696SDavid.Hollister@Sun.COM } 31810696SDavid.Hollister@Sun.COM 319*12207SChris.Horne@Sun.COM if (rv) { 320*12207SChris.Horne@Sun.COM /* 321*12207SChris.Horne@Sun.COM * Delay one stabilization time after the apparent sync above 322*12207SChris.Horne@Sun.COM * and verify accuracy - resync if not accurate. 323*12207SChris.Horne@Sun.COM */ 324*12207SChris.Horne@Sun.COM (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock, 325*12207SChris.Horne@Sun.COM mapp->dam_stable_ticks, TR_MICROSEC); 326*12207SChris.Horne@Sun.COM if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) || 327*12207SChris.Horne@Sun.COM (!bitset_is_null(&mapp->dam_report_set)) || 328*12207SChris.Horne@Sun.COM (mapp->dam_tid != 0))) 329*12207SChris.Horne@Sun.COM goto again; 330*12207SChris.Horne@Sun.COM } 33110696SDavid.Hollister@Sun.COM mutex_exit(&mapp->dam_lock); 332*12207SChris.Horne@Sun.COM 333*12207SChris.Horne@Sun.COM DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, 334*12207SChris.Horne@Sun.COM int, rv, dam_t *, mapp); 335*12207SChris.Horne@Sun.COM return (rv); 336*12207SChris.Horne@Sun.COM } 33710696SDavid.Hollister@Sun.COM 338*12207SChris.Horne@Sun.COM /* 339*12207SChris.Horne@Sun.COM * Return 1 if active set is empty 340*12207SChris.Horne@Sun.COM */ 341*12207SChris.Horne@Sun.COM int 342*12207SChris.Horne@Sun.COM damap_is_empty(damap_t *damapp) 343*12207SChris.Horne@Sun.COM { 344*12207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp; 345*12207SChris.Horne@Sun.COM int rv; 346*12207SChris.Horne@Sun.COM 347*12207SChris.Horne@Sun.COM mutex_enter(&mapp->dam_lock); 348*12207SChris.Horne@Sun.COM rv = bitset_is_null(&mapp->dam_active_set); 349*12207SChris.Horne@Sun.COM mutex_exit(&mapp->dam_lock); 350*12207SChris.Horne@Sun.COM return (rv); 35110696SDavid.Hollister@Sun.COM } 35210696SDavid.Hollister@Sun.COM 35310696SDavid.Hollister@Sun.COM /* 35410696SDavid.Hollister@Sun.COM * Get the name of a device address map 35510696SDavid.Hollister@Sun.COM * 35610696SDavid.Hollister@Sun.COM * damapp: address map 35710696SDavid.Hollister@Sun.COM * 35810696SDavid.Hollister@Sun.COM * Returns: name 35910696SDavid.Hollister@Sun.COM */ 36010696SDavid.Hollister@Sun.COM char * 36110696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp) 36210696SDavid.Hollister@Sun.COM { 36310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 36410696SDavid.Hollister@Sun.COM 36510696SDavid.Hollister@Sun.COM return (mapp ? mapp->dam_name : "UNKNOWN_damap"); 36610696SDavid.Hollister@Sun.COM } 36710696SDavid.Hollister@Sun.COM 36810696SDavid.Hollister@Sun.COM /* 369*12207SChris.Horne@Sun.COM * Get the current size of the device address map 370*12207SChris.Horne@Sun.COM * 371*12207SChris.Horne@Sun.COM * damapp: address map 372*12207SChris.Horne@Sun.COM * 373*12207SChris.Horne@Sun.COM * Returns: size 374*12207SChris.Horne@Sun.COM */ 375*12207SChris.Horne@Sun.COM int 376*12207SChris.Horne@Sun.COM damap_size(damap_t *damapp) 377*12207SChris.Horne@Sun.COM { 378*12207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp; 379*12207SChris.Horne@Sun.COM 380*12207SChris.Horne@Sun.COM return (mapp->dam_size); 381*12207SChris.Horne@Sun.COM } 382*12207SChris.Horne@Sun.COM 383*12207SChris.Horne@Sun.COM /* 38410696SDavid.Hollister@Sun.COM * Report an address to per-address report 38510696SDavid.Hollister@Sun.COM * 38610696SDavid.Hollister@Sun.COM * damapp: address map handle 38710696SDavid.Hollister@Sun.COM * address: address in ascii string representation 38811068SJohn.Danielson@Sun.COM * addridp: address ID 38910696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data 39010696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private (passed to activate/deactivate cb) 39110696SDavid.Hollister@Sun.COM * 39210696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 39310696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 39410696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted 39510696SDavid.Hollister@Sun.COM */ 39610696SDavid.Hollister@Sun.COM int 39711068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp, 39811068SJohn.Danielson@Sun.COM nvlist_t *nvl, void *addr_priv) 39910696SDavid.Hollister@Sun.COM { 40010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 40110696SDavid.Hollister@Sun.COM id_t addrid; 40210696SDavid.Hollister@Sun.COM dam_da_t *passp; 40310696SDavid.Hollister@Sun.COM 40411068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) 40510696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 40610696SDavid.Hollister@Sun.COM 40711068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name, 40811068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 40911068SJohn.Danielson@Sun.COM 41011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 41111068SJohn.Danielson@Sun.COM if ((dam_map_alloc(mapp) != DAM_SUCCESS) || 41211068SJohn.Danielson@Sun.COM ((addrid = dam_get_addrid(mapp, address)) == 0)) { 41311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 41410696SDavid.Hollister@Sun.COM return (DAM_MAPFULL); 41510696SDavid.Hollister@Sun.COM } 41610696SDavid.Hollister@Sun.COM 41710696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 41810696SDavid.Hollister@Sun.COM ASSERT(passp != NULL); 41910696SDavid.Hollister@Sun.COM 42010696SDavid.Hollister@Sun.COM /* 42110696SDavid.Hollister@Sun.COM * If re-reporting the same address (add or remove) clear 42210696SDavid.Hollister@Sun.COM * the existing report 42310696SDavid.Hollister@Sun.COM */ 42410696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 42511068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name, 42611068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 42711068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 42811068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 42910696SDavid.Hollister@Sun.COM passp->da_jitter++; 43010696SDavid.Hollister@Sun.COM } 43110696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv; 43210696SDavid.Hollister@Sun.COM if (nvl) 43310696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 43410696SDavid.Hollister@Sun.COM 43511068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD); 43611068SJohn.Danielson@Sun.COM if (addridp != NULL) 43711068SJohn.Danielson@Sun.COM *addridp = (damap_id_t)addrid; 43811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 43910696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 44010696SDavid.Hollister@Sun.COM } 44110696SDavid.Hollister@Sun.COM 44210696SDavid.Hollister@Sun.COM /* 44310696SDavid.Hollister@Sun.COM * Report removal of address from per-address report 44410696SDavid.Hollister@Sun.COM * 44510696SDavid.Hollister@Sun.COM * damapp: address map 44610696SDavid.Hollister@Sun.COM * address: address in ascii string representation 44710696SDavid.Hollister@Sun.COM * 44810696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 44910696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 45010696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 45110696SDavid.Hollister@Sun.COM */ 45210696SDavid.Hollister@Sun.COM int 45310696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address) 45410696SDavid.Hollister@Sun.COM { 45510696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 45610696SDavid.Hollister@Sun.COM id_t addrid; 45710696SDavid.Hollister@Sun.COM dam_da_t *passp; 45810696SDavid.Hollister@Sun.COM 45911068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) 46010696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 46110696SDavid.Hollister@Sun.COM 46211068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name, 46311068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 46411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 46511068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) { 46611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 46711068SJohn.Danielson@Sun.COM return (DAM_MAPFULL); 46811068SJohn.Danielson@Sun.COM } 46911068SJohn.Danielson@Sun.COM 47011068SJohn.Danielson@Sun.COM /* 47111068SJohn.Danielson@Sun.COM * if reporting the removal of an address which is not in the map 47211068SJohn.Danielson@Sun.COM * return success 47311068SJohn.Danielson@Sun.COM */ 47410696SDavid.Hollister@Sun.COM if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { 47511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 47610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 47710696SDavid.Hollister@Sun.COM } 47810696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 47910696SDavid.Hollister@Sun.COM ASSERT(passp); 48010696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 48111068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name, 48211068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 48311068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 48411068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 48510696SDavid.Hollister@Sun.COM passp->da_jitter++; 48610696SDavid.Hollister@Sun.COM } 48711068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL); 48811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 48910696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 49010696SDavid.Hollister@Sun.COM } 49110696SDavid.Hollister@Sun.COM 49212000SReed.Liu@Sun.COM static int 49312000SReed.Liu@Sun.COM damap_addrset_flush_locked(damap_t *damapp) 49412000SReed.Liu@Sun.COM { 495*12207SChris.Horne@Sun.COM dam_t *mapp = (dam_t *)damapp; 49612000SReed.Liu@Sun.COM int idx; 49712000SReed.Liu@Sun.COM 49812000SReed.Liu@Sun.COM ASSERT(mapp); 49912000SReed.Liu@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 50012000SReed.Liu@Sun.COM if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) { 50112000SReed.Liu@Sun.COM return (DAM_EINVAL); 50212000SReed.Liu@Sun.COM } 50312000SReed.Liu@Sun.COM 50412000SReed.Liu@Sun.COM DTRACE_PROBE2(damap__addrset__flush__locked__enter, char *, 50512000SReed.Liu@Sun.COM mapp->dam_name, dam_t *, mapp); 50612000SReed.Liu@Sun.COM if (mapp->dam_flags & DAM_SETADD) { 50712000SReed.Liu@Sun.COM DTRACE_PROBE2(damap__addrset__flush__locked__reset, char *, 50812000SReed.Liu@Sun.COM mapp->dam_name, dam_t *, mapp); 50912000SReed.Liu@Sun.COM 51012000SReed.Liu@Sun.COM /* 51112000SReed.Liu@Sun.COM * cancel stabilization timeout 51212000SReed.Liu@Sun.COM */ 513*12207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0); 51412000SReed.Liu@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 51512000SReed.Liu@Sun.COM 51612000SReed.Liu@Sun.COM /* 51712000SReed.Liu@Sun.COM * clear pending reports 51812000SReed.Liu@Sun.COM */ 51912000SReed.Liu@Sun.COM for (idx = 1; idx < mapp->dam_high; idx++) { 52012000SReed.Liu@Sun.COM if (DAM_IN_REPORT(mapp, idx)) { 52112000SReed.Liu@Sun.COM dam_addr_report_release(mapp, idx); 52212000SReed.Liu@Sun.COM } 52312000SReed.Liu@Sun.COM } 52412000SReed.Liu@Sun.COM 52512000SReed.Liu@Sun.COM bitset_zero(&mapp->dam_report_set); 52612000SReed.Liu@Sun.COM mapp->dam_flags &= ~DAM_SETADD; 527*12207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv); 52812000SReed.Liu@Sun.COM } 52912000SReed.Liu@Sun.COM 53012000SReed.Liu@Sun.COM return (DAM_SUCCESS); 53112000SReed.Liu@Sun.COM } 53212000SReed.Liu@Sun.COM 53310696SDavid.Hollister@Sun.COM /* 53410696SDavid.Hollister@Sun.COM * Initiate full-set report 53510696SDavid.Hollister@Sun.COM * 53610696SDavid.Hollister@Sun.COM * damapp: address map 53710696SDavid.Hollister@Sun.COM * 53810696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 53910696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 54010696SDavid.Hollister@Sun.COM */ 54110696SDavid.Hollister@Sun.COM int 54210696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp) 54310696SDavid.Hollister@Sun.COM { 54412000SReed.Liu@Sun.COM dam_t *mapp = (dam_t *)damapp; 54512000SReed.Liu@Sun.COM int rv; 54610696SDavid.Hollister@Sun.COM 54712000SReed.Liu@Sun.COM if (mapp == NULL) { 54810696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 54912000SReed.Liu@Sun.COM } 55010696SDavid.Hollister@Sun.COM 55111068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *, 55211068SJohn.Danielson@Sun.COM mapp); 55312000SReed.Liu@Sun.COM 55411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 55511068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) { 55611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 55712000SReed.Liu@Sun.COM 55811068SJohn.Danielson@Sun.COM return (DAM_MAPFULL); 55911068SJohn.Danielson@Sun.COM } 56012000SReed.Liu@Sun.COM 56112000SReed.Liu@Sun.COM rv = damap_addrset_flush_locked(damapp); 56212000SReed.Liu@Sun.COM if (rv == DAM_SUCCESS) { 56312000SReed.Liu@Sun.COM mapp->dam_flags |= DAM_SETADD; 56412000SReed.Liu@Sun.COM } 56512000SReed.Liu@Sun.COM mutex_exit(&mapp->dam_lock); 56612000SReed.Liu@Sun.COM 56712000SReed.Liu@Sun.COM return (rv); 56812000SReed.Liu@Sun.COM } 56911068SJohn.Danielson@Sun.COM 57012000SReed.Liu@Sun.COM /* 57112000SReed.Liu@Sun.COM * Cancel full-set report 57212000SReed.Liu@Sun.COM * 573*12207SChris.Horne@Sun.COM * damapp: address map 57412000SReed.Liu@Sun.COM * 575*12207SChris.Horne@Sun.COM * Returns: DAM_SUCCESS 576*12207SChris.Horne@Sun.COM * DAM_EINVAL Invalid argument(s) 57712000SReed.Liu@Sun.COM */ 57812000SReed.Liu@Sun.COM int 57912000SReed.Liu@Sun.COM damap_addrset_flush(damap_t *damapp) 58012000SReed.Liu@Sun.COM { 58112000SReed.Liu@Sun.COM int rv; 58212000SReed.Liu@Sun.COM dam_t *mapp = (dam_t *)damapp; 58312000SReed.Liu@Sun.COM 58412000SReed.Liu@Sun.COM if (mapp == NULL) { 58512000SReed.Liu@Sun.COM return (DAM_EINVAL); 58610696SDavid.Hollister@Sun.COM } 58712000SReed.Liu@Sun.COM 58812000SReed.Liu@Sun.COM DTRACE_PROBE2(damap__addrset__flush, char *, mapp->dam_name, 58912000SReed.Liu@Sun.COM dam_t *, mapp); 59012000SReed.Liu@Sun.COM 59112000SReed.Liu@Sun.COM mutex_enter(&mapp->dam_lock); 59212000SReed.Liu@Sun.COM rv = damap_addrset_flush_locked(damapp); 59311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 59412000SReed.Liu@Sun.COM 59512000SReed.Liu@Sun.COM return (rv); 59610696SDavid.Hollister@Sun.COM } 59710696SDavid.Hollister@Sun.COM 59810696SDavid.Hollister@Sun.COM /* 59910696SDavid.Hollister@Sun.COM * Report address to full-set report 60010696SDavid.Hollister@Sun.COM * 60110696SDavid.Hollister@Sun.COM * damapp: address map handle 60210696SDavid.Hollister@Sun.COM * address: address in ascii string representation 60310696SDavid.Hollister@Sun.COM * rindx: index if address stabilizes 60410696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data 60510696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private data (passed to activate/release cb) 60610696SDavid.Hollister@Sun.COM * 60710696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 60810696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 60910696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted 61010696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 61110696SDavid.Hollister@Sun.COM */ 61210696SDavid.Hollister@Sun.COM int 61310696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx, 61410696SDavid.Hollister@Sun.COM nvlist_t *nvl, void *addr_priv) 61510696SDavid.Hollister@Sun.COM { 61610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 61710696SDavid.Hollister@Sun.COM id_t addrid; 61810696SDavid.Hollister@Sun.COM dam_da_t *passp; 61910696SDavid.Hollister@Sun.COM 62011068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) 62110696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 62210696SDavid.Hollister@Sun.COM 62311068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name, 62411068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 62510696SDavid.Hollister@Sun.COM 62611068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 62711068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) { 62811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 62911068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 63011068SJohn.Danielson@Sun.COM } 63111068SJohn.Danielson@Sun.COM 63210696SDavid.Hollister@Sun.COM if ((addrid = dam_get_addrid(mapp, address)) == 0) { 63311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 63410696SDavid.Hollister@Sun.COM return (DAM_MAPFULL); 63510696SDavid.Hollister@Sun.COM } 63610696SDavid.Hollister@Sun.COM 63710696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 63810696SDavid.Hollister@Sun.COM ASSERT(passp); 63910696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 64011068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addrset__add__jitter, char *, 64111068SJohn.Danielson@Sun.COM mapp->dam_name, char *, address, dam_t *, mapp); 64211068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 64310696SDavid.Hollister@Sun.COM passp->da_jitter++; 64410696SDavid.Hollister@Sun.COM } 64510696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv; 64610696SDavid.Hollister@Sun.COM if (nvl) 64710696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 64810696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid); 64910696SDavid.Hollister@Sun.COM if (ridx) 65010696SDavid.Hollister@Sun.COM *ridx = (damap_id_t)addrid; 65111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 65210696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 65310696SDavid.Hollister@Sun.COM } 65410696SDavid.Hollister@Sun.COM 65510696SDavid.Hollister@Sun.COM /* 65610696SDavid.Hollister@Sun.COM * Commit full-set report for stabilization 65710696SDavid.Hollister@Sun.COM * 65810696SDavid.Hollister@Sun.COM * damapp: address map handle 65910696SDavid.Hollister@Sun.COM * flags: (currently 0) 66010696SDavid.Hollister@Sun.COM * 66110696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 66210696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 66310696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 66410696SDavid.Hollister@Sun.COM */ 66510696SDavid.Hollister@Sun.COM int 66610696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags) 66710696SDavid.Hollister@Sun.COM { 66810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 66910696SDavid.Hollister@Sun.COM int i; 67010696SDavid.Hollister@Sun.COM 67111068SJohn.Danielson@Sun.COM if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) 67210696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 67310696SDavid.Hollister@Sun.COM 67411068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name, 67511068SJohn.Danielson@Sun.COM dam_t *, mapp); 67610696SDavid.Hollister@Sun.COM 67711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 67811068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) { 67911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 68011068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 68111068SJohn.Danielson@Sun.COM } 68211068SJohn.Danielson@Sun.COM 68311068SJohn.Danielson@Sun.COM if (flags & DAMAP_END_RESET) { 68411068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__end__reset, char *, 68511068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 686*12207SChris.Horne@Sun.COM dam_sched_timeout(NULL, mapp, 0); 68710696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) 68810696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, i)) 68911068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, i); 69010696SDavid.Hollister@Sun.COM } else { 69110696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime(); 692*12207SChris.Horne@Sun.COM dam_sched_timeout(dam_addrset_stable_cb, mapp, 693*12207SChris.Horne@Sun.COM mapp->dam_stable_ticks); 69410696SDavid.Hollister@Sun.COM } 69511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 69610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 69710696SDavid.Hollister@Sun.COM } 69810696SDavid.Hollister@Sun.COM 69910696SDavid.Hollister@Sun.COM /* 70010696SDavid.Hollister@Sun.COM * Return nvlist registered with reported address 70110696SDavid.Hollister@Sun.COM * 70210696SDavid.Hollister@Sun.COM * damapp: address map handle 70311068SJohn.Danielson@Sun.COM * addrid: address ID 70410696SDavid.Hollister@Sun.COM * 70510696SDavid.Hollister@Sun.COM * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) 70610696SDavid.Hollister@Sun.COM * NULL 70710696SDavid.Hollister@Sun.COM */ 70810696SDavid.Hollister@Sun.COM nvlist_t * 70910696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid) 71010696SDavid.Hollister@Sun.COM { 71110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 71210696SDavid.Hollister@Sun.COM dam_da_t *pass; 71310696SDavid.Hollister@Sun.COM 71411068SJohn.Danielson@Sun.COM if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) { 71511068SJohn.Danielson@Sun.COM if (pass = ddi_get_soft_state(mapp->dam_da, addrid)) 71610696SDavid.Hollister@Sun.COM return (pass->da_nvl); 71710696SDavid.Hollister@Sun.COM } 71810696SDavid.Hollister@Sun.COM return (NULL); 71910696SDavid.Hollister@Sun.COM } 72010696SDavid.Hollister@Sun.COM 72110696SDavid.Hollister@Sun.COM /* 72210696SDavid.Hollister@Sun.COM * Return address string 72310696SDavid.Hollister@Sun.COM * 72410696SDavid.Hollister@Sun.COM * damapp: address map handle 72511068SJohn.Danielson@Sun.COM * addrid: address ID 72610696SDavid.Hollister@Sun.COM * 72710696SDavid.Hollister@Sun.COM * Returns: char * Address string 72810696SDavid.Hollister@Sun.COM * NULL 72910696SDavid.Hollister@Sun.COM */ 73010696SDavid.Hollister@Sun.COM char * 73111068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid) 73210696SDavid.Hollister@Sun.COM { 73310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 73410696SDavid.Hollister@Sun.COM 73511068SJohn.Danielson@Sun.COM if (mapp->dam_high) 73611068SJohn.Danielson@Sun.COM return (ddi_strid_id2str(mapp->dam_addr_hash, addrid)); 73711068SJohn.Danielson@Sun.COM else 73811068SJohn.Danielson@Sun.COM return (NULL); 73910696SDavid.Hollister@Sun.COM } 74010696SDavid.Hollister@Sun.COM 74110696SDavid.Hollister@Sun.COM /* 74210696SDavid.Hollister@Sun.COM * Release address reference in map 74310696SDavid.Hollister@Sun.COM * 74410696SDavid.Hollister@Sun.COM * damapp: address map handle 74511068SJohn.Danielson@Sun.COM * addrid: address ID 74610696SDavid.Hollister@Sun.COM */ 74710696SDavid.Hollister@Sun.COM void 74810696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid) 74910696SDavid.Hollister@Sun.COM { 75010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 75111068SJohn.Danielson@Sun.COM dam_da_t *passp; 75211068SJohn.Danielson@Sun.COM char *addr; 75310696SDavid.Hollister@Sun.COM 75411068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 75511068SJohn.Danielson@Sun.COM ASSERT(passp); 75611068SJohn.Danielson@Sun.COM 75711068SJohn.Danielson@Sun.COM addr = damap_id2addr(damapp, addrid); 75811068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr, 75911068SJohn.Danielson@Sun.COM dam_t *, mapp, int, passp->da_ref); 76011068SJohn.Danielson@Sun.COM 76111068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 76211068SJohn.Danielson@Sun.COM 76311068SJohn.Danielson@Sun.COM /* 76411068SJohn.Danielson@Sun.COM * teardown address if last outstanding reference 76511068SJohn.Danielson@Sun.COM */ 76611068SJohn.Danielson@Sun.COM if (--passp->da_ref == 0) 76711068SJohn.Danielson@Sun.COM dam_addr_release(mapp, (id_t)addrid); 76811068SJohn.Danielson@Sun.COM 76911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 77010696SDavid.Hollister@Sun.COM } 77110696SDavid.Hollister@Sun.COM 77210696SDavid.Hollister@Sun.COM /* 77310696SDavid.Hollister@Sun.COM * Return current reference count on address reference in map 77410696SDavid.Hollister@Sun.COM * 77510696SDavid.Hollister@Sun.COM * damapp: address map handle 77611068SJohn.Danielson@Sun.COM * addrid: address ID 77710696SDavid.Hollister@Sun.COM * 77810696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 77910696SDavid.Hollister@Sun.COM * DAM_FAILURE 78010696SDavid.Hollister@Sun.COM */ 78110696SDavid.Hollister@Sun.COM int 78211068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid) 78310696SDavid.Hollister@Sun.COM { 78410696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 78510696SDavid.Hollister@Sun.COM dam_da_t *passp; 78610696SDavid.Hollister@Sun.COM int ref = -1; 78710696SDavid.Hollister@Sun.COM 78811068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 78910696SDavid.Hollister@Sun.COM if (passp) 79010696SDavid.Hollister@Sun.COM ref = passp->da_ref; 79111068SJohn.Danielson@Sun.COM 79210696SDavid.Hollister@Sun.COM return (ref); 79310696SDavid.Hollister@Sun.COM } 79410696SDavid.Hollister@Sun.COM 79510696SDavid.Hollister@Sun.COM /* 79610696SDavid.Hollister@Sun.COM * Return next address ID in list 79710696SDavid.Hollister@Sun.COM * 79810696SDavid.Hollister@Sun.COM * damapp: address map handle 79910696SDavid.Hollister@Sun.COM * damap_list: address ID list passed to config|unconfig 80010696SDavid.Hollister@Sun.COM * returned by look by lookup_all 80110696SDavid.Hollister@Sun.COM * last: last ID returned, 0 is start of list 80210696SDavid.Hollister@Sun.COM * 80310696SDavid.Hollister@Sun.COM * Returns: addrid Next ID from the list 80410696SDavid.Hollister@Sun.COM * 0 End of the list 80510696SDavid.Hollister@Sun.COM */ 80610696SDavid.Hollister@Sun.COM damap_id_t 80710696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last) 80810696SDavid.Hollister@Sun.COM { 80910696SDavid.Hollister@Sun.COM int i, start; 81010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 81110696SDavid.Hollister@Sun.COM bitset_t *dam_list = (bitset_t *)damap_list; 81210696SDavid.Hollister@Sun.COM 81310696SDavid.Hollister@Sun.COM if (!mapp || !dam_list) 81410696SDavid.Hollister@Sun.COM return ((damap_id_t)0); 81510696SDavid.Hollister@Sun.COM 81610696SDavid.Hollister@Sun.COM start = (int)last + 1; 81711068SJohn.Danielson@Sun.COM for (i = start; i < mapp->dam_high; i++) { 81811068SJohn.Danielson@Sun.COM if (bitset_in_set(dam_list, i)) { 81910696SDavid.Hollister@Sun.COM return ((damap_id_t)i); 82011068SJohn.Danielson@Sun.COM } 82111068SJohn.Danielson@Sun.COM } 82210696SDavid.Hollister@Sun.COM return ((damap_id_t)0); 82310696SDavid.Hollister@Sun.COM } 82410696SDavid.Hollister@Sun.COM 82510696SDavid.Hollister@Sun.COM /* 82610696SDavid.Hollister@Sun.COM * Set config private data 82710696SDavid.Hollister@Sun.COM * 82810696SDavid.Hollister@Sun.COM * damapp: address map handle 82911068SJohn.Danielson@Sun.COM * addrid: address ID 83010696SDavid.Hollister@Sun.COM * cfg_priv: configuration private data 83110696SDavid.Hollister@Sun.COM * 83210696SDavid.Hollister@Sun.COM */ 83310696SDavid.Hollister@Sun.COM void 83411068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv) 83510696SDavid.Hollister@Sun.COM { 83610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 83710696SDavid.Hollister@Sun.COM dam_da_t *passp; 83810696SDavid.Hollister@Sun.COM 83911068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 84011068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 84110696SDavid.Hollister@Sun.COM if (!passp) { 84211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 84310696SDavid.Hollister@Sun.COM return; 84410696SDavid.Hollister@Sun.COM } 84510696SDavid.Hollister@Sun.COM passp->da_cfg_priv = cfg_priv; 84611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 84710696SDavid.Hollister@Sun.COM } 84810696SDavid.Hollister@Sun.COM 84910696SDavid.Hollister@Sun.COM /* 85010696SDavid.Hollister@Sun.COM * Get config private data 85110696SDavid.Hollister@Sun.COM * 85210696SDavid.Hollister@Sun.COM * damapp: address map handle 85311068SJohn.Danielson@Sun.COM * addrid: address ID 85410696SDavid.Hollister@Sun.COM * 85510696SDavid.Hollister@Sun.COM * Returns: configuration private data 85610696SDavid.Hollister@Sun.COM */ 85710696SDavid.Hollister@Sun.COM void * 85811068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid) 85910696SDavid.Hollister@Sun.COM { 86010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 86110696SDavid.Hollister@Sun.COM dam_da_t *passp; 86210696SDavid.Hollister@Sun.COM void *rv; 86310696SDavid.Hollister@Sun.COM 86411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 86511068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 86610696SDavid.Hollister@Sun.COM if (!passp) { 86711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 86810696SDavid.Hollister@Sun.COM return (NULL); 86910696SDavid.Hollister@Sun.COM } 87010696SDavid.Hollister@Sun.COM rv = passp->da_cfg_priv; 87111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 87210696SDavid.Hollister@Sun.COM return (rv); 87310696SDavid.Hollister@Sun.COM } 87410696SDavid.Hollister@Sun.COM 87510696SDavid.Hollister@Sun.COM /* 87610696SDavid.Hollister@Sun.COM * Lookup a single address in the active address map 87710696SDavid.Hollister@Sun.COM * 87810696SDavid.Hollister@Sun.COM * damapp: address map handle 87910696SDavid.Hollister@Sun.COM * address: address string 88010696SDavid.Hollister@Sun.COM * 88110696SDavid.Hollister@Sun.COM * Returns: ID of active/stable address 88210696SDavid.Hollister@Sun.COM * 0 Address not in stable set 88310696SDavid.Hollister@Sun.COM * 88410696SDavid.Hollister@Sun.COM * Future: Allow the caller to wait for stabilize before returning not found. 88510696SDavid.Hollister@Sun.COM */ 88610696SDavid.Hollister@Sun.COM damap_id_t 88710696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address) 88810696SDavid.Hollister@Sun.COM { 88910696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 89010696SDavid.Hollister@Sun.COM id_t addrid = 0; 89110696SDavid.Hollister@Sun.COM dam_da_t *passp = NULL; 89210696SDavid.Hollister@Sun.COM 89311068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name, 89411068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 89511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 89611068SJohn.Danielson@Sun.COM if (!mapp->dam_high) 89711068SJohn.Danielson@Sun.COM addrid = 0; 89811068SJohn.Danielson@Sun.COM else 89911068SJohn.Danielson@Sun.COM addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); 90010696SDavid.Hollister@Sun.COM if (addrid) { 90110696SDavid.Hollister@Sun.COM if (DAM_IS_STABLE(mapp, addrid)) { 90210696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 90310696SDavid.Hollister@Sun.COM ASSERT(passp); 90410696SDavid.Hollister@Sun.COM if (passp) { 90510696SDavid.Hollister@Sun.COM passp->da_ref++; 90610696SDavid.Hollister@Sun.COM } else { 90710696SDavid.Hollister@Sun.COM addrid = 0; 90810696SDavid.Hollister@Sun.COM } 90910696SDavid.Hollister@Sun.COM } else { 91010696SDavid.Hollister@Sun.COM addrid = 0; 91110696SDavid.Hollister@Sun.COM } 91210696SDavid.Hollister@Sun.COM } 91311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 91411068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name, 91511068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp, int, addrid); 91610696SDavid.Hollister@Sun.COM return ((damap_id_t)addrid); 91710696SDavid.Hollister@Sun.COM } 91810696SDavid.Hollister@Sun.COM 91910696SDavid.Hollister@Sun.COM 92010696SDavid.Hollister@Sun.COM /* 92110696SDavid.Hollister@Sun.COM * Return the list of stable addresses in the map 92210696SDavid.Hollister@Sun.COM * 92310696SDavid.Hollister@Sun.COM * damapp: address map handle 92410696SDavid.Hollister@Sun.COM * id_listp: pointer to list of address IDs in stable map (returned) 92510696SDavid.Hollister@Sun.COM * 92610696SDavid.Hollister@Sun.COM * Returns: # of entries returned in alist 92710696SDavid.Hollister@Sun.COM */ 92810696SDavid.Hollister@Sun.COM int 92910696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp) 93010696SDavid.Hollister@Sun.COM { 93110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 93210696SDavid.Hollister@Sun.COM int mapsz = mapp->dam_size; 93310696SDavid.Hollister@Sun.COM int n_ids, i; 93410696SDavid.Hollister@Sun.COM bitset_t *bsp; 93511068SJohn.Danielson@Sun.COM char *addrp; 93610696SDavid.Hollister@Sun.COM dam_da_t *passp; 93710696SDavid.Hollister@Sun.COM 93811068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name, 93911068SJohn.Danielson@Sun.COM dam_t *, mapp); 94011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 94111068SJohn.Danielson@Sun.COM if (!mapp->dam_high) { 94211068SJohn.Danielson@Sun.COM *id_listp = (damap_id_list_t)NULL; 94311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 94411068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup__all__nomap, char *, 94511068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp, int, 0); 94611068SJohn.Danielson@Sun.COM return (0); 94711068SJohn.Danielson@Sun.COM } 94810696SDavid.Hollister@Sun.COM bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); 94910696SDavid.Hollister@Sun.COM bitset_init(bsp); 95010696SDavid.Hollister@Sun.COM bitset_resize(bsp, mapsz); 95110696SDavid.Hollister@Sun.COM bitset_copy(&mapp->dam_active_set, bsp); 95210696SDavid.Hollister@Sun.COM for (n_ids = 0, i = 1; i < mapsz; i++) { 95310696SDavid.Hollister@Sun.COM if (bitset_in_set(bsp, i)) { 95410696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i); 95510696SDavid.Hollister@Sun.COM ASSERT(passp); 95610696SDavid.Hollister@Sun.COM if (passp) { 95711068SJohn.Danielson@Sun.COM addrp = damap_id2addr(damapp, i); 95811068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup__all__item, char *, 95911068SJohn.Danielson@Sun.COM mapp->dam_name, char *, addrp, dam_t *, 96011068SJohn.Danielson@Sun.COM mapp); 96110696SDavid.Hollister@Sun.COM passp->da_ref++; 96210696SDavid.Hollister@Sun.COM n_ids++; 96310696SDavid.Hollister@Sun.COM } 96410696SDavid.Hollister@Sun.COM } 96510696SDavid.Hollister@Sun.COM } 96610696SDavid.Hollister@Sun.COM if (n_ids) { 96710696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)bsp; 96811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 96910696SDavid.Hollister@Sun.COM return (n_ids); 97010696SDavid.Hollister@Sun.COM } else { 97110696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)NULL; 97210696SDavid.Hollister@Sun.COM bitset_fini(bsp); 97310696SDavid.Hollister@Sun.COM kmem_free(bsp, sizeof (*bsp)); 97411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 97510696SDavid.Hollister@Sun.COM return (0); 97610696SDavid.Hollister@Sun.COM } 97710696SDavid.Hollister@Sun.COM } 97810696SDavid.Hollister@Sun.COM 97910696SDavid.Hollister@Sun.COM /* 98010696SDavid.Hollister@Sun.COM * Release the address list returned by damap_lookup_all() 98110696SDavid.Hollister@Sun.COM * 98210696SDavid.Hollister@Sun.COM * mapp: address map handle 98310696SDavid.Hollister@Sun.COM * id_list: list of address IDs returned in damap_lookup_all() 98410696SDavid.Hollister@Sun.COM */ 98510696SDavid.Hollister@Sun.COM void 98610696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list) 98710696SDavid.Hollister@Sun.COM { 98810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 98910696SDavid.Hollister@Sun.COM int i; 99010696SDavid.Hollister@Sun.COM 99110696SDavid.Hollister@Sun.COM if (id_list == NULL) 99210696SDavid.Hollister@Sun.COM return; 99310696SDavid.Hollister@Sun.COM 99411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 99510696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 99610696SDavid.Hollister@Sun.COM if (bitset_in_set((bitset_t *)id_list, i)) 99711068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, i); 99810696SDavid.Hollister@Sun.COM } 99911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 100010696SDavid.Hollister@Sun.COM bitset_fini((bitset_t *)id_list); 100110696SDavid.Hollister@Sun.COM kmem_free((void *)id_list, sizeof (bitset_t)); 100210696SDavid.Hollister@Sun.COM } 100310696SDavid.Hollister@Sun.COM 100410696SDavid.Hollister@Sun.COM /* 100511068SJohn.Danielson@Sun.COM * activate an address that has passed the stabilization interval 100611068SJohn.Danielson@Sun.COM */ 100711068SJohn.Danielson@Sun.COM static void 100811068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid) 100911068SJohn.Danielson@Sun.COM { 101011068SJohn.Danielson@Sun.COM dam_da_t *passp; 101111068SJohn.Danielson@Sun.COM int config_rv; 101211068SJohn.Danielson@Sun.COM char *addrstr; 101311068SJohn.Danielson@Sun.COM 101411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 101511068SJohn.Danielson@Sun.COM bitset_add(&mapp->dam_active_set, addrid); 101611068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 101711068SJohn.Danielson@Sun.COM ASSERT(passp); 101811068SJohn.Danielson@Sun.COM 101911068SJohn.Danielson@Sun.COM /* 102011068SJohn.Danielson@Sun.COM * copy the reported nvlist and provider private data 102111068SJohn.Danielson@Sun.COM */ 102211068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 102311068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name, 102411068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 102511068SJohn.Danielson@Sun.COM passp->da_nvl = passp->da_nvl_rpt; 102611068SJohn.Danielson@Sun.COM passp->da_ppriv = passp->da_ppriv_rpt; 102711068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL; 102811068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL; 102911068SJohn.Danielson@Sun.COM passp->da_last_stable = gethrtime(); 103011068SJohn.Danielson@Sun.COM passp->da_stable_cnt++; 103111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 103211068SJohn.Danielson@Sun.COM if (mapp->dam_activate_cb) { 103311068SJohn.Danielson@Sun.COM (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr, 103411068SJohn.Danielson@Sun.COM addrid, &passp->da_ppriv_rpt); 103511068SJohn.Danielson@Sun.COM } 103611068SJohn.Danielson@Sun.COM 103711068SJohn.Danielson@Sun.COM /* 103811068SJohn.Danielson@Sun.COM * call the address-specific configuration action as part of 103911068SJohn.Danielson@Sun.COM * activation. 104011068SJohn.Danielson@Sun.COM */ 104111068SJohn.Danielson@Sun.COM config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, 104211068SJohn.Danielson@Sun.COM addrid); 104311068SJohn.Danielson@Sun.COM if (config_rv != DAM_SUCCESS) { 104411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 104511068SJohn.Danielson@Sun.COM passp->da_flags |= DA_FAILED_CONFIG; 104611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 104711068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__activate__config__failure, 104811068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); 104911363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr, 105011363SReed.Liu@Sun.COM DAMAP_DEACT_RSN_CFG_FAIL); 105111363SReed.Liu@Sun.COM } else { 105211363SReed.Liu@Sun.COM DTRACE_PROBE3(damap__addr__activate__end, char *, 105311363SReed.Liu@Sun.COM mapp->dam_name, char *, addrstr, dam_t *, mapp); 105411068SJohn.Danielson@Sun.COM } 105511068SJohn.Danielson@Sun.COM } 105611068SJohn.Danielson@Sun.COM 105711068SJohn.Danielson@Sun.COM /* 105811068SJohn.Danielson@Sun.COM * deactivate a previously stable address 105911068SJohn.Danielson@Sun.COM */ 106011068SJohn.Danielson@Sun.COM static void 106111068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid) 106211068SJohn.Danielson@Sun.COM { 106311068SJohn.Danielson@Sun.COM char *addrstr; 106411068SJohn.Danielson@Sun.COM 106511068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 106611068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name, 106711068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 106811068SJohn.Danielson@Sun.COM 106911068SJohn.Danielson@Sun.COM /* 107011068SJohn.Danielson@Sun.COM * call the unconfiguration callback 107111068SJohn.Danielson@Sun.COM */ 107211068SJohn.Danielson@Sun.COM (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid); 107311363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE); 107411363SReed.Liu@Sun.COM } 107511363SReed.Liu@Sun.COM 107611363SReed.Liu@Sun.COM static void 107711363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr, 107811363SReed.Liu@Sun.COM damap_deact_rsn_t deact_rsn) 107911363SReed.Liu@Sun.COM { 108011363SReed.Liu@Sun.COM dam_da_t *passp; 108111363SReed.Liu@Sun.COM 108211068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 108311068SJohn.Danielson@Sun.COM ASSERT(passp); 108411068SJohn.Danielson@Sun.COM if (mapp->dam_deactivate_cb) 108511068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, 108611068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid), 108711363SReed.Liu@Sun.COM addrid, passp->da_ppriv, deact_rsn); 108811068SJohn.Danielson@Sun.COM 108911068SJohn.Danielson@Sun.COM /* 109011068SJohn.Danielson@Sun.COM * clear the active bit and free the backing info for 109111068SJohn.Danielson@Sun.COM * this address 109211068SJohn.Danielson@Sun.COM */ 109311068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 109411068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_active_set, addrid); 109511068SJohn.Danielson@Sun.COM passp->da_ppriv = NULL; 109611068SJohn.Danielson@Sun.COM if (passp->da_nvl) 109711068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl); 109811068SJohn.Danielson@Sun.COM passp->da_nvl = NULL; 109911068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL; 110011068SJohn.Danielson@Sun.COM if (passp->da_nvl_rpt) 110111068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl_rpt); 110211068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL; 110311068SJohn.Danielson@Sun.COM 110411068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name, 110511068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 110611068SJohn.Danielson@Sun.COM 110711068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, addrid); 110811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 110911068SJohn.Danielson@Sun.COM } 111011068SJohn.Danielson@Sun.COM 111111068SJohn.Danielson@Sun.COM /* 111211068SJohn.Danielson@Sun.COM * taskq callback for multi-thread activation 111311068SJohn.Danielson@Sun.COM */ 111411068SJohn.Danielson@Sun.COM static void 111511068SJohn.Danielson@Sun.COM dam_tq_config(void *arg) 111611068SJohn.Danielson@Sun.COM { 111711068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg; 111811068SJohn.Danielson@Sun.COM 111911068SJohn.Danielson@Sun.COM dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id); 112011068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd)); 112111068SJohn.Danielson@Sun.COM } 112211068SJohn.Danielson@Sun.COM 112311068SJohn.Danielson@Sun.COM /* 112411068SJohn.Danielson@Sun.COM * taskq callback for multi-thread deactivation 112511068SJohn.Danielson@Sun.COM */ 112611068SJohn.Danielson@Sun.COM static void 112711068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg) 112811068SJohn.Danielson@Sun.COM { 112911068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg; 113011068SJohn.Danielson@Sun.COM 113111068SJohn.Danielson@Sun.COM dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id); 113211068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd)); 113311068SJohn.Danielson@Sun.COM } 113411068SJohn.Danielson@Sun.COM 113511068SJohn.Danielson@Sun.COM /* 113610696SDavid.Hollister@Sun.COM * Activate a set of stabilized addresses 113710696SDavid.Hollister@Sun.COM */ 113810696SDavid.Hollister@Sun.COM static void 113911068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate) 114010696SDavid.Hollister@Sun.COM { 114111068SJohn.Danielson@Sun.COM 114211068SJohn.Danielson@Sun.COM int i, nset; 114311068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL; 114411068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL; 114511068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN]; 114611068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri; 114710696SDavid.Hollister@Sun.COM 114811068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) { 114911068SJohn.Danielson@Sun.COM /* 115011068SJohn.Danielson@Sun.COM * calculate the # of taskq threads to create 115111068SJohn.Danielson@Sun.COM */ 115211068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++) 115311068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i)) 115411068SJohn.Danielson@Sun.COM nset++; 115511068SJohn.Danielson@Sun.COM ASSERT(nset); 115611068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name); 115711068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1, 115811068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE); 115911068SJohn.Danielson@Sun.COM } 116010696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 116111068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i)) { 116211068SJohn.Danielson@Sun.COM if (!tqp) 116311068SJohn.Danielson@Sun.COM dam_addr_activate(mapp, i); 116411068SJohn.Danielson@Sun.COM else { 116511068SJohn.Danielson@Sun.COM /* 116611068SJohn.Danielson@Sun.COM * multi-threaded activation 116711068SJohn.Danielson@Sun.COM */ 116811068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); 116911068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp; 117011068SJohn.Danielson@Sun.COM tqd->tqd_id = i; 117111068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp, dam_tq_config, 117211854SChris.Horne@Sun.COM tqd, TQ_SLEEP); 117311068SJohn.Danielson@Sun.COM } 117410696SDavid.Hollister@Sun.COM } 117511068SJohn.Danielson@Sun.COM } 117611068SJohn.Danielson@Sun.COM if (tqp) { 117711068SJohn.Danielson@Sun.COM taskq_wait(tqp); 117811068SJohn.Danielson@Sun.COM taskq_destroy(tqp); 117910696SDavid.Hollister@Sun.COM } 118010696SDavid.Hollister@Sun.COM } 118110696SDavid.Hollister@Sun.COM 118210696SDavid.Hollister@Sun.COM /* 118311068SJohn.Danielson@Sun.COM * Deactivate a set of stabilized addresses 118410696SDavid.Hollister@Sun.COM */ 118510696SDavid.Hollister@Sun.COM static void 118611068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate) 118710696SDavid.Hollister@Sun.COM { 118811068SJohn.Danielson@Sun.COM int i, nset; 118911068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL; 119011068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL; 119111068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN]; 119211068SJohn.Danielson@Sun.COM 119311068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name, 119411068SJohn.Danielson@Sun.COM dam_t *, mapp); 119510696SDavid.Hollister@Sun.COM 119611068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) { 119711068SJohn.Danielson@Sun.COM /* 119811068SJohn.Danielson@Sun.COM * compute the # of taskq threads to dispatch 119911068SJohn.Danielson@Sun.COM */ 120011068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++) 120111068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i)) 120211068SJohn.Danielson@Sun.COM nset++; 120311068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "deactv-%s", 120411068SJohn.Danielson@Sun.COM mapp->dam_name); 120511068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1, 120611068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE); 120711068SJohn.Danielson@Sun.COM } 120810696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 120911068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i)) { 121011068SJohn.Danielson@Sun.COM if (!tqp) { 121111068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i); 121211068SJohn.Danielson@Sun.COM } else { 121311068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); 121411068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp; 121511068SJohn.Danielson@Sun.COM tqd->tqd_id = i; 121611068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp, 121711854SChris.Horne@Sun.COM dam_tq_unconfig, tqd, TQ_SLEEP); 121811068SJohn.Danielson@Sun.COM } 121910696SDavid.Hollister@Sun.COM } 122010696SDavid.Hollister@Sun.COM } 122111068SJohn.Danielson@Sun.COM 122211068SJohn.Danielson@Sun.COM if (tqp) { 122311068SJohn.Danielson@Sun.COM taskq_wait(tqp); 122411068SJohn.Danielson@Sun.COM taskq_destroy(tqp); 122511068SJohn.Danielson@Sun.COM } 122610696SDavid.Hollister@Sun.COM } 122710696SDavid.Hollister@Sun.COM 122810696SDavid.Hollister@Sun.COM /* 122911068SJohn.Danielson@Sun.COM * Release a previously activated address 123010696SDavid.Hollister@Sun.COM */ 123110696SDavid.Hollister@Sun.COM static void 123211068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid) 123310696SDavid.Hollister@Sun.COM { 123410696SDavid.Hollister@Sun.COM dam_da_t *passp; 123511068SJohn.Danielson@Sun.COM char *addrstr; 123610696SDavid.Hollister@Sun.COM 123711068SJohn.Danielson@Sun.COM 123811068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 123910696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 124010696SDavid.Hollister@Sun.COM ASSERT(passp); 124110696SDavid.Hollister@Sun.COM 124211068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 124311068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name, 124411068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 124510696SDavid.Hollister@Sun.COM 124610696SDavid.Hollister@Sun.COM /* 124711068SJohn.Danielson@Sun.COM * defer releasing the address until outstanding references 124811068SJohn.Danielson@Sun.COM * are released 124910696SDavid.Hollister@Sun.COM */ 125011068SJohn.Danielson@Sun.COM if (passp->da_ref > 1) { 125111068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__addr__release__outstanding__refs, 125211068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp, 125311068SJohn.Danielson@Sun.COM int, passp->da_ref); 125410696SDavid.Hollister@Sun.COM return; 125511068SJohn.Danielson@Sun.COM } 125610696SDavid.Hollister@Sun.COM 125710696SDavid.Hollister@Sun.COM /* 125811068SJohn.Danielson@Sun.COM * allow pending reports to stabilize 125910696SDavid.Hollister@Sun.COM */ 126011068SJohn.Danielson@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 126111068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__release__report__pending, 126211068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); 126310696SDavid.Hollister@Sun.COM return; 126410696SDavid.Hollister@Sun.COM } 126511068SJohn.Danielson@Sun.COM 126610696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid); 126710696SDavid.Hollister@Sun.COM ddi_soft_state_free(mapp->dam_da, addrid); 126810696SDavid.Hollister@Sun.COM } 126910696SDavid.Hollister@Sun.COM 127010696SDavid.Hollister@Sun.COM /* 127110696SDavid.Hollister@Sun.COM * process stabilized address reports 127210696SDavid.Hollister@Sun.COM */ 127310696SDavid.Hollister@Sun.COM static void 127411068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg) 127510696SDavid.Hollister@Sun.COM { 127610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 127710696SDavid.Hollister@Sun.COM bitset_t delta; 127810696SDavid.Hollister@Sun.COM bitset_t cfg; 127910696SDavid.Hollister@Sun.COM bitset_t uncfg; 128010696SDavid.Hollister@Sun.COM int has_cfg, has_uncfg; 128111068SJohn.Danielson@Sun.COM uint32_t i, n_active; 128211068SJohn.Danielson@Sun.COM 128311068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name, 128411068SJohn.Danielson@Sun.COM dam_t *, mapp); 128510696SDavid.Hollister@Sun.COM 128610696SDavid.Hollister@Sun.COM bitset_init(&delta); 128710696SDavid.Hollister@Sun.COM bitset_resize(&delta, mapp->dam_size); 128810696SDavid.Hollister@Sun.COM bitset_init(&cfg); 128910696SDavid.Hollister@Sun.COM bitset_resize(&cfg, mapp->dam_size); 129010696SDavid.Hollister@Sun.COM bitset_init(&uncfg); 129110696SDavid.Hollister@Sun.COM bitset_resize(&uncfg, mapp->dam_size); 129210696SDavid.Hollister@Sun.COM 129311068SJohn.Danielson@Sun.COM /* 129411068SJohn.Danielson@Sun.COM * determine which addresses have changed during 129511068SJohn.Danielson@Sun.COM * this stabilization cycle 129611068SJohn.Danielson@Sun.COM */ 129711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 129811068SJohn.Danielson@Sun.COM ASSERT(mapp->dam_flags & DAM_SPEND); 129910696SDavid.Hollister@Sun.COM if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, 130010696SDavid.Hollister@Sun.COM &delta)) { 130111068SJohn.Danielson@Sun.COM /* 130211068SJohn.Danielson@Sun.COM * no difference 130311068SJohn.Danielson@Sun.COM */ 130410696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set); 1305*12207SChris.Horne@Sun.COM mapp->dam_flags &= ~DAM_SPEND; 1306*12207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv); 130711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 1308*12207SChris.Horne@Sun.COM 130910696SDavid.Hollister@Sun.COM bitset_fini(&uncfg); 131010696SDavid.Hollister@Sun.COM bitset_fini(&cfg); 131110696SDavid.Hollister@Sun.COM bitset_fini(&delta); 131211068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__stabilize__map__nochange, char *, 131311068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 131410696SDavid.Hollister@Sun.COM return; 131510696SDavid.Hollister@Sun.COM } 131611068SJohn.Danielson@Sun.COM 131711068SJohn.Danielson@Sun.COM /* 131811068SJohn.Danielson@Sun.COM * compute the sets of addresses to be activated and deactivated 131911068SJohn.Danielson@Sun.COM */ 132010696SDavid.Hollister@Sun.COM has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); 132110696SDavid.Hollister@Sun.COM has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); 132211068SJohn.Danielson@Sun.COM 132311068SJohn.Danielson@Sun.COM /* 132411068SJohn.Danielson@Sun.COM * drop map lock while invoking callouts 132511068SJohn.Danielson@Sun.COM */ 132611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 132711068SJohn.Danielson@Sun.COM 132811068SJohn.Danielson@Sun.COM /* 132911068SJohn.Danielson@Sun.COM * activate all newly stable addresss 133011068SJohn.Danielson@Sun.COM */ 133111068SJohn.Danielson@Sun.COM if (has_cfg) 133210696SDavid.Hollister@Sun.COM dam_addrset_activate(mapp, &cfg); 133311068SJohn.Danielson@Sun.COM 133411068SJohn.Danielson@Sun.COM /* 133511068SJohn.Danielson@Sun.COM * deactivate addresss which are no longer in the map 133611068SJohn.Danielson@Sun.COM */ 133711068SJohn.Danielson@Sun.COM if (has_uncfg) 133811068SJohn.Danielson@Sun.COM dam_addrset_deactivate(mapp, &uncfg); 133911068SJohn.Danielson@Sun.COM 134011068SJohn.Danielson@Sun.COM 134111068SJohn.Danielson@Sun.COM /* 134211068SJohn.Danielson@Sun.COM * timestamp the last stable time and increment the kstat keeping 134311068SJohn.Danielson@Sun.COM * the # of of stable cycles for the map 134411068SJohn.Danielson@Sun.COM */ 134511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 134610696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set); 134710696SDavid.Hollister@Sun.COM mapp->dam_last_stable = gethrtime(); 134810696SDavid.Hollister@Sun.COM mapp->dam_stable_cnt++; 134911068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_cycles); 135011068SJohn.Danielson@Sun.COM 135111068SJohn.Danielson@Sun.COM /* 135211068SJohn.Danielson@Sun.COM * determine the number of stable addresses 135311068SJohn.Danielson@Sun.COM * and update the n_active kstat for this map 135411068SJohn.Danielson@Sun.COM */ 135511068SJohn.Danielson@Sun.COM for (i = 1, n_active = 0; i < mapp->dam_high; i++) 135611068SJohn.Danielson@Sun.COM if (bitset_in_set(&mapp->dam_active_set, i)) 135711068SJohn.Danielson@Sun.COM n_active++; 135811068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_active, n_active); 135911068SJohn.Danielson@Sun.COM 136011068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name, 136111068SJohn.Danielson@Sun.COM dam_t *, mapp, int, n_active); 136211068SJohn.Danielson@Sun.COM 1363*12207SChris.Horne@Sun.COM mapp->dam_flags &= ~DAM_SPEND; 1364*12207SChris.Horne@Sun.COM cv_signal(&mapp->dam_sync_cv); 136511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 1366*12207SChris.Horne@Sun.COM 136710696SDavid.Hollister@Sun.COM bitset_fini(&uncfg); 136810696SDavid.Hollister@Sun.COM bitset_fini(&cfg); 136910696SDavid.Hollister@Sun.COM bitset_fini(&delta); 137010696SDavid.Hollister@Sun.COM } 137110696SDavid.Hollister@Sun.COM 137210696SDavid.Hollister@Sun.COM /* 137310696SDavid.Hollister@Sun.COM * per-address stabilization timeout 137410696SDavid.Hollister@Sun.COM */ 137510696SDavid.Hollister@Sun.COM static void 137610696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg) 137710696SDavid.Hollister@Sun.COM { 137810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 137910696SDavid.Hollister@Sun.COM int i; 138010696SDavid.Hollister@Sun.COM dam_da_t *passp; 138110696SDavid.Hollister@Sun.COM int spend = 0; 138210696SDavid.Hollister@Sun.COM int tpend = 0; 1383*12207SChris.Horne@Sun.COM int64_t ts, next_ticks, delta_ticks; 138410696SDavid.Hollister@Sun.COM 138511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 138610696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) { 138711068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *, 138811068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 138911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 139010696SDavid.Hollister@Sun.COM return; 139110696SDavid.Hollister@Sun.COM } 139210696SDavid.Hollister@Sun.COM mapp->dam_tid = 0; 139311068SJohn.Danielson@Sun.COM 139410696SDavid.Hollister@Sun.COM /* 139510696SDavid.Hollister@Sun.COM * If still under stabilization, reschedule timeout, 139611068SJohn.Danielson@Sun.COM * otherwise dispatch the task to activate and deactivate the 139711068SJohn.Danielson@Sun.COM * new stable address 139810696SDavid.Hollister@Sun.COM */ 139910696SDavid.Hollister@Sun.COM if (mapp->dam_flags & DAM_SPEND) { 140011068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun); 140110696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++; 1402*12207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp, 1403*12207SChris.Horne@Sun.COM mapp->dam_stable_ticks); 140411068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__overrun, char *, 140511068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 140611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 140710696SDavid.Hollister@Sun.COM return; 140810696SDavid.Hollister@Sun.COM } 140910696SDavid.Hollister@Sun.COM 141011068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0); 141111068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0; 141211068SJohn.Danielson@Sun.COM 141311068SJohn.Danielson@Sun.COM /* 141411068SJohn.Danielson@Sun.COM * copy the current active set to the stable map 141511068SJohn.Danielson@Sun.COM * for each address being reported, decrement its 141611068SJohn.Danielson@Sun.COM * stabilize deadline, and if stable, add or remove the 141711068SJohn.Danielson@Sun.COM * address from the stable set 141811068SJohn.Danielson@Sun.COM */ 141910696SDavid.Hollister@Sun.COM bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); 1420*12207SChris.Horne@Sun.COM ts = ddi_get_lbolt64(); 1421*12207SChris.Horne@Sun.COM next_ticks = mapp->dam_stable_ticks; 142210696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 142310696SDavid.Hollister@Sun.COM if (!bitset_in_set(&mapp->dam_report_set, i)) 142410696SDavid.Hollister@Sun.COM continue; 142510696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i); 142610696SDavid.Hollister@Sun.COM ASSERT(passp); 142710696SDavid.Hollister@Sun.COM 142810696SDavid.Hollister@Sun.COM /* report has stabilized */ 142910696SDavid.Hollister@Sun.COM if (passp->da_deadline <= ts) { 143010696SDavid.Hollister@Sun.COM bitset_del(&mapp->dam_report_set, i); 143111068SJohn.Danielson@Sun.COM if (passp->da_flags & DA_RELE) 143210696SDavid.Hollister@Sun.COM bitset_del(&mapp->dam_stable_set, i); 143311068SJohn.Danielson@Sun.COM else 143410696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_stable_set, i); 143510696SDavid.Hollister@Sun.COM spend++; 143610696SDavid.Hollister@Sun.COM continue; 143710696SDavid.Hollister@Sun.COM } 143810696SDavid.Hollister@Sun.COM 143910696SDavid.Hollister@Sun.COM /* 144011068SJohn.Danielson@Sun.COM * not stabilized, determine next map timeout 144110696SDavid.Hollister@Sun.COM */ 144210696SDavid.Hollister@Sun.COM tpend++; 1443*12207SChris.Horne@Sun.COM delta_ticks = passp->da_deadline - ts; 1444*12207SChris.Horne@Sun.COM if (delta_ticks < next_ticks) 1445*12207SChris.Horne@Sun.COM next_ticks = delta_ticks; 144610696SDavid.Hollister@Sun.COM } 144710696SDavid.Hollister@Sun.COM 144810696SDavid.Hollister@Sun.COM /* 144911068SJohn.Danielson@Sun.COM * schedule system_taskq activation of stabilized reports 145010696SDavid.Hollister@Sun.COM */ 145110696SDavid.Hollister@Sun.COM if (spend) { 145211068SJohn.Danielson@Sun.COM if (taskq_dispatch(system_taskq, dam_stabilize_map, 145311854SChris.Horne@Sun.COM mapp, TQ_NOSLEEP | TQ_NOQUEUE)) { 1454*12207SChris.Horne@Sun.COM mapp->dam_flags |= DAM_SPEND; 145511068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__start, char *, 145611068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 145711068SJohn.Danielson@Sun.COM } else { 145810696SDavid.Hollister@Sun.COM tpend++; 145911854SChris.Horne@Sun.COM 146011854SChris.Horne@Sun.COM /* 146111854SChris.Horne@Sun.COM * Avoid waiting the entire stabalization 146211854SChris.Horne@Sun.COM * time again if taskq_diskpatch fails. 146311854SChris.Horne@Sun.COM */ 1464*12207SChris.Horne@Sun.COM delta_ticks = drv_usectohz( 146511854SChris.Horne@Sun.COM damap_taskq_dispatch_retry_usec); 1466*12207SChris.Horne@Sun.COM if (delta_ticks < next_ticks) 1467*12207SChris.Horne@Sun.COM next_ticks = delta_ticks; 146811068SJohn.Danielson@Sun.COM } 146910696SDavid.Hollister@Sun.COM } 147010696SDavid.Hollister@Sun.COM 147110696SDavid.Hollister@Sun.COM /* 147211068SJohn.Danielson@Sun.COM * reschedule the stabilization timer if there are reports 147311068SJohn.Danielson@Sun.COM * still pending 147410696SDavid.Hollister@Sun.COM */ 147510696SDavid.Hollister@Sun.COM if (tpend) 1476*12207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp, 1477*12207SChris.Horne@Sun.COM (clock_t)next_ticks); 147811068SJohn.Danielson@Sun.COM 147911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 148010696SDavid.Hollister@Sun.COM } 148110696SDavid.Hollister@Sun.COM 148210696SDavid.Hollister@Sun.COM /* 148311068SJohn.Danielson@Sun.COM * fullset stabilization timeout callback 148410696SDavid.Hollister@Sun.COM */ 148510696SDavid.Hollister@Sun.COM static void 148611068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg) 148710696SDavid.Hollister@Sun.COM { 148810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 148910696SDavid.Hollister@Sun.COM 149011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 149110696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) { 149211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 149311068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__cancelled, 149411068SJohn.Danielson@Sun.COM char *, mapp->dam_name, dam_t *, mapp); 149510696SDavid.Hollister@Sun.COM return; 149610696SDavid.Hollister@Sun.COM } 149710696SDavid.Hollister@Sun.COM mapp->dam_tid = 0; 149810696SDavid.Hollister@Sun.COM 149910696SDavid.Hollister@Sun.COM /* 150011068SJohn.Danielson@Sun.COM * If map still underoing stabilization reschedule timeout, 150111068SJohn.Danielson@Sun.COM * else dispatch the task to configure the new stable set of 150211068SJohn.Danielson@Sun.COM * addresses. 150310696SDavid.Hollister@Sun.COM */ 150411854SChris.Horne@Sun.COM if ((mapp->dam_flags & DAM_SPEND) || 150511854SChris.Horne@Sun.COM (taskq_dispatch(system_taskq, dam_stabilize_map, mapp, 150611854SChris.Horne@Sun.COM TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) { 150711068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun); 150810696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++; 1509*12207SChris.Horne@Sun.COM dam_sched_timeout(dam_addrset_stable_cb, mapp, 1510*12207SChris.Horne@Sun.COM drv_usectohz(damap_taskq_dispatch_retry_usec)); 151111854SChris.Horne@Sun.COM 151211068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *, 151311068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 151411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 151511068SJohn.Danielson@Sun.COM return; 151610696SDavid.Hollister@Sun.COM } 151711068SJohn.Danielson@Sun.COM 151811068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0); 151911068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0; 152011068SJohn.Danielson@Sun.COM bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); 152111068SJohn.Danielson@Sun.COM bitset_zero(&mapp->dam_report_set); 152211068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_SPEND; 152311068SJohn.Danielson@Sun.COM mapp->dam_flags &= ~DAM_SETADD; 1524*12207SChris.Horne@Sun.COM /* NOTE: don't need cv_signal since DAM_SPEND is still set */ 1525*12207SChris.Horne@Sun.COM 152611068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__start, char *, 152711068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 152811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 152910696SDavid.Hollister@Sun.COM } 153010696SDavid.Hollister@Sun.COM 153110696SDavid.Hollister@Sun.COM /* 1532*12207SChris.Horne@Sun.COM * schedule map timeout in 'ticks' ticks 1533*12207SChris.Horne@Sun.COM * if map timer is currently running, cancel if ticks == 0 153410696SDavid.Hollister@Sun.COM */ 153510696SDavid.Hollister@Sun.COM static void 1536*12207SChris.Horne@Sun.COM dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks) 153710696SDavid.Hollister@Sun.COM { 153810696SDavid.Hollister@Sun.COM timeout_id_t tid; 153910696SDavid.Hollister@Sun.COM 1540*12207SChris.Horne@Sun.COM DTRACE_PROBE3(damap__sched__timeout, char *, mapp->dam_name, 1541*12207SChris.Horne@Sun.COM dam_t *, mapp, int, ticks); 154211068SJohn.Danielson@Sun.COM 154311068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 154410696SDavid.Hollister@Sun.COM if ((tid = mapp->dam_tid) != 0) { 1545*12207SChris.Horne@Sun.COM if (ticks == 0) { 154611068SJohn.Danielson@Sun.COM mapp->dam_tid = 0; 154711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 154811068SJohn.Danielson@Sun.COM (void) untimeout(tid); 154911068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 155011068SJohn.Danielson@Sun.COM } 155111068SJohn.Danielson@Sun.COM } else { 1552*12207SChris.Horne@Sun.COM if (timeout_cb && (ticks != 0)) 1553*12207SChris.Horne@Sun.COM mapp->dam_tid = timeout(timeout_cb, mapp, ticks); 155410696SDavid.Hollister@Sun.COM } 155510696SDavid.Hollister@Sun.COM } 155610696SDavid.Hollister@Sun.COM 155710696SDavid.Hollister@Sun.COM /* 155811068SJohn.Danielson@Sun.COM * report addition or removal of an address 155910696SDavid.Hollister@Sun.COM */ 156010696SDavid.Hollister@Sun.COM static void 156111068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type) 156210696SDavid.Hollister@Sun.COM { 156311068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid); 156411068SJohn.Danielson@Sun.COM 156511068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name, 156611068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp, int, rpt_type); 156711068SJohn.Danielson@Sun.COM 156811068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 156910696SDavid.Hollister@Sun.COM ASSERT(!DAM_IN_REPORT(mapp, addrid)); 157010696SDavid.Hollister@Sun.COM passp->da_last_report = gethrtime(); 157110696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime(); 157210696SDavid.Hollister@Sun.COM passp->da_report_cnt++; 1573*12207SChris.Horne@Sun.COM passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks; 157411068SJohn.Danielson@Sun.COM if (rpt_type == RPT_ADDR_DEL) 157510696SDavid.Hollister@Sun.COM passp->da_flags |= DA_RELE; 157611068SJohn.Danielson@Sun.COM else if (rpt_type == RPT_ADDR_ADD) 157710696SDavid.Hollister@Sun.COM passp->da_flags &= ~DA_RELE; 157810696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid); 1579*12207SChris.Horne@Sun.COM dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks); 158010696SDavid.Hollister@Sun.COM } 158110696SDavid.Hollister@Sun.COM 158210696SDavid.Hollister@Sun.COM /* 158310696SDavid.Hollister@Sun.COM * release an address report 158410696SDavid.Hollister@Sun.COM */ 158510696SDavid.Hollister@Sun.COM static void 158611068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid) 158710696SDavid.Hollister@Sun.COM { 158810696SDavid.Hollister@Sun.COM dam_da_t *passp; 158911068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid); 159010696SDavid.Hollister@Sun.COM 159111068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name, 159211068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 159311068SJohn.Danielson@Sun.COM 159411068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 159510696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 159610696SDavid.Hollister@Sun.COM ASSERT(passp); 159711068SJohn.Danielson@Sun.COM /* 159811068SJohn.Danielson@Sun.COM * clear the report bit 159911068SJohn.Danielson@Sun.COM * if the address has a registered deactivation handler and 160011601SDavid.Hollister@Sun.COM * we are holding a private data pointer and the address has not 160111601SDavid.Hollister@Sun.COM * stabilized, deactivate the address (private data). 160211068SJohn.Danielson@Sun.COM */ 160311068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_report_set, addrid); 160411601SDavid.Hollister@Sun.COM if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb && 160511601SDavid.Hollister@Sun.COM passp->da_ppriv_rpt) { 160611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 160711068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, 160811068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid), 160911601SDavid.Hollister@Sun.COM addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL); 161011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 161111068SJohn.Danielson@Sun.COM } 161210696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = NULL; 161310696SDavid.Hollister@Sun.COM if (passp->da_nvl_rpt) 161410696SDavid.Hollister@Sun.COM nvlist_free(passp->da_nvl_rpt); 161510696SDavid.Hollister@Sun.COM } 161610696SDavid.Hollister@Sun.COM 161710696SDavid.Hollister@Sun.COM /* 161810696SDavid.Hollister@Sun.COM * return the map ID of an address 161910696SDavid.Hollister@Sun.COM */ 162010696SDavid.Hollister@Sun.COM static id_t 162110696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address) 162210696SDavid.Hollister@Sun.COM { 162310696SDavid.Hollister@Sun.COM damap_id_t addrid; 162410696SDavid.Hollister@Sun.COM dam_da_t *passp; 162510696SDavid.Hollister@Sun.COM 162611068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 162710696SDavid.Hollister@Sun.COM if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { 162811068SJohn.Danielson@Sun.COM if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash, 162910696SDavid.Hollister@Sun.COM address)) == (damap_id_t)0) { 163010696SDavid.Hollister@Sun.COM return (0); 163110696SDavid.Hollister@Sun.COM } 163210696SDavid.Hollister@Sun.COM if (ddi_soft_state_zalloc(mapp->dam_da, addrid) != 163310696SDavid.Hollister@Sun.COM DDI_SUCCESS) { 163410696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid); 163510696SDavid.Hollister@Sun.COM return (0); 163610696SDavid.Hollister@Sun.COM } 163711068SJohn.Danielson@Sun.COM 163810696SDavid.Hollister@Sun.COM if (addrid >= mapp->dam_high) 163910696SDavid.Hollister@Sun.COM mapp->dam_high = addrid + 1; 164011068SJohn.Danielson@Sun.COM 164111068SJohn.Danielson@Sun.COM /* 164211068SJohn.Danielson@Sun.COM * expand bitmaps if ID has outgrown old map size 164311068SJohn.Danielson@Sun.COM */ 164411068SJohn.Danielson@Sun.COM if (mapp->dam_high > mapp->dam_size) { 164511068SJohn.Danielson@Sun.COM mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP; 164611068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size); 164711068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size); 164811068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size); 164911068SJohn.Danielson@Sun.COM } 165011068SJohn.Danielson@Sun.COM 165111068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 165211068SJohn.Danielson@Sun.COM passp->da_ref = 1; 165311068SJohn.Danielson@Sun.COM passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash, 165411068SJohn.Danielson@Sun.COM addrid); /* for mdb */ 165510696SDavid.Hollister@Sun.COM } 165610696SDavid.Hollister@Sun.COM return (addrid); 165710696SDavid.Hollister@Sun.COM } 165810696SDavid.Hollister@Sun.COM 165910696SDavid.Hollister@Sun.COM /* 166010696SDavid.Hollister@Sun.COM * create and install map statistics 166110696SDavid.Hollister@Sun.COM */ 166210696SDavid.Hollister@Sun.COM static int 166310696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp) 166410696SDavid.Hollister@Sun.COM { 166510696SDavid.Hollister@Sun.COM kstat_t *mapsp; 166610696SDavid.Hollister@Sun.COM struct dam_kstats *statsp; 166710696SDavid.Hollister@Sun.COM 166810696SDavid.Hollister@Sun.COM mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", 166910696SDavid.Hollister@Sun.COM KSTAT_TYPE_NAMED, 167010696SDavid.Hollister@Sun.COM sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); 167111068SJohn.Danielson@Sun.COM 167211068SJohn.Danielson@Sun.COM if (mapsp == NULL) 167310696SDavid.Hollister@Sun.COM return (DDI_FAILURE); 167410696SDavid.Hollister@Sun.COM 167510696SDavid.Hollister@Sun.COM statsp = (struct dam_kstats *)mapsp->ks_data; 167611068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32); 167711068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32); 167811068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32); 167911068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32); 168010696SDavid.Hollister@Sun.COM kstat_install(mapsp); 168110696SDavid.Hollister@Sun.COM mapp->dam_kstatsp = mapsp; 168210696SDavid.Hollister@Sun.COM return (DDI_SUCCESS); 168310696SDavid.Hollister@Sun.COM } 1684