1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/note.h> 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/buf.h> 32 #include <sys/kmem.h> 33 #include <sys/cmn_err.h> 34 #include <sys/debug.h> 35 #include <sys/sunndi.h> 36 #include <sys/kstat.h> 37 #include <sys/conf.h> 38 #include <sys/ddi_timer.h> 39 #include <sys/devctl.h> 40 #include <sys/callb.h> 41 #include <sys/sysevent.h> 42 #include <sys/taskq.h> 43 #include <sys/ddi.h> 44 #include <sys/bitset.h> 45 #include <sys/damap.h> 46 #include <sys/damap_impl.h> 47 48 #ifdef DEBUG 49 static int damap_debug = 0; 50 #endif /* DEBUG */ 51 52 static void dam_addrset_activate(dam_t *, bitset_t *); 53 static void dam_addrset_release(dam_t *, bitset_t *); 54 static void dam_activate_taskq(void *); 55 static void dam_addr_stable_cb(void *); 56 static void dam_set_stable_cb(void *); 57 static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)()); 58 static void dam_add_report(dam_t *, dam_da_t *, id_t, int); 59 static void dam_release(dam_t *, id_t); 60 static void dam_release_report(dam_t *, id_t); 61 static void dam_deactivate_addr(dam_t *, id_t); 62 static id_t dam_get_addrid(dam_t *, char *); 63 static int dam_kstat_create(dam_t *); 64 static void dam_kstat_destroy(dam_t *); 65 66 #define DAM_INCR_STAT(mapp, stat) \ 67 if ((mapp)->dam_kstatsp) { \ 68 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 69 stp->stat.value.ui32++; \ 70 } 71 72 #define DAM_SET_STAT(mapp, stat, val) \ 73 if ((mapp)->dam_kstatsp) { \ 74 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \ 75 stp->stat.value.ui32 = (val); \ 76 } 77 78 /* 79 * Create new device address map 80 * 81 * ident: map name (kstat) 82 * size: max # of map entries 83 * rptmode: type or mode of reporting 84 * stable_usec: # of quiescent microseconds before report/map is stable 85 * 86 * activate_arg: address provider activation-callout private 87 * activate_cb: address provider activation callback handler 88 * deactivate_cb: address provider deactivation callback handler 89 * 90 * config_arg: configuration-callout private 91 * config_cb: class configuration callout 92 * unconfig_cb: class unconfiguration callout 93 * 94 * damapp: pointer to map handle (return) 95 * 96 * Returns: DAM_SUCCESS 97 * DAM_EINVAL Invalid argument(s) 98 * DAM_FAILURE General failure 99 */ 100 int 101 damap_create(char *ident, size_t size, damap_rptmode_t rptmode, 102 clock_t stable_usec, 103 void *activate_arg, damap_activate_cb_t activate_cb, 104 damap_deactivate_cb_t deactivate_cb, 105 void *config_arg, damap_configure_cb_t configure_cb, 106 damap_unconfig_cb_t unconfig_cb, 107 damap_t **damapp) 108 { 109 dam_t *mapp; 110 void *softstate_p; 111 112 DTRACE_PROBE1(damap__create__entry, char *, ident); 113 if ((configure_cb == NULL) || (unconfig_cb == NULL)) 114 return (DAM_EINVAL); 115 116 if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) != 117 DDI_SUCCESS) 118 return (DAM_FAILURE); 119 120 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP); 121 if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) { 122 ddi_soft_state_fini(&softstate_p); 123 kmem_free(mapp, sizeof (*mapp)); 124 return (DAM_FAILURE); 125 } 126 127 mapp->dam_da = softstate_p; 128 mapp->dam_stabletmo = drv_usectohz(stable_usec); 129 mapp->dam_size = size; 130 mapp->dam_high = 1; 131 mapp->dam_rptmode = rptmode; 132 133 mapp->dam_activate_arg = activate_arg; 134 mapp->dam_activate_cb = (activate_cb_t)activate_cb; 135 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb; 136 137 mapp->dam_config_arg = config_arg; 138 mapp->dam_configure_cb = (configure_cb_t)configure_cb; 139 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb; 140 141 if (ident) 142 mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP); 143 144 bitset_init(&mapp->dam_active_set); 145 bitset_resize(&mapp->dam_active_set, size); 146 bitset_init(&mapp->dam_stable_set); 147 bitset_resize(&mapp->dam_stable_set, size); 148 bitset_init(&mapp->dam_report_set); 149 bitset_resize(&mapp->dam_report_set, size); 150 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL); 151 cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL); 152 mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI, 153 0); 154 *damapp = (damap_t *)mapp; 155 if (dam_kstat_create(mapp) != DDI_SUCCESS) { 156 damap_destroy((damap_t *)mapp); 157 return (DAM_FAILURE); 158 } 159 160 DTRACE_PROBE1(damap__create__exit, dam_t *, mapp); 161 return (DAM_SUCCESS); 162 } 163 164 /* 165 * Destroy device address map 166 * 167 * damapp: address map 168 * 169 * Returns: DAM_SUCCESS 170 * DAM_EINVAL Invalid argument(s) 171 * DAM_FAILURE General failure 172 */ 173 void 174 damap_destroy(damap_t *damapp) 175 { 176 int i; 177 dam_t *mapp = (dam_t *)damapp; 178 179 ASSERT(mapp); 180 181 DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *, 182 mapp->dam_name); 183 184 DAM_FLAG_SET(mapp, DAM_DESTROYPEND); 185 (void) damap_sync(damapp); 186 187 /* 188 * cancel pending timeouts and kill off the taskq 189 */ 190 dam_sched_tmo(mapp, 0, NULL); 191 ddi_taskq_wait(mapp->dam_taskqp); 192 ddi_taskq_destroy(mapp->dam_taskqp); 193 194 for (i = 1; i < mapp->dam_high; i++) { 195 if (ddi_get_soft_state(mapp->dam_da, i) == NULL) 196 continue; 197 if (DAM_IN_REPORT(mapp, i)) 198 dam_release_report(mapp, i); 199 if (DAM_IS_STABLE(mapp, i)) 200 dam_deactivate_addr(mapp, i); 201 ddi_strid_free(mapp->dam_addr_hash, i); 202 ddi_soft_state_free(mapp->dam_da, i); 203 } 204 ddi_strid_fini(&mapp->dam_addr_hash); 205 ddi_soft_state_fini(&mapp->dam_da); 206 bitset_fini(&mapp->dam_active_set); 207 bitset_fini(&mapp->dam_stable_set); 208 bitset_fini(&mapp->dam_report_set); 209 dam_kstat_destroy(mapp); 210 mutex_destroy(&mapp->dam_lock); 211 cv_destroy(&mapp->dam_cv); 212 if (mapp->dam_name) 213 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1); 214 kmem_free(mapp, sizeof (*mapp)); 215 DTRACE_PROBE(damap__destroy__exit); 216 } 217 218 /* 219 * Wait for map stability. 220 * 221 * damapp: address map 222 */ 223 int 224 damap_sync(damap_t *damapp) 225 { 226 227 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK) 228 229 dam_t *mapp = (dam_t *)damapp; 230 int none_active; 231 232 ASSERT(mapp); 233 234 DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp); 235 236 mutex_enter(&mapp->dam_lock); 237 while ((mapp->dam_flags & WAITFOR_FLAGS) || 238 (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) { 239 cv_wait(&mapp->dam_cv, &mapp->dam_lock); 240 } 241 242 none_active = bitset_is_null(&mapp->dam_active_set); 243 244 mutex_exit(&mapp->dam_lock); 245 DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active); 246 247 return (none_active); 248 } 249 250 /* 251 * Get the name of a device address map 252 * 253 * damapp: address map 254 * 255 * Returns: name 256 */ 257 char * 258 damap_name(damap_t *damapp) 259 { 260 dam_t *mapp = (dam_t *)damapp; 261 262 return (mapp ? mapp->dam_name : "UNKNOWN_damap"); 263 } 264 265 /* 266 * Report an address to per-address report 267 * 268 * damapp: address map handle 269 * address: address in ascii string representation 270 * rindx: index if address stabilizes 271 * nvl: optional nvlist of configuration-private data 272 * addr_priv: optional provider-private (passed to activate/deactivate cb) 273 * 274 * Returns: DAM_SUCCESS 275 * DAM_EINVAL Invalid argument(s) 276 * DAM_MAPFULL address map exhausted 277 */ 278 int 279 damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl, 280 void *addr_priv) 281 { 282 dam_t *mapp = (dam_t *)damapp; 283 id_t addrid; 284 dam_da_t *passp; 285 286 DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp, 287 char *, address); 288 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 289 (mapp->dam_flags & DAM_DESTROYPEND)) 290 return (DAM_EINVAL); 291 292 DAM_LOCK(mapp, ADDR_LOCK); 293 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 294 DAM_UNLOCK(mapp, ADDR_LOCK); 295 return (DAM_MAPFULL); 296 } 297 298 passp = ddi_get_soft_state(mapp->dam_da, addrid); 299 ASSERT(passp != NULL); 300 301 /* 302 * If re-reporting the same address (add or remove) clear 303 * the existing report 304 */ 305 if (DAM_IN_REPORT(mapp, addrid)) { 306 DAM_INCR_STAT(mapp, dam_rereport); 307 dam_release_report(mapp, addrid); 308 passp->da_jitter++; 309 } 310 passp->da_ppriv_rpt = addr_priv; 311 if (nvl) 312 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 313 314 dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD); 315 if (ridx != NULL) 316 *ridx = (damap_id_t)addrid; 317 DAM_UNLOCK(mapp, ADDR_LOCK); 318 DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *, 319 address, int, addrid); 320 return (DAM_SUCCESS); 321 } 322 323 /* 324 * Report removal of address from per-address report 325 * 326 * damapp: address map 327 * address: address in ascii string representation 328 * 329 * Returns: DAM_SUCCESS 330 * DAM_EINVAL Invalid argument(s) 331 * DAM_FAILURE General failure 332 */ 333 int 334 damap_addr_del(damap_t *damapp, char *address) 335 { 336 dam_t *mapp = (dam_t *)damapp; 337 id_t addrid; 338 dam_da_t *passp; 339 340 DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp, 341 char *, address); 342 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) || 343 (mapp->dam_flags & DAM_DESTROYPEND)) 344 return (DAM_EINVAL); 345 346 DAM_LOCK(mapp, ADDR_LOCK); 347 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) { 348 DAM_UNLOCK(mapp, ADDR_LOCK); 349 return (DAM_SUCCESS); 350 } 351 passp = ddi_get_soft_state(mapp->dam_da, addrid); 352 ASSERT(passp); 353 if (DAM_IN_REPORT(mapp, addrid)) { 354 DAM_INCR_STAT(mapp, dam_rereport); 355 dam_release_report(mapp, addrid); 356 passp->da_jitter++; 357 } 358 dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL); 359 DAM_UNLOCK(mapp, ADDR_LOCK); 360 DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp, 361 char *, address, int, addrid); 362 return (DAM_SUCCESS); 363 } 364 365 /* 366 * Initiate full-set report 367 * 368 * damapp: address map 369 * 370 * Returns: DAM_SUCCESS 371 * DAM_EINVAL Invalid argument(s) 372 */ 373 int 374 damap_addrset_begin(damap_t *damapp) 375 { 376 dam_t *mapp = (dam_t *)damapp; 377 int i; 378 379 DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp); 380 381 if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 382 (mapp->dam_flags & DAM_DESTROYPEND)) 383 return (DAM_EINVAL); 384 385 DAM_LOCK(mapp, MAP_LOCK); 386 /* 387 * reset any pending reports 388 */ 389 if (mapp->dam_flags & DAM_SETADD) { 390 /* 391 * cancel stabilization timeout 392 */ 393 dam_sched_tmo(mapp, 0, NULL); 394 DAM_INCR_STAT(mapp, dam_rereport); 395 DAM_UNLOCK(mapp, MAP_LOCK); 396 DAM_LOCK(mapp, ADDR_LOCK); 397 for (i = 1; i < mapp->dam_high; i++) { 398 if (DAM_IN_REPORT(mapp, i)) 399 dam_release_report(mapp, i); 400 } 401 DAM_UNLOCK(mapp, ADDR_LOCK); 402 DAM_LOCK(mapp, MAP_LOCK); 403 } 404 DAM_FLAG_SET(mapp, DAM_SETADD); 405 bitset_zero(&mapp->dam_report_set); 406 DAM_UNLOCK(mapp, MAP_LOCK); 407 DTRACE_PROBE(damap__addrset__begin__exit); 408 return (DAM_SUCCESS); 409 } 410 411 /* 412 * Report address to full-set report 413 * 414 * damapp: address map handle 415 * address: address in ascii string representation 416 * rindx: index if address stabilizes 417 * nvl: optional nvlist of configuration-private data 418 * addr_priv: optional provider-private data (passed to activate/release cb) 419 * 420 * Returns: DAM_SUCCESS 421 * DAM_EINVAL Invalid argument(s) 422 * DAM_MAPFULL address map exhausted 423 * DAM_FAILURE General failure 424 */ 425 int 426 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx, 427 nvlist_t *nvl, void *addr_priv) 428 { 429 dam_t *mapp = (dam_t *)damapp; 430 id_t addrid; 431 dam_da_t *passp; 432 433 DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp, 434 char *, address); 435 436 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 437 (mapp->dam_flags & DAM_DESTROYPEND)) 438 return (DAM_EINVAL); 439 440 if (!(mapp->dam_flags & DAM_SETADD)) 441 return (DAM_FAILURE); 442 443 DAM_LOCK(mapp, ADDR_LOCK); 444 if ((addrid = dam_get_addrid(mapp, address)) == 0) { 445 DAM_UNLOCK(mapp, ADDR_LOCK); 446 return (DAM_MAPFULL); 447 } 448 449 passp = ddi_get_soft_state(mapp->dam_da, addrid); 450 ASSERT(passp); 451 if (DAM_IN_REPORT(mapp, addrid)) { 452 dam_release_report(mapp, addrid); 453 passp->da_jitter++; 454 } 455 passp->da_ppriv_rpt = addr_priv; 456 if (nvl) 457 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP); 458 DAM_LOCK(mapp, MAP_LOCK); 459 bitset_add(&mapp->dam_report_set, addrid); 460 DAM_UNLOCK(mapp, MAP_LOCK); 461 if (ridx) 462 *ridx = (damap_id_t)addrid; 463 DAM_UNLOCK(mapp, ADDR_LOCK); 464 DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *, 465 address, int, addrid); 466 return (DAM_SUCCESS); 467 } 468 469 /* 470 * Commit full-set report for stabilization 471 * 472 * damapp: address map handle 473 * flags: (currently 0) 474 * 475 * Returns: DAM_SUCCESS 476 * DAM_EINVAL Invalid argument(s) 477 * DAM_FAILURE General failure 478 */ 479 int 480 damap_addrset_end(damap_t *damapp, int flags) 481 { 482 dam_t *mapp = (dam_t *)damapp; 483 int i; 484 485 DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp); 486 487 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) || 488 (mapp->dam_flags & DAM_DESTROYPEND)) 489 return (DAM_EINVAL); 490 491 if (!(mapp->dam_flags & DAM_SETADD)) 492 return (DAM_FAILURE); 493 494 if (flags & DAMAP_RESET) { 495 DAM_LOCK(mapp, MAP_LOCK); 496 dam_sched_tmo(mapp, 0, NULL); 497 DAM_UNLOCK(mapp, MAP_LOCK); 498 DAM_LOCK(mapp, ADDR_LOCK); 499 for (i = 1; i < mapp->dam_high; i++) 500 if (DAM_IN_REPORT(mapp, i)) 501 dam_release_report(mapp, i); 502 DAM_UNLOCK(mapp, ADDR_LOCK); 503 } else { 504 mapp->dam_last_update = gethrtime(); 505 DAM_LOCK(mapp, MAP_LOCK); 506 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 507 DAM_UNLOCK(mapp, MAP_LOCK); 508 } 509 DTRACE_PROBE(damap__addrset__end__exit); 510 return (DAM_SUCCESS); 511 } 512 513 /* 514 * Return nvlist registered with reported address 515 * 516 * damapp: address map handle 517 * aid: address ID 518 * 519 * Returns: nvlist_t * provider supplied via damap_addr{set}_add()) 520 * NULL 521 */ 522 nvlist_t * 523 damap_id2nvlist(damap_t *damapp, damap_id_t addrid) 524 { 525 dam_t *mapp = (dam_t *)damapp; 526 id_t aid = (id_t)addrid; 527 dam_da_t *pass; 528 529 if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) { 530 if (pass = ddi_get_soft_state(mapp->dam_da, aid)) 531 return (pass->da_nvl); 532 } 533 return (NULL); 534 } 535 536 /* 537 * Return address string 538 * 539 * damapp: address map handle 540 * aid: address ID 541 * 542 * Returns: char * Address string 543 * NULL 544 */ 545 char * 546 damap_id2addr(damap_t *damapp, damap_id_t aid) 547 { 548 dam_t *mapp = (dam_t *)damapp; 549 550 return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid)); 551 } 552 553 /* 554 * Hold address reference in map 555 * 556 * damapp: address map handle 557 * aid: address ID 558 * 559 * Returns: DAM_SUCCESS 560 * DAM_FAILURE 561 */ 562 int 563 damap_id_hold(damap_t *damapp, damap_id_t aid) 564 { 565 dam_t *mapp = (dam_t *)damapp; 566 dam_da_t *passp; 567 568 569 DAM_LOCK(mapp, ADDR_LOCK); 570 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 571 if (!passp) { 572 DAM_UNLOCK(mapp, ADDR_LOCK); 573 return (DAM_FAILURE); 574 } 575 passp->da_ref++; 576 DAM_UNLOCK(mapp, ADDR_LOCK); 577 return (DAM_SUCCESS); 578 } 579 580 /* 581 * Release address reference in map 582 * 583 * damapp: address map handle 584 * aid: address ID 585 */ 586 void 587 damap_id_rele(damap_t *damapp, damap_id_t addrid) 588 { 589 dam_t *mapp = (dam_t *)damapp; 590 591 DAM_LOCK(mapp, ADDR_LOCK); 592 dam_release(mapp, (id_t)addrid); 593 DAM_UNLOCK(mapp, ADDR_LOCK); 594 } 595 596 /* 597 * Return current reference count on address reference in map 598 * 599 * damapp: address map handle 600 * aid: address ID 601 * 602 * Returns: DAM_SUCCESS 603 * DAM_FAILURE 604 */ 605 int 606 damap_id_ref(damap_t *damapp, damap_id_t aid) 607 { 608 dam_t *mapp = (dam_t *)damapp; 609 dam_da_t *passp; 610 int ref = -1; 611 612 DAM_LOCK(mapp, ADDR_LOCK); 613 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 614 if (passp) 615 ref = passp->da_ref; 616 DAM_UNLOCK(mapp, ADDR_LOCK); 617 return (ref); 618 } 619 620 /* 621 * Return next address ID in list 622 * 623 * damapp: address map handle 624 * damap_list: address ID list passed to config|unconfig 625 * returned by look by lookup_all 626 * last: last ID returned, 0 is start of list 627 * 628 * Returns: addrid Next ID from the list 629 * 0 End of the list 630 */ 631 damap_id_t 632 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last) 633 { 634 int i, start; 635 dam_t *mapp = (dam_t *)damapp; 636 bitset_t *dam_list = (bitset_t *)damap_list; 637 638 if (!mapp || !dam_list) 639 return ((damap_id_t)0); 640 641 start = (int)last + 1; 642 for (i = start; i < mapp->dam_high; i++) 643 if (bitset_in_set(dam_list, i)) 644 return ((damap_id_t)i); 645 return ((damap_id_t)0); 646 } 647 648 /* 649 * Set config private data 650 * 651 * damapp: address map handle 652 * aid: address ID 653 * cfg_priv: configuration private data 654 * 655 */ 656 void 657 damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv) 658 { 659 dam_t *mapp = (dam_t *)damapp; 660 dam_da_t *passp; 661 662 663 DAM_LOCK(mapp, ADDR_LOCK); 664 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 665 if (!passp) { 666 DAM_UNLOCK(mapp, ADDR_LOCK); 667 return; 668 } 669 passp->da_cfg_priv = cfg_priv; 670 DAM_UNLOCK(mapp, ADDR_LOCK); 671 } 672 673 /* 674 * Get config private data 675 * 676 * damapp: address map handle 677 * aid: address ID 678 * 679 * Returns: configuration private data 680 */ 681 void * 682 damap_id_priv_get(damap_t *damapp, damap_id_t aid) 683 { 684 dam_t *mapp = (dam_t *)damapp; 685 dam_da_t *passp; 686 void *rv; 687 688 689 DAM_LOCK(mapp, ADDR_LOCK); 690 passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid); 691 if (!passp) { 692 DAM_UNLOCK(mapp, ADDR_LOCK); 693 return (NULL); 694 } 695 rv = passp->da_cfg_priv; 696 DAM_UNLOCK(mapp, ADDR_LOCK); 697 return (rv); 698 } 699 700 /* 701 * Lookup a single address in the active address map 702 * 703 * damapp: address map handle 704 * address: address string 705 * 706 * Returns: ID of active/stable address 707 * 0 Address not in stable set 708 * 709 * Future: Allow the caller to wait for stabilize before returning not found. 710 */ 711 damap_id_t 712 damap_lookup(damap_t *damapp, char *address) 713 { 714 dam_t *mapp = (dam_t *)damapp; 715 id_t addrid = 0; 716 dam_da_t *passp = NULL; 717 718 DAM_LOCK(mapp, ADDR_LOCK); 719 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address); 720 if (addrid) { 721 DAM_LOCK(mapp, MAP_LOCK); 722 if (DAM_IS_STABLE(mapp, addrid)) { 723 passp = ddi_get_soft_state(mapp->dam_da, addrid); 724 ASSERT(passp); 725 if (passp) { 726 passp->da_ref++; 727 } else { 728 addrid = 0; 729 } 730 } else { 731 addrid = 0; 732 } 733 DAM_UNLOCK(mapp, MAP_LOCK); 734 } 735 DAM_UNLOCK(mapp, ADDR_LOCK); 736 return ((damap_id_t)addrid); 737 } 738 739 740 /* 741 * Return the list of stable addresses in the map 742 * 743 * damapp: address map handle 744 * id_listp: pointer to list of address IDs in stable map (returned) 745 * 746 * Returns: # of entries returned in alist 747 */ 748 int 749 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp) 750 { 751 dam_t *mapp = (dam_t *)damapp; 752 int mapsz = mapp->dam_size; 753 int n_ids, i; 754 bitset_t *bsp; 755 dam_da_t *passp; 756 757 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP); 758 bitset_init(bsp); 759 bitset_resize(bsp, mapsz); 760 DAM_LOCK(mapp, MAP_LOCK); 761 bitset_copy(&mapp->dam_active_set, bsp); 762 DAM_UNLOCK(mapp, MAP_LOCK); 763 DAM_LOCK(mapp, ADDR_LOCK); 764 for (n_ids = 0, i = 1; i < mapsz; i++) { 765 if (bitset_in_set(bsp, i)) { 766 passp = ddi_get_soft_state(mapp->dam_da, i); 767 ASSERT(passp); 768 if (passp) { 769 passp->da_ref++; 770 n_ids++; 771 } 772 } 773 } 774 DAM_UNLOCK(mapp, ADDR_LOCK); 775 if (n_ids) { 776 *id_listp = (damap_id_list_t)bsp; 777 return (n_ids); 778 } else { 779 *id_listp = (damap_id_list_t)NULL; 780 bitset_fini(bsp); 781 kmem_free(bsp, sizeof (*bsp)); 782 return (0); 783 } 784 } 785 786 /* 787 * Release the address list returned by damap_lookup_all() 788 * 789 * mapp: address map handle 790 * id_list: list of address IDs returned in damap_lookup_all() 791 */ 792 void 793 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list) 794 { 795 dam_t *mapp = (dam_t *)damapp; 796 int i; 797 798 if (id_list == NULL) 799 return; 800 801 DAM_LOCK(mapp, ADDR_LOCK); 802 for (i = 1; i < mapp->dam_high; i++) { 803 if (bitset_in_set((bitset_t *)id_list, i)) 804 (void) dam_release(mapp, i); 805 } 806 DAM_UNLOCK(mapp, ADDR_LOCK); 807 bitset_fini((bitset_t *)id_list); 808 kmem_free((void *)id_list, sizeof (bitset_t)); 809 } 810 811 /* 812 * Activate a set of stabilized addresses 813 */ 814 static void 815 dam_addrset_activate(dam_t *mapp, bitset_t *active_set) 816 { 817 dam_da_t *passp; 818 char *addrstr; 819 int i; 820 uint32_t n_active = 0; 821 822 for (i = 1; i < mapp->dam_high; i++) { 823 if (bitset_in_set(&mapp->dam_active_set, i)) 824 n_active++; 825 if (!bitset_in_set(active_set, i)) 826 continue; 827 n_active++; 828 passp = ddi_get_soft_state(mapp->dam_da, i); 829 ASSERT(passp); 830 if (mapp->dam_activate_cb) { 831 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i); 832 (*mapp->dam_activate_cb)( 833 mapp->dam_activate_arg, addrstr, i, 834 &passp->da_ppriv_rpt); 835 } 836 DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i); 837 DAM_LOCK(mapp, MAP_LOCK); 838 bitset_add(&mapp->dam_active_set, i); 839 /* 840 * copy the reported nvlist and provider private data 841 */ 842 passp->da_nvl = passp->da_nvl_rpt; 843 passp->da_ppriv = passp->da_ppriv_rpt; 844 passp->da_ppriv_rpt = NULL; 845 passp->da_nvl_rpt = NULL; 846 passp->da_last_stable = gethrtime(); 847 passp->da_stable_cnt++; 848 DAM_UNLOCK(mapp, MAP_LOCK); 849 DAM_SET_STAT(mapp, dam_numstable, n_active); 850 } 851 } 852 853 /* 854 * Release a set of stabilized addresses 855 */ 856 static void 857 dam_addrset_release(dam_t *mapp, bitset_t *release_set) 858 { 859 int i; 860 861 DAM_LOCK(mapp, ADDR_LOCK); 862 for (i = 1; i < mapp->dam_high; i++) { 863 if (bitset_in_set(release_set, i)) { 864 DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp, 865 int, i); 866 DAM_LOCK(mapp, MAP_LOCK); 867 bitset_del(&mapp->dam_active_set, i); 868 DAM_UNLOCK(mapp, MAP_LOCK); 869 (void) dam_release(mapp, i); 870 } 871 } 872 DAM_UNLOCK(mapp, ADDR_LOCK); 873 } 874 875 /* 876 * release a previously activated address 877 */ 878 static void 879 dam_release(dam_t *mapp, id_t addrid) 880 { 881 dam_da_t *passp; 882 883 DAM_ASSERT_LOCKED(mapp, ADDR_LOCK); 884 passp = ddi_get_soft_state(mapp->dam_da, addrid); 885 ASSERT(passp); 886 887 /* 888 * invoke the deactivation callback to notify 889 * this address is no longer active 890 */ 891 dam_deactivate_addr(mapp, addrid); 892 893 /* 894 * allow pending reports for this address to stabilize 895 */ 896 if (DAM_IN_REPORT(mapp, addrid)) 897 return; 898 899 /* 900 * defer teardown until outstanding references are released 901 */ 902 if (--passp->da_ref) { 903 passp->da_flags |= DA_RELE; 904 return; 905 } 906 ddi_strid_free(mapp->dam_addr_hash, addrid); 907 ddi_soft_state_free(mapp->dam_da, addrid); 908 } 909 910 /* 911 * process stabilized address reports 912 */ 913 static void 914 dam_activate_taskq(void *arg) 915 { 916 dam_t *mapp = (dam_t *)arg; 917 bitset_t delta; 918 bitset_t cfg; 919 bitset_t uncfg; 920 int has_cfg, has_uncfg; 921 922 bitset_init(&delta); 923 bitset_resize(&delta, mapp->dam_size); 924 bitset_init(&cfg); 925 bitset_resize(&cfg, mapp->dam_size); 926 bitset_init(&uncfg); 927 bitset_resize(&uncfg, mapp->dam_size); 928 929 DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp); 930 DAM_LOCK(mapp, MAP_LOCK); 931 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set, 932 &delta)) { 933 bitset_zero(&mapp->dam_stable_set); 934 DAM_FLAG_CLR(mapp, DAM_SPEND); 935 DAM_UNLOCK(mapp, MAP_LOCK); 936 bitset_fini(&uncfg); 937 bitset_fini(&cfg); 938 bitset_fini(&delta); 939 return; 940 } 941 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg); 942 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg); 943 DAM_UNLOCK(mapp, MAP_LOCK); 944 if (has_cfg) { 945 dam_addrset_activate(mapp, &cfg); 946 (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg); 947 } 948 if (has_uncfg) { 949 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg); 950 dam_addrset_release(mapp, &uncfg); 951 } 952 DAM_LOCK(mapp, MAP_LOCK); 953 bitset_zero(&mapp->dam_stable_set); 954 DAM_FLAG_CLR(mapp, DAM_SPEND); 955 mapp->dam_last_stable = gethrtime(); 956 mapp->dam_stable_cnt++; 957 DAM_INCR_STAT(mapp, dam_stable); 958 DAM_UNLOCK(mapp, MAP_LOCK); 959 bitset_fini(&uncfg); 960 bitset_fini(&cfg); 961 bitset_fini(&delta); 962 DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp); 963 } 964 965 /* 966 * per-address stabilization timeout 967 */ 968 static void 969 dam_addr_stable_cb(void *arg) 970 { 971 dam_t *mapp = (dam_t *)arg; 972 int i; 973 dam_da_t *passp; 974 int spend = 0; 975 int tpend = 0; 976 int64_t next_tmov = mapp->dam_stabletmo; 977 int64_t tmo_delta; 978 int64_t ts = lbolt64; 979 980 DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp); 981 DAM_LOCK(mapp, MAP_LOCK); 982 if (mapp->dam_tid == 0) { 983 DAM_UNLOCK(mapp, MAP_LOCK); 984 return; 985 } 986 mapp->dam_tid = 0; 987 /* 988 * If still under stabilization, reschedule timeout, 989 * else dispatch the task to activate & deactivate the stable 990 * set. 991 */ 992 if (mapp->dam_flags & DAM_SPEND) { 993 DAM_INCR_STAT(mapp, dam_stable_blocked); 994 mapp->dam_stable_overrun++; 995 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 996 DAM_UNLOCK(mapp, MAP_LOCK); 997 DTRACE_PROBE1(damap__addr__stable__cb__overrun, 998 dam_t *, mapp); 999 return; 1000 } 1001 1002 bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set); 1003 for (i = 1; i < mapp->dam_high; i++) { 1004 if (!bitset_in_set(&mapp->dam_report_set, i)) 1005 continue; 1006 /* 1007 * Stabilize each address 1008 */ 1009 passp = ddi_get_soft_state(mapp->dam_da, i); 1010 ASSERT(passp); 1011 if (!passp) { 1012 cmn_err(CE_WARN, "Clearing report no softstate %d", i); 1013 bitset_del(&mapp->dam_report_set, i); 1014 continue; 1015 } 1016 1017 /* report has stabilized */ 1018 if (passp->da_deadline <= ts) { 1019 bitset_del(&mapp->dam_report_set, i); 1020 if (passp->da_flags & DA_RELE) { 1021 DTRACE_PROBE2(damap__addr__stable__del, 1022 dam_t *, mapp, int, i); 1023 bitset_del(&mapp->dam_stable_set, i); 1024 } else { 1025 DTRACE_PROBE2(damap__addr__stable__add, 1026 dam_t *, mapp, int, i); 1027 bitset_add(&mapp->dam_stable_set, i); 1028 } 1029 spend++; 1030 continue; 1031 } 1032 1033 /* 1034 * not stabilized, determine next (future) map timeout 1035 */ 1036 tpend++; 1037 tmo_delta = passp->da_deadline - ts; 1038 if (tmo_delta < next_tmov) 1039 next_tmov = tmo_delta; 1040 } 1041 1042 /* 1043 * schedule taskq activation of stabilized reports 1044 */ 1045 if (spend) { 1046 if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 1047 mapp, DDI_NOSLEEP) == DDI_SUCCESS) { 1048 DAM_FLAG_SET(mapp, DAM_SPEND); 1049 } else 1050 tpend++; 1051 } 1052 1053 /* 1054 * schedule timeout to handle future stabalization of active reports 1055 */ 1056 if (tpend) 1057 dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb); 1058 DAM_UNLOCK(mapp, MAP_LOCK); 1059 DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp); 1060 } 1061 1062 /* 1063 * fullset stabilization timeout 1064 */ 1065 static void 1066 dam_set_stable_cb(void *arg) 1067 { 1068 dam_t *mapp = (dam_t *)arg; 1069 1070 DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp); 1071 1072 DAM_LOCK(mapp, MAP_LOCK); 1073 if (mapp->dam_tid == 0) { 1074 DAM_UNLOCK(mapp, MAP_LOCK); 1075 return; 1076 } 1077 mapp->dam_tid = 0; 1078 1079 /* 1080 * If still under stabilization, reschedule timeout, 1081 * else dispatch the task to activate & deactivate the stable 1082 * set. 1083 */ 1084 if (mapp->dam_flags & DAM_SPEND) { 1085 DAM_INCR_STAT(mapp, dam_stable_blocked); 1086 mapp->dam_stable_overrun++; 1087 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 1088 DTRACE_PROBE1(damap__set__stable__cb__overrun, 1089 dam_t *, mapp); 1090 } else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq, 1091 mapp, DDI_NOSLEEP) == DDI_FAILURE) { 1092 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb); 1093 } else { 1094 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set); 1095 bitset_zero(&mapp->dam_report_set); 1096 DAM_FLAG_CLR(mapp, DAM_SETADD); 1097 DAM_FLAG_SET(mapp, DAM_SPEND); 1098 } 1099 DAM_UNLOCK(mapp, MAP_LOCK); 1100 DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp); 1101 } 1102 1103 /* 1104 * reschedule map timeout 'tmo_ms' ticks 1105 */ 1106 static void 1107 dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)()) 1108 { 1109 timeout_id_t tid; 1110 1111 if ((tid = mapp->dam_tid) != 0) { 1112 mapp->dam_tid = 0; 1113 DAM_UNLOCK(mapp, MAP_LOCK); 1114 (void) untimeout(tid); 1115 DAM_LOCK(mapp, MAP_LOCK); 1116 } 1117 1118 if (tmo_cb && (tmo_ms != 0)) 1119 mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms); 1120 } 1121 1122 /* 1123 * record report addition or removal of an address 1124 */ 1125 static void 1126 dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report) 1127 { 1128 ASSERT(!DAM_IN_REPORT(mapp, addrid)); 1129 passp->da_last_report = gethrtime(); 1130 mapp->dam_last_update = gethrtime(); 1131 passp->da_report_cnt++; 1132 passp->da_deadline = lbolt64 + mapp->dam_stabletmo; 1133 if (report == RPT_ADDR_DEL) 1134 passp->da_flags |= DA_RELE; 1135 else if (report == RPT_ADDR_ADD) 1136 passp->da_flags &= ~DA_RELE; 1137 DAM_LOCK(mapp, MAP_LOCK); 1138 bitset_add(&mapp->dam_report_set, addrid); 1139 dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb); 1140 DAM_UNLOCK(mapp, MAP_LOCK); 1141 1142 } 1143 1144 /* 1145 * release an address report 1146 */ 1147 static void 1148 dam_release_report(dam_t *mapp, id_t addrid) 1149 { 1150 dam_da_t *passp; 1151 1152 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1153 ASSERT(passp); 1154 passp->da_ppriv_rpt = NULL; 1155 if (passp->da_nvl_rpt) 1156 nvlist_free(passp->da_nvl_rpt); 1157 passp->da_nvl_rpt = NULL; 1158 DAM_LOCK(mapp, MAP_LOCK); 1159 bitset_del(&mapp->dam_report_set, addrid); 1160 DAM_UNLOCK(mapp, MAP_LOCK); 1161 } 1162 1163 /* 1164 * deactivate a previously stable address 1165 */ 1166 static void 1167 dam_deactivate_addr(dam_t *mapp, id_t addrid) 1168 { 1169 dam_da_t *passp; 1170 1171 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1172 ASSERT(passp); 1173 if (passp == NULL) 1174 return; 1175 DAM_UNLOCK(mapp, ADDR_LOCK); 1176 if (mapp->dam_deactivate_cb) 1177 (*mapp->dam_deactivate_cb)( 1178 mapp->dam_activate_arg, 1179 ddi_strid_id2str(mapp->dam_addr_hash, 1180 addrid), addrid, passp->da_ppriv); 1181 DAM_LOCK(mapp, ADDR_LOCK); 1182 passp->da_ppriv = NULL; 1183 if (passp->da_nvl) 1184 nvlist_free(passp->da_nvl); 1185 passp->da_nvl = NULL; 1186 } 1187 1188 /* 1189 * return the map ID of an address 1190 */ 1191 static id_t 1192 dam_get_addrid(dam_t *mapp, char *address) 1193 { 1194 damap_id_t addrid; 1195 dam_da_t *passp; 1196 1197 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) { 1198 if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash, 1199 address)) == (damap_id_t)0) { 1200 return (0); 1201 } 1202 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) != 1203 DDI_SUCCESS) { 1204 ddi_strid_free(mapp->dam_addr_hash, addrid); 1205 return (0); 1206 } 1207 if (addrid >= mapp->dam_high) 1208 mapp->dam_high = addrid + 1; 1209 } 1210 passp = ddi_get_soft_state(mapp->dam_da, addrid); 1211 if (passp == NULL) 1212 return (0); 1213 passp->da_ref++; 1214 if (passp->da_addr == NULL) 1215 passp->da_addr = ddi_strid_id2str( 1216 mapp->dam_addr_hash, addrid); /* for mdb */ 1217 return (addrid); 1218 } 1219 1220 /* 1221 * create and install map statistics 1222 */ 1223 static int 1224 dam_kstat_create(dam_t *mapp) 1225 { 1226 kstat_t *mapsp; 1227 struct dam_kstats *statsp; 1228 1229 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap", 1230 KSTAT_TYPE_NAMED, 1231 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0); 1232 if (mapsp == NULL) { 1233 return (DDI_FAILURE); 1234 } 1235 1236 statsp = (struct dam_kstats *)mapsp->ks_data; 1237 kstat_named_init(&statsp->dam_stable, "stable cycles", 1238 KSTAT_DATA_UINT32); 1239 kstat_named_init(&statsp->dam_stable_blocked, 1240 "stable cycle overrun", KSTAT_DATA_UINT32); 1241 kstat_named_init(&statsp->dam_rereport, 1242 "restarted reports", KSTAT_DATA_UINT32); 1243 kstat_named_init(&statsp->dam_numstable, 1244 "# of stable map entries", KSTAT_DATA_UINT32); 1245 kstat_install(mapsp); 1246 mapp->dam_kstatsp = mapsp; 1247 return (DDI_SUCCESS); 1248 } 1249 1250 /* 1251 * destroy map stats 1252 */ 1253 static void 1254 dam_kstat_destroy(dam_t *mapp) 1255 { 1256 1257 kstat_delete(mapp->dam_kstatsp); 1258 } 1259