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