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         if (passp->da_nvl)
1114                 nvlist_free(passp->da_nvl);
1115         passp->da_nvl = NULL;
1116         passp->da_ppriv_rpt = NULL;
1117         if (passp->da_nvl_rpt)
1118                 nvlist_free(passp->da_nvl_rpt);
1119         passp->da_nvl_rpt = NULL;
1120 
1121         DTRACE_PROBE3(damap__addr__deactivate__end,
1122             char *, mapp->dam_name, dam_t *, mapp,
1123             char *, addrstr);
1124 
1125         (void) dam_addr_release(mapp, addrid);
1126         mutex_exit(&mapp->dam_lock);
1127 }
1128 
1129 /*
1130  * taskq callback for multi-thread activation
1131  */
1132 static void
1133 dam_tq_config(void *arg)
1134 {
1135         cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1136 
1137         dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1138         kmem_free(tqd, sizeof (*tqd));
1139 }
1140 
1141 /*
1142  * taskq callback for multi-thread deactivation
1143  */
1144 static void
1145 dam_tq_unconfig(void *arg)
1146 {
1147         cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1148 
1149         dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1150         kmem_free(tqd, sizeof (*tqd));
1151 }
1152 
1153 /*
1154  * Activate a set of stabilized addresses
1155  */
1156 static void
1157 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1158 {
1159 
1160         int i, nset;
1161         taskq_t *tqp = NULL;
1162         cfg_tqd_t *tqd = NULL;
1163         char tqn[TASKQ_NAMELEN];
1164         extern pri_t maxclsyspri;
1165 
1166         if (mapp->dam_options & DAMAP_MTCONFIG) {
1167                 /*
1168                  * calculate the # of taskq threads to create
1169                  */
1170                 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1171                         if (bitset_in_set(activate, i))
1172                                 nset++;
1173                 ASSERT(nset);
1174                 (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1175                 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1176                     INT_MAX, TASKQ_PREPOPULATE);
1177         }
1178         for (i = 1; i < mapp->dam_high; i++) {
1179                 if (bitset_in_set(activate, i)) {
1180                         if (!tqp)
1181                                 dam_addr_activate(mapp, i);
1182                         else {
1183                                 /*
1184                                  * multi-threaded activation
1185                                  */
1186                                 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1187                                 tqd->tqd_mapp = mapp;
1188                                 tqd->tqd_id = i;
1189                                 (void) taskq_dispatch(tqp, dam_tq_config,
1190                                     tqd, TQ_SLEEP);
1191                         }
1192                 }
1193         }
1194         if (tqp) {
1195                 taskq_wait(tqp);
1196                 taskq_destroy(tqp);
1197         }
1198 }
1199 
1200 /*
1201  * Deactivate a set of stabilized addresses
1202  */
1203 static void
1204 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1205 {
1206         int i, nset;
1207         taskq_t *tqp = NULL;
1208         cfg_tqd_t *tqd = NULL;
1209         char tqn[TASKQ_NAMELEN];
1210 
1211         DTRACE_PROBE2(damap__addrset__deactivate,
1212             char *, mapp->dam_name, dam_t *, mapp);
1213 
1214         if (mapp->dam_options & DAMAP_MTCONFIG) {
1215                 /*
1216                  * compute the # of taskq threads to dispatch
1217                  */
1218                 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1219                         if (bitset_in_set(deactivate, i))
1220                                 nset++;
1221                 (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1222                     mapp->dam_name);
1223                 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1224                     INT_MAX, TASKQ_PREPOPULATE);
1225         }
1226         for (i = 1; i < mapp->dam_high; i++) {
1227                 if (bitset_in_set(deactivate, i)) {
1228                         if (!tqp) {
1229                                 dam_addr_deactivate(mapp, i);
1230                         } else {
1231                                 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1232                                 tqd->tqd_mapp = mapp;
1233                                 tqd->tqd_id = i;
1234                                 (void) taskq_dispatch(tqp,
1235                                     dam_tq_unconfig, tqd, TQ_SLEEP);
1236                         }
1237                 }
1238         }
1239 
1240         if (tqp) {
1241                 taskq_wait(tqp);
1242                 taskq_destroy(tqp);
1243         }
1244 }
1245 
1246 /*
1247  * Release a previously activated address
1248  */
1249 static void
1250 dam_addr_release(dam_t *mapp, id_t addrid)
1251 {
1252         dam_da_t *passp;
1253         char     *addrstr;
1254 
1255 
1256         ASSERT(mutex_owned(&mapp->dam_lock));
1257         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1258         ASSERT(passp);
1259 
1260         addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1261         DTRACE_PROBE3(damap__addr__release,
1262             char *, mapp->dam_name, dam_t *, mapp,
1263             char *, addrstr);
1264 
1265         /*
1266          * defer releasing the address until outstanding references
1267          * are released
1268          */
1269         if (passp->da_ref > 1) {
1270                 DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1271                     char *, mapp->dam_name, dam_t *, mapp,
1272                     char *, addrstr, int, passp->da_ref);
1273                 return;
1274         }
1275 
1276         /*
1277          * allow pending reports to stabilize
1278          */
1279         if (DAM_IN_REPORT(mapp, addrid)) {
1280                 DTRACE_PROBE3(damap__addr__release__report__pending,
1281                     char *, mapp->dam_name, dam_t *, mapp,
1282                     char *, addrstr);
1283                 return;
1284         }
1285 
1286         ddi_strid_free(mapp->dam_addr_hash, addrid);
1287         ddi_soft_state_free(mapp->dam_da, addrid);
1288 }
1289 
1290 /*
1291  * process stabilized address reports
1292  */
1293 static void
1294 dam_stabilize_map(void *arg)
1295 {
1296         dam_t *mapp = (dam_t *)arg;
1297         bitset_t delta;
1298         bitset_t cfg;
1299         bitset_t uncfg;
1300         int has_cfg, has_uncfg;
1301         uint32_t i, n_active;
1302 
1303         DTRACE_PROBE2(damap__stabilize__map,
1304             char *, mapp->dam_name, dam_t *, mapp);
1305 
1306         bitset_init(&delta);
1307         bitset_resize(&delta, mapp->dam_size);
1308         bitset_init(&cfg);
1309         bitset_resize(&cfg, mapp->dam_size);
1310         bitset_init(&uncfg);
1311         bitset_resize(&uncfg, mapp->dam_size);
1312 
1313         /*
1314          * determine which addresses have changed during
1315          * this stabilization cycle
1316          */
1317         mutex_enter(&mapp->dam_lock);
1318         ASSERT(mapp->dam_flags & DAM_SPEND);
1319         if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1320             &delta)) {
1321                 /*
1322                  * no difference
1323                  */
1324                 bitset_zero(&mapp->dam_stable_set);
1325                 mapp->dam_flags &= ~DAM_SPEND;
1326                 cv_signal(&mapp->dam_sync_cv);
1327                 mutex_exit(&mapp->dam_lock);
1328 
1329                 bitset_fini(&uncfg);
1330                 bitset_fini(&cfg);
1331                 bitset_fini(&delta);
1332                 DTRACE_PROBE2(damap__stabilize__map__nochange,
1333                     char *, mapp->dam_name, dam_t *, mapp);
1334                 return;
1335         }
1336 
1337         /*
1338          * compute the sets of addresses to be activated and deactivated
1339          */
1340         has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1341         has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1342 
1343         /*
1344          * drop map lock while invoking callouts
1345          */
1346         mutex_exit(&mapp->dam_lock);
1347 
1348         /*
1349          * activate all newly stable addresss
1350          */
1351         if (has_cfg)
1352                 dam_addrset_activate(mapp, &cfg);
1353 
1354         /*
1355          * deactivate addresss which are no longer in the map
1356          */
1357         if (has_uncfg)
1358                 dam_addrset_deactivate(mapp, &uncfg);
1359 
1360 
1361         /*
1362          * timestamp the last stable time and increment the kstat keeping
1363          * the # of of stable cycles for the map
1364          */
1365         mutex_enter(&mapp->dam_lock);
1366         bitset_zero(&mapp->dam_stable_set);
1367         mapp->dam_last_stable = gethrtime();
1368         mapp->dam_stable_cnt++;
1369         DAM_INCR_STAT(mapp, dam_cycles);
1370 
1371         /*
1372          * determine the number of stable addresses
1373          * and update the n_active kstat for this map
1374          */
1375         for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1376                 if (bitset_in_set(&mapp->dam_active_set, i))
1377                         n_active++;
1378         DAM_SET_STAT(mapp, dam_active, n_active);
1379 
1380         DTRACE_PROBE3(damap__map__stable__end,
1381             char *, mapp->dam_name, dam_t *, mapp,
1382             int, n_active);
1383 
1384         mapp->dam_flags &= ~DAM_SPEND;
1385         cv_signal(&mapp->dam_sync_cv);
1386         mutex_exit(&mapp->dam_lock);
1387 
1388         bitset_fini(&uncfg);
1389         bitset_fini(&cfg);
1390         bitset_fini(&delta);
1391 }
1392 
1393 /*
1394  * per-address stabilization timeout
1395  */
1396 static void
1397 dam_addr_stable_cb(void *arg)
1398 {
1399         dam_t *mapp = (dam_t *)arg;
1400         int i;
1401         dam_da_t *passp;
1402         int spend = 0;
1403         int tpend = 0;
1404         int64_t ts, next_ticks, delta_ticks;
1405 
1406         mutex_enter(&mapp->dam_lock);
1407         if (mapp->dam_tid == 0) {
1408                 DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1409                     char *, mapp->dam_name, dam_t *, mapp);
1410                 mutex_exit(&mapp->dam_lock);
1411                 return;
1412         }
1413         mapp->dam_tid = 0;
1414 
1415         /*
1416          * If still under stabilization, reschedule timeout,
1417          * otherwise dispatch the task to activate and deactivate the
1418          * new stable address
1419          */
1420         if (mapp->dam_flags & DAM_SPEND) {
1421                 DAM_INCR_STAT(mapp, dam_overrun);
1422                 mapp->dam_stable_overrun++;
1423                 DTRACE_PROBE2(damap__map__addr__stable__overrun,
1424                     char *, mapp->dam_name, dam_t *, mapp);
1425                 dam_sched_timeout(dam_addr_stable_cb, mapp,
1426                     mapp->dam_stable_ticks);
1427                 mutex_exit(&mapp->dam_lock);
1428                 return;
1429         }
1430 
1431         DAM_SET_STAT(mapp, dam_overrun, 0);
1432         mapp->dam_stable_overrun = 0;
1433 
1434         /* See if any reports stabalized and compute next timeout. */
1435         ts = ddi_get_lbolt64();
1436         next_ticks = mapp->dam_stable_ticks;
1437         for (i = 1; i < mapp->dam_high; i++) {
1438                 if (bitset_in_set(&mapp->dam_report_set, i)) {
1439                         passp = ddi_get_soft_state(mapp->dam_da, i);
1440                         ASSERT(passp);
1441 
1442                         if (passp->da_deadline <= ts)
1443                                 spend++;        /* report has stabilized */
1444                         else {
1445                                 /* not stabilized, determine next map timeout */
1446                                 tpend++;
1447                                 delta_ticks = passp->da_deadline - ts;
1448                                 if (delta_ticks < next_ticks)
1449                                         next_ticks = delta_ticks;
1450                         }
1451                 }
1452         }
1453 
1454         /*
1455          * schedule system_taskq activation of stabilized reports
1456          */
1457         if (spend) {
1458                 if (taskq_dispatch(system_taskq, dam_stabilize_map,
1459                     mapp, TQ_NOSLEEP | TQ_NOQUEUE)) {
1460                         DTRACE_PROBE2(damap__map__addr__stable__start,
1461                             char *, mapp->dam_name, dam_t *, mapp);
1462 
1463                         /*
1464                          * The stable_set we compute below stays pending until
1465                          * processed by dam_stabilize_map. We can't set
1466                          * DAM_SPEND (or bitset_del things from the
1467                          * report_set) until we *know* that we can handoff the
1468                          * result to dam_stabilize_map. If dam_stabilize_map
1469                          * starts executing before we are complete, it will
1470                          * block on the dam_lock mutex until we are ready.
1471                          */
1472                         mapp->dam_flags |= DAM_SPEND;
1473 
1474                         /*
1475                          * Copy the current active_set to the stable_set, then
1476                          * add or remove stabilized report_set address from
1477                          * the stable set (and delete them from the report_set).
1478                          */
1479                         bitset_copy(&mapp->dam_active_set,
1480                             &mapp->dam_stable_set);
1481                         for (i = 1; i < mapp->dam_high; i++) {
1482                                 if (!bitset_in_set(&mapp->dam_report_set, i))
1483                                         continue;
1484 
1485                                 passp = ddi_get_soft_state(mapp->dam_da, i);
1486                                 if (passp->da_deadline > ts)
1487                                         continue; /* report not stabilized */
1488 
1489                                 /* report has stabilized */
1490                                 if (passp->da_flags & DA_RELE)
1491                                         bitset_del(&mapp->dam_stable_set, i);
1492                                 else
1493                                         bitset_add(&mapp->dam_stable_set, i);
1494 
1495                                 bitset_del(&mapp->dam_report_set, i);
1496                         }
1497                 } else {
1498                         DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1499                             char *, mapp->dam_name, dam_t *, mapp);
1500 
1501                         /*
1502                          * Avoid waiting the entire stabalization
1503                          * time again if taskq_diskpatch fails.
1504                          */
1505                         tpend++;
1506                         delta_ticks = drv_usectohz(
1507                             damap_taskq_dispatch_retry_usec);
1508                         if (delta_ticks < next_ticks)
1509                                 next_ticks = delta_ticks;
1510                 }
1511         }
1512 
1513         /*
1514          * reschedule the stabilization timer if there are reports
1515          * still pending
1516          */
1517         if (tpend) {
1518                 DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1519                     mapp->dam_name, dam_t *, mapp);
1520                 dam_sched_timeout(dam_addr_stable_cb, mapp,
1521                     (clock_t)next_ticks);
1522         }
1523 
1524         mutex_exit(&mapp->dam_lock);
1525 }
1526 
1527 /*
1528  * fullset stabilization timeout callback
1529  */
1530 static void
1531 dam_addrset_stable_cb(void *arg)
1532 {
1533         dam_t *mapp = (dam_t *)arg;
1534 
1535         mutex_enter(&mapp->dam_lock);
1536         if (mapp->dam_tid == 0) {
1537                 mutex_exit(&mapp->dam_lock);
1538                 DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1539                     char *, mapp->dam_name, dam_t *, mapp);
1540                 return;
1541         }
1542         mapp->dam_tid = 0;
1543 
1544         /*
1545          * If map still underoing stabilization reschedule timeout,
1546          * else dispatch the task to configure the new stable set of
1547          * addresses.
1548          */
1549         if ((mapp->dam_flags & DAM_SPEND) ||
1550             (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1551             TQ_NOSLEEP | TQ_NOQUEUE) == NULL)) {
1552                 DAM_INCR_STAT(mapp, dam_overrun);
1553                 mapp->dam_stable_overrun++;
1554                 dam_sched_timeout(dam_addrset_stable_cb, mapp,
1555                     drv_usectohz(damap_taskq_dispatch_retry_usec));
1556 
1557                 DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1558                     char *, mapp->dam_name, dam_t *, mapp);
1559                 mutex_exit(&mapp->dam_lock);
1560                 return;
1561         }
1562 
1563         DAM_SET_STAT(mapp, dam_overrun, 0);
1564         mapp->dam_stable_overrun = 0;
1565         bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1566         bitset_zero(&mapp->dam_report_set);
1567         mapp->dam_flags |= DAM_SPEND;
1568         mapp->dam_flags &= ~DAM_SETADD;
1569         /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1570 
1571         DTRACE_PROBE2(damap__map__addrset__stable__start,
1572             char *, mapp->dam_name, dam_t *, mapp);
1573         mutex_exit(&mapp->dam_lock);
1574 }
1575 
1576 /*
1577  * schedule map timeout in 'ticks' ticks
1578  * if map timer is currently running, cancel if ticks == 0
1579  */
1580 static void
1581 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1582 {
1583         timeout_id_t tid;
1584 
1585         DTRACE_PROBE4(damap__sched__timeout,
1586             char *, mapp->dam_name, dam_t *, mapp,
1587             int, ticks, timeout_id_t, mapp->dam_tid);
1588 
1589         ASSERT(mutex_owned(&mapp->dam_lock));
1590         if ((tid = mapp->dam_tid) != 0) {
1591                 if (ticks == 0) {
1592                         mapp->dam_tid = 0;
1593                         mutex_exit(&mapp->dam_lock);
1594                         (void) untimeout(tid);
1595                         mutex_enter(&mapp->dam_lock);
1596                 }
1597         } else {
1598                 if (timeout_cb && (ticks != 0))
1599                         mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1600         }
1601 }
1602 
1603 /*
1604  * report addition or removal of an address
1605  */
1606 static void
1607 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1608 {
1609         char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1610 
1611         DTRACE_PROBE4(damap__addr__report,
1612             char *, mapp->dam_name, dam_t *, mapp,
1613             char *, addrstr, int, rpt_type);
1614 
1615         ASSERT(mutex_owned(&mapp->dam_lock));
1616         ASSERT(!DAM_IN_REPORT(mapp, addrid));
1617         passp->da_last_report = gethrtime();
1618         mapp->dam_last_update = gethrtime();
1619         passp->da_report_cnt++;
1620         passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1621         if (rpt_type == RPT_ADDR_DEL)
1622                 passp->da_flags |= DA_RELE;
1623         else if (rpt_type == RPT_ADDR_ADD)
1624                 passp->da_flags &= ~DA_RELE;
1625         bitset_add(&mapp->dam_report_set, addrid);
1626         dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1627 }
1628 
1629 /*
1630  * release an address report
1631  */
1632 static void
1633 dam_addr_report_release(dam_t *mapp, id_t addrid)
1634 {
1635         dam_da_t *passp;
1636         char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1637 
1638         DTRACE_PROBE3(damap__addr__report__release,
1639             char *, mapp->dam_name, dam_t *, mapp,
1640             char *, addrstr);
1641 
1642         ASSERT(mutex_owned(&mapp->dam_lock));
1643         passp = ddi_get_soft_state(mapp->dam_da, addrid);
1644         ASSERT(passp);
1645         /*
1646          * clear the report bit
1647          * if the address has a registered deactivation handler and
1648          * we are holding a private data pointer and the address has not
1649          * stabilized, deactivate the address (private data).
1650          */
1651         bitset_del(&mapp->dam_report_set, addrid);
1652         if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1653             passp->da_ppriv_rpt) {
1654                 mutex_exit(&mapp->dam_lock);
1655                 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1656                     ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1657                     addrid, passp->da_ppriv_rpt, DAMAP_DEACT_RSN_UNSTBL);
1658                 mutex_enter(&mapp->dam_lock);
1659         }
1660         passp->da_ppriv_rpt = NULL;
1661         if (passp->da_nvl_rpt)
1662                 nvlist_free(passp->da_nvl_rpt);
1663 }
1664 
1665 /*
1666  * return the map ID of an address
1667  */
1668 static id_t
1669 dam_get_addrid(dam_t *mapp, char *address)
1670 {
1671         damap_id_t addrid;
1672         dam_da_t *passp;
1673 
1674         ASSERT(mutex_owned(&mapp->dam_lock));
1675         if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1676                 if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1677                     address)) == (damap_id_t)0) {
1678                         return (0);
1679                 }
1680                 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1681                     DDI_SUCCESS) {
1682                         ddi_strid_free(mapp->dam_addr_hash, addrid);
1683                         return (0);
1684                 }
1685 
1686                 if (addrid >= mapp->dam_high)
1687                         mapp->dam_high = addrid + 1;
1688 
1689                 /*
1690                  * expand bitmaps if ID has outgrown old map size
1691                  */
1692                 if (mapp->dam_high > mapp->dam_size) {
1693                         mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1694                         bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1695                         bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1696                         bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1697                 }
1698 
1699                 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1700                 passp->da_ref = 1;
1701                 passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1702                     addrid); /* for mdb */
1703         }
1704         return (addrid);
1705 }
1706 
1707 /*
1708  * create and install map statistics
1709  */
1710 static int
1711 dam_kstat_create(dam_t *mapp)
1712 {
1713         kstat_t                 *mapsp;
1714         struct dam_kstats       *statsp;
1715 
1716         mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1717             KSTAT_TYPE_NAMED,
1718             sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1719 
1720         if (mapsp == NULL)
1721                 return (DDI_FAILURE);
1722 
1723         statsp = (struct dam_kstats *)mapsp->ks_data;
1724         kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1725         kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1726         kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1727         kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1728         kstat_install(mapsp);
1729         mapp->dam_kstatsp = mapsp;
1730         return (DDI_SUCCESS);
1731 }