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