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