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