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*11601SDavid.Hollister@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2410696SDavid.Hollister@Sun.COM * Use is subject to license terms. 2510696SDavid.Hollister@Sun.COM */ 2610696SDavid.Hollister@Sun.COM 2710696SDavid.Hollister@Sun.COM #include <sys/note.h> 2810696SDavid.Hollister@Sun.COM #include <sys/types.h> 2910696SDavid.Hollister@Sun.COM #include <sys/param.h> 3010696SDavid.Hollister@Sun.COM #include <sys/systm.h> 3110696SDavid.Hollister@Sun.COM #include <sys/buf.h> 3210696SDavid.Hollister@Sun.COM #include <sys/kmem.h> 3310696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h> 3410696SDavid.Hollister@Sun.COM #include <sys/debug.h> 3510696SDavid.Hollister@Sun.COM #include <sys/sunndi.h> 3610696SDavid.Hollister@Sun.COM #include <sys/kstat.h> 3710696SDavid.Hollister@Sun.COM #include <sys/conf.h> 3810696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h> 3910696SDavid.Hollister@Sun.COM #include <sys/devctl.h> 4010696SDavid.Hollister@Sun.COM #include <sys/callb.h> 4110696SDavid.Hollister@Sun.COM #include <sys/sysevent.h> 4210696SDavid.Hollister@Sun.COM #include <sys/taskq.h> 4310696SDavid.Hollister@Sun.COM #include <sys/ddi.h> 4410696SDavid.Hollister@Sun.COM #include <sys/bitset.h> 4510696SDavid.Hollister@Sun.COM #include <sys/damap.h> 4610696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h> 4710696SDavid.Hollister@Sun.COM 4810696SDavid.Hollister@Sun.COM #ifdef DEBUG 4910696SDavid.Hollister@Sun.COM static int damap_debug = 0; 5010696SDavid.Hollister@Sun.COM #endif /* DEBUG */ 5110696SDavid.Hollister@Sun.COM 5211068SJohn.Danielson@Sun.COM extern taskq_t *system_taskq; 5311068SJohn.Danielson@Sun.COM 5410696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *); 5511068SJohn.Danielson@Sun.COM static void dam_addrset_deactivate(dam_t *, bitset_t *); 5611068SJohn.Danielson@Sun.COM static void dam_stabilize_map(void *); 5710696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *); 5811068SJohn.Danielson@Sun.COM static void dam_addrset_stable_cb(void *); 5910696SDavid.Hollister@Sun.COM static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)()); 6011068SJohn.Danielson@Sun.COM static void dam_addr_report(dam_t *, dam_da_t *, id_t, int); 6111068SJohn.Danielson@Sun.COM static void dam_addr_release(dam_t *, id_t); 6211068SJohn.Danielson@Sun.COM static void dam_addr_report_release(dam_t *, id_t); 6311068SJohn.Danielson@Sun.COM static void dam_addr_deactivate(dam_t *, id_t); 6411363SReed.Liu@Sun.COM static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t); 6510696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *); 6610696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *); 6711068SJohn.Danielson@Sun.COM static int dam_map_alloc(dam_t *); 6810696SDavid.Hollister@Sun.COM 6910696SDavid.Hollister@Sun.COM #define DAM_INCR_STAT(mapp, stat) \ 7010696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \ 7110696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 7210696SDavid.Hollister@Sun.COM stp->stat.value.ui32++; \ 7310696SDavid.Hollister@Sun.COM } 7410696SDavid.Hollister@Sun.COM 7510696SDavid.Hollister@Sun.COM #define DAM_SET_STAT(mapp, stat, val) \ 7610696SDavid.Hollister@Sun.COM if ((mapp)->dam_kstatsp) { \ 7710696SDavid.Hollister@Sun.COM struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 7810696SDavid.Hollister@Sun.COM stp->stat.value.ui32 = (val); \ 7910696SDavid.Hollister@Sun.COM } 8010696SDavid.Hollister@Sun.COM 8111068SJohn.Danielson@Sun.COM 8211068SJohn.Danielson@Sun.COM /* 8311068SJohn.Danielson@Sun.COM * increase damap size by 64 entries at a time 8411068SJohn.Danielson@Sun.COM */ 8511068SJohn.Danielson@Sun.COM #define DAM_SIZE_BUMP 64 8611068SJohn.Danielson@Sun.COM 8711068SJohn.Danielson@Sun.COM /* 8811068SJohn.Danielson@Sun.COM * config/unconfig taskq data 8911068SJohn.Danielson@Sun.COM */ 9011068SJohn.Danielson@Sun.COM typedef struct { 9111068SJohn.Danielson@Sun.COM dam_t *tqd_mapp; 9211068SJohn.Danielson@Sun.COM id_t tqd_id; 9311068SJohn.Danielson@Sun.COM } cfg_tqd_t; 9411068SJohn.Danielson@Sun.COM 9511068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri; 9611068SJohn.Danielson@Sun.COM 9710696SDavid.Hollister@Sun.COM /* 9810696SDavid.Hollister@Sun.COM * Create new device address map 9910696SDavid.Hollister@Sun.COM * 10011068SJohn.Danielson@Sun.COM * name: map name (kstat unique) 10110696SDavid.Hollister@Sun.COM * size: max # of map entries 10211068SJohn.Danielson@Sun.COM * mode: style of address reports: per-address or fullset 10310696SDavid.Hollister@Sun.COM * stable_usec: # of quiescent microseconds before report/map is stable 10410696SDavid.Hollister@Sun.COM * 10510696SDavid.Hollister@Sun.COM * activate_arg: address provider activation-callout private 10610696SDavid.Hollister@Sun.COM * activate_cb: address provider activation callback handler 10710696SDavid.Hollister@Sun.COM * deactivate_cb: address provider deactivation callback handler 10810696SDavid.Hollister@Sun.COM * 10910696SDavid.Hollister@Sun.COM * config_arg: configuration-callout private 11010696SDavid.Hollister@Sun.COM * config_cb: class configuration callout 11110696SDavid.Hollister@Sun.COM * unconfig_cb: class unconfiguration callout 11210696SDavid.Hollister@Sun.COM * 11310696SDavid.Hollister@Sun.COM * damapp: pointer to map handle (return) 11410696SDavid.Hollister@Sun.COM * 11510696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 11610696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 11710696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 11810696SDavid.Hollister@Sun.COM */ 11910696SDavid.Hollister@Sun.COM int 12011068SJohn.Danielson@Sun.COM damap_create(char *name, damap_rptmode_t mode, int map_opts, 12111068SJohn.Danielson@Sun.COM clock_t stable_usec, void *activate_arg, damap_activate_cb_t activate_cb, 12210696SDavid.Hollister@Sun.COM damap_deactivate_cb_t deactivate_cb, 12310696SDavid.Hollister@Sun.COM void *config_arg, damap_configure_cb_t configure_cb, 12410696SDavid.Hollister@Sun.COM damap_unconfig_cb_t unconfig_cb, 12510696SDavid.Hollister@Sun.COM damap_t **damapp) 12610696SDavid.Hollister@Sun.COM { 12710696SDavid.Hollister@Sun.COM dam_t *mapp; 12810696SDavid.Hollister@Sun.COM 12911068SJohn.Danielson@Sun.COM if (configure_cb == NULL || unconfig_cb == NULL || name == NULL) 13010696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 13110696SDavid.Hollister@Sun.COM 13211068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__create, char *, name, 13311068SJohn.Danielson@Sun.COM damap_rptmode_t, mode, clock_t, stable_usec); 13410696SDavid.Hollister@Sun.COM 13510696SDavid.Hollister@Sun.COM mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); 13611068SJohn.Danielson@Sun.COM mapp->dam_options = map_opts; 13710696SDavid.Hollister@Sun.COM mapp->dam_stabletmo = drv_usectohz(stable_usec); 13811068SJohn.Danielson@Sun.COM mapp->dam_size = 0; 13911068SJohn.Danielson@Sun.COM mapp->dam_rptmode = mode; 14010696SDavid.Hollister@Sun.COM mapp->dam_activate_arg = activate_arg; 14110696SDavid.Hollister@Sun.COM mapp->dam_activate_cb = (activate_cb_t)activate_cb; 14210696SDavid.Hollister@Sun.COM mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; 14310696SDavid.Hollister@Sun.COM mapp->dam_config_arg = config_arg; 14410696SDavid.Hollister@Sun.COM mapp->dam_configure_cb = (configure_cb_t)configure_cb; 14510696SDavid.Hollister@Sun.COM mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; 14611068SJohn.Danielson@Sun.COM mapp->dam_name = i_ddi_strdup(name, KM_SLEEP); 14710696SDavid.Hollister@Sun.COM mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); 14810696SDavid.Hollister@Sun.COM cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL); 14911068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_active_set); 15011068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_stable_set); 15111068SJohn.Danielson@Sun.COM bitset_init(&mapp->dam_report_set); 15210696SDavid.Hollister@Sun.COM *damapp = (damap_t *)mapp; 15310696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 15410696SDavid.Hollister@Sun.COM } 15510696SDavid.Hollister@Sun.COM 15610696SDavid.Hollister@Sun.COM /* 15711068SJohn.Danielson@Sun.COM * Allocate backing resources 15811068SJohn.Danielson@Sun.COM * 15911068SJohn.Danielson@Sun.COM * DAMs are lightly backed on create - major allocations occur 16011068SJohn.Danielson@Sun.COM * at the time a report is made to the map, and are extended on 16111068SJohn.Danielson@Sun.COM * a demand basis. 16211068SJohn.Danielson@Sun.COM */ 16311068SJohn.Danielson@Sun.COM static int 16411068SJohn.Danielson@Sun.COM dam_map_alloc(dam_t *mapp) 16511068SJohn.Danielson@Sun.COM { 16611068SJohn.Danielson@Sun.COM void *softstate_p; 16711068SJohn.Danielson@Sun.COM 16811068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 16911068SJohn.Danielson@Sun.COM if (mapp->dam_flags & DAM_DESTROYPEND) 17011068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 17111068SJohn.Danielson@Sun.COM 17211068SJohn.Danielson@Sun.COM /* 17311068SJohn.Danielson@Sun.COM * dam_high > 0 signals map allocation complete 17411068SJohn.Danielson@Sun.COM */ 17511068SJohn.Danielson@Sun.COM if (mapp->dam_high) 17611068SJohn.Danielson@Sun.COM return (DAM_SUCCESS); 17711068SJohn.Danielson@Sun.COM 17811068SJohn.Danielson@Sun.COM mapp->dam_size = DAM_SIZE_BUMP; 17911068SJohn.Danielson@Sun.COM if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), 18011068SJohn.Danielson@Sun.COM mapp->dam_size) != DDI_SUCCESS) 18111068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 18211068SJohn.Danielson@Sun.COM 18311068SJohn.Danielson@Sun.COM if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) != 18411068SJohn.Danielson@Sun.COM DDI_SUCCESS) { 18511068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p); 18611068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 18711068SJohn.Danielson@Sun.COM } 18811068SJohn.Danielson@Sun.COM if (dam_kstat_create(mapp) != DDI_SUCCESS) { 18911068SJohn.Danielson@Sun.COM ddi_soft_state_fini(softstate_p); 19011068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash); 19111068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 19211068SJohn.Danielson@Sun.COM } 19311068SJohn.Danielson@Sun.COM mapp->dam_da = softstate_p; 19411068SJohn.Danielson@Sun.COM mapp->dam_high = 1; 19511068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size); 19611068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size); 19711068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size); 19811068SJohn.Danielson@Sun.COM return (DAM_SUCCESS); 19911068SJohn.Danielson@Sun.COM } 20011068SJohn.Danielson@Sun.COM 20111068SJohn.Danielson@Sun.COM /* 20211068SJohn.Danielson@Sun.COM * Destroy address map 20310696SDavid.Hollister@Sun.COM * 20410696SDavid.Hollister@Sun.COM * damapp: address map 20510696SDavid.Hollister@Sun.COM * 20610696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 20710696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 20810696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 20910696SDavid.Hollister@Sun.COM */ 21010696SDavid.Hollister@Sun.COM void 21110696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp) 21210696SDavid.Hollister@Sun.COM { 21310696SDavid.Hollister@Sun.COM int i; 21410696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 21510696SDavid.Hollister@Sun.COM 21610696SDavid.Hollister@Sun.COM ASSERT(mapp); 21710696SDavid.Hollister@Sun.COM 21811068SJohn.Danielson@Sun.COM DTRACE_PROBE1(damap__destroy, char *, mapp->dam_name); 21910696SDavid.Hollister@Sun.COM 22011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 22110696SDavid.Hollister@Sun.COM 22210696SDavid.Hollister@Sun.COM /* 22311068SJohn.Danielson@Sun.COM * prevent new reports from being added to the map 22410696SDavid.Hollister@Sun.COM */ 22511068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_DESTROYPEND; 22611068SJohn.Danielson@Sun.COM 22711068SJohn.Danielson@Sun.COM if (mapp->dam_high) { 22811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 22911068SJohn.Danielson@Sun.COM /* 23011068SJohn.Danielson@Sun.COM * wait for outstanding reports to stabilize and cancel 23111068SJohn.Danielson@Sun.COM * the timer for this map 23211068SJohn.Danielson@Sun.COM */ 23311068SJohn.Danielson@Sun.COM (void) damap_sync(damapp); 23411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 23511068SJohn.Danielson@Sun.COM dam_sched_tmo(mapp, 0, NULL); 23610696SDavid.Hollister@Sun.COM 23711068SJohn.Danielson@Sun.COM /* 23811068SJohn.Danielson@Sun.COM * map is at full stop 23911068SJohn.Danielson@Sun.COM * release the contents of the map, invoking the 24011068SJohn.Danielson@Sun.COM * detactivation protocol as addresses are released 24111068SJohn.Danielson@Sun.COM */ 24211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 24311068SJohn.Danielson@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 24411068SJohn.Danielson@Sun.COM if (ddi_get_soft_state(mapp->dam_da, i) == NULL) 24511068SJohn.Danielson@Sun.COM continue; 24611068SJohn.Danielson@Sun.COM 24711068SJohn.Danielson@Sun.COM ASSERT(DAM_IN_REPORT(mapp, i) == 0); 24811068SJohn.Danielson@Sun.COM 24911068SJohn.Danielson@Sun.COM if (DAM_IS_STABLE(mapp, i)) { 25011068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i); 25111068SJohn.Danielson@Sun.COM } else { 25211068SJohn.Danielson@Sun.COM ddi_strid_free(mapp->dam_addr_hash, i); 25311068SJohn.Danielson@Sun.COM ddi_soft_state_free(mapp->dam_da, i); 25411068SJohn.Danielson@Sun.COM } 25511068SJohn.Danielson@Sun.COM } 25611068SJohn.Danielson@Sun.COM ddi_strid_fini(&mapp->dam_addr_hash); 25711068SJohn.Danielson@Sun.COM ddi_soft_state_fini(&mapp->dam_da); 25811068SJohn.Danielson@Sun.COM kstat_delete(mapp->dam_kstatsp); 25910696SDavid.Hollister@Sun.COM } 26010696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_active_set); 26110696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_stable_set); 26210696SDavid.Hollister@Sun.COM bitset_fini(&mapp->dam_report_set); 26310696SDavid.Hollister@Sun.COM mutex_destroy(&mapp->dam_lock); 26410696SDavid.Hollister@Sun.COM cv_destroy(&mapp->dam_cv); 26510696SDavid.Hollister@Sun.COM if (mapp->dam_name) 26610696SDavid.Hollister@Sun.COM kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); 26710696SDavid.Hollister@Sun.COM kmem_free(mapp, sizeof (*mapp)); 26810696SDavid.Hollister@Sun.COM } 26910696SDavid.Hollister@Sun.COM 27010696SDavid.Hollister@Sun.COM /* 27110696SDavid.Hollister@Sun.COM * Wait for map stability. 27210696SDavid.Hollister@Sun.COM * 27310696SDavid.Hollister@Sun.COM * damapp: address map 27410696SDavid.Hollister@Sun.COM */ 27510696SDavid.Hollister@Sun.COM int 27610696SDavid.Hollister@Sun.COM damap_sync(damap_t *damapp) 27710696SDavid.Hollister@Sun.COM { 27811068SJohn.Danielson@Sun.COM #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND) 27910696SDavid.Hollister@Sun.COM 28010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 28110696SDavid.Hollister@Sun.COM int none_active; 28210696SDavid.Hollister@Sun.COM 28310696SDavid.Hollister@Sun.COM ASSERT(mapp); 28410696SDavid.Hollister@Sun.COM 28511068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__sync__start, char *, mapp->dam_name, 28611068SJohn.Danielson@Sun.COM dam_t *, mapp); 28710696SDavid.Hollister@Sun.COM 28811068SJohn.Danielson@Sun.COM /* 28911068SJohn.Danielson@Sun.COM * block where waiting for 29011068SJohn.Danielson@Sun.COM * a) stabilization pending or a fullset update pending 29111068SJohn.Danielson@Sun.COM * b) any scheduled timeouts to fire 29211068SJohn.Danielson@Sun.COM * c) the report set to finalize (bitset is null) 29311068SJohn.Danielson@Sun.COM */ 29410696SDavid.Hollister@Sun.COM mutex_enter(&mapp->dam_lock); 29510696SDavid.Hollister@Sun.COM while ((mapp->dam_flags & WAITFOR_FLAGS) || 29610696SDavid.Hollister@Sun.COM (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) { 29711068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__sync__waiting, char *, mapp->dam_name, 29811068SJohn.Danielson@Sun.COM dam_t *, mapp); 29910696SDavid.Hollister@Sun.COM cv_wait(&mapp->dam_cv, &mapp->dam_lock); 30010696SDavid.Hollister@Sun.COM } 30110696SDavid.Hollister@Sun.COM 30210696SDavid.Hollister@Sun.COM none_active = bitset_is_null(&mapp->dam_active_set); 30310696SDavid.Hollister@Sun.COM 30410696SDavid.Hollister@Sun.COM mutex_exit(&mapp->dam_lock); 30511068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__map__sync__end, char *, mapp->dam_name, int, 30611068SJohn.Danielson@Sun.COM none_active, dam_t *, mapp); 30710696SDavid.Hollister@Sun.COM 30810696SDavid.Hollister@Sun.COM return (none_active); 30910696SDavid.Hollister@Sun.COM } 31010696SDavid.Hollister@Sun.COM 31110696SDavid.Hollister@Sun.COM /* 31210696SDavid.Hollister@Sun.COM * Get the name of a device address map 31310696SDavid.Hollister@Sun.COM * 31410696SDavid.Hollister@Sun.COM * damapp: address map 31510696SDavid.Hollister@Sun.COM * 31610696SDavid.Hollister@Sun.COM * Returns: name 31710696SDavid.Hollister@Sun.COM */ 31810696SDavid.Hollister@Sun.COM char * 31910696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp) 32010696SDavid.Hollister@Sun.COM { 32110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 32210696SDavid.Hollister@Sun.COM 32310696SDavid.Hollister@Sun.COM return (mapp ? mapp->dam_name : "UNKNOWN_damap"); 32410696SDavid.Hollister@Sun.COM } 32510696SDavid.Hollister@Sun.COM 32610696SDavid.Hollister@Sun.COM /* 32710696SDavid.Hollister@Sun.COM * Report an address to per-address report 32810696SDavid.Hollister@Sun.COM * 32910696SDavid.Hollister@Sun.COM * damapp: address map handle 33010696SDavid.Hollister@Sun.COM * address: address in ascii string representation 33111068SJohn.Danielson@Sun.COM * addridp: address ID 33210696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data 33310696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private (passed to activate/deactivate cb) 33410696SDavid.Hollister@Sun.COM * 33510696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 33610696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 33710696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted 33810696SDavid.Hollister@Sun.COM */ 33910696SDavid.Hollister@Sun.COM int 34011068SJohn.Danielson@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp, 34111068SJohn.Danielson@Sun.COM nvlist_t *nvl, void *addr_priv) 34210696SDavid.Hollister@Sun.COM { 34310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 34410696SDavid.Hollister@Sun.COM id_t addrid; 34510696SDavid.Hollister@Sun.COM dam_da_t *passp; 34610696SDavid.Hollister@Sun.COM 34711068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) 34810696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 34910696SDavid.Hollister@Sun.COM 35011068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__add, char *, mapp->dam_name, 35111068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 35211068SJohn.Danielson@Sun.COM 35311068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 35411068SJohn.Danielson@Sun.COM if ((dam_map_alloc(mapp) != DAM_SUCCESS) || 35511068SJohn.Danielson@Sun.COM ((addrid = dam_get_addrid(mapp, address)) == 0)) { 35611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 35710696SDavid.Hollister@Sun.COM return (DAM_MAPFULL); 35810696SDavid.Hollister@Sun.COM } 35910696SDavid.Hollister@Sun.COM 36010696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 36110696SDavid.Hollister@Sun.COM ASSERT(passp != NULL); 36210696SDavid.Hollister@Sun.COM 36310696SDavid.Hollister@Sun.COM /* 36410696SDavid.Hollister@Sun.COM * If re-reporting the same address (add or remove) clear 36510696SDavid.Hollister@Sun.COM * the existing report 36610696SDavid.Hollister@Sun.COM */ 36710696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 36811068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__add__jitter, char *, mapp->dam_name, 36911068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 37011068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 37111068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 37210696SDavid.Hollister@Sun.COM passp->da_jitter++; 37310696SDavid.Hollister@Sun.COM } 37410696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv; 37510696SDavid.Hollister@Sun.COM if (nvl) 37610696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 37710696SDavid.Hollister@Sun.COM 37811068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD); 37911068SJohn.Danielson@Sun.COM if (addridp != NULL) 38011068SJohn.Danielson@Sun.COM *addridp = (damap_id_t)addrid; 38111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 38210696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 38310696SDavid.Hollister@Sun.COM } 38410696SDavid.Hollister@Sun.COM 38510696SDavid.Hollister@Sun.COM /* 38610696SDavid.Hollister@Sun.COM * Report removal of address from per-address report 38710696SDavid.Hollister@Sun.COM * 38810696SDavid.Hollister@Sun.COM * damapp: address map 38910696SDavid.Hollister@Sun.COM * address: address in ascii string representation 39010696SDavid.Hollister@Sun.COM * 39110696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 39210696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 39310696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 39410696SDavid.Hollister@Sun.COM */ 39510696SDavid.Hollister@Sun.COM int 39610696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address) 39710696SDavid.Hollister@Sun.COM { 39810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 39910696SDavid.Hollister@Sun.COM id_t addrid; 40010696SDavid.Hollister@Sun.COM dam_da_t *passp; 40110696SDavid.Hollister@Sun.COM 40211068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR)) 40310696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 40410696SDavid.Hollister@Sun.COM 40511068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__del, char *, mapp->dam_name, 40611068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 40711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 40811068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) { 40911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 41011068SJohn.Danielson@Sun.COM return (DAM_MAPFULL); 41111068SJohn.Danielson@Sun.COM } 41211068SJohn.Danielson@Sun.COM 41311068SJohn.Danielson@Sun.COM /* 41411068SJohn.Danielson@Sun.COM * if reporting the removal of an address which is not in the map 41511068SJohn.Danielson@Sun.COM * return success 41611068SJohn.Danielson@Sun.COM */ 41710696SDavid.Hollister@Sun.COM if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { 41811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 41910696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 42010696SDavid.Hollister@Sun.COM } 42110696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 42210696SDavid.Hollister@Sun.COM ASSERT(passp); 42310696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 42411068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__del__jitter, char *, mapp->dam_name, 42511068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 42611068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 42711068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 42810696SDavid.Hollister@Sun.COM passp->da_jitter++; 42910696SDavid.Hollister@Sun.COM } 43011068SJohn.Danielson@Sun.COM dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL); 43111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 43210696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 43310696SDavid.Hollister@Sun.COM } 43410696SDavid.Hollister@Sun.COM 43510696SDavid.Hollister@Sun.COM /* 43610696SDavid.Hollister@Sun.COM * Initiate full-set report 43710696SDavid.Hollister@Sun.COM * 43810696SDavid.Hollister@Sun.COM * damapp: address map 43910696SDavid.Hollister@Sun.COM * 44010696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 44110696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 44210696SDavid.Hollister@Sun.COM */ 44310696SDavid.Hollister@Sun.COM int 44410696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp) 44510696SDavid.Hollister@Sun.COM { 44610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 44710696SDavid.Hollister@Sun.COM int i; 44810696SDavid.Hollister@Sun.COM 44911068SJohn.Danielson@Sun.COM if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) 45010696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 45110696SDavid.Hollister@Sun.COM 45211068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__begin, char *, mapp->dam_name, dam_t *, 45311068SJohn.Danielson@Sun.COM mapp); 45411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 45511068SJohn.Danielson@Sun.COM if (dam_map_alloc(mapp) != DAM_SUCCESS) { 45611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 45711068SJohn.Danielson@Sun.COM return (DAM_MAPFULL); 45811068SJohn.Danielson@Sun.COM } 45910696SDavid.Hollister@Sun.COM if (mapp->dam_flags & DAM_SETADD) { 46011068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__begin__reset, char *, 46111068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 46210696SDavid.Hollister@Sun.COM /* 46310696SDavid.Hollister@Sun.COM * cancel stabilization timeout 46410696SDavid.Hollister@Sun.COM */ 46510696SDavid.Hollister@Sun.COM dam_sched_tmo(mapp, 0, NULL); 46611068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_jitter); 46711068SJohn.Danielson@Sun.COM 46811068SJohn.Danielson@Sun.COM /* 46911068SJohn.Danielson@Sun.COM * clear pending reports 47011068SJohn.Danielson@Sun.COM */ 47110696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 47210696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, i)) 47311068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, i); 47410696SDavid.Hollister@Sun.COM } 47510696SDavid.Hollister@Sun.COM } 47610696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_report_set); 47711068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_SETADD; 47811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 47910696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 48010696SDavid.Hollister@Sun.COM } 48110696SDavid.Hollister@Sun.COM 48210696SDavid.Hollister@Sun.COM /* 48310696SDavid.Hollister@Sun.COM * Report address to full-set report 48410696SDavid.Hollister@Sun.COM * 48510696SDavid.Hollister@Sun.COM * damapp: address map handle 48610696SDavid.Hollister@Sun.COM * address: address in ascii string representation 48710696SDavid.Hollister@Sun.COM * rindx: index if address stabilizes 48810696SDavid.Hollister@Sun.COM * nvl: optional nvlist of configuration-private data 48910696SDavid.Hollister@Sun.COM * addr_priv: optional provider-private data (passed to activate/release cb) 49010696SDavid.Hollister@Sun.COM * 49110696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 49210696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 49310696SDavid.Hollister@Sun.COM * DAM_MAPFULL address map exhausted 49410696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 49510696SDavid.Hollister@Sun.COM */ 49610696SDavid.Hollister@Sun.COM int 49710696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx, 49810696SDavid.Hollister@Sun.COM nvlist_t *nvl, void *addr_priv) 49910696SDavid.Hollister@Sun.COM { 50010696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 50110696SDavid.Hollister@Sun.COM id_t addrid; 50210696SDavid.Hollister@Sun.COM dam_da_t *passp; 50310696SDavid.Hollister@Sun.COM 50411068SJohn.Danielson@Sun.COM if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) 50510696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 50610696SDavid.Hollister@Sun.COM 50711068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addrset__add, char *, mapp->dam_name, 50811068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 50910696SDavid.Hollister@Sun.COM 51011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 51111068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) { 51211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 51311068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 51411068SJohn.Danielson@Sun.COM } 51511068SJohn.Danielson@Sun.COM 51610696SDavid.Hollister@Sun.COM if ((addrid = dam_get_addrid(mapp, address)) == 0) { 51711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 51810696SDavid.Hollister@Sun.COM return (DAM_MAPFULL); 51910696SDavid.Hollister@Sun.COM } 52010696SDavid.Hollister@Sun.COM 52110696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 52210696SDavid.Hollister@Sun.COM ASSERT(passp); 52310696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 52411068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addrset__add__jitter, char *, 52511068SJohn.Danielson@Sun.COM mapp->dam_name, char *, address, dam_t *, mapp); 52611068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, addrid); 52710696SDavid.Hollister@Sun.COM passp->da_jitter++; 52810696SDavid.Hollister@Sun.COM } 52910696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = addr_priv; 53010696SDavid.Hollister@Sun.COM if (nvl) 53110696SDavid.Hollister@Sun.COM (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 53210696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid); 53310696SDavid.Hollister@Sun.COM if (ridx) 53410696SDavid.Hollister@Sun.COM *ridx = (damap_id_t)addrid; 53511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 53610696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 53710696SDavid.Hollister@Sun.COM } 53810696SDavid.Hollister@Sun.COM 53910696SDavid.Hollister@Sun.COM /* 54010696SDavid.Hollister@Sun.COM * Commit full-set report for stabilization 54110696SDavid.Hollister@Sun.COM * 54210696SDavid.Hollister@Sun.COM * damapp: address map handle 54310696SDavid.Hollister@Sun.COM * flags: (currently 0) 54410696SDavid.Hollister@Sun.COM * 54510696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 54610696SDavid.Hollister@Sun.COM * DAM_EINVAL Invalid argument(s) 54710696SDavid.Hollister@Sun.COM * DAM_FAILURE General failure 54810696SDavid.Hollister@Sun.COM */ 54910696SDavid.Hollister@Sun.COM int 55010696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags) 55110696SDavid.Hollister@Sun.COM { 55210696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 55310696SDavid.Hollister@Sun.COM int i; 55410696SDavid.Hollister@Sun.COM 55511068SJohn.Danielson@Sun.COM if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET)) 55610696SDavid.Hollister@Sun.COM return (DAM_EINVAL); 55710696SDavid.Hollister@Sun.COM 55811068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__end, char *, mapp->dam_name, 55911068SJohn.Danielson@Sun.COM dam_t *, mapp); 56010696SDavid.Hollister@Sun.COM 56111068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 56211068SJohn.Danielson@Sun.COM if (!(mapp->dam_flags & DAM_SETADD)) { 56311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 56411068SJohn.Danielson@Sun.COM return (DAM_FAILURE); 56511068SJohn.Danielson@Sun.COM } 56611068SJohn.Danielson@Sun.COM 56711068SJohn.Danielson@Sun.COM if (flags & DAMAP_END_RESET) { 56811068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__end__reset, char *, 56911068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 57010696SDavid.Hollister@Sun.COM dam_sched_tmo(mapp, 0, NULL); 57110696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) 57210696SDavid.Hollister@Sun.COM if (DAM_IN_REPORT(mapp, i)) 57311068SJohn.Danielson@Sun.COM dam_addr_report_release(mapp, i); 57410696SDavid.Hollister@Sun.COM } else { 57510696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime(); 57611068SJohn.Danielson@Sun.COM dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb); 57710696SDavid.Hollister@Sun.COM } 57811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 57910696SDavid.Hollister@Sun.COM return (DAM_SUCCESS); 58010696SDavid.Hollister@Sun.COM } 58110696SDavid.Hollister@Sun.COM 58210696SDavid.Hollister@Sun.COM /* 58310696SDavid.Hollister@Sun.COM * Return nvlist registered with reported address 58410696SDavid.Hollister@Sun.COM * 58510696SDavid.Hollister@Sun.COM * damapp: address map handle 58611068SJohn.Danielson@Sun.COM * addrid: address ID 58710696SDavid.Hollister@Sun.COM * 58810696SDavid.Hollister@Sun.COM * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) 58910696SDavid.Hollister@Sun.COM * NULL 59010696SDavid.Hollister@Sun.COM */ 59110696SDavid.Hollister@Sun.COM nvlist_t * 59210696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid) 59310696SDavid.Hollister@Sun.COM { 59410696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 59510696SDavid.Hollister@Sun.COM dam_da_t *pass; 59610696SDavid.Hollister@Sun.COM 59711068SJohn.Danielson@Sun.COM if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) { 59811068SJohn.Danielson@Sun.COM if (pass = ddi_get_soft_state(mapp->dam_da, addrid)) 59910696SDavid.Hollister@Sun.COM return (pass->da_nvl); 60010696SDavid.Hollister@Sun.COM } 60110696SDavid.Hollister@Sun.COM return (NULL); 60210696SDavid.Hollister@Sun.COM } 60310696SDavid.Hollister@Sun.COM 60410696SDavid.Hollister@Sun.COM /* 60510696SDavid.Hollister@Sun.COM * Return address string 60610696SDavid.Hollister@Sun.COM * 60710696SDavid.Hollister@Sun.COM * damapp: address map handle 60811068SJohn.Danielson@Sun.COM * addrid: address ID 60910696SDavid.Hollister@Sun.COM * 61010696SDavid.Hollister@Sun.COM * Returns: char * Address string 61110696SDavid.Hollister@Sun.COM * NULL 61210696SDavid.Hollister@Sun.COM */ 61310696SDavid.Hollister@Sun.COM char * 61411068SJohn.Danielson@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t addrid) 61510696SDavid.Hollister@Sun.COM { 61610696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 61710696SDavid.Hollister@Sun.COM 61811068SJohn.Danielson@Sun.COM if (mapp->dam_high) 61911068SJohn.Danielson@Sun.COM return (ddi_strid_id2str(mapp->dam_addr_hash, addrid)); 62011068SJohn.Danielson@Sun.COM else 62111068SJohn.Danielson@Sun.COM return (NULL); 62210696SDavid.Hollister@Sun.COM } 62310696SDavid.Hollister@Sun.COM 62410696SDavid.Hollister@Sun.COM /* 62510696SDavid.Hollister@Sun.COM * Release address reference in map 62610696SDavid.Hollister@Sun.COM * 62710696SDavid.Hollister@Sun.COM * damapp: address map handle 62811068SJohn.Danielson@Sun.COM * addrid: address ID 62910696SDavid.Hollister@Sun.COM */ 63010696SDavid.Hollister@Sun.COM void 63110696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid) 63210696SDavid.Hollister@Sun.COM { 63310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 63411068SJohn.Danielson@Sun.COM dam_da_t *passp; 63511068SJohn.Danielson@Sun.COM char *addr; 63610696SDavid.Hollister@Sun.COM 63711068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 63811068SJohn.Danielson@Sun.COM ASSERT(passp); 63911068SJohn.Danielson@Sun.COM 64011068SJohn.Danielson@Sun.COM addr = damap_id2addr(damapp, addrid); 64111068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__id__rele, char *, mapp->dam_name, char *, addr, 64211068SJohn.Danielson@Sun.COM dam_t *, mapp, int, passp->da_ref); 64311068SJohn.Danielson@Sun.COM 64411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 64511068SJohn.Danielson@Sun.COM 64611068SJohn.Danielson@Sun.COM /* 64711068SJohn.Danielson@Sun.COM * teardown address if last outstanding reference 64811068SJohn.Danielson@Sun.COM */ 64911068SJohn.Danielson@Sun.COM if (--passp->da_ref == 0) 65011068SJohn.Danielson@Sun.COM dam_addr_release(mapp, (id_t)addrid); 65111068SJohn.Danielson@Sun.COM 65211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 65310696SDavid.Hollister@Sun.COM } 65410696SDavid.Hollister@Sun.COM 65510696SDavid.Hollister@Sun.COM /* 65610696SDavid.Hollister@Sun.COM * Return current reference count on address reference in map 65710696SDavid.Hollister@Sun.COM * 65810696SDavid.Hollister@Sun.COM * damapp: address map handle 65911068SJohn.Danielson@Sun.COM * addrid: address ID 66010696SDavid.Hollister@Sun.COM * 66110696SDavid.Hollister@Sun.COM * Returns: DAM_SUCCESS 66210696SDavid.Hollister@Sun.COM * DAM_FAILURE 66310696SDavid.Hollister@Sun.COM */ 66410696SDavid.Hollister@Sun.COM int 66511068SJohn.Danielson@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t addrid) 66610696SDavid.Hollister@Sun.COM { 66710696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 66810696SDavid.Hollister@Sun.COM dam_da_t *passp; 66910696SDavid.Hollister@Sun.COM int ref = -1; 67010696SDavid.Hollister@Sun.COM 67111068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 67210696SDavid.Hollister@Sun.COM if (passp) 67310696SDavid.Hollister@Sun.COM ref = passp->da_ref; 67411068SJohn.Danielson@Sun.COM 67510696SDavid.Hollister@Sun.COM return (ref); 67610696SDavid.Hollister@Sun.COM } 67710696SDavid.Hollister@Sun.COM 67810696SDavid.Hollister@Sun.COM /* 67910696SDavid.Hollister@Sun.COM * Return next address ID in list 68010696SDavid.Hollister@Sun.COM * 68110696SDavid.Hollister@Sun.COM * damapp: address map handle 68210696SDavid.Hollister@Sun.COM * damap_list: address ID list passed to config|unconfig 68310696SDavid.Hollister@Sun.COM * returned by look by lookup_all 68410696SDavid.Hollister@Sun.COM * last: last ID returned, 0 is start of list 68510696SDavid.Hollister@Sun.COM * 68610696SDavid.Hollister@Sun.COM * Returns: addrid Next ID from the list 68710696SDavid.Hollister@Sun.COM * 0 End of the list 68810696SDavid.Hollister@Sun.COM */ 68910696SDavid.Hollister@Sun.COM damap_id_t 69010696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last) 69110696SDavid.Hollister@Sun.COM { 69210696SDavid.Hollister@Sun.COM int i, start; 69310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 69410696SDavid.Hollister@Sun.COM bitset_t *dam_list = (bitset_t *)damap_list; 69510696SDavid.Hollister@Sun.COM 69610696SDavid.Hollister@Sun.COM if (!mapp || !dam_list) 69710696SDavid.Hollister@Sun.COM return ((damap_id_t)0); 69810696SDavid.Hollister@Sun.COM 69910696SDavid.Hollister@Sun.COM start = (int)last + 1; 70011068SJohn.Danielson@Sun.COM for (i = start; i < mapp->dam_high; i++) { 70111068SJohn.Danielson@Sun.COM if (bitset_in_set(dam_list, i)) { 70210696SDavid.Hollister@Sun.COM return ((damap_id_t)i); 70311068SJohn.Danielson@Sun.COM } 70411068SJohn.Danielson@Sun.COM } 70510696SDavid.Hollister@Sun.COM return ((damap_id_t)0); 70610696SDavid.Hollister@Sun.COM } 70710696SDavid.Hollister@Sun.COM 70810696SDavid.Hollister@Sun.COM /* 70910696SDavid.Hollister@Sun.COM * Set config private data 71010696SDavid.Hollister@Sun.COM * 71110696SDavid.Hollister@Sun.COM * damapp: address map handle 71211068SJohn.Danielson@Sun.COM * addrid: address ID 71310696SDavid.Hollister@Sun.COM * cfg_priv: configuration private data 71410696SDavid.Hollister@Sun.COM * 71510696SDavid.Hollister@Sun.COM */ 71610696SDavid.Hollister@Sun.COM void 71711068SJohn.Danielson@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv) 71810696SDavid.Hollister@Sun.COM { 71910696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 72010696SDavid.Hollister@Sun.COM dam_da_t *passp; 72110696SDavid.Hollister@Sun.COM 72211068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 72311068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 72410696SDavid.Hollister@Sun.COM if (!passp) { 72511068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 72610696SDavid.Hollister@Sun.COM return; 72710696SDavid.Hollister@Sun.COM } 72810696SDavid.Hollister@Sun.COM passp->da_cfg_priv = cfg_priv; 72911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 73010696SDavid.Hollister@Sun.COM } 73110696SDavid.Hollister@Sun.COM 73210696SDavid.Hollister@Sun.COM /* 73310696SDavid.Hollister@Sun.COM * Get config private data 73410696SDavid.Hollister@Sun.COM * 73510696SDavid.Hollister@Sun.COM * damapp: address map handle 73611068SJohn.Danielson@Sun.COM * addrid: address ID 73710696SDavid.Hollister@Sun.COM * 73810696SDavid.Hollister@Sun.COM * Returns: configuration private data 73910696SDavid.Hollister@Sun.COM */ 74010696SDavid.Hollister@Sun.COM void * 74111068SJohn.Danielson@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t addrid) 74210696SDavid.Hollister@Sun.COM { 74310696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 74410696SDavid.Hollister@Sun.COM dam_da_t *passp; 74510696SDavid.Hollister@Sun.COM void *rv; 74610696SDavid.Hollister@Sun.COM 74711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 74811068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid); 74910696SDavid.Hollister@Sun.COM if (!passp) { 75011068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 75110696SDavid.Hollister@Sun.COM return (NULL); 75210696SDavid.Hollister@Sun.COM } 75310696SDavid.Hollister@Sun.COM rv = passp->da_cfg_priv; 75411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 75510696SDavid.Hollister@Sun.COM return (rv); 75610696SDavid.Hollister@Sun.COM } 75710696SDavid.Hollister@Sun.COM 75810696SDavid.Hollister@Sun.COM /* 75910696SDavid.Hollister@Sun.COM * Lookup a single address in the active address map 76010696SDavid.Hollister@Sun.COM * 76110696SDavid.Hollister@Sun.COM * damapp: address map handle 76210696SDavid.Hollister@Sun.COM * address: address string 76310696SDavid.Hollister@Sun.COM * 76410696SDavid.Hollister@Sun.COM * Returns: ID of active/stable address 76510696SDavid.Hollister@Sun.COM * 0 Address not in stable set 76610696SDavid.Hollister@Sun.COM * 76710696SDavid.Hollister@Sun.COM * Future: Allow the caller to wait for stabilize before returning not found. 76810696SDavid.Hollister@Sun.COM */ 76910696SDavid.Hollister@Sun.COM damap_id_t 77010696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address) 77110696SDavid.Hollister@Sun.COM { 77210696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 77310696SDavid.Hollister@Sun.COM id_t addrid = 0; 77410696SDavid.Hollister@Sun.COM dam_da_t *passp = NULL; 77510696SDavid.Hollister@Sun.COM 77611068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup, char *, mapp->dam_name, 77711068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp); 77811068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 77911068SJohn.Danielson@Sun.COM if (!mapp->dam_high) 78011068SJohn.Danielson@Sun.COM addrid = 0; 78111068SJohn.Danielson@Sun.COM else 78211068SJohn.Danielson@Sun.COM addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); 78310696SDavid.Hollister@Sun.COM if (addrid) { 78410696SDavid.Hollister@Sun.COM if (DAM_IS_STABLE(mapp, addrid)) { 78510696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 78610696SDavid.Hollister@Sun.COM ASSERT(passp); 78710696SDavid.Hollister@Sun.COM if (passp) { 78810696SDavid.Hollister@Sun.COM passp->da_ref++; 78910696SDavid.Hollister@Sun.COM } else { 79010696SDavid.Hollister@Sun.COM addrid = 0; 79110696SDavid.Hollister@Sun.COM } 79210696SDavid.Hollister@Sun.COM } else { 79310696SDavid.Hollister@Sun.COM addrid = 0; 79410696SDavid.Hollister@Sun.COM } 79510696SDavid.Hollister@Sun.COM } 79611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 79711068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__lookup__return, char *, mapp->dam_name, 79811068SJohn.Danielson@Sun.COM char *, address, dam_t *, mapp, int, addrid); 79910696SDavid.Hollister@Sun.COM return ((damap_id_t)addrid); 80010696SDavid.Hollister@Sun.COM } 80110696SDavid.Hollister@Sun.COM 80210696SDavid.Hollister@Sun.COM 80310696SDavid.Hollister@Sun.COM /* 80410696SDavid.Hollister@Sun.COM * Return the list of stable addresses in the map 80510696SDavid.Hollister@Sun.COM * 80610696SDavid.Hollister@Sun.COM * damapp: address map handle 80710696SDavid.Hollister@Sun.COM * id_listp: pointer to list of address IDs in stable map (returned) 80810696SDavid.Hollister@Sun.COM * 80910696SDavid.Hollister@Sun.COM * Returns: # of entries returned in alist 81010696SDavid.Hollister@Sun.COM */ 81110696SDavid.Hollister@Sun.COM int 81210696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp) 81310696SDavid.Hollister@Sun.COM { 81410696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 81510696SDavid.Hollister@Sun.COM int mapsz = mapp->dam_size; 81610696SDavid.Hollister@Sun.COM int n_ids, i; 81710696SDavid.Hollister@Sun.COM bitset_t *bsp; 81811068SJohn.Danielson@Sun.COM char *addrp; 81910696SDavid.Hollister@Sun.COM dam_da_t *passp; 82010696SDavid.Hollister@Sun.COM 82111068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__lookup__all, char *, mapp->dam_name, 82211068SJohn.Danielson@Sun.COM dam_t *, mapp); 82311068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 82411068SJohn.Danielson@Sun.COM if (!mapp->dam_high) { 82511068SJohn.Danielson@Sun.COM *id_listp = (damap_id_list_t)NULL; 82611068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 82711068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup__all__nomap, char *, 82811068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp, int, 0); 82911068SJohn.Danielson@Sun.COM return (0); 83011068SJohn.Danielson@Sun.COM } 83110696SDavid.Hollister@Sun.COM bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); 83210696SDavid.Hollister@Sun.COM bitset_init(bsp); 83310696SDavid.Hollister@Sun.COM bitset_resize(bsp, mapsz); 83410696SDavid.Hollister@Sun.COM bitset_copy(&mapp->dam_active_set, bsp); 83510696SDavid.Hollister@Sun.COM for (n_ids = 0, i = 1; i < mapsz; i++) { 83610696SDavid.Hollister@Sun.COM if (bitset_in_set(bsp, i)) { 83710696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i); 83810696SDavid.Hollister@Sun.COM ASSERT(passp); 83910696SDavid.Hollister@Sun.COM if (passp) { 84011068SJohn.Danielson@Sun.COM addrp = damap_id2addr(damapp, i); 84111068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__lookup__all__item, char *, 84211068SJohn.Danielson@Sun.COM mapp->dam_name, char *, addrp, dam_t *, 84311068SJohn.Danielson@Sun.COM mapp); 84410696SDavid.Hollister@Sun.COM passp->da_ref++; 84510696SDavid.Hollister@Sun.COM n_ids++; 84610696SDavid.Hollister@Sun.COM } 84710696SDavid.Hollister@Sun.COM } 84810696SDavid.Hollister@Sun.COM } 84910696SDavid.Hollister@Sun.COM if (n_ids) { 85010696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)bsp; 85111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 85210696SDavid.Hollister@Sun.COM return (n_ids); 85310696SDavid.Hollister@Sun.COM } else { 85410696SDavid.Hollister@Sun.COM *id_listp = (damap_id_list_t)NULL; 85510696SDavid.Hollister@Sun.COM bitset_fini(bsp); 85610696SDavid.Hollister@Sun.COM kmem_free(bsp, sizeof (*bsp)); 85711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 85810696SDavid.Hollister@Sun.COM return (0); 85910696SDavid.Hollister@Sun.COM } 86010696SDavid.Hollister@Sun.COM } 86110696SDavid.Hollister@Sun.COM 86210696SDavid.Hollister@Sun.COM /* 86310696SDavid.Hollister@Sun.COM * Release the address list returned by damap_lookup_all() 86410696SDavid.Hollister@Sun.COM * 86510696SDavid.Hollister@Sun.COM * mapp: address map handle 86610696SDavid.Hollister@Sun.COM * id_list: list of address IDs returned in damap_lookup_all() 86710696SDavid.Hollister@Sun.COM */ 86810696SDavid.Hollister@Sun.COM void 86910696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list) 87010696SDavid.Hollister@Sun.COM { 87110696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)damapp; 87210696SDavid.Hollister@Sun.COM int i; 87310696SDavid.Hollister@Sun.COM 87410696SDavid.Hollister@Sun.COM if (id_list == NULL) 87510696SDavid.Hollister@Sun.COM return; 87610696SDavid.Hollister@Sun.COM 87711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 87810696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 87910696SDavid.Hollister@Sun.COM if (bitset_in_set((bitset_t *)id_list, i)) 88011068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, i); 88110696SDavid.Hollister@Sun.COM } 88211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 88310696SDavid.Hollister@Sun.COM bitset_fini((bitset_t *)id_list); 88410696SDavid.Hollister@Sun.COM kmem_free((void *)id_list, sizeof (bitset_t)); 88510696SDavid.Hollister@Sun.COM } 88610696SDavid.Hollister@Sun.COM 88710696SDavid.Hollister@Sun.COM /* 88811068SJohn.Danielson@Sun.COM * activate an address that has passed the stabilization interval 88911068SJohn.Danielson@Sun.COM */ 89011068SJohn.Danielson@Sun.COM static void 89111068SJohn.Danielson@Sun.COM dam_addr_activate(dam_t *mapp, id_t addrid) 89211068SJohn.Danielson@Sun.COM { 89311068SJohn.Danielson@Sun.COM dam_da_t *passp; 89411068SJohn.Danielson@Sun.COM int config_rv; 89511068SJohn.Danielson@Sun.COM char *addrstr; 89611068SJohn.Danielson@Sun.COM 89711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 89811068SJohn.Danielson@Sun.COM bitset_add(&mapp->dam_active_set, addrid); 89911068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 90011068SJohn.Danielson@Sun.COM ASSERT(passp); 90111068SJohn.Danielson@Sun.COM 90211068SJohn.Danielson@Sun.COM /* 90311068SJohn.Danielson@Sun.COM * copy the reported nvlist and provider private data 90411068SJohn.Danielson@Sun.COM */ 90511068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 90611068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__activate__start, char *, mapp->dam_name, 90711068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 90811068SJohn.Danielson@Sun.COM passp->da_nvl = passp->da_nvl_rpt; 90911068SJohn.Danielson@Sun.COM passp->da_ppriv = passp->da_ppriv_rpt; 91011068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL; 91111068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL; 91211068SJohn.Danielson@Sun.COM passp->da_last_stable = gethrtime(); 91311068SJohn.Danielson@Sun.COM passp->da_stable_cnt++; 91411068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 91511068SJohn.Danielson@Sun.COM if (mapp->dam_activate_cb) { 91611068SJohn.Danielson@Sun.COM (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr, 91711068SJohn.Danielson@Sun.COM addrid, &passp->da_ppriv_rpt); 91811068SJohn.Danielson@Sun.COM } 91911068SJohn.Danielson@Sun.COM 92011068SJohn.Danielson@Sun.COM /* 92111068SJohn.Danielson@Sun.COM * call the address-specific configuration action as part of 92211068SJohn.Danielson@Sun.COM * activation. 92311068SJohn.Danielson@Sun.COM */ 92411068SJohn.Danielson@Sun.COM config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, 92511068SJohn.Danielson@Sun.COM addrid); 92611068SJohn.Danielson@Sun.COM if (config_rv != DAM_SUCCESS) { 92711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 92811068SJohn.Danielson@Sun.COM passp->da_flags |= DA_FAILED_CONFIG; 92911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 93011068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__activate__config__failure, 93111068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); 93211363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr, 93311363SReed.Liu@Sun.COM DAMAP_DEACT_RSN_CFG_FAIL); 93411363SReed.Liu@Sun.COM } else { 93511363SReed.Liu@Sun.COM DTRACE_PROBE3(damap__addr__activate__end, char *, 93611363SReed.Liu@Sun.COM mapp->dam_name, char *, addrstr, dam_t *, mapp); 93711068SJohn.Danielson@Sun.COM } 93811068SJohn.Danielson@Sun.COM } 93911068SJohn.Danielson@Sun.COM 94011068SJohn.Danielson@Sun.COM /* 94111068SJohn.Danielson@Sun.COM * deactivate a previously stable address 94211068SJohn.Danielson@Sun.COM */ 94311068SJohn.Danielson@Sun.COM static void 94411068SJohn.Danielson@Sun.COM dam_addr_deactivate(dam_t *mapp, id_t addrid) 94511068SJohn.Danielson@Sun.COM { 94611068SJohn.Danielson@Sun.COM char *addrstr; 94711068SJohn.Danielson@Sun.COM 94811068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 94911068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__start, char *, mapp->dam_name, 95011068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 95111068SJohn.Danielson@Sun.COM 95211068SJohn.Danielson@Sun.COM /* 95311068SJohn.Danielson@Sun.COM * call the unconfiguration callback 95411068SJohn.Danielson@Sun.COM */ 95511068SJohn.Danielson@Sun.COM (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid); 95611363SReed.Liu@Sun.COM dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE); 95711363SReed.Liu@Sun.COM } 95811363SReed.Liu@Sun.COM 95911363SReed.Liu@Sun.COM static void 96011363SReed.Liu@Sun.COM dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr, 96111363SReed.Liu@Sun.COM damap_deact_rsn_t deact_rsn) 96211363SReed.Liu@Sun.COM { 96311363SReed.Liu@Sun.COM dam_da_t *passp; 96411363SReed.Liu@Sun.COM 96511068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 96611068SJohn.Danielson@Sun.COM ASSERT(passp); 96711068SJohn.Danielson@Sun.COM if (mapp->dam_deactivate_cb) 96811068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, 96911068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid), 97011363SReed.Liu@Sun.COM addrid, passp->da_ppriv, deact_rsn); 97111068SJohn.Danielson@Sun.COM 97211068SJohn.Danielson@Sun.COM /* 97311068SJohn.Danielson@Sun.COM * clear the active bit and free the backing info for 97411068SJohn.Danielson@Sun.COM * this address 97511068SJohn.Danielson@Sun.COM */ 97611068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 97711068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_active_set, addrid); 97811068SJohn.Danielson@Sun.COM passp->da_ppriv = NULL; 97911068SJohn.Danielson@Sun.COM if (passp->da_nvl) 98011068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl); 98111068SJohn.Danielson@Sun.COM passp->da_nvl = NULL; 98211068SJohn.Danielson@Sun.COM passp->da_ppriv_rpt = NULL; 98311068SJohn.Danielson@Sun.COM if (passp->da_nvl_rpt) 98411068SJohn.Danielson@Sun.COM nvlist_free(passp->da_nvl_rpt); 98511068SJohn.Danielson@Sun.COM passp->da_nvl_rpt = NULL; 98611068SJohn.Danielson@Sun.COM 98711068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__deactivate__end, char *, mapp->dam_name, 98811068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 98911068SJohn.Danielson@Sun.COM 99011068SJohn.Danielson@Sun.COM (void) dam_addr_release(mapp, addrid); 99111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 99211068SJohn.Danielson@Sun.COM } 99311068SJohn.Danielson@Sun.COM 99411068SJohn.Danielson@Sun.COM /* 99511068SJohn.Danielson@Sun.COM * taskq callback for multi-thread activation 99611068SJohn.Danielson@Sun.COM */ 99711068SJohn.Danielson@Sun.COM static void 99811068SJohn.Danielson@Sun.COM dam_tq_config(void *arg) 99911068SJohn.Danielson@Sun.COM { 100011068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg; 100111068SJohn.Danielson@Sun.COM 100211068SJohn.Danielson@Sun.COM dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id); 100311068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd)); 100411068SJohn.Danielson@Sun.COM } 100511068SJohn.Danielson@Sun.COM 100611068SJohn.Danielson@Sun.COM /* 100711068SJohn.Danielson@Sun.COM * taskq callback for multi-thread deactivation 100811068SJohn.Danielson@Sun.COM */ 100911068SJohn.Danielson@Sun.COM static void 101011068SJohn.Danielson@Sun.COM dam_tq_unconfig(void *arg) 101111068SJohn.Danielson@Sun.COM { 101211068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = (cfg_tqd_t *)arg; 101311068SJohn.Danielson@Sun.COM 101411068SJohn.Danielson@Sun.COM dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id); 101511068SJohn.Danielson@Sun.COM kmem_free(tqd, sizeof (*tqd)); 101611068SJohn.Danielson@Sun.COM } 101711068SJohn.Danielson@Sun.COM 101811068SJohn.Danielson@Sun.COM /* 101910696SDavid.Hollister@Sun.COM * Activate a set of stabilized addresses 102010696SDavid.Hollister@Sun.COM */ 102110696SDavid.Hollister@Sun.COM static void 102211068SJohn.Danielson@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *activate) 102310696SDavid.Hollister@Sun.COM { 102411068SJohn.Danielson@Sun.COM 102511068SJohn.Danielson@Sun.COM int i, nset; 102611068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL; 102711068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL; 102811068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN]; 102911068SJohn.Danielson@Sun.COM extern pri_t maxclsyspri; 103010696SDavid.Hollister@Sun.COM 103111068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) { 103211068SJohn.Danielson@Sun.COM /* 103311068SJohn.Danielson@Sun.COM * calculate the # of taskq threads to create 103411068SJohn.Danielson@Sun.COM */ 103511068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++) 103611068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i)) 103711068SJohn.Danielson@Sun.COM nset++; 103811068SJohn.Danielson@Sun.COM ASSERT(nset); 103911068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name); 104011068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1, 104111068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE); 104211068SJohn.Danielson@Sun.COM } 104310696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 104411068SJohn.Danielson@Sun.COM if (bitset_in_set(activate, i)) { 104511068SJohn.Danielson@Sun.COM if (!tqp) 104611068SJohn.Danielson@Sun.COM dam_addr_activate(mapp, i); 104711068SJohn.Danielson@Sun.COM else { 104811068SJohn.Danielson@Sun.COM /* 104911068SJohn.Danielson@Sun.COM * multi-threaded activation 105011068SJohn.Danielson@Sun.COM */ 105111068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); 105211068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp; 105311068SJohn.Danielson@Sun.COM tqd->tqd_id = i; 105411068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp, dam_tq_config, 105511068SJohn.Danielson@Sun.COM tqd, KM_SLEEP); 105611068SJohn.Danielson@Sun.COM } 105710696SDavid.Hollister@Sun.COM } 105811068SJohn.Danielson@Sun.COM } 105911068SJohn.Danielson@Sun.COM if (tqp) { 106011068SJohn.Danielson@Sun.COM taskq_wait(tqp); 106111068SJohn.Danielson@Sun.COM taskq_destroy(tqp); 106210696SDavid.Hollister@Sun.COM } 106310696SDavid.Hollister@Sun.COM } 106410696SDavid.Hollister@Sun.COM 106510696SDavid.Hollister@Sun.COM /* 106611068SJohn.Danielson@Sun.COM * Deactivate a set of stabilized addresses 106710696SDavid.Hollister@Sun.COM */ 106810696SDavid.Hollister@Sun.COM static void 106911068SJohn.Danielson@Sun.COM dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate) 107010696SDavid.Hollister@Sun.COM { 107111068SJohn.Danielson@Sun.COM int i, nset; 107211068SJohn.Danielson@Sun.COM taskq_t *tqp = NULL; 107311068SJohn.Danielson@Sun.COM cfg_tqd_t *tqd = NULL; 107411068SJohn.Danielson@Sun.COM char tqn[TASKQ_NAMELEN]; 107511068SJohn.Danielson@Sun.COM 107611068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__addrset__deactivate, char *, mapp->dam_name, 107711068SJohn.Danielson@Sun.COM dam_t *, mapp); 107810696SDavid.Hollister@Sun.COM 107911068SJohn.Danielson@Sun.COM if (mapp->dam_options & DAMAP_MTCONFIG) { 108011068SJohn.Danielson@Sun.COM /* 108111068SJohn.Danielson@Sun.COM * compute the # of taskq threads to dispatch 108211068SJohn.Danielson@Sun.COM */ 108311068SJohn.Danielson@Sun.COM for (i = 1, nset = 0; i < mapp->dam_high; i++) 108411068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i)) 108511068SJohn.Danielson@Sun.COM nset++; 108611068SJohn.Danielson@Sun.COM (void) snprintf(tqn, sizeof (tqn), "deactv-%s", 108711068SJohn.Danielson@Sun.COM mapp->dam_name); 108811068SJohn.Danielson@Sun.COM tqp = taskq_create(tqn, nset, maxclsyspri, 1, 108911068SJohn.Danielson@Sun.COM INT_MAX, TASKQ_PREPOPULATE); 109011068SJohn.Danielson@Sun.COM } 109110696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 109211068SJohn.Danielson@Sun.COM if (bitset_in_set(deactivate, i)) { 109311068SJohn.Danielson@Sun.COM if (!tqp) { 109411068SJohn.Danielson@Sun.COM dam_addr_deactivate(mapp, i); 109511068SJohn.Danielson@Sun.COM } else { 109611068SJohn.Danielson@Sun.COM tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP); 109711068SJohn.Danielson@Sun.COM tqd->tqd_mapp = mapp; 109811068SJohn.Danielson@Sun.COM tqd->tqd_id = i; 109911068SJohn.Danielson@Sun.COM (void) taskq_dispatch(tqp, 110011068SJohn.Danielson@Sun.COM dam_tq_unconfig, tqd, KM_SLEEP); 110111068SJohn.Danielson@Sun.COM } 110210696SDavid.Hollister@Sun.COM } 110310696SDavid.Hollister@Sun.COM } 110411068SJohn.Danielson@Sun.COM 110511068SJohn.Danielson@Sun.COM if (tqp) { 110611068SJohn.Danielson@Sun.COM taskq_wait(tqp); 110711068SJohn.Danielson@Sun.COM taskq_destroy(tqp); 110811068SJohn.Danielson@Sun.COM } 110910696SDavid.Hollister@Sun.COM } 111010696SDavid.Hollister@Sun.COM 111110696SDavid.Hollister@Sun.COM /* 111211068SJohn.Danielson@Sun.COM * Release a previously activated address 111310696SDavid.Hollister@Sun.COM */ 111410696SDavid.Hollister@Sun.COM static void 111511068SJohn.Danielson@Sun.COM dam_addr_release(dam_t *mapp, id_t addrid) 111610696SDavid.Hollister@Sun.COM { 111710696SDavid.Hollister@Sun.COM dam_da_t *passp; 111811068SJohn.Danielson@Sun.COM char *addrstr; 111910696SDavid.Hollister@Sun.COM 112011068SJohn.Danielson@Sun.COM 112111068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 112210696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 112310696SDavid.Hollister@Sun.COM ASSERT(passp); 112410696SDavid.Hollister@Sun.COM 112511068SJohn.Danielson@Sun.COM addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid); 112611068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__release, char *, mapp->dam_name, 112711068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 112810696SDavid.Hollister@Sun.COM 112910696SDavid.Hollister@Sun.COM /* 113011068SJohn.Danielson@Sun.COM * defer releasing the address until outstanding references 113111068SJohn.Danielson@Sun.COM * are released 113210696SDavid.Hollister@Sun.COM */ 113311068SJohn.Danielson@Sun.COM if (passp->da_ref > 1) { 113411068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__addr__release__outstanding__refs, 113511068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp, 113611068SJohn.Danielson@Sun.COM int, passp->da_ref); 113710696SDavid.Hollister@Sun.COM return; 113811068SJohn.Danielson@Sun.COM } 113910696SDavid.Hollister@Sun.COM 114010696SDavid.Hollister@Sun.COM /* 114111068SJohn.Danielson@Sun.COM * allow pending reports to stabilize 114210696SDavid.Hollister@Sun.COM */ 114311068SJohn.Danielson@Sun.COM if (DAM_IN_REPORT(mapp, addrid)) { 114411068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__release__report__pending, 114511068SJohn.Danielson@Sun.COM char *, mapp->dam_name, char *, addrstr, dam_t *, mapp); 114610696SDavid.Hollister@Sun.COM return; 114710696SDavid.Hollister@Sun.COM } 114811068SJohn.Danielson@Sun.COM 114910696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid); 115010696SDavid.Hollister@Sun.COM ddi_soft_state_free(mapp->dam_da, addrid); 115110696SDavid.Hollister@Sun.COM } 115210696SDavid.Hollister@Sun.COM 115310696SDavid.Hollister@Sun.COM /* 115410696SDavid.Hollister@Sun.COM * process stabilized address reports 115510696SDavid.Hollister@Sun.COM */ 115610696SDavid.Hollister@Sun.COM static void 115711068SJohn.Danielson@Sun.COM dam_stabilize_map(void *arg) 115810696SDavid.Hollister@Sun.COM { 115910696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 116010696SDavid.Hollister@Sun.COM bitset_t delta; 116110696SDavid.Hollister@Sun.COM bitset_t cfg; 116210696SDavid.Hollister@Sun.COM bitset_t uncfg; 116310696SDavid.Hollister@Sun.COM int has_cfg, has_uncfg; 116411068SJohn.Danielson@Sun.COM uint32_t i, n_active; 116511068SJohn.Danielson@Sun.COM 116611068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__stabilize__map, char *, mapp->dam_name, 116711068SJohn.Danielson@Sun.COM dam_t *, mapp); 116810696SDavid.Hollister@Sun.COM 116910696SDavid.Hollister@Sun.COM bitset_init(&delta); 117010696SDavid.Hollister@Sun.COM bitset_resize(&delta, mapp->dam_size); 117110696SDavid.Hollister@Sun.COM bitset_init(&cfg); 117210696SDavid.Hollister@Sun.COM bitset_resize(&cfg, mapp->dam_size); 117310696SDavid.Hollister@Sun.COM bitset_init(&uncfg); 117410696SDavid.Hollister@Sun.COM bitset_resize(&uncfg, mapp->dam_size); 117510696SDavid.Hollister@Sun.COM 117611068SJohn.Danielson@Sun.COM /* 117711068SJohn.Danielson@Sun.COM * determine which addresses have changed during 117811068SJohn.Danielson@Sun.COM * this stabilization cycle 117911068SJohn.Danielson@Sun.COM */ 118011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 118111068SJohn.Danielson@Sun.COM ASSERT(mapp->dam_flags & DAM_SPEND); 118210696SDavid.Hollister@Sun.COM if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, 118310696SDavid.Hollister@Sun.COM &delta)) { 118411068SJohn.Danielson@Sun.COM /* 118511068SJohn.Danielson@Sun.COM * no difference 118611068SJohn.Danielson@Sun.COM */ 118710696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set); 118811068SJohn.Danielson@Sun.COM mapp->dam_flags &= ~DAM_SPEND; 118911068SJohn.Danielson@Sun.COM cv_signal(&mapp->dam_cv); 119011068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 119110696SDavid.Hollister@Sun.COM bitset_fini(&uncfg); 119210696SDavid.Hollister@Sun.COM bitset_fini(&cfg); 119310696SDavid.Hollister@Sun.COM bitset_fini(&delta); 119411068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__stabilize__map__nochange, char *, 119511068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 119610696SDavid.Hollister@Sun.COM return; 119710696SDavid.Hollister@Sun.COM } 119811068SJohn.Danielson@Sun.COM 119911068SJohn.Danielson@Sun.COM /* 120011068SJohn.Danielson@Sun.COM * compute the sets of addresses to be activated and deactivated 120111068SJohn.Danielson@Sun.COM */ 120210696SDavid.Hollister@Sun.COM has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); 120310696SDavid.Hollister@Sun.COM has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); 120411068SJohn.Danielson@Sun.COM 120511068SJohn.Danielson@Sun.COM /* 120611068SJohn.Danielson@Sun.COM * drop map lock while invoking callouts 120711068SJohn.Danielson@Sun.COM */ 120811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 120911068SJohn.Danielson@Sun.COM 121011068SJohn.Danielson@Sun.COM /* 121111068SJohn.Danielson@Sun.COM * activate all newly stable addresss 121211068SJohn.Danielson@Sun.COM */ 121311068SJohn.Danielson@Sun.COM if (has_cfg) 121410696SDavid.Hollister@Sun.COM dam_addrset_activate(mapp, &cfg); 121511068SJohn.Danielson@Sun.COM 121611068SJohn.Danielson@Sun.COM /* 121711068SJohn.Danielson@Sun.COM * deactivate addresss which are no longer in the map 121811068SJohn.Danielson@Sun.COM */ 121911068SJohn.Danielson@Sun.COM if (has_uncfg) 122011068SJohn.Danielson@Sun.COM dam_addrset_deactivate(mapp, &uncfg); 122111068SJohn.Danielson@Sun.COM 122211068SJohn.Danielson@Sun.COM 122311068SJohn.Danielson@Sun.COM /* 122411068SJohn.Danielson@Sun.COM * timestamp the last stable time and increment the kstat keeping 122511068SJohn.Danielson@Sun.COM * the # of of stable cycles for the map 122611068SJohn.Danielson@Sun.COM */ 122711068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 122810696SDavid.Hollister@Sun.COM bitset_zero(&mapp->dam_stable_set); 122910696SDavid.Hollister@Sun.COM mapp->dam_last_stable = gethrtime(); 123010696SDavid.Hollister@Sun.COM mapp->dam_stable_cnt++; 123111068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_cycles); 123211068SJohn.Danielson@Sun.COM 123311068SJohn.Danielson@Sun.COM /* 123411068SJohn.Danielson@Sun.COM * determine the number of stable addresses 123511068SJohn.Danielson@Sun.COM * and update the n_active kstat for this map 123611068SJohn.Danielson@Sun.COM */ 123711068SJohn.Danielson@Sun.COM for (i = 1, n_active = 0; i < mapp->dam_high; i++) 123811068SJohn.Danielson@Sun.COM if (bitset_in_set(&mapp->dam_active_set, i)) 123911068SJohn.Danielson@Sun.COM n_active++; 124011068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_active, n_active); 124111068SJohn.Danielson@Sun.COM 124211068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__map__stable__end, char *, mapp->dam_name, 124311068SJohn.Danielson@Sun.COM dam_t *, mapp, int, n_active); 124411068SJohn.Danielson@Sun.COM 124511068SJohn.Danielson@Sun.COM mapp->dam_flags &= ~DAM_SPEND; 124611068SJohn.Danielson@Sun.COM cv_signal(&mapp->dam_cv); 124711068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 124810696SDavid.Hollister@Sun.COM bitset_fini(&uncfg); 124910696SDavid.Hollister@Sun.COM bitset_fini(&cfg); 125010696SDavid.Hollister@Sun.COM bitset_fini(&delta); 125110696SDavid.Hollister@Sun.COM } 125210696SDavid.Hollister@Sun.COM 125310696SDavid.Hollister@Sun.COM /* 125410696SDavid.Hollister@Sun.COM * per-address stabilization timeout 125510696SDavid.Hollister@Sun.COM */ 125610696SDavid.Hollister@Sun.COM static void 125710696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg) 125810696SDavid.Hollister@Sun.COM { 125910696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 126010696SDavid.Hollister@Sun.COM int i; 126110696SDavid.Hollister@Sun.COM dam_da_t *passp; 126210696SDavid.Hollister@Sun.COM int spend = 0; 126310696SDavid.Hollister@Sun.COM int tpend = 0; 126410696SDavid.Hollister@Sun.COM int64_t next_tmov = mapp->dam_stabletmo; 126510696SDavid.Hollister@Sun.COM int64_t tmo_delta; 126611066Srafael.vanoni@sun.com int64_t ts = ddi_get_lbolt64(); 126710696SDavid.Hollister@Sun.COM 126811068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 126910696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) { 127011068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__cancelled, char *, 127111068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 127211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 127310696SDavid.Hollister@Sun.COM return; 127410696SDavid.Hollister@Sun.COM } 127510696SDavid.Hollister@Sun.COM mapp->dam_tid = 0; 127611068SJohn.Danielson@Sun.COM 127710696SDavid.Hollister@Sun.COM /* 127810696SDavid.Hollister@Sun.COM * If still under stabilization, reschedule timeout, 127911068SJohn.Danielson@Sun.COM * otherwise dispatch the task to activate and deactivate the 128011068SJohn.Danielson@Sun.COM * new stable address 128110696SDavid.Hollister@Sun.COM */ 128210696SDavid.Hollister@Sun.COM if (mapp->dam_flags & DAM_SPEND) { 128311068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun); 128410696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++; 128510696SDavid.Hollister@Sun.COM dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 128611068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__overrun, char *, 128711068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 128811068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 128910696SDavid.Hollister@Sun.COM return; 129010696SDavid.Hollister@Sun.COM } 129110696SDavid.Hollister@Sun.COM 129211068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0); 129311068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0; 129411068SJohn.Danielson@Sun.COM 129511068SJohn.Danielson@Sun.COM /* 129611068SJohn.Danielson@Sun.COM * copy the current active set to the stable map 129711068SJohn.Danielson@Sun.COM * for each address being reported, decrement its 129811068SJohn.Danielson@Sun.COM * stabilize deadline, and if stable, add or remove the 129911068SJohn.Danielson@Sun.COM * address from the stable set 130011068SJohn.Danielson@Sun.COM */ 130110696SDavid.Hollister@Sun.COM bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); 130210696SDavid.Hollister@Sun.COM for (i = 1; i < mapp->dam_high; i++) { 130310696SDavid.Hollister@Sun.COM if (!bitset_in_set(&mapp->dam_report_set, i)) 130410696SDavid.Hollister@Sun.COM continue; 130510696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, i); 130610696SDavid.Hollister@Sun.COM ASSERT(passp); 130710696SDavid.Hollister@Sun.COM 130810696SDavid.Hollister@Sun.COM /* report has stabilized */ 130910696SDavid.Hollister@Sun.COM if (passp->da_deadline <= ts) { 131010696SDavid.Hollister@Sun.COM bitset_del(&mapp->dam_report_set, i); 131111068SJohn.Danielson@Sun.COM if (passp->da_flags & DA_RELE) 131210696SDavid.Hollister@Sun.COM bitset_del(&mapp->dam_stable_set, i); 131311068SJohn.Danielson@Sun.COM else 131410696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_stable_set, i); 131510696SDavid.Hollister@Sun.COM spend++; 131610696SDavid.Hollister@Sun.COM continue; 131710696SDavid.Hollister@Sun.COM } 131810696SDavid.Hollister@Sun.COM 131910696SDavid.Hollister@Sun.COM /* 132011068SJohn.Danielson@Sun.COM * not stabilized, determine next map timeout 132110696SDavid.Hollister@Sun.COM */ 132210696SDavid.Hollister@Sun.COM tpend++; 132310696SDavid.Hollister@Sun.COM tmo_delta = passp->da_deadline - ts; 132410696SDavid.Hollister@Sun.COM if (tmo_delta < next_tmov) 132510696SDavid.Hollister@Sun.COM next_tmov = tmo_delta; 132610696SDavid.Hollister@Sun.COM } 132710696SDavid.Hollister@Sun.COM 132810696SDavid.Hollister@Sun.COM /* 132911068SJohn.Danielson@Sun.COM * schedule system_taskq activation of stabilized reports 133010696SDavid.Hollister@Sun.COM */ 133110696SDavid.Hollister@Sun.COM if (spend) { 133211068SJohn.Danielson@Sun.COM if (taskq_dispatch(system_taskq, dam_stabilize_map, 133311068SJohn.Danielson@Sun.COM mapp, TQ_NOSLEEP)) { 133411068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_SPEND; 133511068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addr__stable__start, char *, 133611068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 133711068SJohn.Danielson@Sun.COM } else { 133810696SDavid.Hollister@Sun.COM tpend++; 133911068SJohn.Danielson@Sun.COM } 134010696SDavid.Hollister@Sun.COM } 134110696SDavid.Hollister@Sun.COM 134210696SDavid.Hollister@Sun.COM /* 134311068SJohn.Danielson@Sun.COM * reschedule the stabilization timer if there are reports 134411068SJohn.Danielson@Sun.COM * still pending 134510696SDavid.Hollister@Sun.COM */ 134610696SDavid.Hollister@Sun.COM if (tpend) 134710696SDavid.Hollister@Sun.COM dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb); 134811068SJohn.Danielson@Sun.COM 134911068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 135010696SDavid.Hollister@Sun.COM } 135110696SDavid.Hollister@Sun.COM 135210696SDavid.Hollister@Sun.COM /* 135311068SJohn.Danielson@Sun.COM * fullset stabilization timeout callback 135410696SDavid.Hollister@Sun.COM */ 135510696SDavid.Hollister@Sun.COM static void 135611068SJohn.Danielson@Sun.COM dam_addrset_stable_cb(void *arg) 135710696SDavid.Hollister@Sun.COM { 135810696SDavid.Hollister@Sun.COM dam_t *mapp = (dam_t *)arg; 135910696SDavid.Hollister@Sun.COM 136011068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 136110696SDavid.Hollister@Sun.COM if (mapp->dam_tid == 0) { 136211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 136311068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__cancelled, 136411068SJohn.Danielson@Sun.COM char *, mapp->dam_name, dam_t *, mapp); 136510696SDavid.Hollister@Sun.COM return; 136610696SDavid.Hollister@Sun.COM } 136710696SDavid.Hollister@Sun.COM mapp->dam_tid = 0; 136810696SDavid.Hollister@Sun.COM 136910696SDavid.Hollister@Sun.COM /* 137011068SJohn.Danielson@Sun.COM * If map still underoing stabilization reschedule timeout, 137111068SJohn.Danielson@Sun.COM * else dispatch the task to configure the new stable set of 137211068SJohn.Danielson@Sun.COM * addresses. 137310696SDavid.Hollister@Sun.COM */ 137411068SJohn.Danielson@Sun.COM if ((mapp->dam_flags & DAM_SPEND) || (taskq_dispatch(system_taskq, 137511068SJohn.Danielson@Sun.COM dam_stabilize_map, mapp, TQ_NOSLEEP) == NULL)) { 137611068SJohn.Danielson@Sun.COM DAM_INCR_STAT(mapp, dam_overrun); 137710696SDavid.Hollister@Sun.COM mapp->dam_stable_overrun++; 137811068SJohn.Danielson@Sun.COM dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addrset_stable_cb); 137911068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__overrun, char *, 138011068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 138111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 138211068SJohn.Danielson@Sun.COM return; 138310696SDavid.Hollister@Sun.COM } 138411068SJohn.Danielson@Sun.COM 138511068SJohn.Danielson@Sun.COM DAM_SET_STAT(mapp, dam_overrun, 0); 138611068SJohn.Danielson@Sun.COM mapp->dam_stable_overrun = 0; 138711068SJohn.Danielson@Sun.COM bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); 138811068SJohn.Danielson@Sun.COM bitset_zero(&mapp->dam_report_set); 138911068SJohn.Danielson@Sun.COM mapp->dam_flags |= DAM_SPEND; 139011068SJohn.Danielson@Sun.COM mapp->dam_flags &= ~DAM_SETADD; 139111068SJohn.Danielson@Sun.COM DTRACE_PROBE2(damap__map__addrset__stable__start, char *, 139211068SJohn.Danielson@Sun.COM mapp->dam_name, dam_t *, mapp); 139311068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 139410696SDavid.Hollister@Sun.COM } 139510696SDavid.Hollister@Sun.COM 139610696SDavid.Hollister@Sun.COM /* 139711068SJohn.Danielson@Sun.COM * schedule map timeout 'tmo_ms' ticks 139811068SJohn.Danielson@Sun.COM * if map timer is currently running, cancel if tmo_ms == 0 139910696SDavid.Hollister@Sun.COM */ 140010696SDavid.Hollister@Sun.COM static void 140110696SDavid.Hollister@Sun.COM dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)()) 140210696SDavid.Hollister@Sun.COM { 140310696SDavid.Hollister@Sun.COM timeout_id_t tid; 140410696SDavid.Hollister@Sun.COM 140511068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__sched__tmo, char *, mapp->dam_name, dam_t *, mapp, 140611068SJohn.Danielson@Sun.COM clock_t, tmo_ms); 140711068SJohn.Danielson@Sun.COM 140811068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 140910696SDavid.Hollister@Sun.COM if ((tid = mapp->dam_tid) != 0) { 141011068SJohn.Danielson@Sun.COM if (tmo_ms == 0) { 141111068SJohn.Danielson@Sun.COM mapp->dam_tid = 0; 141211068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 141311068SJohn.Danielson@Sun.COM (void) untimeout(tid); 141411068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 141511068SJohn.Danielson@Sun.COM } 141611068SJohn.Danielson@Sun.COM } else { 141711068SJohn.Danielson@Sun.COM if (tmo_cb && (tmo_ms != 0)) 141811068SJohn.Danielson@Sun.COM mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); 141910696SDavid.Hollister@Sun.COM } 142010696SDavid.Hollister@Sun.COM } 142110696SDavid.Hollister@Sun.COM 142210696SDavid.Hollister@Sun.COM /* 142311068SJohn.Danielson@Sun.COM * report addition or removal of an address 142410696SDavid.Hollister@Sun.COM */ 142510696SDavid.Hollister@Sun.COM static void 142611068SJohn.Danielson@Sun.COM dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type) 142710696SDavid.Hollister@Sun.COM { 142811068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid); 142911068SJohn.Danielson@Sun.COM 143011068SJohn.Danielson@Sun.COM DTRACE_PROBE4(damap__addr__report, char *, mapp->dam_name, 143111068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp, int, rpt_type); 143211068SJohn.Danielson@Sun.COM 143311068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 143410696SDavid.Hollister@Sun.COM ASSERT(!DAM_IN_REPORT(mapp, addrid)); 143510696SDavid.Hollister@Sun.COM passp->da_last_report = gethrtime(); 143610696SDavid.Hollister@Sun.COM mapp->dam_last_update = gethrtime(); 143710696SDavid.Hollister@Sun.COM passp->da_report_cnt++; 143811066Srafael.vanoni@sun.com passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stabletmo; 143911068SJohn.Danielson@Sun.COM if (rpt_type == RPT_ADDR_DEL) 144010696SDavid.Hollister@Sun.COM passp->da_flags |= DA_RELE; 144111068SJohn.Danielson@Sun.COM else if (rpt_type == RPT_ADDR_ADD) 144210696SDavid.Hollister@Sun.COM passp->da_flags &= ~DA_RELE; 144310696SDavid.Hollister@Sun.COM bitset_add(&mapp->dam_report_set, addrid); 144410696SDavid.Hollister@Sun.COM dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 144510696SDavid.Hollister@Sun.COM } 144610696SDavid.Hollister@Sun.COM 144710696SDavid.Hollister@Sun.COM /* 144810696SDavid.Hollister@Sun.COM * release an address report 144910696SDavid.Hollister@Sun.COM */ 145010696SDavid.Hollister@Sun.COM static void 145111068SJohn.Danielson@Sun.COM dam_addr_report_release(dam_t *mapp, id_t addrid) 145210696SDavid.Hollister@Sun.COM { 145310696SDavid.Hollister@Sun.COM dam_da_t *passp; 145411068SJohn.Danielson@Sun.COM char *addrstr = damap_id2addr((damap_t *)mapp, addrid); 145510696SDavid.Hollister@Sun.COM 145611068SJohn.Danielson@Sun.COM DTRACE_PROBE3(damap__addr__report__release, char *, mapp->dam_name, 145711068SJohn.Danielson@Sun.COM char *, addrstr, dam_t *, mapp); 145811068SJohn.Danielson@Sun.COM 145911068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 146010696SDavid.Hollister@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 146110696SDavid.Hollister@Sun.COM ASSERT(passp); 146211068SJohn.Danielson@Sun.COM /* 146311068SJohn.Danielson@Sun.COM * clear the report bit 146411068SJohn.Danielson@Sun.COM * if the address has a registered deactivation handler and 1465*11601SDavid.Hollister@Sun.COM * we are holding a private data pointer and the address has not 1466*11601SDavid.Hollister@Sun.COM * stabilized, deactivate the address (private data). 146711068SJohn.Danielson@Sun.COM */ 146811068SJohn.Danielson@Sun.COM bitset_del(&mapp->dam_report_set, addrid); 1469*11601SDavid.Hollister@Sun.COM if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb && 1470*11601SDavid.Hollister@Sun.COM passp->da_ppriv_rpt) { 147111068SJohn.Danielson@Sun.COM mutex_exit(&mapp->dam_lock); 147211068SJohn.Danielson@Sun.COM (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg, 147311068SJohn.Danielson@Sun.COM ddi_strid_id2str(mapp->dam_addr_hash, addrid), 1474*11601SDavid.Hollister@Sun.COM addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL); 147511068SJohn.Danielson@Sun.COM mutex_enter(&mapp->dam_lock); 147611068SJohn.Danielson@Sun.COM } 147710696SDavid.Hollister@Sun.COM passp->da_ppriv_rpt = NULL; 147810696SDavid.Hollister@Sun.COM if (passp->da_nvl_rpt) 147910696SDavid.Hollister@Sun.COM nvlist_free(passp->da_nvl_rpt); 148010696SDavid.Hollister@Sun.COM } 148110696SDavid.Hollister@Sun.COM 148210696SDavid.Hollister@Sun.COM /* 148310696SDavid.Hollister@Sun.COM * return the map ID of an address 148410696SDavid.Hollister@Sun.COM */ 148510696SDavid.Hollister@Sun.COM static id_t 148610696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address) 148710696SDavid.Hollister@Sun.COM { 148810696SDavid.Hollister@Sun.COM damap_id_t addrid; 148910696SDavid.Hollister@Sun.COM dam_da_t *passp; 149010696SDavid.Hollister@Sun.COM 149111068SJohn.Danielson@Sun.COM ASSERT(mutex_owned(&mapp->dam_lock)); 149210696SDavid.Hollister@Sun.COM if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { 149311068SJohn.Danielson@Sun.COM if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash, 149410696SDavid.Hollister@Sun.COM address)) == (damap_id_t)0) { 149510696SDavid.Hollister@Sun.COM return (0); 149610696SDavid.Hollister@Sun.COM } 149710696SDavid.Hollister@Sun.COM if (ddi_soft_state_zalloc(mapp->dam_da, addrid) != 149810696SDavid.Hollister@Sun.COM DDI_SUCCESS) { 149910696SDavid.Hollister@Sun.COM ddi_strid_free(mapp->dam_addr_hash, addrid); 150010696SDavid.Hollister@Sun.COM return (0); 150110696SDavid.Hollister@Sun.COM } 150211068SJohn.Danielson@Sun.COM 150310696SDavid.Hollister@Sun.COM if (addrid >= mapp->dam_high) 150410696SDavid.Hollister@Sun.COM mapp->dam_high = addrid + 1; 150511068SJohn.Danielson@Sun.COM 150611068SJohn.Danielson@Sun.COM /* 150711068SJohn.Danielson@Sun.COM * expand bitmaps if ID has outgrown old map size 150811068SJohn.Danielson@Sun.COM */ 150911068SJohn.Danielson@Sun.COM if (mapp->dam_high > mapp->dam_size) { 151011068SJohn.Danielson@Sun.COM mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP; 151111068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_active_set, mapp->dam_size); 151211068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_stable_set, mapp->dam_size); 151311068SJohn.Danielson@Sun.COM bitset_resize(&mapp->dam_report_set, mapp->dam_size); 151411068SJohn.Danielson@Sun.COM } 151511068SJohn.Danielson@Sun.COM 151611068SJohn.Danielson@Sun.COM passp = ddi_get_soft_state(mapp->dam_da, addrid); 151711068SJohn.Danielson@Sun.COM passp->da_ref = 1; 151811068SJohn.Danielson@Sun.COM passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash, 151911068SJohn.Danielson@Sun.COM addrid); /* for mdb */ 152010696SDavid.Hollister@Sun.COM } 152110696SDavid.Hollister@Sun.COM return (addrid); 152210696SDavid.Hollister@Sun.COM } 152310696SDavid.Hollister@Sun.COM 152410696SDavid.Hollister@Sun.COM /* 152510696SDavid.Hollister@Sun.COM * create and install map statistics 152610696SDavid.Hollister@Sun.COM */ 152710696SDavid.Hollister@Sun.COM static int 152810696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp) 152910696SDavid.Hollister@Sun.COM { 153010696SDavid.Hollister@Sun.COM kstat_t *mapsp; 153110696SDavid.Hollister@Sun.COM struct dam_kstats *statsp; 153210696SDavid.Hollister@Sun.COM 153310696SDavid.Hollister@Sun.COM mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", 153410696SDavid.Hollister@Sun.COM KSTAT_TYPE_NAMED, 153510696SDavid.Hollister@Sun.COM sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); 153611068SJohn.Danielson@Sun.COM 153711068SJohn.Danielson@Sun.COM if (mapsp == NULL) 153810696SDavid.Hollister@Sun.COM return (DDI_FAILURE); 153910696SDavid.Hollister@Sun.COM 154010696SDavid.Hollister@Sun.COM statsp = (struct dam_kstats *)mapsp->ks_data; 154111068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32); 154211068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32); 154311068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32); 154411068SJohn.Danielson@Sun.COM kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32); 154510696SDavid.Hollister@Sun.COM kstat_install(mapsp); 154610696SDavid.Hollister@Sun.COM mapp->dam_kstatsp = mapsp; 154710696SDavid.Hollister@Sun.COM return (DDI_SUCCESS); 154810696SDavid.Hollister@Sun.COM } 1549