1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 #include <sys/note.h>
  27 #include <sys/types.h>
  28 #include <sys/param.h>
  29 #include <sys/systm.h>
  30 #include <sys/buf.h>
  31 #include <sys/kmem.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/debug.h>
  34 #include <sys/sunndi.h>
  35 #include <sys/kstat.h>
  36 #include <sys/conf.h>
  37 #include <sys/ddi_periodic.h>
  38 #include <sys/devctl.h>
  39 #include <sys/callb.h>
  40 #include <sys/sysevent.h>
  41 #include <sys/taskq.h>
  42 #include <sys/ddi.h>
  43 #include <sys/bitset.h>
  44 #include <sys/damap.h>
  45 #include <sys/damap_impl.h>
  46 
  47 #ifdef DEBUG
  48 static int damap_debug = 0;
  49 #endif /* DEBUG */
  50 
  51 extern taskq_t *system_taskq;
  52 
  53 static void dam_addrset_activate(dam_t *, bitset_t *);
  54 static void dam_addrset_deactivate(dam_t *, bitset_t *);
  55 static void dam_stabilize_map(void *);
  56 static void dam_addr_stable_cb(void *);
  57 static void dam_addrset_stable_cb(void *);
  58 static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
  59 static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
  60 static void dam_addr_release(dam_t *, id_t);
  61 static void dam_addr_report_release(dam_t *, id_t);
  62 static void dam_addr_deactivate(dam_t *, id_t);
  63 static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
  64 static id_t dam_get_addrid(dam_t *, char *);
  65 static int dam_kstat_create(dam_t *);
  66 static int dam_map_alloc(dam_t *);
  67 
  68 #define DAM_INCR_STAT(mapp, stat)                               \
  69         if ((mapp)->dam_kstatsp) {                           \
  70                 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;    \
  71                 stp->stat.value.ui32++;                              \
  72         }
  73 
  74 #define DAM_SET_STAT(mapp, stat, val)                           \
  75         if ((mapp)->dam_kstatsp) {                           \
  76                 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;    \
  77                 stp->stat.value.ui32 = (val);                        \
  78         }
  79 
  80 
  81 /*
  82  * increase damap size by 64 entries at a time
  83  */
  84 #define DAM_SIZE_BUMP   64
  85 
  86 int     damap_taskq_dispatch_retry_usec = 1000;
  87 
  88 /*
  89  * config/unconfig taskq data
  90  */
  91 typedef struct {
  92         dam_t *tqd_mapp;
  93         id_t tqd_id;
  94 } cfg_tqd_t;
  95 
  96 extern pri_t maxclsyspri;
  97 
  98 /*
  99  * Create new device address map
 100  *
 101  * name:                map name (kstat unique)
 102  * size:                max # of map entries
 103  * mode:                style of address reports: per-address or fullset
 104  * stable_usec:         # of quiescent microseconds before report/map is stable
 105  *
 106  * activate_arg:        address provider activation-callout private
 107  * activate_cb:         address provider activation callback handler
 108  * deactivate_cb:       address provider deactivation callback handler
 109  *
 110  * config_arg:          configuration-callout private
 111  * config_cb:           class configuration callout
 112  * unconfig_cb:         class unconfiguration callout
 113  *
 114  * damapp:              pointer to map handle (return)
 115  *
 116  * Returns:     DAM_SUCCESS
 117  *              DAM_EINVAL      Invalid argument(s)
 118  *              DAM_FAILURE     General failure
 119  */
 120 int
 121 damap_create(char *name, damap_rptmode_t mode, int map_opts,
 122     int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
 123     damap_deactivate_cb_t deactivate_cb,
 124     void *config_arg, damap_configure_cb_t configure_cb,
 125     damap_unconfig_cb_t unconfig_cb,
 126     damap_t **damapp)
 127 {
 128         dam_t *mapp;
 129 
 130         if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
 131                 return (DAM_EINVAL);
 132 
 133         mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
 134         mapp->dam_options = map_opts;
 135         mapp->dam_stable_ticks = drv_usectohz(stable_usec);
 136         mapp->dam_size = 0;
 137         mapp->dam_rptmode = mode;
 138         mapp->dam_activate_arg = activate_arg;
 139         mapp->dam_activate_cb = (activate_cb_t)activate_cb;
 140         mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
 141         mapp->dam_config_arg = config_arg;
 142         mapp->dam_configure_cb = (configure_cb_t)configure_cb;
 143         mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
 144         mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
 145         mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
 146         cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
 147         bitset_init(&mapp->dam_active_set);
 148         bitset_init(&mapp->dam_stable_set);
 149         bitset_init(&mapp->dam_report_set);
 150         *damapp = (damap_t *)mapp;
 151 
 152         DTRACE_PROBE5(damap__create,
 153             char *, mapp->dam_name, damap_t *, mapp,
 154             damap_rptmode_t, mode, int, map_opts, int, stable_usec);
 155 
 156         return (DAM_SUCCESS);
 157 }
 158 
 159 /*
 160  * Allocate backing resources
 161  *
 162  * DAMs are lightly backed on create - major allocations occur
 163  * at the time a report is made to the map, and are extended on
 164  * a demand basis.
 165  */
 166 static int
 167 dam_map_alloc(dam_t *mapp)
 168 {
 169         void *softstate_p;
 170 
 171         ASSERT(mutex_owned(&mapp->dam_lock));
 172         if (mapp->dam_flags & DAM_DESTROYPEND)
 173                 return (DAM_FAILURE);
 174 
 175         /*
 176          * dam_high > 0 signals map allocation complete
 177          */
 178         if (mapp->dam_high)
 179                 return (DAM_SUCCESS);
 180 
 181         mapp->dam_size = DAM_SIZE_BUMP;
 182         if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
 183             mapp->dam_size) != DDI_SUCCESS)
 184                 return (DAM_FAILURE);
 185 
 186         if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
 187             DDI_SUCCESS) {
 188                 ddi_soft_state_fini(softstate_p);
 189                 return (DAM_FAILURE);
 190         }
 191         if (dam_kstat_create(mapp) != DDI_SUCCESS) {
 192                 ddi_soft_state_fini(softstate_p);
 193                 ddi_strid_fini(&mapp->dam_addr_hash);
 194                 return (DAM_FAILURE);
 195         }
 196         mapp->dam_da = softstate_p;
 197         mapp->dam_high = 1;
 198         bitset_resize(&mapp->dam_active_set, mapp->dam_size);
 199         bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
 200         bitset_resize(&mapp->dam_report_set, mapp->dam_size);
 201         return (DAM_SUCCESS);
 202 }
 203 
 204 /*
 205  * Destroy address map
 206  *
 207  * damapp:      address map
 208  *
 209  * Returns:     DAM_SUCCESS
 210  *              DAM_EINVAL      Invalid argument(s)
 211  *              DAM_FAILURE     General failure
 212  */
 213 void
 214 damap_destroy(damap_t *damapp)
 215 {
 216         int i;
 217         dam_t *mapp = (dam_t *)damapp;
 218 
 219         ASSERT(mapp);
 220 
 221         DTRACE_PROBE2(damap__destroy,
 222             char *, mapp->dam_name, damap_t *, mapp);
 223 
 224         mutex_enter(&mapp->dam_lock);
 225 
 226         /*
 227          * prevent new reports from being added to the map
 228          */
 229         mapp->dam_flags |= DAM_DESTROYPEND;
 230 
 231         if (mapp->dam_high) {
 232                 mutex_exit(&mapp->dam_lock);
 233                 /*
 234                  * wait for outstanding reports to stabilize and cancel
 235                  * the timer for this map
 236                  */
 237                 (void) damap_sync(damapp, 0);
 238                 mutex_enter(&mapp->dam_lock);
 239                 dam_sched_timeout(NULL, mapp, 0);
 240 
 241                 /*
 242                  * map is at full stop
 243                  * release the contents of the map, invoking the
 244                  * detactivation protocol as addresses are released
 245                  */
 246                 mutex_exit(&mapp->dam_lock);
 247                 for (i = 1; i < mapp->dam_high; i++) {
 248                         if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
 249                                 continue;
 250 
 251                         ASSERT(DAM_IN_REPORT(mapp, i) == 0);
 252 
 253                         if (DAM_IS_STABLE(mapp, i)) {
 254                                 dam_addr_deactivate(mapp, i);
 255                         } else {
 256                                 ddi_strid_free(mapp->dam_addr_hash, i);
 257                                 ddi_soft_state_free(mapp->dam_da, i);
 258                         }
 259                 }
 260                 ddi_strid_fini(&mapp->dam_addr_hash);
 261                 ddi_soft_state_fini(&mapp->dam_da);
 262                 kstat_delete(mapp->dam_kstatsp);
 263         } else
 264                 mutex_exit(&mapp->dam_lock);
 265 
 266         bitset_fini(&mapp->dam_active_set);
 267         bitset_fini(&mapp->dam_stable_set);
 268         bitset_fini(&mapp->dam_report_set);
 269         mutex_destroy(&mapp->dam_lock);
 270         cv_destroy(&mapp->dam_sync_cv);
 271         if (mapp->dam_name)
 272                 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
 273         kmem_free(mapp, sizeof (*mapp));
 274 }
 275 
 276 /*
 277  * Wait for map stability.  If sync was successfull then return 1.
 278  * If called with a non-zero sync_usec, then a return value of 0 means a
 279  * timeout occurred prior to sync completion. NOTE: if sync_usec is
 280  * non-zero, it should be much longer than dam_stable_ticks.
 281  *
 282  * damapp:      address map
 283  * sync_usec:   micorseconds until we give up on sync completion.
 284  */
 285 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
 286 int
 287 damap_sync(damap_t *damapp, int sync_usec)
 288 {
 289         dam_t   *mapp = (dam_t *)damapp;
 290         int     rv;
 291 
 292         ASSERT(mapp);
 293         DTRACE_PROBE3(damap__map__sync__start,
 294             char *, mapp->dam_name, dam_t *, mapp,
 295             int, sync_usec);
 296 
 297         /*
 298          * Block when waiting for
 299          *      a) stabilization pending or a fullset update pending
 300          *      b) the report set to finalize (bitset is null)
 301          *      c) any scheduled timeouts to fire
 302          */
 303         rv = 1;                                 /* return synced */
 304         mutex_enter(&mapp->dam_lock);
 305 again:  while ((mapp->dam_flags & WAITFOR_FLAGS) ||
 306             (!bitset_is_null(&mapp->dam_report_set)) ||
 307             (mapp->dam_tid != 0)) {
 308                 DTRACE_PROBE2(damap__map__sync__waiting,
 309                     char *, mapp->dam_name, dam_t *, mapp);
 310 
 311                 /* Wait for condition relayed via timeout */
 312                 if (sync_usec) {
 313                         if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
 314                             drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
 315                                 mapp->dam_sync_to_cnt++;
 316                                 rv = 0;         /* return timeout */
 317                                 break;
 318                         }
 319                 } else
 320                         cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
 321         }
 322 
 323         if (rv) {
 324                 /*
 325                  * Delay one stabilization time after the apparent sync above
 326                  * and verify accuracy - resync if not accurate.
 327                  */
 328                 (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
 329                     mapp->dam_stable_ticks, TR_MICROSEC);
 330                 if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
 331                     (!bitset_is_null(&mapp->dam_report_set)) ||
 332                     (mapp->dam_tid != 0)))
 333                         goto again;
 334         }
 335         mutex_exit(&mapp->dam_lock);
 336 
 337         DTRACE_PROBE3(damap__map__sync__end,
 338             char *, mapp->dam_name, dam_t *, mapp,
 339             int, rv);
 340         return (rv);
 341 }
 342 
 343 /*
 344  * Return 1 if active set is empty
 345  */
 346 int
 347 damap_is_empty(damap_t *damapp)
 348 {
 349         dam_t   *mapp = (dam_t *)damapp;
 350         int     rv;
 351 
 352         mutex_enter(&mapp->dam_lock);
 353         rv = bitset_is_null(&mapp->dam_active_set);
 354         mutex_exit(&mapp->dam_lock);
 355         return (rv);
 356 }
 357 
 358 /*
 359  * Get the name of a device address map
 360  *
 361  * damapp:      address map
 362  *
 363  * Returns:     name
 364  */
 365 char *
 366 damap_name(damap_t *damapp)
 367 {
 368         dam_t *mapp = (dam_t *)damapp;
 369 
 370         return (mapp ? mapp->dam_name : "UNKNOWN_damap");
 371 }
 372 
 373 /*
 374  * Get the current size of the device address map
 375  *
 376  * damapp:      address map
 377  *
 378  * Returns:     size
 379  */
 380 int
 381 damap_size(damap_t *damapp)
 382 {
 383         dam_t *mapp = (dam_t *)damapp;
 384 
 385         return (mapp->dam_size);
 386 }
 387 
 388 /*
 389  * Report an address to per-address report
 390  *
 391  * damapp:      address map handle
 392  * address:     address in ascii string representation
 393  * addridp:     address ID
 394  * nvl:         optional nvlist of configuration-private data
 395  * addr_priv:   optional provider-private (passed to activate/deactivate cb)
 396  *
 397  * Returns:     DAM_SUCCESS
 398  *              DAM_EINVAL      Invalid argument(s)
 399  *              DAM_MAPFULL     address map exhausted
 400  */
 401 int
 402 damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
 403     nvlist_t *nvl, void *addr_priv)
 404 {
 405         dam_t *mapp = (dam_t *)damapp;
 406         id_t addrid;
 407         dam_da_t *passp;
 408 
 409         if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 410                 return (DAM_EINVAL);
 411 
 412         DTRACE_PROBE3(damap__addr__add,
 413             char *, mapp->dam_name, dam_t *, mapp,
 414             char *, address);
 415 
 416         mutex_enter(&mapp->dam_lock);
 417         if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
 418             ((addrid = dam_get_addrid(mapp, address)) == 0)) {
 419                 mutex_exit(&mapp->dam_lock);
 420                 return (DAM_MAPFULL);
 421         }
 422 
 423         passp = ddi_get_soft_state(mapp->dam_da, addrid);
 424         ASSERT(passp != NULL);
 425 
 426         /*
 427          * If re-reporting the same address (add or remove) clear
 428          * the existing report
 429          */
 430         if (DAM_IN_REPORT(mapp, addrid)) {
 431                 DTRACE_PROBE3(damap__addr__add__jitter,
 432                     char *, mapp->dam_name, dam_t *, mapp,
 433                     char *, address);
 434                 DAM_INCR_STAT(mapp, dam_jitter);
 435                 dam_addr_report_release(mapp, addrid);
 436                 passp->da_jitter++;
 437         }
 438         passp->da_ppriv_rpt = addr_priv;
 439         if (nvl)
 440                 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
 441 
 442         dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
 443         if (addridp != NULL)
 444                 *addridp = (damap_id_t)addrid;
 445         mutex_exit(&mapp->dam_lock);
 446         return (DAM_SUCCESS);
 447 }
 448 
 449 /*
 450  * Report removal of address from per-address report
 451  *
 452  * damapp:      address map
 453  * address:     address in ascii string representation
 454  *
 455  * Returns:     DAM_SUCCESS
 456  *              DAM_EINVAL      Invalid argument(s)
 457  *              DAM_FAILURE     General failure
 458  */
 459 int
 460 damap_addr_del(damap_t *damapp, char *address)
 461 {
 462         dam_t *mapp = (dam_t *)damapp;
 463         id_t addrid;
 464         dam_da_t *passp;
 465 
 466         if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
 467                 return (DAM_EINVAL);
 468 
 469         DTRACE_PROBE3(damap__addr__del,
 470             char *, mapp->dam_name, dam_t *, mapp,
 471             char *, address);
 472         mutex_enter(&mapp->dam_lock);
 473         if (dam_map_alloc(mapp) != DAM_SUCCESS) {
 474                 mutex_exit(&mapp->dam_lock);
 475                 return (DAM_MAPFULL);
 476         }
 477 
 478         /*
 479          * if reporting the removal of an address which is not in the map
 480          * return success
 481          */
 482         if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
 483                 mutex_exit(&mapp->dam_lock);
 484                 return (DAM_SUCCESS);
 485         }
 486         passp = ddi_get_soft_state(mapp->dam_da, addrid);
 487         ASSERT(passp);
 488         if (DAM_IN_REPORT(mapp, addrid)) {
 489                 DTRACE_PROBE3(damap__addr__del__jitter,
 490                     char *, mapp->dam_name, dam_t *, mapp,
 491                     char *, address);
 492                 DAM_INCR_STAT(mapp, dam_jitter);
 493                 dam_addr_report_release(mapp, addrid);
 494                 passp->da_jitter++;
 495         }
 496         dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
 497         mutex_exit(&mapp->dam_lock);
 498         return (DAM_SUCCESS);
 499 }
 500 
 501 static int
 502 damap_addrset_flush_locked(damap_t *damapp)
 503 {
 504         dam_t   *mapp = (dam_t *)damapp;
 505         int     idx;
 506 
 507         ASSERT(mapp);
 508         ASSERT(mutex_owned(&mapp->dam_lock));
 509         if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
 510                 return (DAM_EINVAL);
 511         }
 512 
 513         DTRACE_PROBE2(damap__addrset__flush__locked__enter,
 514             char *, mapp->dam_name, dam_t *, mapp);
 515         if (mapp->dam_flags & DAM_SETADD) {
 516                 DTRACE_PROBE2(damap__addrset__flush__locked__reset,
 517                     char *, mapp->dam_name, dam_t *, mapp);
 518 
 519                 /*
 520                  * cancel stabilization timeout
 521                  */
 522                 dam_sched_timeout(NULL, mapp, 0);
 523                 DAM_INCR_STAT(mapp, dam_jitter);
 524 
 525                 /*
 526                  * clear pending reports
 527                  */
 528                 for (idx = 1; idx < mapp->dam_high; idx++) {
 529                         if (DAM_IN_REPORT(mapp, idx)) {
 530                                 dam_addr_report_release(mapp, idx);
 531                         }
 532                 }
 533 
 534                 bitset_zero(&mapp->dam_report_set);
 535                 mapp->dam_flags &= ~DAM_SETADD;
 536                 cv_signal(&mapp->dam_sync_cv);
 537         }
 538 
 539         return (DAM_SUCCESS);
 540 }
 541 
 542 /*
 543  * Initiate full-set report
 544  *
 545  * damapp:      address map
 546  *
 547  * Returns:     DAM_SUCCESS
 548  *              DAM_EINVAL      Invalid argument(s)
 549  */
 550 int
 551 damap_addrset_begin(damap_t *damapp)
 552 {
 553         dam_t   *mapp = (dam_t *)damapp;
 554         int     rv;
 555 
 556         if (mapp == NULL) {
 557                 return (DAM_EINVAL);
 558         }
 559 
 560         DTRACE_PROBE2(damap__addrset__begin,
 561             char *, mapp->dam_name, dam_t *, mapp);
 562 
 563         mutex_enter(&mapp->dam_lock);
 564         if (dam_map_alloc(mapp) != DAM_SUCCESS) {
 565                 mutex_exit(&mapp->dam_lock);
 566 
 567                 return (DAM_MAPFULL);
 568         }
 569 
 570         rv = damap_addrset_flush_locked(damapp);
 571         if (rv == DAM_SUCCESS) {
 572                 mapp->dam_flags |= DAM_SETADD;
 573         }
 574         mutex_exit(&mapp->dam_lock);
 575 
 576         return (rv);
 577 }
 578 
 579 /*
 580  * Cancel full-set report
 581  *
 582  * damapp:      address map
 583  *
 584  * Returns:     DAM_SUCCESS
 585  *              DAM_EINVAL      Invalid argument(s)
 586  */
 587 int
 588 damap_addrset_flush(damap_t *damapp)
 589 {
 590         int     rv;
 591         dam_t   *mapp = (dam_t *)damapp;
 592 
 593         if (mapp == NULL) {
 594                 return (DAM_EINVAL);
 595         }
 596 
 597         DTRACE_PROBE2(damap__addrset__flush,
 598             char *, mapp->dam_name, dam_t *, mapp);
 599 
 600         mutex_enter(&mapp->dam_lock);
 601         rv = damap_addrset_flush_locked(damapp);
 602         mutex_exit(&mapp->dam_lock);
 603 
 604         return (rv);
 605 }
 606 
 607 /*
 608  * Report address to full-set report
 609  *
 610  * damapp:      address map handle
 611  * address:     address in ascii string representation
 612  * rindx:       index if address stabilizes
 613  * nvl:         optional nvlist of configuration-private data
 614  * addr_priv:   optional provider-private data (passed to activate/release cb)
 615  *
 616  * Returns:     DAM_SUCCESS
 617  *              DAM_EINVAL      Invalid argument(s)
 618  *              DAM_MAPFULL     address map exhausted
 619  *              DAM_FAILURE     General failure
 620  */
 621 int
 622 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
 623     nvlist_t *nvl, void *addr_priv)
 624 {
 625         dam_t *mapp = (dam_t *)damapp;
 626         id_t addrid;
 627         dam_da_t *passp;
 628 
 629         if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 630                 return (DAM_EINVAL);
 631 
 632         DTRACE_PROBE3(damap__addrset__add,
 633             char *, mapp->dam_name, dam_t *, mapp, char *, address);
 634 
 635         mutex_enter(&mapp->dam_lock);
 636         if (!(mapp->dam_flags & DAM_SETADD)) {
 637                 mutex_exit(&mapp->dam_lock);
 638                 return (DAM_FAILURE);
 639         }
 640 
 641         if ((addrid = dam_get_addrid(mapp, address)) == 0) {
 642                 mutex_exit(&mapp->dam_lock);
 643                 return (DAM_MAPFULL);
 644         }
 645 
 646         passp = ddi_get_soft_state(mapp->dam_da, addrid);
 647         ASSERT(passp);
 648         if (DAM_IN_REPORT(mapp, addrid)) {
 649                 DTRACE_PROBE3(damap__addrset__add__jitter,
 650                     char *, mapp->dam_name, dam_t *, mapp,
 651                     char *, address);
 652                 dam_addr_report_release(mapp, addrid);
 653                 passp->da_jitter++;
 654         }
 655         passp->da_ppriv_rpt = addr_priv;
 656         if (nvl)
 657                 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
 658         bitset_add(&mapp->dam_report_set, addrid);
 659         if (ridx)
 660                 *ridx = (damap_id_t)addrid;
 661         mutex_exit(&mapp->dam_lock);
 662         return (DAM_SUCCESS);
 663 }
 664 
 665 /*
 666  * Commit full-set report for stabilization
 667  *
 668  * damapp:      address map handle
 669  * flags:       (currently 0)
 670  *
 671  * Returns:     DAM_SUCCESS
 672  *              DAM_EINVAL      Invalid argument(s)
 673  *              DAM_FAILURE     General failure
 674  */
 675 int
 676 damap_addrset_end(damap_t *damapp, int flags)
 677 {
 678         dam_t *mapp = (dam_t *)damapp;
 679         int i;
 680 
 681         if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
 682                 return (DAM_EINVAL);
 683 
 684         DTRACE_PROBE2(damap__addrset__end,
 685             char *, mapp->dam_name, dam_t *, mapp);
 686 
 687         mutex_enter(&mapp->dam_lock);
 688         if (!(mapp->dam_flags & DAM_SETADD)) {
 689                 mutex_exit(&mapp->dam_lock);
 690                 return (DAM_FAILURE);
 691         }
 692 
 693         if (flags & DAMAP_END_RESET) {
 694                 DTRACE_PROBE2(damap__addrset__end__reset,
 695                     char *, mapp->dam_name, dam_t *, mapp);
 696                 dam_sched_timeout(NULL, mapp, 0);
 697                 for (i = 1; i < mapp->dam_high; i++)
 698                         if (DAM_IN_REPORT(mapp, i))
 699                                 dam_addr_report_release(mapp, i);
 700         } else {
 701                 mapp->dam_last_update = gethrtime();
 702                 dam_sched_timeout(dam_addrset_stable_cb, mapp,
 703                     mapp->dam_stable_ticks);
 704         }
 705         mutex_exit(&mapp->dam_lock);
 706         return (DAM_SUCCESS);
 707 }
 708 
 709 /*
 710  * Return nvlist registered with reported address
 711  *
 712  * damapp:      address map handle
 713  * addrid:      address ID
 714  *
 715  * Returns:     nvlist_t *      provider supplied via damap_addr{set}_add())
 716  *              NULL
 717  */
 718 nvlist_t *
 719 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
 720 {
 721         dam_t *mapp = (dam_t *)damapp;
 722         dam_da_t *pass;
 723 
 724         if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
 725                 if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
 726                         return (pass->da_nvl);
 727         }
 728         return (NULL);
 729 }
 730 
 731 /*
 732  * Return address string
 733  *
 734  * damapp:      address map handle
 735  * addrid:      address ID
 736  *
 737  * Returns:     char *          Address string
 738  *              NULL
 739  */
 740 char *
 741 damap_id2addr(damap_t *damapp, damap_id_t addrid)
 742 {
 743         dam_t *mapp = (dam_t *)damapp;
 744 
 745         if (mapp->dam_high)
 746                 return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
 747         else
 748                 return (NULL);
 749 }
 750 
 751 /*
 752  * Release address reference in map
 753  *
 754  * damapp:      address map handle
 755  * addrid:      address ID
 756  */
 757 void
 758 damap_id_rele(damap_t *damapp, damap_id_t addrid)
 759 {
 760         dam_t *mapp = (dam_t *)damapp;
 761         dam_da_t *passp;
 762         char *addr;
 763 
 764         passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 765         ASSERT(passp);
 766 
 767         addr = damap_id2addr(damapp, addrid);
 768         DTRACE_PROBE4(damap__id__rele,
 769             char *, mapp->dam_name, dam_t *, mapp,
 770             char *, addr, int, passp->da_ref);
 771 
 772         mutex_enter(&mapp->dam_lock);
 773 
 774         /*
 775          * teardown address if last outstanding reference
 776          */
 777         if (--passp->da_ref == 0)
 778                 dam_addr_release(mapp, (id_t)addrid);
 779 
 780         mutex_exit(&mapp->dam_lock);
 781 }
 782 
 783 /*
 784  * Return current reference count on address reference in map
 785  *
 786  * damapp:      address map handle
 787  * addrid:      address ID
 788  *
 789  * Returns:     DAM_SUCCESS
 790  *              DAM_FAILURE
 791  */
 792 int
 793 damap_id_ref(damap_t *damapp, damap_id_t addrid)
 794 {
 795         dam_t *mapp = (dam_t *)damapp;
 796         dam_da_t *passp;
 797         int ref = -1;
 798 
 799         passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 800         if (passp)
 801                 ref = passp->da_ref;
 802 
 803         return (ref);
 804 }
 805 
 806 /*
 807  * Return next address ID in list
 808  *
 809  * damapp:      address map handle
 810  * damap_list:  address ID list passed to config|unconfig
 811  *              returned by look by lookup_all
 812  * last:        last ID returned, 0 is start of list
 813  *
 814  * Returns:     addrid          Next ID from the list
 815  *              0               End of the list
 816  */
 817 damap_id_t
 818 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
 819 {
 820         int i, start;
 821         dam_t *mapp = (dam_t *)damapp;
 822         bitset_t *dam_list = (bitset_t *)damap_list;
 823 
 824         if (!mapp || !dam_list)
 825                 return ((damap_id_t)0);
 826 
 827         start = (int)last + 1;
 828         for (i = start; i < mapp->dam_high; i++) {
 829                 if (bitset_in_set(dam_list, i)) {
 830                         return ((damap_id_t)i);
 831                 }
 832         }
 833         return ((damap_id_t)0);
 834 }
 835 
 836 /*
 837  * Set config private data
 838  *
 839  * damapp:      address map handle
 840  * addrid:      address ID
 841  * cfg_priv:    configuration private data
 842  *
 843  */
 844 void
 845 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
 846 {
 847         dam_t *mapp = (dam_t *)damapp;
 848         dam_da_t *passp;
 849 
 850         mutex_enter(&mapp->dam_lock);
 851         passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 852         if (!passp) {
 853                 mutex_exit(&mapp->dam_lock);
 854                 return;
 855         }
 856         passp->da_cfg_priv = cfg_priv;
 857         mutex_exit(&mapp->dam_lock);
 858 }
 859 
 860 /*
 861  * Get config private data
 862  *
 863  * damapp:      address map handle
 864  * addrid:      address ID
 865  *
 866  * Returns:     configuration private data
 867  */
 868 void *
 869 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
 870 {
 871         dam_t *mapp = (dam_t *)damapp;
 872         dam_da_t *passp;
 873         void *rv;
 874 
 875         mutex_enter(&mapp->dam_lock);
 876         passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
 877         if (!passp) {
 878                 mutex_exit(&mapp->dam_lock);
 879                 return (NULL);
 880         }
 881         rv = passp->da_cfg_priv;
 882         mutex_exit(&mapp->dam_lock);
 883         return (rv);
 884 }
 885 
 886 /*
 887  * Lookup a single address in the active address map
 888  *
 889  * damapp:      address map handle
 890  * address:     address string
 891  *
 892  * Returns:     ID of active/stable address
 893  *              0       Address not in stable set
 894  *
 895  * Future: Allow the caller to wait for stabilize before returning not found.
 896  */
 897 damap_id_t
 898 damap_lookup(damap_t *damapp, char *address)
 899 {
 900         dam_t *mapp = (dam_t *)damapp;
 901         id_t addrid = 0;
 902         dam_da_t *passp = NULL;
 903 
 904         DTRACE_PROBE3(damap__lookup,
 905             char *, mapp->dam_name, dam_t *, mapp,
 906             char *, address);
 907         mutex_enter(&mapp->dam_lock);
 908         if (!mapp->dam_high)
 909                 addrid = 0;
 910         else
 911                 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
 912         if (addrid) {
 913                 if (DAM_IS_STABLE(mapp, addrid)) {
 914                         passp = ddi_get_soft_state(mapp->dam_da, addrid);
 915                         ASSERT(passp);
 916                         if (passp) {
 917                                 passp->da_ref++;
 918                         } else {
 919                                 addrid = 0;
 920                         }
 921                 } else {
 922                         addrid = 0;
 923                 }
 924         }
 925         mutex_exit(&mapp->dam_lock);
 926         DTRACE_PROBE4(damap__lookup__return,
 927             char *, mapp->dam_name, dam_t *, mapp,
 928             char *, address, int, addrid);
 929         return ((damap_id_t)addrid);
 930 }
 931 
 932 
 933 /*
 934  * Return the list of stable addresses in the map
 935  *
 936  * damapp:      address map handle
 937  * id_listp:    pointer to list of address IDs in stable map (returned)
 938  *
 939  * Returns:     # of entries returned in alist
 940  */
 941 int
 942 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
 943 {
 944         dam_t *mapp = (dam_t *)damapp;
 945         int mapsz = mapp->dam_size;
 946         int n_ids, i;
 947         bitset_t *bsp;
 948         char     *addrp;
 949         dam_da_t *passp;
 950 
 951         DTRACE_PROBE2(damap__lookup__all,
 952             char *, mapp->dam_name, dam_t *, mapp);
 953         mutex_enter(&mapp->dam_lock);
 954         if (!mapp->dam_high) {
 955                 *id_listp = (damap_id_list_t)NULL;
 956                 mutex_exit(&mapp->dam_lock);
 957                 DTRACE_PROBE2(damap__lookup__all__nomap,
 958                     char *, mapp->dam_name, dam_t *, mapp);
 959                 return (0);
 960         }
 961         bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
 962         bitset_init(bsp);
 963         bitset_resize(bsp, mapsz);
 964         bitset_copy(&mapp->dam_active_set, bsp);
 965         for (n_ids = 0, i = 1; i < mapsz; i++) {
 966                 if (bitset_in_set(bsp, i)) {
 967                         passp = ddi_get_soft_state(mapp->dam_da, i);
 968                         ASSERT(passp);
 969                         if (passp) {
 970                                 addrp = damap_id2addr(damapp, i);
 971                                 DTRACE_PROBE3(damap__lookup__all__item,
 972                                     char *, mapp->dam_name, dam_t *, mapp,
 973                                     char *, addrp);
 974                                 passp->da_ref++;
 975                                 n_ids++;
 976                         }
 977                 }
 978         }
 979         if (n_ids) {
 980                 *id_listp = (damap_id_list_t)bsp;
 981                 mutex_exit(&mapp->dam_lock);
 982                 return (n_ids);
 983         } else {
 984                 *id_listp = (damap_id_list_t)NULL;
 985                 bitset_fini(bsp);
 986                 kmem_free(bsp, sizeof (*bsp));
 987                 mutex_exit(&mapp->dam_lock);
 988                 return (0);
 989         }
 990 }
 991 
 992 /*
 993  * Release the address list returned by damap_lookup_all()
 994  *
 995  * mapp:        address map handle
 996  * id_list:     list of address IDs returned in damap_lookup_all()
 997  */
 998 void
 999 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
1000 {
1001         dam_t *mapp = (dam_t *)damapp;
1002         int i;
1003 
1004         if (id_list == NULL)
1005                 return;
1006 
1007         mutex_enter(&mapp->dam_lock);
1008         for (i = 1; i < mapp->dam_high; i++) {
1009                 if (bitset_in_set((bitset_t *)id_list, i))
1010                         (void) dam_addr_release(mapp, i);
1011         }
1012         mutex_exit(&mapp->dam_lock);
1013         bitset_fini((bitset_t *)id_list);
1014         kmem_free((void *)id_list, sizeof (bitset_t));
1015 }
1016 
1017 /*
1018  * activate an address that has passed the stabilization interval
1019  */
1020 static void
1021 dam_addr_activate(dam_t *mapp, id_t addrid)
1022 {
1023         dam_da_t *passp;
1024         int config_rv;
1025         char *addrstr;
1026 
1027         mutex_enter(&mapp->dam_lock);
1028         bitset_add(&mapp->dam_active_set, addrid);
1029         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1030         ASSERT(passp);
1031 
1032         /*
1033          * copy the reported nvlist and provider private data
1034          */
1035         addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1036         DTRACE_PROBE3(damap__addr__activate__start,
1037             char *, mapp->dam_name, dam_t *, mapp,
1038             char *, addrstr);
1039         passp->da_nvl = passp->da_nvl_rpt;
1040         passp->da_ppriv = passp->da_ppriv_rpt;
1041         passp->da_ppriv_rpt = NULL;
1042         passp->da_nvl_rpt = NULL;
1043         passp->da_last_stable = gethrtime();
1044         passp->da_stable_cnt++;
1045         mutex_exit(&mapp->dam_lock);
1046         if (mapp->dam_activate_cb) {
1047                 (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
1048                     addrid, &passp->da_ppriv_rpt);
1049         }
1050 
1051         /*
1052          * call the address-specific configuration action as part of
1053          * activation.
1054          */
1055         config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
1056             addrid);
1057         if (config_rv != DAM_SUCCESS) {
1058                 mutex_enter(&mapp->dam_lock);
1059                 passp->da_flags |= DA_FAILED_CONFIG;
1060                 mutex_exit(&mapp->dam_lock);
1061                 DTRACE_PROBE3(damap__addr__activate__config__failure,
1062                     char *, mapp->dam_name, dam_t *, mapp,
1063                     char *, addrstr);
1064                 dam_deact_cleanup(mapp, addrid, addrstr,
1065                     DAMAP_DEACT_RSN_CFG_FAIL);
1066         } else {
1067                 DTRACE_PROBE3(damap__addr__activate__end,
1068                     char *, mapp->dam_name, dam_t *, mapp,
1069                     char *, addrstr);
1070         }
1071 }
1072 
1073 /*
1074  * deactivate a previously stable address
1075  */
1076 static void
1077 dam_addr_deactivate(dam_t *mapp, id_t addrid)
1078 {
1079         char *addrstr;
1080 
1081         addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1082         DTRACE_PROBE3(damap__addr__deactivate__start,
1083             char *, mapp->dam_name, dam_t *, mapp,
1084             char *, addrstr);
1085 
1086         /*
1087          * call the unconfiguration callback
1088          */
1089         (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1090         dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1091 }
1092 
1093 static void
1094 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1095     damap_deact_rsn_t deact_rsn)
1096 {
1097         dam_da_t *passp;
1098 
1099         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1100         ASSERT(passp);
1101         if (mapp->dam_deactivate_cb)
1102                 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1103                     ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1104                     addrid, passp->da_ppriv, deact_rsn);
1105 
1106         /*
1107          * clear the active bit and free the backing info for
1108          * this address
1109          */
1110         mutex_enter(&mapp->dam_lock);
1111         bitset_del(&mapp->dam_active_set, addrid);
1112         passp->da_ppriv = NULL;
1113         nvlist_free(passp->da_nvl);
1114         passp->da_nvl = NULL;
1115         passp->da_ppriv_rpt = NULL;
1116         nvlist_free(passp->da_nvl_rpt);
1117         passp->da_nvl_rpt = NULL;
1118 
1119         DTRACE_PROBE3(damap__addr__deactivate__end,
1120             char *, mapp->dam_name, dam_t *, mapp,
1121             char *, addrstr);
1122 
1123         (void) dam_addr_release(mapp, addrid);
1124         mutex_exit(&mapp->dam_lock);
1125 }
1126 
1127 /*
1128  * taskq callback for multi-thread activation
1129  */
1130 static void
1131 dam_tq_config(void *arg)
1132 {
1133         cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1134 
1135         dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1136         kmem_free(tqd, sizeof (*tqd));
1137 }
1138 
1139 /*
1140  * taskq callback for multi-thread deactivation
1141  */
1142 static void
1143 dam_tq_unconfig(void *arg)
1144 {
1145         cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1146 
1147         dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1148         kmem_free(tqd, sizeof (*tqd));
1149 }
1150 
1151 /*
1152  * Activate a set of stabilized addresses
1153  */
1154 static void
1155 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1156 {
1157 
1158         int i, nset;
1159         taskq_t *tqp = NULL;
1160         cfg_tqd_t *tqd = NULL;
1161         char tqn[TASKQ_NAMELEN];
1162         extern pri_t maxclsyspri;
1163 
1164         if (mapp->dam_options & DAMAP_MTCONFIG) {
1165                 /*
1166                  * calculate the # of taskq threads to create
1167                  */
1168                 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1169                         if (bitset_in_set(activate, i))
1170                                 nset++;
1171                 ASSERT(nset);
1172                 (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1173                 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1174                     INT_MAX, TASKQ_PREPOPULATE);
1175         }
1176         for (i = 1; i < mapp->dam_high; i++) {
1177                 if (bitset_in_set(activate, i)) {
1178                         if (!tqp)
1179                                 dam_addr_activate(mapp, i);
1180                         else {
1181                                 /*
1182                                  * multi-threaded activation
1183                                  */
1184                                 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1185                                 tqd->tqd_mapp = mapp;
1186                                 tqd->tqd_id = i;
1187                                 (void) taskq_dispatch(tqp, dam_tq_config,
1188                                     tqd, TQ_SLEEP);
1189                         }
1190                 }
1191         }
1192         if (tqp) {
1193                 taskq_wait(tqp);
1194                 taskq_destroy(tqp);
1195         }
1196 }
1197 
1198 /*
1199  * Deactivate a set of stabilized addresses
1200  */
1201 static void
1202 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1203 {
1204         int i, nset;
1205         taskq_t *tqp = NULL;
1206         cfg_tqd_t *tqd = NULL;
1207         char tqn[TASKQ_NAMELEN];
1208 
1209         DTRACE_PROBE2(damap__addrset__deactivate,
1210             char *, mapp->dam_name, dam_t *, mapp);
1211 
1212         if (mapp->dam_options & DAMAP_MTCONFIG) {
1213                 /*
1214                  * compute the # of taskq threads to dispatch
1215                  */
1216                 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1217                         if (bitset_in_set(deactivate, i))
1218                                 nset++;
1219                 (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1220                     mapp->dam_name);
1221                 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1222                     INT_MAX, TASKQ_PREPOPULATE);
1223         }
1224         for (i = 1; i < mapp->dam_high; i++) {
1225                 if (bitset_in_set(deactivate, i)) {
1226                         if (!tqp) {
1227                                 dam_addr_deactivate(mapp, i);
1228                         } else {
1229                                 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1230                                 tqd->tqd_mapp = mapp;
1231                                 tqd->tqd_id = i;
1232                                 (void) taskq_dispatch(tqp,
1233                                     dam_tq_unconfig, tqd, TQ_SLEEP);
1234                         }
1235                 }
1236         }
1237 
1238         if (tqp) {
1239                 taskq_wait(tqp);
1240                 taskq_destroy(tqp);
1241         }
1242 }
1243 
1244 /*
1245  * Release a previously activated address
1246  */
1247 static void
1248 dam_addr_release(dam_t *mapp, id_t addrid)
1249 {
1250         dam_da_t *passp;
1251         char     *addrstr;
1252 
1253 
1254         ASSERT(mutex_owned(&mapp->dam_lock));
1255         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1256         ASSERT(passp);
1257 
1258         addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1259         DTRACE_PROBE3(damap__addr__release,
1260             char *, mapp->dam_name, dam_t *, mapp,
1261             char *, addrstr);
1262 
1263         /*
1264          * defer releasing the address until outstanding references
1265          * are released
1266          */
1267         if (passp->da_ref > 1) {
1268                 DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1269                     char *, mapp->dam_name, dam_t *, mapp,
1270                     char *, addrstr, int, passp->da_ref);
1271                 return;
1272         }
1273 
1274         /*
1275          * allow pending reports to stabilize
1276          */
1277         if (DAM_IN_REPORT(mapp, addrid)) {
1278                 DTRACE_PROBE3(damap__addr__release__report__pending,
1279                     char *, mapp->dam_name, dam_t *, mapp,
1280                     char *, addrstr);
1281                 return;
1282         }
1283 
1284         ddi_strid_free(mapp->dam_addr_hash, addrid);
1285         ddi_soft_state_free(mapp->dam_da, addrid);
1286 }
1287 
1288 /*
1289  * process stabilized address reports
1290  */
1291 static void
1292 dam_stabilize_map(void *arg)
1293 {
1294         dam_t *mapp = (dam_t *)arg;
1295         bitset_t delta;
1296         bitset_t cfg;
1297         bitset_t uncfg;
1298         int has_cfg, has_uncfg;
1299         uint32_t i, n_active;
1300 
1301         DTRACE_PROBE2(damap__stabilize__map,
1302             char *, mapp->dam_name, dam_t *, mapp);
1303 
1304         bitset_init(&delta);
1305         bitset_resize(&delta, mapp->dam_size);
1306         bitset_init(&cfg);
1307         bitset_resize(&cfg, mapp->dam_size);
1308         bitset_init(&uncfg);
1309         bitset_resize(&uncfg, mapp->dam_size);
1310 
1311         /*
1312          * determine which addresses have changed during
1313          * this stabilization cycle
1314          */
1315         mutex_enter(&mapp->dam_lock);
1316         ASSERT(mapp->dam_flags & DAM_SPEND);
1317         if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1318             &delta)) {
1319                 /*
1320                  * no difference
1321                  */
1322                 bitset_zero(&mapp->dam_stable_set);
1323                 mapp->dam_flags &= ~DAM_SPEND;
1324                 cv_signal(&mapp->dam_sync_cv);
1325                 mutex_exit(&mapp->dam_lock);
1326 
1327                 bitset_fini(&uncfg);
1328                 bitset_fini(&cfg);
1329                 bitset_fini(&delta);
1330                 DTRACE_PROBE2(damap__stabilize__map__nochange,
1331                     char *, mapp->dam_name, dam_t *, mapp);
1332                 return;
1333         }
1334 
1335         /*
1336          * compute the sets of addresses to be activated and deactivated
1337          */
1338         has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1339         has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1340 
1341         /*
1342          * drop map lock while invoking callouts
1343          */
1344         mutex_exit(&mapp->dam_lock);
1345 
1346         /*
1347          * activate all newly stable addresss
1348          */
1349         if (has_cfg)
1350                 dam_addrset_activate(mapp, &cfg);
1351 
1352         /*
1353          * deactivate addresss which are no longer in the map
1354          */
1355         if (has_uncfg)
1356                 dam_addrset_deactivate(mapp, &uncfg);
1357 
1358 
1359         /*
1360          * timestamp the last stable time and increment the kstat keeping
1361          * the # of of stable cycles for the map
1362          */
1363         mutex_enter(&mapp->dam_lock);
1364         bitset_zero(&mapp->dam_stable_set);
1365         mapp->dam_last_stable = gethrtime();
1366         mapp->dam_stable_cnt++;
1367         DAM_INCR_STAT(mapp, dam_cycles);
1368 
1369         /*
1370          * determine the number of stable addresses
1371          * and update the n_active kstat for this map
1372          */
1373         for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1374                 if (bitset_in_set(&mapp->dam_active_set, i))
1375                         n_active++;
1376         DAM_SET_STAT(mapp, dam_active, n_active);
1377 
1378         DTRACE_PROBE3(damap__map__stable__end,
1379             char *, mapp->dam_name, dam_t *, mapp,
1380             int, n_active);
1381 
1382         mapp->dam_flags &= ~DAM_SPEND;
1383         cv_signal(&mapp->dam_sync_cv);
1384         mutex_exit(&mapp->dam_lock);
1385 
1386         bitset_fini(&uncfg);
1387         bitset_fini(&cfg);
1388         bitset_fini(&delta);
1389 }
1390 
1391 /*
1392  * per-address stabilization timeout
1393  */
1394 static void
1395 dam_addr_stable_cb(void *arg)
1396 {
1397         dam_t *mapp = (dam_t *)arg;
1398         int i;
1399         dam_da_t *passp;
1400         int spend = 0;
1401         int tpend = 0;
1402         int64_t ts, next_ticks, delta_ticks;
1403 
1404         mutex_enter(&mapp->dam_lock);
1405         if (mapp->dam_tid == 0) {
1406                 DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1407                     char *, mapp->dam_name, dam_t *, mapp);
1408                 mutex_exit(&mapp->dam_lock);
1409                 return;
1410         }
1411         mapp->dam_tid = 0;
1412 
1413         /*
1414          * If still under stabilization, reschedule timeout,
1415          * otherwise dispatch the task to activate and deactivate the
1416          * new stable address
1417          */
1418         if (mapp->dam_flags & DAM_SPEND) {
1419                 DAM_INCR_STAT(mapp, dam_overrun);
1420                 mapp->dam_stable_overrun++;
1421                 DTRACE_PROBE2(damap__map__addr__stable__overrun,
1422                     char *, mapp->dam_name, dam_t *, mapp);
1423                 dam_sched_timeout(dam_addr_stable_cb, mapp,
1424                     mapp->dam_stable_ticks);
1425                 mutex_exit(&mapp->dam_lock);
1426                 return;
1427         }
1428 
1429         DAM_SET_STAT(mapp, dam_overrun, 0);
1430         mapp->dam_stable_overrun = 0;
1431 
1432         /* See if any reports stabalized and compute next timeout. */
1433         ts = ddi_get_lbolt64();
1434         next_ticks = mapp->dam_stable_ticks;
1435         for (i = 1; i < mapp->dam_high; i++) {
1436                 if (bitset_in_set(&mapp->dam_report_set, i)) {
1437                         passp = ddi_get_soft_state(mapp->dam_da, i);
1438                         ASSERT(passp);
1439 
1440                         if (passp->da_deadline <= ts)
1441                                 spend++;        /* report has stabilized */
1442                         else {
1443                                 /* not stabilized, determine next map timeout */
1444                                 tpend++;
1445                                 delta_ticks = passp->da_deadline - ts;
1446                                 if (delta_ticks < next_ticks)
1447                                         next_ticks = delta_ticks;
1448                         }
1449                 }
1450         }
1451 
1452         /*
1453          * schedule system_taskq activation of stabilized reports
1454          */
1455         if (spend) {
1456                 if (taskq_dispatch(system_taskq, dam_stabilize_map,
1457                     mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1458                         DTRACE_PROBE2(damap__map__addr__stable__start,
1459                             char *, mapp->dam_name, dam_t *, mapp);
1460 
1461                         /*
1462                          * The stable_set we compute below stays pending until
1463                          * processed by dam_stabilize_map. We can't set
1464                          * DAM_SPEND (or bitset_del things from the
1465                          * report_set) until we *know* that we can handoff the
1466                          * result to dam_stabilize_map. If dam_stabilize_map
1467                          * starts executing before we are complete, it will
1468                          * block on the dam_lock mutex until we are ready.
1469                          */
1470                         mapp->dam_flags |= DAM_SPEND;
1471 
1472                         /*
1473                          * Copy the current active_set to the stable_set, then
1474                          * add or remove stabilized report_set address from
1475                          * the stable set (and delete them from the report_set).
1476                          */
1477                         bitset_copy(&mapp->dam_active_set,
1478                             &mapp->dam_stable_set);
1479                         for (i = 1; i < mapp->dam_high; i++) {
1480                                 if (!bitset_in_set(&mapp->dam_report_set, i))
1481                                         continue;
1482 
1483                                 passp = ddi_get_soft_state(mapp->dam_da, i);
1484                                 if (passp->da_deadline > ts)
1485                                         continue; /* report not stabilized */
1486 
1487                                 /* report has stabilized */
1488                                 if (passp->da_flags & DA_RELE)
1489                                         bitset_del(&mapp->dam_stable_set, i);
1490                                 else
1491                                         bitset_add(&mapp->dam_stable_set, i);
1492 
1493                                 bitset_del(&mapp->dam_report_set, i);
1494                         }
1495                 } else {
1496                         DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1497                             char *, mapp->dam_name, dam_t *, mapp);
1498 
1499                         /*
1500                          * Avoid waiting the entire stabalization
1501                          * time again if taskq_diskpatch fails.
1502                          */
1503                         tpend++;
1504                         delta_ticks = drv_usectohz(
1505                             damap_taskq_dispatch_retry_usec);
1506                         if (delta_ticks < next_ticks)
1507                                 next_ticks = delta_ticks;
1508                 }
1509         }
1510 
1511         /*
1512          * reschedule the stabilization timer if there are reports
1513          * still pending
1514          */
1515         if (tpend) {
1516                 DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1517                     mapp->dam_name, dam_t *, mapp);
1518                 dam_sched_timeout(dam_addr_stable_cb, mapp,
1519                     (clock_t)next_ticks);
1520         }
1521 
1522         mutex_exit(&mapp->dam_lock);
1523 }
1524 
1525 /*
1526  * fullset stabilization timeout callback
1527  */
1528 static void
1529 dam_addrset_stable_cb(void *arg)
1530 {
1531         dam_t *mapp = (dam_t *)arg;
1532 
1533         mutex_enter(&mapp->dam_lock);
1534         if (mapp->dam_tid == 0) {
1535                 mutex_exit(&mapp->dam_lock);
1536                 DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1537                     char *, mapp->dam_name, dam_t *, mapp);
1538                 return;
1539         }
1540         mapp->dam_tid = 0;
1541 
1542         /*
1543          * If map still underoing stabilization reschedule timeout,
1544          * else dispatch the task to configure the new stable set of
1545          * addresses.
1546          */
1547         if ((mapp->dam_flags & DAM_SPEND) ||
1548             (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1549             TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1550                 DAM_INCR_STAT(mapp, dam_overrun);
1551                 mapp->dam_stable_overrun++;
1552                 dam_sched_timeout(dam_addrset_stable_cb, mapp,
1553                     drv_usectohz(damap_taskq_dispatch_retry_usec));
1554 
1555                 DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1556                     char *, mapp->dam_name, dam_t *, mapp);
1557                 mutex_exit(&mapp->dam_lock);
1558                 return;
1559         }
1560 
1561         DAM_SET_STAT(mapp, dam_overrun, 0);
1562         mapp->dam_stable_overrun = 0;
1563         bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1564         bitset_zero(&mapp->dam_report_set);
1565         mapp->dam_flags |= DAM_SPEND;
1566         mapp->dam_flags &= ~DAM_SETADD;
1567         /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1568 
1569         DTRACE_PROBE2(damap__map__addrset__stable__start,
1570             char *, mapp->dam_name, dam_t *, mapp);
1571         mutex_exit(&mapp->dam_lock);
1572 }
1573 
1574 /*
1575  * schedule map timeout in 'ticks' ticks
1576  * if map timer is currently running, cancel if ticks == 0
1577  */
1578 static void
1579 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1580 {
1581         timeout_id_t tid;
1582 
1583         DTRACE_PROBE4(damap__sched__timeout,
1584             char *, mapp->dam_name, dam_t *, mapp,
1585             int, ticks, timeout_id_t, mapp->dam_tid);
1586 
1587         ASSERT(mutex_owned(&mapp->dam_lock));
1588         if ((tid = mapp->dam_tid) != 0) {
1589                 if (ticks == 0) {
1590                         mapp->dam_tid = 0;
1591                         mutex_exit(&mapp->dam_lock);
1592                         (void) untimeout(tid);
1593                         mutex_enter(&mapp->dam_lock);
1594                 }
1595         } else {
1596                 if (timeout_cb && (ticks != 0))
1597                         mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1598         }
1599 }
1600 
1601 /*
1602  * report addition or removal of an address
1603  */
1604 static void
1605 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1606 {
1607         char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1608 
1609         DTRACE_PROBE4(damap__addr__report,
1610             char *, mapp->dam_name, dam_t *, mapp,
1611             char *, addrstr, int, rpt_type);
1612 
1613         ASSERT(mutex_owned(&mapp->dam_lock));
1614         ASSERT(!DAM_IN_REPORT(mapp, addrid));
1615         passp->da_last_report = gethrtime();
1616         mapp->dam_last_update = gethrtime();
1617         passp->da_report_cnt++;
1618         passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1619         if (rpt_type == RPT_ADDR_DEL)
1620                 passp->da_flags |= DA_RELE;
1621         else if (rpt_type == RPT_ADDR_ADD)
1622                 passp->da_flags &= ~DA_RELE;
1623         bitset_add(&mapp->dam_report_set, addrid);
1624         dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1625 }
1626 
1627 /*
1628  * release an address report
1629  */
1630 static void
1631 dam_addr_report_release(dam_t *mapp, id_t addrid)
1632 {
1633         dam_da_t *passp;
1634         char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1635 
1636         DTRACE_PROBE3(damap__addr__report__release,
1637             char *, mapp->dam_name, dam_t *, mapp,
1638             char *, addrstr);
1639 
1640         ASSERT(mutex_owned(&mapp->dam_lock));
1641         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1642         ASSERT(passp);
1643         /*
1644          * clear the report bit
1645          * if the address has a registered deactivation handler and
1646          * we are holding a private data pointer and the address has not
1647          * stabilized, deactivate the address (private data).
1648          */
1649         bitset_del(&mapp->dam_report_set, addrid);
1650         if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1651             passp->da_ppriv_rpt) {
1652                 mutex_exit(&mapp->dam_lock);
1653                 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1654                     ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1655                     addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1656                 mutex_enter(&mapp->dam_lock);
1657         }
1658         passp->da_ppriv_rpt = NULL;
1659         nvlist_free(passp->da_nvl_rpt);
1660 }
1661 
1662 /*
1663  * return the map ID of an address
1664  */
1665 static id_t
1666 dam_get_addrid(dam_t *mapp, char *address)
1667 {
1668         damap_id_t addrid;
1669         dam_da_t *passp;
1670 
1671         ASSERT(mutex_owned(&mapp->dam_lock));
1672         if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1673                 if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1674                     address)) == (damap_id_t)0) {
1675                         return (0);
1676                 }
1677                 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1678                     DDI_SUCCESS) {
1679                         ddi_strid_free(mapp->dam_addr_hash, addrid);
1680                         return (0);
1681                 }
1682 
1683                 if (addrid >= mapp->dam_high)
1684                         mapp->dam_high = addrid + 1;
1685 
1686                 /*
1687                  * expand bitmaps if ID has outgrown old map size
1688                  */
1689                 if (mapp->dam_high > mapp->dam_size) {
1690                         mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1691                         bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1692                         bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1693                         bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1694                 }
1695 
1696                 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1697                 passp->da_ref = 1;
1698                 passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1699                     addrid); /* for mdb */
1700         }
1701         return (addrid);
1702 }
1703 
1704 /*
1705  * create and install map statistics
1706  */
1707 static int
1708 dam_kstat_create(dam_t *mapp)
1709 {
1710         kstat_t                 *mapsp;
1711         struct dam_kstats       *statsp;
1712 
1713         mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1714             KSTAT_TYPE_NAMED,
1715             sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1716 
1717         if (mapsp == NULL)
1718                 return (DDI_FAILURE);
1719 
1720         statsp = (struct dam_kstats *)mapsp->ks_data;
1721         kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1722         kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1723         kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1724         kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1725         kstat_install(mapsp);
1726         mapp->dam_kstatsp = mapsp;
1727         return (DDI_SUCCESS);
1728 }