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