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