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