1*4c06356bSdh142964 /* 2*4c06356bSdh142964 * CDDL HEADER START 3*4c06356bSdh142964 * 4*4c06356bSdh142964 * The contents of this file are subject to the terms of the 5*4c06356bSdh142964 * Common Development and Distribution License (the "License"). 6*4c06356bSdh142964 * You may not use this file except in compliance with the License. 7*4c06356bSdh142964 * 8*4c06356bSdh142964 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4c06356bSdh142964 * or http://www.opensolaris.org/os/licensing. 10*4c06356bSdh142964 * See the License for the specific language governing permissions 11*4c06356bSdh142964 * and limitations under the License. 12*4c06356bSdh142964 * 13*4c06356bSdh142964 * When distributing Covered Code, include this CDDL HEADER in each 14*4c06356bSdh142964 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4c06356bSdh142964 * If applicable, add the following below this CDDL HEADER, with the 16*4c06356bSdh142964 * fields enclosed by brackets "[]" replaced with your own identifying 17*4c06356bSdh142964 * information: Portions Copyright [yyyy] [name of copyright owner] 18*4c06356bSdh142964 * 19*4c06356bSdh142964 * CDDL HEADER END 20*4c06356bSdh142964 */ 21*4c06356bSdh142964 22*4c06356bSdh142964 /* 23*4c06356bSdh142964 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*4c06356bSdh142964 * Use is subject to license terms. 25*4c06356bSdh142964 */ 26*4c06356bSdh142964 27*4c06356bSdh142964 #include <sys/note.h> 28*4c06356bSdh142964 #include <sys/types.h> 29*4c06356bSdh142964 #include <sys/param.h> 30*4c06356bSdh142964 #include <sys/systm.h> 31*4c06356bSdh142964 #include <sys/buf.h> 32*4c06356bSdh142964 #include <sys/kmem.h> 33*4c06356bSdh142964 #include <sys/cmn_err.h> 34*4c06356bSdh142964 #include <sys/debug.h> 35*4c06356bSdh142964 #include <sys/sunndi.h> 36*4c06356bSdh142964 #include <sys/kstat.h> 37*4c06356bSdh142964 #include <sys/conf.h> 38*4c06356bSdh142964 #include <sys/ddi_timer.h> 39*4c06356bSdh142964 #include <sys/devctl.h> 40*4c06356bSdh142964 #include <sys/callb.h> 41*4c06356bSdh142964 #include <sys/sysevent.h> 42*4c06356bSdh142964 #include <sys/taskq.h> 43*4c06356bSdh142964 #include <sys/ddi.h> 44*4c06356bSdh142964 #include <sys/bitset.h> 45*4c06356bSdh142964 #include <sys/damap.h> 46*4c06356bSdh142964 #include <sys/damap_impl.h> 47*4c06356bSdh142964 48*4c06356bSdh142964 #ifdef DEBUG 49*4c06356bSdh142964 static int damap_debug = 0; 50*4c06356bSdh142964 #endif /* DEBUG */ 51*4c06356bSdh142964 52*4c06356bSdh142964 static void dam_addrset_activate(dam_t *, bitset_t *); 53*4c06356bSdh142964 static void dam_addrset_release(dam_t *, bitset_t *); 54*4c06356bSdh142964 static void dam_activate_taskq(void *); 55*4c06356bSdh142964 static void dam_addr_stable_cb(void *); 56*4c06356bSdh142964 static void dam_set_stable_cb(void *); 57*4c06356bSdh142964 static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)()); 58*4c06356bSdh142964 static void dam_add_report(dam_t *, dam_da_t *, id_t, int); 59*4c06356bSdh142964 static void dam_release(dam_t *, id_t); 60*4c06356bSdh142964 static void dam_release_report(dam_t *, id_t); 61*4c06356bSdh142964 static void dam_deactivate_addr(dam_t *, id_t); 62*4c06356bSdh142964 static id_t dam_get_addrid(dam_t *, char *); 63*4c06356bSdh142964 static int dam_kstat_create(dam_t *); 64*4c06356bSdh142964 static void dam_kstat_destroy(dam_t *); 65*4c06356bSdh142964 66*4c06356bSdh142964 #define DAM_INCR_STAT(mapp, stat) \ 67*4c06356bSdh142964 if ((mapp)->dam_kstatsp) { \ 68*4c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 69*4c06356bSdh142964 stp->stat.value.ui32++; \ 70*4c06356bSdh142964 } 71*4c06356bSdh142964 72*4c06356bSdh142964 #define DAM_SET_STAT(mapp, stat, val) \ 73*4c06356bSdh142964 if ((mapp)->dam_kstatsp) { \ 74*4c06356bSdh142964 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 75*4c06356bSdh142964 stp->stat.value.ui32 = (val); \ 76*4c06356bSdh142964 } 77*4c06356bSdh142964 78*4c06356bSdh142964 /* 79*4c06356bSdh142964 * Create new device address map 80*4c06356bSdh142964 * 81*4c06356bSdh142964 * ident: map name (kstat) 82*4c06356bSdh142964 * size: max # of map entries 83*4c06356bSdh142964 * rptmode: type or mode of reporting 84*4c06356bSdh142964 * stable_usec: # of quiescent microseconds before report/map is stable 85*4c06356bSdh142964 * 86*4c06356bSdh142964 * activate_arg: address provider activation-callout private 87*4c06356bSdh142964 * activate_cb: address provider activation callback handler 88*4c06356bSdh142964 * deactivate_cb: address provider deactivation callback handler 89*4c06356bSdh142964 * 90*4c06356bSdh142964 * config_arg: configuration-callout private 91*4c06356bSdh142964 * config_cb: class configuration callout 92*4c06356bSdh142964 * unconfig_cb: class unconfiguration callout 93*4c06356bSdh142964 * 94*4c06356bSdh142964 * damapp: pointer to map handle (return) 95*4c06356bSdh142964 * 96*4c06356bSdh142964 * Returns: DAM_SUCCESS 97*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 98*4c06356bSdh142964 * DAM_FAILURE General failure 99*4c06356bSdh142964 */ 100*4c06356bSdh142964 int 101*4c06356bSdh142964 damap_create(char *ident, size_t size, damap_rptmode_t rptmode, 102*4c06356bSdh142964 clock_t stable_usec, 103*4c06356bSdh142964 void *activate_arg, damap_activate_cb_t activate_cb, 104*4c06356bSdh142964 damap_deactivate_cb_t deactivate_cb, 105*4c06356bSdh142964 void *config_arg, damap_configure_cb_t configure_cb, 106*4c06356bSdh142964 damap_unconfig_cb_t unconfig_cb, 107*4c06356bSdh142964 damap_t **damapp) 108*4c06356bSdh142964 { 109*4c06356bSdh142964 dam_t *mapp; 110*4c06356bSdh142964 void *softstate_p; 111*4c06356bSdh142964 112*4c06356bSdh142964 DTRACE_PROBE1(damap__create__entry, char *, ident); 113*4c06356bSdh142964 if ((configure_cb == NULL) || (unconfig_cb == NULL)) 114*4c06356bSdh142964 return (DAM_EINVAL); 115*4c06356bSdh142964 116*4c06356bSdh142964 if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) != 117*4c06356bSdh142964 DDI_SUCCESS) 118*4c06356bSdh142964 return (DAM_FAILURE); 119*4c06356bSdh142964 120*4c06356bSdh142964 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); 121*4c06356bSdh142964 if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) { 122*4c06356bSdh142964 ddi_soft_state_fini(&softstate_p); 123*4c06356bSdh142964 kmem_free(mapp, sizeof (*mapp)); 124*4c06356bSdh142964 return (DAM_FAILURE); 125*4c06356bSdh142964 } 126*4c06356bSdh142964 127*4c06356bSdh142964 mapp->dam_da = softstate_p; 128*4c06356bSdh142964 mapp->dam_stabletmo = drv_usectohz(stable_usec); 129*4c06356bSdh142964 mapp->dam_size = size; 130*4c06356bSdh142964 mapp->dam_high = 1; 131*4c06356bSdh142964 mapp->dam_rptmode = rptmode; 132*4c06356bSdh142964 133*4c06356bSdh142964 mapp->dam_activate_arg = activate_arg; 134*4c06356bSdh142964 mapp->dam_activate_cb = (activate_cb_t)activate_cb; 135*4c06356bSdh142964 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; 136*4c06356bSdh142964 137*4c06356bSdh142964 mapp->dam_config_arg = config_arg; 138*4c06356bSdh142964 mapp->dam_configure_cb = (configure_cb_t)configure_cb; 139*4c06356bSdh142964 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; 140*4c06356bSdh142964 141*4c06356bSdh142964 if (ident) 142*4c06356bSdh142964 mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP); 143*4c06356bSdh142964 144*4c06356bSdh142964 bitset_init(&mapp->dam_active_set); 145*4c06356bSdh142964 bitset_resize(&mapp->dam_active_set, size); 146*4c06356bSdh142964 bitset_init(&mapp->dam_stable_set); 147*4c06356bSdh142964 bitset_resize(&mapp->dam_stable_set, size); 148*4c06356bSdh142964 bitset_init(&mapp->dam_report_set); 149*4c06356bSdh142964 bitset_resize(&mapp->dam_report_set, size); 150*4c06356bSdh142964 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); 151*4c06356bSdh142964 cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL); 152*4c06356bSdh142964 mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI, 153*4c06356bSdh142964 0); 154*4c06356bSdh142964 *damapp = (damap_t *)mapp; 155*4c06356bSdh142964 if (dam_kstat_create(mapp) != DDI_SUCCESS) { 156*4c06356bSdh142964 damap_destroy((damap_t *)mapp); 157*4c06356bSdh142964 return (DAM_FAILURE); 158*4c06356bSdh142964 } 159*4c06356bSdh142964 160*4c06356bSdh142964 DTRACE_PROBE1(damap__create__exit, dam_t *, mapp); 161*4c06356bSdh142964 return (DAM_SUCCESS); 162*4c06356bSdh142964 } 163*4c06356bSdh142964 164*4c06356bSdh142964 /* 165*4c06356bSdh142964 * Destroy device address map 166*4c06356bSdh142964 * 167*4c06356bSdh142964 * damapp: address map 168*4c06356bSdh142964 * 169*4c06356bSdh142964 * Returns: DAM_SUCCESS 170*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 171*4c06356bSdh142964 * DAM_FAILURE General failure 172*4c06356bSdh142964 */ 173*4c06356bSdh142964 void 174*4c06356bSdh142964 damap_destroy(damap_t *damapp) 175*4c06356bSdh142964 { 176*4c06356bSdh142964 int i; 177*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 178*4c06356bSdh142964 179*4c06356bSdh142964 ASSERT(mapp); 180*4c06356bSdh142964 181*4c06356bSdh142964 DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *, 182*4c06356bSdh142964 mapp->dam_name); 183*4c06356bSdh142964 184*4c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_DESTROYPEND); 185*4c06356bSdh142964 (void) damap_sync(damapp); 186*4c06356bSdh142964 187*4c06356bSdh142964 /* 188*4c06356bSdh142964 * cancel pending timeouts and kill off the taskq 189*4c06356bSdh142964 */ 190*4c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 191*4c06356bSdh142964 ddi_taskq_wait(mapp->dam_taskqp); 192*4c06356bSdh142964 ddi_taskq_destroy(mapp->dam_taskqp); 193*4c06356bSdh142964 194*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 195*4c06356bSdh142964 if (ddi_get_soft_state(mapp->dam_da, i) == NULL) 196*4c06356bSdh142964 continue; 197*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 198*4c06356bSdh142964 dam_release_report(mapp, i); 199*4c06356bSdh142964 if (DAM_IS_STABLE(mapp, i)) 200*4c06356bSdh142964 dam_deactivate_addr(mapp, i); 201*4c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, i); 202*4c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, i); 203*4c06356bSdh142964 } 204*4c06356bSdh142964 ddi_strid_fini(&mapp->dam_addr_hash); 205*4c06356bSdh142964 ddi_soft_state_fini(&mapp->dam_da); 206*4c06356bSdh142964 bitset_fini(&mapp->dam_active_set); 207*4c06356bSdh142964 bitset_fini(&mapp->dam_stable_set); 208*4c06356bSdh142964 bitset_fini(&mapp->dam_report_set); 209*4c06356bSdh142964 dam_kstat_destroy(mapp); 210*4c06356bSdh142964 mutex_destroy(&mapp->dam_lock); 211*4c06356bSdh142964 cv_destroy(&mapp->dam_cv); 212*4c06356bSdh142964 if (mapp->dam_name) 213*4c06356bSdh142964 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); 214*4c06356bSdh142964 kmem_free(mapp, sizeof (*mapp)); 215*4c06356bSdh142964 DTRACE_PROBE(damap__destroy__exit); 216*4c06356bSdh142964 } 217*4c06356bSdh142964 218*4c06356bSdh142964 /* 219*4c06356bSdh142964 * Wait for map stability. 220*4c06356bSdh142964 * 221*4c06356bSdh142964 * damapp: address map 222*4c06356bSdh142964 */ 223*4c06356bSdh142964 int 224*4c06356bSdh142964 damap_sync(damap_t *damapp) 225*4c06356bSdh142964 { 226*4c06356bSdh142964 227*4c06356bSdh142964 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK) 228*4c06356bSdh142964 229*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 230*4c06356bSdh142964 int none_active; 231*4c06356bSdh142964 232*4c06356bSdh142964 ASSERT(mapp); 233*4c06356bSdh142964 234*4c06356bSdh142964 DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp); 235*4c06356bSdh142964 236*4c06356bSdh142964 mutex_enter(&mapp->dam_lock); 237*4c06356bSdh142964 while ((mapp->dam_flags & WAITFOR_FLAGS) || 238*4c06356bSdh142964 (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) { 239*4c06356bSdh142964 cv_wait(&mapp->dam_cv, &mapp->dam_lock); 240*4c06356bSdh142964 } 241*4c06356bSdh142964 242*4c06356bSdh142964 none_active = bitset_is_null(&mapp->dam_active_set); 243*4c06356bSdh142964 244*4c06356bSdh142964 mutex_exit(&mapp->dam_lock); 245*4c06356bSdh142964 DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active); 246*4c06356bSdh142964 247*4c06356bSdh142964 return (none_active); 248*4c06356bSdh142964 } 249*4c06356bSdh142964 250*4c06356bSdh142964 /* 251*4c06356bSdh142964 * Get the name of a device address map 252*4c06356bSdh142964 * 253*4c06356bSdh142964 * damapp: address map 254*4c06356bSdh142964 * 255*4c06356bSdh142964 * Returns: name 256*4c06356bSdh142964 */ 257*4c06356bSdh142964 char * 258*4c06356bSdh142964 damap_name(damap_t *damapp) 259*4c06356bSdh142964 { 260*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 261*4c06356bSdh142964 262*4c06356bSdh142964 return (mapp ? mapp->dam_name : "UNKNOWN_damap"); 263*4c06356bSdh142964 } 264*4c06356bSdh142964 265*4c06356bSdh142964 /* 266*4c06356bSdh142964 * Report an address to per-address report 267*4c06356bSdh142964 * 268*4c06356bSdh142964 * damapp: address map handle 269*4c06356bSdh142964 * address: address in ascii string representation 270*4c06356bSdh142964 * rindx: index if address stabilizes 271*4c06356bSdh142964 * nvl: optional nvlist of configuration-private data 272*4c06356bSdh142964 * addr_priv: optional provider-private (passed to activate/deactivate cb) 273*4c06356bSdh142964 * 274*4c06356bSdh142964 * Returns: DAM_SUCCESS 275*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 276*4c06356bSdh142964 * DAM_MAPFULL address map exhausted 277*4c06356bSdh142964 */ 278*4c06356bSdh142964 int 279*4c06356bSdh142964 damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl, 280*4c06356bSdh142964 void *addr_priv) 281*4c06356bSdh142964 { 282*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 283*4c06356bSdh142964 id_t addrid; 284*4c06356bSdh142964 dam_da_t *passp; 285*4c06356bSdh142964 286*4c06356bSdh142964 DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp, 287*4c06356bSdh142964 char *, address); 288*4c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 289*4c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 290*4c06356bSdh142964 return (DAM_EINVAL); 291*4c06356bSdh142964 292*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 293*4c06356bSdh142964 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 294*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 295*4c06356bSdh142964 return (DAM_MAPFULL); 296*4c06356bSdh142964 } 297*4c06356bSdh142964 298*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 299*4c06356bSdh142964 ASSERT(passp != NULL); 300*4c06356bSdh142964 301*4c06356bSdh142964 /* 302*4c06356bSdh142964 * If re-reporting the same address (add or remove) clear 303*4c06356bSdh142964 * the existing report 304*4c06356bSdh142964 */ 305*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 306*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 307*4c06356bSdh142964 dam_release_report(mapp, addrid); 308*4c06356bSdh142964 passp->da_jitter++; 309*4c06356bSdh142964 } 310*4c06356bSdh142964 passp->da_ppriv_rpt = addr_priv; 311*4c06356bSdh142964 if (nvl) 312*4c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 313*4c06356bSdh142964 314*4c06356bSdh142964 dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD); 315*4c06356bSdh142964 if (ridx != NULL) 316*4c06356bSdh142964 *ridx = (damap_id_t)addrid; 317*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 318*4c06356bSdh142964 DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *, 319*4c06356bSdh142964 address, int, addrid); 320*4c06356bSdh142964 return (DAM_SUCCESS); 321*4c06356bSdh142964 } 322*4c06356bSdh142964 323*4c06356bSdh142964 /* 324*4c06356bSdh142964 * Report removal of address from per-address report 325*4c06356bSdh142964 * 326*4c06356bSdh142964 * damapp: address map 327*4c06356bSdh142964 * address: address in ascii string representation 328*4c06356bSdh142964 * 329*4c06356bSdh142964 * Returns: DAM_SUCCESS 330*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 331*4c06356bSdh142964 * DAM_FAILURE General failure 332*4c06356bSdh142964 */ 333*4c06356bSdh142964 int 334*4c06356bSdh142964 damap_addr_del(damap_t *damapp, char *address) 335*4c06356bSdh142964 { 336*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 337*4c06356bSdh142964 id_t addrid; 338*4c06356bSdh142964 dam_da_t *passp; 339*4c06356bSdh142964 340*4c06356bSdh142964 DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp, 341*4c06356bSdh142964 char *, address); 342*4c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 343*4c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 344*4c06356bSdh142964 return (DAM_EINVAL); 345*4c06356bSdh142964 346*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 347*4c06356bSdh142964 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { 348*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 349*4c06356bSdh142964 return (DAM_SUCCESS); 350*4c06356bSdh142964 } 351*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 352*4c06356bSdh142964 ASSERT(passp); 353*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 354*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 355*4c06356bSdh142964 dam_release_report(mapp, addrid); 356*4c06356bSdh142964 passp->da_jitter++; 357*4c06356bSdh142964 } 358*4c06356bSdh142964 dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL); 359*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 360*4c06356bSdh142964 DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp, 361*4c06356bSdh142964 char *, address, int, addrid); 362*4c06356bSdh142964 return (DAM_SUCCESS); 363*4c06356bSdh142964 } 364*4c06356bSdh142964 365*4c06356bSdh142964 /* 366*4c06356bSdh142964 * Initiate full-set report 367*4c06356bSdh142964 * 368*4c06356bSdh142964 * damapp: address map 369*4c06356bSdh142964 * 370*4c06356bSdh142964 * Returns: DAM_SUCCESS 371*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 372*4c06356bSdh142964 */ 373*4c06356bSdh142964 int 374*4c06356bSdh142964 damap_addrset_begin(damap_t *damapp) 375*4c06356bSdh142964 { 376*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 377*4c06356bSdh142964 int i; 378*4c06356bSdh142964 379*4c06356bSdh142964 DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp); 380*4c06356bSdh142964 381*4c06356bSdh142964 if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 382*4c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 383*4c06356bSdh142964 return (DAM_EINVAL); 384*4c06356bSdh142964 385*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 386*4c06356bSdh142964 /* 387*4c06356bSdh142964 * reset any pending reports 388*4c06356bSdh142964 */ 389*4c06356bSdh142964 if (mapp->dam_flags & DAM_SETADD) { 390*4c06356bSdh142964 /* 391*4c06356bSdh142964 * cancel stabilization timeout 392*4c06356bSdh142964 */ 393*4c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 394*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_rereport); 395*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 396*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 397*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 398*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 399*4c06356bSdh142964 dam_release_report(mapp, i); 400*4c06356bSdh142964 } 401*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 402*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 403*4c06356bSdh142964 } 404*4c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SETADD); 405*4c06356bSdh142964 bitset_zero(&mapp->dam_report_set); 406*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 407*4c06356bSdh142964 DTRACE_PROBE(damap__addrset__begin__exit); 408*4c06356bSdh142964 return (DAM_SUCCESS); 409*4c06356bSdh142964 } 410*4c06356bSdh142964 411*4c06356bSdh142964 /* 412*4c06356bSdh142964 * Report address to full-set report 413*4c06356bSdh142964 * 414*4c06356bSdh142964 * damapp: address map handle 415*4c06356bSdh142964 * address: address in ascii string representation 416*4c06356bSdh142964 * rindx: index if address stabilizes 417*4c06356bSdh142964 * nvl: optional nvlist of configuration-private data 418*4c06356bSdh142964 * addr_priv: optional provider-private data (passed to activate/release cb) 419*4c06356bSdh142964 * 420*4c06356bSdh142964 * Returns: DAM_SUCCESS 421*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 422*4c06356bSdh142964 * DAM_MAPFULL address map exhausted 423*4c06356bSdh142964 * DAM_FAILURE General failure 424*4c06356bSdh142964 */ 425*4c06356bSdh142964 int 426*4c06356bSdh142964 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx, 427*4c06356bSdh142964 nvlist_t *nvl, void *addr_priv) 428*4c06356bSdh142964 { 429*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 430*4c06356bSdh142964 id_t addrid; 431*4c06356bSdh142964 dam_da_t *passp; 432*4c06356bSdh142964 433*4c06356bSdh142964 DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp, 434*4c06356bSdh142964 char *, address); 435*4c06356bSdh142964 436*4c06356bSdh142964 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 437*4c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 438*4c06356bSdh142964 return (DAM_EINVAL); 439*4c06356bSdh142964 440*4c06356bSdh142964 if (!(mapp->dam_flags & DAM_SETADD)) 441*4c06356bSdh142964 return (DAM_FAILURE); 442*4c06356bSdh142964 443*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 444*4c06356bSdh142964 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 445*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 446*4c06356bSdh142964 return (DAM_MAPFULL); 447*4c06356bSdh142964 } 448*4c06356bSdh142964 449*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 450*4c06356bSdh142964 ASSERT(passp); 451*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) { 452*4c06356bSdh142964 dam_release_report(mapp, addrid); 453*4c06356bSdh142964 passp->da_jitter++; 454*4c06356bSdh142964 } 455*4c06356bSdh142964 passp->da_ppriv_rpt = addr_priv; 456*4c06356bSdh142964 if (nvl) 457*4c06356bSdh142964 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 458*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 459*4c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid); 460*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 461*4c06356bSdh142964 if (ridx) 462*4c06356bSdh142964 *ridx = (damap_id_t)addrid; 463*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 464*4c06356bSdh142964 DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *, 465*4c06356bSdh142964 address, int, addrid); 466*4c06356bSdh142964 return (DAM_SUCCESS); 467*4c06356bSdh142964 } 468*4c06356bSdh142964 469*4c06356bSdh142964 /* 470*4c06356bSdh142964 * Commit full-set report for stabilization 471*4c06356bSdh142964 * 472*4c06356bSdh142964 * damapp: address map handle 473*4c06356bSdh142964 * flags: (currently 0) 474*4c06356bSdh142964 * 475*4c06356bSdh142964 * Returns: DAM_SUCCESS 476*4c06356bSdh142964 * DAM_EINVAL Invalid argument(s) 477*4c06356bSdh142964 * DAM_FAILURE General failure 478*4c06356bSdh142964 */ 479*4c06356bSdh142964 int 480*4c06356bSdh142964 damap_addrset_end(damap_t *damapp, int flags) 481*4c06356bSdh142964 { 482*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 483*4c06356bSdh142964 int i; 484*4c06356bSdh142964 485*4c06356bSdh142964 DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp); 486*4c06356bSdh142964 487*4c06356bSdh142964 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 488*4c06356bSdh142964 (mapp->dam_flags & DAM_DESTROYPEND)) 489*4c06356bSdh142964 return (DAM_EINVAL); 490*4c06356bSdh142964 491*4c06356bSdh142964 if (!(mapp->dam_flags & DAM_SETADD)) 492*4c06356bSdh142964 return (DAM_FAILURE); 493*4c06356bSdh142964 494*4c06356bSdh142964 if (flags & DAMAP_RESET) { 495*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 496*4c06356bSdh142964 dam_sched_tmo(mapp, 0, NULL); 497*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 498*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 499*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) 500*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, i)) 501*4c06356bSdh142964 dam_release_report(mapp, i); 502*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 503*4c06356bSdh142964 } else { 504*4c06356bSdh142964 mapp->dam_last_update = gethrtime(); 505*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 506*4c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 507*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 508*4c06356bSdh142964 } 509*4c06356bSdh142964 DTRACE_PROBE(damap__addrset__end__exit); 510*4c06356bSdh142964 return (DAM_SUCCESS); 511*4c06356bSdh142964 } 512*4c06356bSdh142964 513*4c06356bSdh142964 /* 514*4c06356bSdh142964 * Return nvlist registered with reported address 515*4c06356bSdh142964 * 516*4c06356bSdh142964 * damapp: address map handle 517*4c06356bSdh142964 * aid: address ID 518*4c06356bSdh142964 * 519*4c06356bSdh142964 * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) 520*4c06356bSdh142964 * NULL 521*4c06356bSdh142964 */ 522*4c06356bSdh142964 nvlist_t * 523*4c06356bSdh142964 damap_id2nvlist(damap_t *damapp, damap_id_t addrid) 524*4c06356bSdh142964 { 525*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 526*4c06356bSdh142964 id_t aid = (id_t)addrid; 527*4c06356bSdh142964 dam_da_t *pass; 528*4c06356bSdh142964 529*4c06356bSdh142964 if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) { 530*4c06356bSdh142964 if (pass = ddi_get_soft_state(mapp->dam_da, aid)) 531*4c06356bSdh142964 return (pass->da_nvl); 532*4c06356bSdh142964 } 533*4c06356bSdh142964 return (NULL); 534*4c06356bSdh142964 } 535*4c06356bSdh142964 536*4c06356bSdh142964 /* 537*4c06356bSdh142964 * Return address string 538*4c06356bSdh142964 * 539*4c06356bSdh142964 * damapp: address map handle 540*4c06356bSdh142964 * aid: address ID 541*4c06356bSdh142964 * 542*4c06356bSdh142964 * Returns: char * Address string 543*4c06356bSdh142964 * NULL 544*4c06356bSdh142964 */ 545*4c06356bSdh142964 char * 546*4c06356bSdh142964 damap_id2addr(damap_t *damapp, damap_id_t aid) 547*4c06356bSdh142964 { 548*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 549*4c06356bSdh142964 550*4c06356bSdh142964 return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid)); 551*4c06356bSdh142964 } 552*4c06356bSdh142964 553*4c06356bSdh142964 /* 554*4c06356bSdh142964 * Hold address reference in map 555*4c06356bSdh142964 * 556*4c06356bSdh142964 * damapp: address map handle 557*4c06356bSdh142964 * aid: address ID 558*4c06356bSdh142964 * 559*4c06356bSdh142964 * Returns: DAM_SUCCESS 560*4c06356bSdh142964 * DAM_FAILURE 561*4c06356bSdh142964 */ 562*4c06356bSdh142964 int 563*4c06356bSdh142964 damap_id_hold(damap_t *damapp, damap_id_t aid) 564*4c06356bSdh142964 { 565*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 566*4c06356bSdh142964 dam_da_t *passp; 567*4c06356bSdh142964 568*4c06356bSdh142964 569*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 570*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 571*4c06356bSdh142964 if (!passp) { 572*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 573*4c06356bSdh142964 return (DAM_FAILURE); 574*4c06356bSdh142964 } 575*4c06356bSdh142964 passp->da_ref++; 576*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 577*4c06356bSdh142964 return (DAM_SUCCESS); 578*4c06356bSdh142964 } 579*4c06356bSdh142964 580*4c06356bSdh142964 /* 581*4c06356bSdh142964 * Release address reference in map 582*4c06356bSdh142964 * 583*4c06356bSdh142964 * damapp: address map handle 584*4c06356bSdh142964 * aid: address ID 585*4c06356bSdh142964 */ 586*4c06356bSdh142964 void 587*4c06356bSdh142964 damap_id_rele(damap_t *damapp, damap_id_t addrid) 588*4c06356bSdh142964 { 589*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 590*4c06356bSdh142964 591*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 592*4c06356bSdh142964 dam_release(mapp, (id_t)addrid); 593*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 594*4c06356bSdh142964 } 595*4c06356bSdh142964 596*4c06356bSdh142964 /* 597*4c06356bSdh142964 * Return current reference count on address reference in map 598*4c06356bSdh142964 * 599*4c06356bSdh142964 * damapp: address map handle 600*4c06356bSdh142964 * aid: address ID 601*4c06356bSdh142964 * 602*4c06356bSdh142964 * Returns: DAM_SUCCESS 603*4c06356bSdh142964 * DAM_FAILURE 604*4c06356bSdh142964 */ 605*4c06356bSdh142964 int 606*4c06356bSdh142964 damap_id_ref(damap_t *damapp, damap_id_t aid) 607*4c06356bSdh142964 { 608*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 609*4c06356bSdh142964 dam_da_t *passp; 610*4c06356bSdh142964 int ref = -1; 611*4c06356bSdh142964 612*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 613*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 614*4c06356bSdh142964 if (passp) 615*4c06356bSdh142964 ref = passp->da_ref; 616*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 617*4c06356bSdh142964 return (ref); 618*4c06356bSdh142964 } 619*4c06356bSdh142964 620*4c06356bSdh142964 /* 621*4c06356bSdh142964 * Return next address ID in list 622*4c06356bSdh142964 * 623*4c06356bSdh142964 * damapp: address map handle 624*4c06356bSdh142964 * damap_list: address ID list passed to config|unconfig 625*4c06356bSdh142964 * returned by look by lookup_all 626*4c06356bSdh142964 * last: last ID returned, 0 is start of list 627*4c06356bSdh142964 * 628*4c06356bSdh142964 * Returns: addrid Next ID from the list 629*4c06356bSdh142964 * 0 End of the list 630*4c06356bSdh142964 */ 631*4c06356bSdh142964 damap_id_t 632*4c06356bSdh142964 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last) 633*4c06356bSdh142964 { 634*4c06356bSdh142964 int i, start; 635*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 636*4c06356bSdh142964 bitset_t *dam_list = (bitset_t *)damap_list; 637*4c06356bSdh142964 638*4c06356bSdh142964 if (!mapp || !dam_list) 639*4c06356bSdh142964 return ((damap_id_t)0); 640*4c06356bSdh142964 641*4c06356bSdh142964 start = (int)last + 1; 642*4c06356bSdh142964 for (i = start; i < mapp->dam_high; i++) 643*4c06356bSdh142964 if (bitset_in_set(dam_list, i)) 644*4c06356bSdh142964 return ((damap_id_t)i); 645*4c06356bSdh142964 return ((damap_id_t)0); 646*4c06356bSdh142964 } 647*4c06356bSdh142964 648*4c06356bSdh142964 /* 649*4c06356bSdh142964 * Set config private data 650*4c06356bSdh142964 * 651*4c06356bSdh142964 * damapp: address map handle 652*4c06356bSdh142964 * aid: address ID 653*4c06356bSdh142964 * cfg_priv: configuration private data 654*4c06356bSdh142964 * 655*4c06356bSdh142964 */ 656*4c06356bSdh142964 void 657*4c06356bSdh142964 damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv) 658*4c06356bSdh142964 { 659*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 660*4c06356bSdh142964 dam_da_t *passp; 661*4c06356bSdh142964 662*4c06356bSdh142964 663*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 664*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 665*4c06356bSdh142964 if (!passp) { 666*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 667*4c06356bSdh142964 return; 668*4c06356bSdh142964 } 669*4c06356bSdh142964 passp->da_cfg_priv = cfg_priv; 670*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 671*4c06356bSdh142964 } 672*4c06356bSdh142964 673*4c06356bSdh142964 /* 674*4c06356bSdh142964 * Get config private data 675*4c06356bSdh142964 * 676*4c06356bSdh142964 * damapp: address map handle 677*4c06356bSdh142964 * aid: address ID 678*4c06356bSdh142964 * 679*4c06356bSdh142964 * Returns: configuration private data 680*4c06356bSdh142964 */ 681*4c06356bSdh142964 void * 682*4c06356bSdh142964 damap_id_priv_get(damap_t *damapp, damap_id_t aid) 683*4c06356bSdh142964 { 684*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 685*4c06356bSdh142964 dam_da_t *passp; 686*4c06356bSdh142964 void *rv; 687*4c06356bSdh142964 688*4c06356bSdh142964 689*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 690*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 691*4c06356bSdh142964 if (!passp) { 692*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 693*4c06356bSdh142964 return (NULL); 694*4c06356bSdh142964 } 695*4c06356bSdh142964 rv = passp->da_cfg_priv; 696*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 697*4c06356bSdh142964 return (rv); 698*4c06356bSdh142964 } 699*4c06356bSdh142964 700*4c06356bSdh142964 /* 701*4c06356bSdh142964 * Lookup a single address in the active address map 702*4c06356bSdh142964 * 703*4c06356bSdh142964 * damapp: address map handle 704*4c06356bSdh142964 * address: address string 705*4c06356bSdh142964 * 706*4c06356bSdh142964 * Returns: ID of active/stable address 707*4c06356bSdh142964 * 0 Address not in stable set 708*4c06356bSdh142964 * 709*4c06356bSdh142964 * Future: Allow the caller to wait for stabilize before returning not found. 710*4c06356bSdh142964 */ 711*4c06356bSdh142964 damap_id_t 712*4c06356bSdh142964 damap_lookup(damap_t *damapp, char *address) 713*4c06356bSdh142964 { 714*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 715*4c06356bSdh142964 id_t addrid = 0; 716*4c06356bSdh142964 dam_da_t *passp = NULL; 717*4c06356bSdh142964 718*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 719*4c06356bSdh142964 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); 720*4c06356bSdh142964 if (addrid) { 721*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 722*4c06356bSdh142964 if (DAM_IS_STABLE(mapp, addrid)) { 723*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 724*4c06356bSdh142964 ASSERT(passp); 725*4c06356bSdh142964 if (passp) { 726*4c06356bSdh142964 passp->da_ref++; 727*4c06356bSdh142964 } else { 728*4c06356bSdh142964 addrid = 0; 729*4c06356bSdh142964 } 730*4c06356bSdh142964 } else { 731*4c06356bSdh142964 addrid = 0; 732*4c06356bSdh142964 } 733*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 734*4c06356bSdh142964 } 735*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 736*4c06356bSdh142964 return ((damap_id_t)addrid); 737*4c06356bSdh142964 } 738*4c06356bSdh142964 739*4c06356bSdh142964 740*4c06356bSdh142964 /* 741*4c06356bSdh142964 * Return the list of stable addresses in the map 742*4c06356bSdh142964 * 743*4c06356bSdh142964 * damapp: address map handle 744*4c06356bSdh142964 * id_listp: pointer to list of address IDs in stable map (returned) 745*4c06356bSdh142964 * 746*4c06356bSdh142964 * Returns: # of entries returned in alist 747*4c06356bSdh142964 */ 748*4c06356bSdh142964 int 749*4c06356bSdh142964 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp) 750*4c06356bSdh142964 { 751*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 752*4c06356bSdh142964 int mapsz = mapp->dam_size; 753*4c06356bSdh142964 int n_ids, i; 754*4c06356bSdh142964 bitset_t *bsp; 755*4c06356bSdh142964 dam_da_t *passp; 756*4c06356bSdh142964 757*4c06356bSdh142964 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); 758*4c06356bSdh142964 bitset_init(bsp); 759*4c06356bSdh142964 bitset_resize(bsp, mapsz); 760*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 761*4c06356bSdh142964 bitset_copy(&mapp->dam_active_set, bsp); 762*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 763*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 764*4c06356bSdh142964 for (n_ids = 0, i = 1; i < mapsz; i++) { 765*4c06356bSdh142964 if (bitset_in_set(bsp, i)) { 766*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 767*4c06356bSdh142964 ASSERT(passp); 768*4c06356bSdh142964 if (passp) { 769*4c06356bSdh142964 passp->da_ref++; 770*4c06356bSdh142964 n_ids++; 771*4c06356bSdh142964 } 772*4c06356bSdh142964 } 773*4c06356bSdh142964 } 774*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 775*4c06356bSdh142964 if (n_ids) { 776*4c06356bSdh142964 *id_listp = (damap_id_list_t)bsp; 777*4c06356bSdh142964 return (n_ids); 778*4c06356bSdh142964 } else { 779*4c06356bSdh142964 *id_listp = (damap_id_list_t)NULL; 780*4c06356bSdh142964 bitset_fini(bsp); 781*4c06356bSdh142964 kmem_free(bsp, sizeof (*bsp)); 782*4c06356bSdh142964 return (0); 783*4c06356bSdh142964 } 784*4c06356bSdh142964 } 785*4c06356bSdh142964 786*4c06356bSdh142964 /* 787*4c06356bSdh142964 * Release the address list returned by damap_lookup_all() 788*4c06356bSdh142964 * 789*4c06356bSdh142964 * mapp: address map handle 790*4c06356bSdh142964 * id_list: list of address IDs returned in damap_lookup_all() 791*4c06356bSdh142964 */ 792*4c06356bSdh142964 void 793*4c06356bSdh142964 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list) 794*4c06356bSdh142964 { 795*4c06356bSdh142964 dam_t *mapp = (dam_t *)damapp; 796*4c06356bSdh142964 int i; 797*4c06356bSdh142964 798*4c06356bSdh142964 if (id_list == NULL) 799*4c06356bSdh142964 return; 800*4c06356bSdh142964 801*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 802*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 803*4c06356bSdh142964 if (bitset_in_set((bitset_t *)id_list, i)) 804*4c06356bSdh142964 (void) dam_release(mapp, i); 805*4c06356bSdh142964 } 806*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 807*4c06356bSdh142964 bitset_fini((bitset_t *)id_list); 808*4c06356bSdh142964 kmem_free((void *)id_list, sizeof (bitset_t)); 809*4c06356bSdh142964 } 810*4c06356bSdh142964 811*4c06356bSdh142964 /* 812*4c06356bSdh142964 * Activate a set of stabilized addresses 813*4c06356bSdh142964 */ 814*4c06356bSdh142964 static void 815*4c06356bSdh142964 dam_addrset_activate(dam_t *mapp, bitset_t *active_set) 816*4c06356bSdh142964 { 817*4c06356bSdh142964 dam_da_t *passp; 818*4c06356bSdh142964 char *addrstr; 819*4c06356bSdh142964 int i; 820*4c06356bSdh142964 uint32_t n_active = 0; 821*4c06356bSdh142964 822*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 823*4c06356bSdh142964 if (bitset_in_set(&mapp->dam_active_set, i)) 824*4c06356bSdh142964 n_active++; 825*4c06356bSdh142964 if (!bitset_in_set(active_set, i)) 826*4c06356bSdh142964 continue; 827*4c06356bSdh142964 n_active++; 828*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 829*4c06356bSdh142964 ASSERT(passp); 830*4c06356bSdh142964 if (mapp->dam_activate_cb) { 831*4c06356bSdh142964 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i); 832*4c06356bSdh142964 (*mapp->dam_activate_cb)( 833*4c06356bSdh142964 mapp->dam_activate_arg, addrstr, i, 834*4c06356bSdh142964 &passp->da_ppriv_rpt); 835*4c06356bSdh142964 } 836*4c06356bSdh142964 DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i); 837*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 838*4c06356bSdh142964 bitset_add(&mapp->dam_active_set, i); 839*4c06356bSdh142964 /* 840*4c06356bSdh142964 * copy the reported nvlist and provider private data 841*4c06356bSdh142964 */ 842*4c06356bSdh142964 passp->da_nvl = passp->da_nvl_rpt; 843*4c06356bSdh142964 passp->da_ppriv = passp->da_ppriv_rpt; 844*4c06356bSdh142964 passp->da_ppriv_rpt = NULL; 845*4c06356bSdh142964 passp->da_nvl_rpt = NULL; 846*4c06356bSdh142964 passp->da_last_stable = gethrtime(); 847*4c06356bSdh142964 passp->da_stable_cnt++; 848*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 849*4c06356bSdh142964 DAM_SET_STAT(mapp, dam_numstable, n_active); 850*4c06356bSdh142964 } 851*4c06356bSdh142964 } 852*4c06356bSdh142964 853*4c06356bSdh142964 /* 854*4c06356bSdh142964 * Release a set of stabilized addresses 855*4c06356bSdh142964 */ 856*4c06356bSdh142964 static void 857*4c06356bSdh142964 dam_addrset_release(dam_t *mapp, bitset_t *release_set) 858*4c06356bSdh142964 { 859*4c06356bSdh142964 int i; 860*4c06356bSdh142964 861*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 862*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 863*4c06356bSdh142964 if (bitset_in_set(release_set, i)) { 864*4c06356bSdh142964 DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp, 865*4c06356bSdh142964 int, i); 866*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 867*4c06356bSdh142964 bitset_del(&mapp->dam_active_set, i); 868*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 869*4c06356bSdh142964 (void) dam_release(mapp, i); 870*4c06356bSdh142964 } 871*4c06356bSdh142964 } 872*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 873*4c06356bSdh142964 } 874*4c06356bSdh142964 875*4c06356bSdh142964 /* 876*4c06356bSdh142964 * release a previously activated address 877*4c06356bSdh142964 */ 878*4c06356bSdh142964 static void 879*4c06356bSdh142964 dam_release(dam_t *mapp, id_t addrid) 880*4c06356bSdh142964 { 881*4c06356bSdh142964 dam_da_t *passp; 882*4c06356bSdh142964 883*4c06356bSdh142964 DAM_ASSERT_LOCKED(mapp, ADDR_LOCK); 884*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 885*4c06356bSdh142964 ASSERT(passp); 886*4c06356bSdh142964 887*4c06356bSdh142964 /* 888*4c06356bSdh142964 * invoke the deactivation callback to notify 889*4c06356bSdh142964 * this address is no longer active 890*4c06356bSdh142964 */ 891*4c06356bSdh142964 dam_deactivate_addr(mapp, addrid); 892*4c06356bSdh142964 893*4c06356bSdh142964 /* 894*4c06356bSdh142964 * allow pending reports for this address to stabilize 895*4c06356bSdh142964 */ 896*4c06356bSdh142964 if (DAM_IN_REPORT(mapp, addrid)) 897*4c06356bSdh142964 return; 898*4c06356bSdh142964 899*4c06356bSdh142964 /* 900*4c06356bSdh142964 * defer teardown until outstanding references are released 901*4c06356bSdh142964 */ 902*4c06356bSdh142964 if (--passp->da_ref) { 903*4c06356bSdh142964 passp->da_flags |= DA_RELE; 904*4c06356bSdh142964 return; 905*4c06356bSdh142964 } 906*4c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid); 907*4c06356bSdh142964 ddi_soft_state_free(mapp->dam_da, addrid); 908*4c06356bSdh142964 } 909*4c06356bSdh142964 910*4c06356bSdh142964 /* 911*4c06356bSdh142964 * process stabilized address reports 912*4c06356bSdh142964 */ 913*4c06356bSdh142964 static void 914*4c06356bSdh142964 dam_activate_taskq(void *arg) 915*4c06356bSdh142964 { 916*4c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 917*4c06356bSdh142964 bitset_t delta; 918*4c06356bSdh142964 bitset_t cfg; 919*4c06356bSdh142964 bitset_t uncfg; 920*4c06356bSdh142964 int has_cfg, has_uncfg; 921*4c06356bSdh142964 922*4c06356bSdh142964 bitset_init(&delta); 923*4c06356bSdh142964 bitset_resize(&delta, mapp->dam_size); 924*4c06356bSdh142964 bitset_init(&cfg); 925*4c06356bSdh142964 bitset_resize(&cfg, mapp->dam_size); 926*4c06356bSdh142964 bitset_init(&uncfg); 927*4c06356bSdh142964 bitset_resize(&uncfg, mapp->dam_size); 928*4c06356bSdh142964 929*4c06356bSdh142964 DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp); 930*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 931*4c06356bSdh142964 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, 932*4c06356bSdh142964 &delta)) { 933*4c06356bSdh142964 bitset_zero(&mapp->dam_stable_set); 934*4c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SPEND); 935*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 936*4c06356bSdh142964 bitset_fini(&uncfg); 937*4c06356bSdh142964 bitset_fini(&cfg); 938*4c06356bSdh142964 bitset_fini(&delta); 939*4c06356bSdh142964 return; 940*4c06356bSdh142964 } 941*4c06356bSdh142964 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); 942*4c06356bSdh142964 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); 943*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 944*4c06356bSdh142964 if (has_cfg) { 945*4c06356bSdh142964 dam_addrset_activate(mapp, &cfg); 946*4c06356bSdh142964 (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg); 947*4c06356bSdh142964 } 948*4c06356bSdh142964 if (has_uncfg) { 949*4c06356bSdh142964 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg); 950*4c06356bSdh142964 dam_addrset_release(mapp, &uncfg); 951*4c06356bSdh142964 } 952*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 953*4c06356bSdh142964 bitset_zero(&mapp->dam_stable_set); 954*4c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SPEND); 955*4c06356bSdh142964 mapp->dam_last_stable = gethrtime(); 956*4c06356bSdh142964 mapp->dam_stable_cnt++; 957*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable); 958*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 959*4c06356bSdh142964 bitset_fini(&uncfg); 960*4c06356bSdh142964 bitset_fini(&cfg); 961*4c06356bSdh142964 bitset_fini(&delta); 962*4c06356bSdh142964 DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp); 963*4c06356bSdh142964 } 964*4c06356bSdh142964 965*4c06356bSdh142964 /* 966*4c06356bSdh142964 * per-address stabilization timeout 967*4c06356bSdh142964 */ 968*4c06356bSdh142964 static void 969*4c06356bSdh142964 dam_addr_stable_cb(void *arg) 970*4c06356bSdh142964 { 971*4c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 972*4c06356bSdh142964 int i; 973*4c06356bSdh142964 dam_da_t *passp; 974*4c06356bSdh142964 int spend = 0; 975*4c06356bSdh142964 int tpend = 0; 976*4c06356bSdh142964 int64_t next_tmov = mapp->dam_stabletmo; 977*4c06356bSdh142964 int64_t tmo_delta; 978*4c06356bSdh142964 int64_t ts = lbolt64; 979*4c06356bSdh142964 980*4c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp); 981*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 982*4c06356bSdh142964 if (mapp->dam_tid == 0) { 983*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 984*4c06356bSdh142964 return; 985*4c06356bSdh142964 } 986*4c06356bSdh142964 mapp->dam_tid = 0; 987*4c06356bSdh142964 /* 988*4c06356bSdh142964 * If still under stabilization, reschedule timeout, 989*4c06356bSdh142964 * else dispatch the task to activate & deactivate the stable 990*4c06356bSdh142964 * set. 991*4c06356bSdh142964 */ 992*4c06356bSdh142964 if (mapp->dam_flags & DAM_SPEND) { 993*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable_blocked); 994*4c06356bSdh142964 mapp->dam_stable_overrun++; 995*4c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 996*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 997*4c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__overrun, 998*4c06356bSdh142964 dam_t *, mapp); 999*4c06356bSdh142964 return; 1000*4c06356bSdh142964 } 1001*4c06356bSdh142964 1002*4c06356bSdh142964 bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); 1003*4c06356bSdh142964 for (i = 1; i < mapp->dam_high; i++) { 1004*4c06356bSdh142964 if (!bitset_in_set(&mapp->dam_report_set, i)) 1005*4c06356bSdh142964 continue; 1006*4c06356bSdh142964 /* 1007*4c06356bSdh142964 * Stabilize each address 1008*4c06356bSdh142964 */ 1009*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, i); 1010*4c06356bSdh142964 ASSERT(passp); 1011*4c06356bSdh142964 if (!passp) { 1012*4c06356bSdh142964 cmn_err(CE_WARN, "Clearing report no softstate %d", i); 1013*4c06356bSdh142964 bitset_del(&mapp->dam_report_set, i); 1014*4c06356bSdh142964 continue; 1015*4c06356bSdh142964 } 1016*4c06356bSdh142964 1017*4c06356bSdh142964 /* report has stabilized */ 1018*4c06356bSdh142964 if (passp->da_deadline <= ts) { 1019*4c06356bSdh142964 bitset_del(&mapp->dam_report_set, i); 1020*4c06356bSdh142964 if (passp->da_flags & DA_RELE) { 1021*4c06356bSdh142964 DTRACE_PROBE2(damap__addr__stable__del, 1022*4c06356bSdh142964 dam_t *, mapp, int, i); 1023*4c06356bSdh142964 bitset_del(&mapp->dam_stable_set, i); 1024*4c06356bSdh142964 } else { 1025*4c06356bSdh142964 DTRACE_PROBE2(damap__addr__stable__add, 1026*4c06356bSdh142964 dam_t *, mapp, int, i); 1027*4c06356bSdh142964 bitset_add(&mapp->dam_stable_set, i); 1028*4c06356bSdh142964 } 1029*4c06356bSdh142964 spend++; 1030*4c06356bSdh142964 continue; 1031*4c06356bSdh142964 } 1032*4c06356bSdh142964 1033*4c06356bSdh142964 /* 1034*4c06356bSdh142964 * not stabilized, determine next (future) map timeout 1035*4c06356bSdh142964 */ 1036*4c06356bSdh142964 tpend++; 1037*4c06356bSdh142964 tmo_delta = passp->da_deadline - ts; 1038*4c06356bSdh142964 if (tmo_delta < next_tmov) 1039*4c06356bSdh142964 next_tmov = tmo_delta; 1040*4c06356bSdh142964 } 1041*4c06356bSdh142964 1042*4c06356bSdh142964 /* 1043*4c06356bSdh142964 * schedule taskq activation of stabilized reports 1044*4c06356bSdh142964 */ 1045*4c06356bSdh142964 if (spend) { 1046*4c06356bSdh142964 if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 1047*4c06356bSdh142964 mapp, DDI_NOSLEEP) == DDI_SUCCESS) { 1048*4c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SPEND); 1049*4c06356bSdh142964 } else 1050*4c06356bSdh142964 tpend++; 1051*4c06356bSdh142964 } 1052*4c06356bSdh142964 1053*4c06356bSdh142964 /* 1054*4c06356bSdh142964 * schedule timeout to handle future stabalization of active reports 1055*4c06356bSdh142964 */ 1056*4c06356bSdh142964 if (tpend) 1057*4c06356bSdh142964 dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb); 1058*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1059*4c06356bSdh142964 DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp); 1060*4c06356bSdh142964 } 1061*4c06356bSdh142964 1062*4c06356bSdh142964 /* 1063*4c06356bSdh142964 * fullset stabilization timeout 1064*4c06356bSdh142964 */ 1065*4c06356bSdh142964 static void 1066*4c06356bSdh142964 dam_set_stable_cb(void *arg) 1067*4c06356bSdh142964 { 1068*4c06356bSdh142964 dam_t *mapp = (dam_t *)arg; 1069*4c06356bSdh142964 1070*4c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp); 1071*4c06356bSdh142964 1072*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 1073*4c06356bSdh142964 if (mapp->dam_tid == 0) { 1074*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1075*4c06356bSdh142964 return; 1076*4c06356bSdh142964 } 1077*4c06356bSdh142964 mapp->dam_tid = 0; 1078*4c06356bSdh142964 1079*4c06356bSdh142964 /* 1080*4c06356bSdh142964 * If still under stabilization, reschedule timeout, 1081*4c06356bSdh142964 * else dispatch the task to activate & deactivate the stable 1082*4c06356bSdh142964 * set. 1083*4c06356bSdh142964 */ 1084*4c06356bSdh142964 if (mapp->dam_flags & DAM_SPEND) { 1085*4c06356bSdh142964 DAM_INCR_STAT(mapp, dam_stable_blocked); 1086*4c06356bSdh142964 mapp->dam_stable_overrun++; 1087*4c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 1088*4c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__overrun, 1089*4c06356bSdh142964 dam_t *, mapp); 1090*4c06356bSdh142964 } else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 1091*4c06356bSdh142964 mapp, DDI_NOSLEEP) == DDI_FAILURE) { 1092*4c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 1093*4c06356bSdh142964 } else { 1094*4c06356bSdh142964 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); 1095*4c06356bSdh142964 bitset_zero(&mapp->dam_report_set); 1096*4c06356bSdh142964 DAM_FLAG_CLR(mapp, DAM_SETADD); 1097*4c06356bSdh142964 DAM_FLAG_SET(mapp, DAM_SPEND); 1098*4c06356bSdh142964 } 1099*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1100*4c06356bSdh142964 DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp); 1101*4c06356bSdh142964 } 1102*4c06356bSdh142964 1103*4c06356bSdh142964 /* 1104*4c06356bSdh142964 * reschedule map timeout 'tmo_ms' ticks 1105*4c06356bSdh142964 */ 1106*4c06356bSdh142964 static void 1107*4c06356bSdh142964 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)()) 1108*4c06356bSdh142964 { 1109*4c06356bSdh142964 timeout_id_t tid; 1110*4c06356bSdh142964 1111*4c06356bSdh142964 if ((tid = mapp->dam_tid) != 0) { 1112*4c06356bSdh142964 mapp->dam_tid = 0; 1113*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1114*4c06356bSdh142964 (void) untimeout(tid); 1115*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 1116*4c06356bSdh142964 } 1117*4c06356bSdh142964 1118*4c06356bSdh142964 if (tmo_cb && (tmo_ms != 0)) 1119*4c06356bSdh142964 mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); 1120*4c06356bSdh142964 } 1121*4c06356bSdh142964 1122*4c06356bSdh142964 /* 1123*4c06356bSdh142964 * record report addition or removal of an address 1124*4c06356bSdh142964 */ 1125*4c06356bSdh142964 static void 1126*4c06356bSdh142964 dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report) 1127*4c06356bSdh142964 { 1128*4c06356bSdh142964 ASSERT(!DAM_IN_REPORT(mapp, addrid)); 1129*4c06356bSdh142964 passp->da_last_report = gethrtime(); 1130*4c06356bSdh142964 mapp->dam_last_update = gethrtime(); 1131*4c06356bSdh142964 passp->da_report_cnt++; 1132*4c06356bSdh142964 passp->da_deadline = lbolt64 + mapp->dam_stabletmo; 1133*4c06356bSdh142964 if (report == RPT_ADDR_DEL) 1134*4c06356bSdh142964 passp->da_flags |= DA_RELE; 1135*4c06356bSdh142964 else if (report == RPT_ADDR_ADD) 1136*4c06356bSdh142964 passp->da_flags &= ~DA_RELE; 1137*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 1138*4c06356bSdh142964 bitset_add(&mapp->dam_report_set, addrid); 1139*4c06356bSdh142964 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 1140*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1141*4c06356bSdh142964 1142*4c06356bSdh142964 } 1143*4c06356bSdh142964 1144*4c06356bSdh142964 /* 1145*4c06356bSdh142964 * release an address report 1146*4c06356bSdh142964 */ 1147*4c06356bSdh142964 static void 1148*4c06356bSdh142964 dam_release_report(dam_t *mapp, id_t addrid) 1149*4c06356bSdh142964 { 1150*4c06356bSdh142964 dam_da_t *passp; 1151*4c06356bSdh142964 1152*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1153*4c06356bSdh142964 ASSERT(passp); 1154*4c06356bSdh142964 passp->da_ppriv_rpt = NULL; 1155*4c06356bSdh142964 if (passp->da_nvl_rpt) 1156*4c06356bSdh142964 nvlist_free(passp->da_nvl_rpt); 1157*4c06356bSdh142964 passp->da_nvl_rpt = NULL; 1158*4c06356bSdh142964 DAM_LOCK(mapp, MAP_LOCK); 1159*4c06356bSdh142964 bitset_del(&mapp->dam_report_set, addrid); 1160*4c06356bSdh142964 DAM_UNLOCK(mapp, MAP_LOCK); 1161*4c06356bSdh142964 } 1162*4c06356bSdh142964 1163*4c06356bSdh142964 /* 1164*4c06356bSdh142964 * deactivate a previously stable address 1165*4c06356bSdh142964 */ 1166*4c06356bSdh142964 static void 1167*4c06356bSdh142964 dam_deactivate_addr(dam_t *mapp, id_t addrid) 1168*4c06356bSdh142964 { 1169*4c06356bSdh142964 dam_da_t *passp; 1170*4c06356bSdh142964 1171*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1172*4c06356bSdh142964 ASSERT(passp); 1173*4c06356bSdh142964 if (passp == NULL) 1174*4c06356bSdh142964 return; 1175*4c06356bSdh142964 DAM_UNLOCK(mapp, ADDR_LOCK); 1176*4c06356bSdh142964 if (mapp->dam_deactivate_cb) 1177*4c06356bSdh142964 (*mapp->dam_deactivate_cb)( 1178*4c06356bSdh142964 mapp->dam_activate_arg, 1179*4c06356bSdh142964 ddi_strid_id2str(mapp->dam_addr_hash, 1180*4c06356bSdh142964 addrid), addrid, passp->da_ppriv); 1181*4c06356bSdh142964 DAM_LOCK(mapp, ADDR_LOCK); 1182*4c06356bSdh142964 passp->da_ppriv = NULL; 1183*4c06356bSdh142964 if (passp->da_nvl) 1184*4c06356bSdh142964 nvlist_free(passp->da_nvl); 1185*4c06356bSdh142964 passp->da_nvl = NULL; 1186*4c06356bSdh142964 } 1187*4c06356bSdh142964 1188*4c06356bSdh142964 /* 1189*4c06356bSdh142964 * return the map ID of an address 1190*4c06356bSdh142964 */ 1191*4c06356bSdh142964 static id_t 1192*4c06356bSdh142964 dam_get_addrid(dam_t *mapp, char *address) 1193*4c06356bSdh142964 { 1194*4c06356bSdh142964 damap_id_t addrid; 1195*4c06356bSdh142964 dam_da_t *passp; 1196*4c06356bSdh142964 1197*4c06356bSdh142964 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { 1198*4c06356bSdh142964 if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash, 1199*4c06356bSdh142964 address)) == (damap_id_t)0) { 1200*4c06356bSdh142964 return (0); 1201*4c06356bSdh142964 } 1202*4c06356bSdh142964 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) != 1203*4c06356bSdh142964 DDI_SUCCESS) { 1204*4c06356bSdh142964 ddi_strid_free(mapp->dam_addr_hash, addrid); 1205*4c06356bSdh142964 return (0); 1206*4c06356bSdh142964 } 1207*4c06356bSdh142964 if (addrid >= mapp->dam_high) 1208*4c06356bSdh142964 mapp->dam_high = addrid + 1; 1209*4c06356bSdh142964 } 1210*4c06356bSdh142964 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1211*4c06356bSdh142964 if (passp == NULL) 1212*4c06356bSdh142964 return (0); 1213*4c06356bSdh142964 passp->da_ref++; 1214*4c06356bSdh142964 if (passp->da_addr == NULL) 1215*4c06356bSdh142964 passp->da_addr = ddi_strid_id2str( 1216*4c06356bSdh142964 mapp->dam_addr_hash, addrid); /* for mdb */ 1217*4c06356bSdh142964 return (addrid); 1218*4c06356bSdh142964 } 1219*4c06356bSdh142964 1220*4c06356bSdh142964 /* 1221*4c06356bSdh142964 * create and install map statistics 1222*4c06356bSdh142964 */ 1223*4c06356bSdh142964 static int 1224*4c06356bSdh142964 dam_kstat_create(dam_t *mapp) 1225*4c06356bSdh142964 { 1226*4c06356bSdh142964 kstat_t *mapsp; 1227*4c06356bSdh142964 struct dam_kstats *statsp; 1228*4c06356bSdh142964 1229*4c06356bSdh142964 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", 1230*4c06356bSdh142964 KSTAT_TYPE_NAMED, 1231*4c06356bSdh142964 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); 1232*4c06356bSdh142964 if (mapsp == NULL) { 1233*4c06356bSdh142964 return (DDI_FAILURE); 1234*4c06356bSdh142964 } 1235*4c06356bSdh142964 1236*4c06356bSdh142964 statsp = (struct dam_kstats *)mapsp->ks_data; 1237*4c06356bSdh142964 kstat_named_init(&statsp->dam_stable, "stable cycles", 1238*4c06356bSdh142964 KSTAT_DATA_UINT32); 1239*4c06356bSdh142964 kstat_named_init(&statsp->dam_stable_blocked, 1240*4c06356bSdh142964 "stable cycle overrun", KSTAT_DATA_UINT32); 1241*4c06356bSdh142964 kstat_named_init(&statsp->dam_rereport, 1242*4c06356bSdh142964 "restarted reports", KSTAT_DATA_UINT32); 1243*4c06356bSdh142964 kstat_named_init(&statsp->dam_numstable, 1244*4c06356bSdh142964 "# of stable map entries", KSTAT_DATA_UINT32); 1245*4c06356bSdh142964 kstat_install(mapsp); 1246*4c06356bSdh142964 mapp->dam_kstatsp = mapsp; 1247*4c06356bSdh142964 return (DDI_SUCCESS); 1248*4c06356bSdh142964 } 1249*4c06356bSdh142964 1250*4c06356bSdh142964 /* 1251*4c06356bSdh142964 * destroy map stats 1252*4c06356bSdh142964 */ 1253*4c06356bSdh142964 static void 1254*4c06356bSdh142964 dam_kstat_destroy(dam_t *mapp) 1255*4c06356bSdh142964 { 1256*4c06356bSdh142964 1257*4c06356bSdh142964 kstat_delete(mapp->dam_kstatsp); 1258*4c06356bSdh142964 } 1259