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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Instance number assignment code 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/errno.h> 36 #include <sys/systm.h> 37 #include <sys/kobj.h> 38 #include <sys/t_lock.h> 39 #include <sys/kmem.h> 40 #include <sys/cmn_err.h> 41 #include <sys/ddi.h> 42 #include <sys/sunddi.h> 43 #include <sys/autoconf.h> 44 #include <sys/systeminfo.h> 45 #include <sys/hwconf.h> 46 #include <sys/reboot.h> 47 #include <sys/ddi_impldefs.h> 48 #include <sys/instance.h> 49 #include <sys/debug.h> 50 #include <sys/sysevent.h> 51 #include <sys/modctl.h> 52 #include <sys/console.h> 53 #include <sys/cladm.h> 54 55 static void in_preassign_instance(void); 56 static void i_log_devfs_instance_mod(void); 57 static int in_get_infile(char *); 58 static void in_removenode(struct devnames *dnp, in_node_t *mp, in_node_t *ap); 59 static in_node_t *in_alloc_node(char *name, char *addr); 60 static int in_eqstr(char *a, char *b); 61 static char *in_name_addr(char **cpp, char **addrp); 62 static in_node_t *in_devwalk(dev_info_t *dip, in_node_t **ap, char *addr); 63 static void in_dealloc_node(in_node_t *np); 64 static in_node_t *in_make_path(char *path); 65 static void in_enlist(in_node_t *ap, in_node_t *np); 66 static int in_inuse(int instance, char *name); 67 static void in_hashdrv(in_drv_t *dp); 68 static in_drv_t *in_drvwalk(in_node_t *np, char *binding_name); 69 static in_drv_t *in_alloc_drv(char *bindingname); 70 static void in_endrv(in_node_t *np, in_drv_t *dp); 71 static void in_dq_drv(in_drv_t *np); 72 static void in_removedrv(struct devnames *dnp, in_drv_t *mp); 73 static int in_pathin(char *cp, int instance, char *bname, struct bind **args); 74 static int in_next_instance(major_t); 75 76 /* external functions */ 77 extern char *i_binding_to_drv_name(char *bname); 78 79 /* 80 * This plus devnames defines the entire software state of the instance world. 81 */ 82 typedef struct in_softstate { 83 in_node_t *ins_root; /* the root of our instance tree */ 84 in_drv_t *ins_no_major; /* majorless drv entries */ 85 /* 86 * Used to serialize access to data structures 87 */ 88 void *ins_thread; 89 kmutex_t ins_serial; 90 kcondvar_t ins_serial_cv; 91 int ins_busy; 92 char ins_dirty; /* need flush */ 93 } in_softstate_t; 94 95 static in_softstate_t e_ddi_inst_state; 96 97 /* 98 * State transition information: 99 * e_ddi_inst_state contains, among other things, the root of a tree of 100 * device nodes used to track instance number assignments. 101 * Each device node may contain multiple driver bindings, represented 102 * by a linked list of in_drv_t nodes, each with an instance assignment 103 * (except for root node). Each in_drv node can be in one of 3 states, 104 * indicated by ind_state: 105 * 106 * IN_UNKNOWN: Each node created in this state. The instance number of 107 * this node is not known. ind_instance is set to -1. 108 * IN_PROVISIONAL: When a node is assigned an instance number in 109 * e_ddi_assign_instance(), its state is set to IN_PROVISIONAL. 110 * Subsequently, the framework will always call either 111 * e_ddi_keep_instance() which makes the node IN_PERMANENT, 112 * or e_ddi_free_instance(), which deletes the node. 113 * IN_PERMANENT: 114 * If e_ddi_keep_instance() is called on an IN_PROVISIONAL node, 115 * its state is set to IN_PERMANENT. 116 */ 117 118 static char *instance_file = INSTANCE_FILE; 119 static char *instance_file_backup = INSTANCE_FILE INSTANCE_FILE_SUFFIX; 120 121 /* 122 * Return values for in_get_infile(). 123 */ 124 #define PTI_FOUND 0 125 #define PTI_NOT_FOUND 1 126 #define PTI_REBUILD 2 127 128 /* 129 * Path to instance file magic string used for first time boot after 130 * an install. If this is the first string in the file we will 131 * automatically rebuild the file. 132 */ 133 #define PTI_MAGIC_STR "#path_to_inst_bootstrap_1" 134 #define PTI_MAGIC_STR_LEN (sizeof (PTI_MAGIC_STR) - 1) 135 136 void 137 e_ddi_instance_init(void) 138 { 139 char *file; 140 int rebuild = 1; 141 struct in_drv *dp; 142 143 mutex_init(&e_ddi_inst_state.ins_serial, NULL, MUTEX_DEFAULT, NULL); 144 cv_init(&e_ddi_inst_state.ins_serial_cv, NULL, CV_DEFAULT, NULL); 145 146 /* 147 * Only one thread is allowed to change the state of the instance 148 * number assignments on the system at any given time. 149 * Note that this is not really necessary, as we are single-threaded 150 * here, but it won't hurt, and it allows us to keep ASSERTS for 151 * our assumptions in the code. 152 */ 153 e_ddi_enter_instance(); 154 155 /* 156 * Create the root node, instance zallocs to 0. 157 * The name and address of this node never get examined, we always 158 * start searching with its first child. 159 */ 160 ASSERT(e_ddi_inst_state.ins_root == NULL); 161 e_ddi_inst_state.ins_root = in_alloc_node(NULL, NULL); 162 dp = in_alloc_drv("rootnex"); 163 in_endrv(e_ddi_inst_state.ins_root, dp); 164 165 file = instance_file; 166 switch (in_get_infile(file)) { 167 default: 168 case PTI_NOT_FOUND: 169 /* make sure path_to_inst is recreated */ 170 boothowto |= RB_RECONFIG; 171 172 /* 173 * Something is wrong. First try the backup file. 174 * If not found, rebuild path_to_inst. Emit a 175 * message about the problem. 176 */ 177 cmn_err(CE_WARN, "%s empty or not found", file); 178 179 file = instance_file_backup; 180 if (in_get_infile(file) != PTI_FOUND) { 181 cmn_err(CE_NOTE, "rebuilding device instance data"); 182 break; 183 } 184 cmn_err(CE_NOTE, "using backup instance data in %s", file); 185 /*FALLTHROUGH*/ 186 187 case PTI_FOUND: 188 /* 189 * We've got a readable file 190 * parse the file into the instance tree 191 */ 192 (void) read_binding_file(file, NULL, in_pathin); 193 rebuild = 0; 194 break; 195 196 case PTI_REBUILD: 197 cmn_err(CE_CONT, 198 "?Using default device instance data\n"); 199 break; 200 } 201 202 /* 203 * The OBP device tree has been copied to the kernel and 204 * bound to drivers at this point. We walk the per-driver 205 * list to preassign instances. Since the bus addr is 206 * unknown at this point, we cannot place the instance 207 * number in the instance tree. This will be done at 208 * a later time. 209 */ 210 if (rebuild) 211 in_preassign_instance(); 212 213 e_ddi_exit_instance(); 214 } 215 216 static void 217 in_preassign_instance() 218 { 219 major_t m; 220 extern major_t devcnt; 221 222 for (m = 0; m < devcnt; m++) { 223 struct devnames *dnp = &devnamesp[m]; 224 dev_info_t *dip = dnp->dn_head; 225 while (dip) { 226 DEVI(dip)->devi_instance = dnp->dn_instance; 227 dnp->dn_instance++; 228 dip = ddi_get_next(dip); 229 } 230 } 231 } 232 233 /* 234 * Checks to see if the /etc/path_to_inst file exists and whether or not 235 * it has the magic string in it. 236 * 237 * Returns one of the following: 238 * 239 * PTI_FOUND - We have found the /etc/path_to_inst file 240 * PTI_REBUILD - We have found the /etc/path_to_inst file and the 241 * first line was PTI_MAGIC_STR. 242 * PTI_NOT_FOUND - We did not find the /etc/path_to_inst file 243 * 244 */ 245 static int 246 in_get_infile(char *filename) 247 { 248 intptr_t file; 249 int return_val; 250 char buf[PTI_MAGIC_STR_LEN]; 251 252 /* 253 * Try to open the file. 254 */ 255 if ((file = kobj_open(filename)) == -1) { 256 return (PTI_NOT_FOUND); 257 } 258 return_val = PTI_FOUND; 259 260 /* 261 * Read the first PTI_MAGIC_STR_LEN bytes from the file to see if 262 * it contains the magic string. If there aren't that many bytes 263 * in the file, then assume file is correct and no magic string 264 * and move on. 265 */ 266 switch (kobj_read(file, buf, PTI_MAGIC_STR_LEN, 0)) { 267 268 case PTI_MAGIC_STR_LEN: 269 /* 270 * If the first PTI_MAGIC_STR_LEN bytes are the magic string 271 * then return PTI_REBUILD. 272 */ 273 if (strncmp(PTI_MAGIC_STR, buf, PTI_MAGIC_STR_LEN) == 0) 274 return_val = PTI_REBUILD; 275 break; 276 277 case 0: 278 /* 279 * If the file is zero bytes in length, then consider the 280 * file to not be found 281 */ 282 return_val = PTI_NOT_FOUND; 283 284 default: /* Do nothing we have a good file */ 285 break; 286 } 287 288 kobj_close(file); 289 return (return_val); 290 } 291 292 int 293 is_pseudo_device(dev_info_t *dip) 294 { 295 dev_info_t *pdip; 296 297 for (pdip = ddi_get_parent(dip); pdip && pdip != ddi_root_node(); 298 pdip = ddi_get_parent(pdip)) { 299 if (strcmp(ddi_get_name(pdip), DEVI_PSEUDO_NEXNAME) == 0) 300 return (1); 301 } 302 return (0); 303 } 304 305 306 static void 307 in_set_instance(dev_info_t *dip, in_drv_t *dp, major_t major) 308 { 309 /* use preassigned instance if available */ 310 if (DEVI(dip)->devi_instance != -1) 311 dp->ind_instance = DEVI(dip)->devi_instance; 312 else 313 dp->ind_instance = in_next_instance(major); 314 } 315 316 /* 317 * Look up an instance number for a dev_info node, and assign one if it does 318 * not have one (the dev_info node has devi_name and devi_addr already set). 319 */ 320 uint_t 321 e_ddi_assign_instance(dev_info_t *dip) 322 { 323 char *name; 324 in_node_t *ap, *np; 325 in_drv_t *dp; 326 major_t major; 327 uint_t ret; 328 char *bname; 329 330 /* 331 * Allow implementation to override 332 */ 333 if ((ret = impl_assign_instance(dip)) != (uint_t)-1) 334 return (ret); 335 336 /* 337 * If this is a pseudo-device, use the instance number 338 * assigned by the pseudo nexus driver. The mutex is 339 * not needed since the instance tree is not used. 340 */ 341 if (is_pseudo_device(dip)) { 342 return (ddi_get_instance(dip)); 343 } 344 345 /* 346 * Only one thread is allowed to change the state of the instance 347 * number assignments on the system at any given time. 348 */ 349 e_ddi_enter_instance(); 350 351 /* 352 * Look for instance node, allocate one if not found 353 */ 354 np = in_devwalk(dip, &ap, NULL); 355 if (np == NULL) { 356 name = ddi_node_name(dip); 357 np = in_alloc_node(name, ddi_get_name_addr(dip)); 358 ASSERT(np != NULL); 359 in_enlist(ap, np); /* insert into tree */ 360 } 361 ASSERT(np == in_devwalk(dip, &ap, NULL)); 362 363 /* 364 * Look for driver entry, allocate one if not found 365 */ 366 bname = (char *)ddi_driver_name(dip); 367 dp = in_drvwalk(np, bname); 368 if (dp == NULL) { 369 dp = in_alloc_drv(bname); 370 ASSERT(dp != NULL); 371 major = ddi_driver_major(dip); 372 ASSERT(major != (major_t)-1); 373 in_endrv(np, dp); 374 in_set_instance(dip, dp, major); 375 dp->ind_state = IN_PROVISIONAL; 376 in_hashdrv(dp); 377 } 378 379 ret = dp->ind_instance; 380 381 e_ddi_exit_instance(); 382 return (ret); 383 } 384 385 static int 386 mkpathname(char *path, in_node_t *np, int len) 387 { 388 int len_needed; 389 390 if (np == e_ddi_inst_state.ins_root) 391 return (DDI_SUCCESS); 392 393 if (mkpathname(path, np->in_parent, len) == DDI_FAILURE) 394 return (DDI_FAILURE); 395 396 len_needed = strlen(path); 397 len_needed += strlen(np->in_node_name) + 1; /* for '/' */ 398 if (np->in_unit_addr) { 399 len_needed += strlen(np->in_unit_addr) + 1; /* for '@' */ 400 } 401 len_needed += 1; /* for '\0' */ 402 403 /* 404 * XX complain 405 */ 406 if (len_needed > len) 407 return (DDI_FAILURE); 408 409 if (np->in_unit_addr[0] == '\0') 410 (void) sprintf(path+strlen(path), "/%s", np->in_node_name); 411 else 412 (void) sprintf(path+strlen(path), "/%s@%s", np->in_node_name, 413 np->in_unit_addr); 414 415 return (DDI_SUCCESS); 416 } 417 418 /* 419 * produce the path to the given instance of a major number. 420 * path must hold MAXPATHLEN string 421 */ 422 int 423 e_ddi_instance_majorinstance_to_path(major_t major, uint_t inst, char *path) 424 { 425 struct devnames *dnp; 426 in_drv_t *dp; 427 int ret; 428 429 e_ddi_enter_instance(); 430 431 /* look for the instance threaded off major */ 432 dnp = &devnamesp[major]; 433 for (dp = dnp->dn_inlist; dp != NULL; dp = dp->ind_next) 434 if (dp->ind_instance == inst) 435 break; 436 437 /* produce path from the node that uses the instance */ 438 if (dp) { 439 *path = 0; 440 ret = mkpathname(path, dp->ind_node, MAXPATHLEN); 441 } else 442 ret = DDI_FAILURE; 443 444 e_ddi_exit_instance(); 445 return (ret); 446 } 447 448 /* 449 * This depends on the list being sorted in ascending instance number 450 * sequence. dn_instance contains the next available instance no. 451 * or IN_SEARCHME, indicating (a) hole(s) in the sequence. 452 */ 453 static int 454 in_next_instance(major_t major) 455 { 456 unsigned int prev; 457 struct devnames *dnp; 458 in_drv_t *dp; 459 460 dnp = &devnamesp[major]; 461 462 ASSERT(major != (major_t)-1); 463 ASSERT(e_ddi_inst_state.ins_busy); 464 if (dnp->dn_instance != IN_SEARCHME) 465 return (dnp->dn_instance++); 466 dp = dnp->dn_inlist; 467 468 /* no existing entries, assign instance 0 */ 469 if (dp == NULL) { 470 dnp->dn_instance = 1; 471 return (0); 472 } 473 474 prev = dp->ind_instance; 475 if (prev != 0) /* hole at beginning of list */ 476 return (0); 477 /* search the list for a hole in the sequence */ 478 for (dp = dp->ind_next; dp; dp = dp->ind_next) { 479 if (dp->ind_instance != prev + 1) 480 return (prev + 1); 481 prev++; 482 } 483 /* 484 * If we got here, then the hole has been patched 485 */ 486 dnp->dn_instance = ++prev + 1; 487 488 return (prev); 489 } 490 491 /* 492 * This call causes us to *forget* the instance number we've generated 493 * for a given device if it was not permanent. 494 */ 495 void 496 e_ddi_free_instance(dev_info_t *dip, char *addr) 497 { 498 char *name; 499 in_node_t *np; 500 in_node_t *ap; /* ancestor node */ 501 major_t major; 502 struct devnames *dnp; 503 in_drv_t *dp; /* in_drv entry */ 504 505 /* 506 * Allow implementation override 507 */ 508 if (impl_free_instance(dip) == DDI_SUCCESS) 509 return; 510 511 /* 512 * If this is a pseudo-device, no instance number 513 * was assigned. 514 */ 515 if (is_pseudo_device(dip)) { 516 return; 517 } 518 519 name = (char *)ddi_driver_name(dip); 520 major = ddi_driver_major(dip); 521 ASSERT(major != (major_t)-1); 522 dnp = &devnamesp[major]; 523 /* 524 * Only one thread is allowed to change the state of the instance 525 * number assignments on the system at any given time. 526 */ 527 e_ddi_enter_instance(); 528 np = in_devwalk(dip, &ap, addr); 529 ASSERT(np); 530 dp = in_drvwalk(np, name); 531 ASSERT(dp); 532 if (dp->ind_state == IN_PROVISIONAL) { 533 in_removedrv(dnp, dp); 534 } 535 if (np->in_drivers == NULL) { 536 in_removenode(dnp, np, ap); 537 } 538 e_ddi_exit_instance(); 539 } 540 541 /* 542 * This makes our memory of an instance assignment permanent 543 */ 544 void 545 e_ddi_keep_instance(dev_info_t *dip) 546 { 547 in_node_t *np, *ap; 548 in_drv_t *dp; 549 550 /* 551 * Allow implementation override 552 */ 553 if (impl_keep_instance(dip) == DDI_SUCCESS) 554 return; 555 556 /* 557 * Nothing to do for pseudo devices. 558 */ 559 if (is_pseudo_device(dip)) 560 return; 561 562 /* 563 * Only one thread is allowed to change the state of the instance 564 * number assignments on the system at any given time. 565 */ 566 e_ddi_enter_instance(); 567 np = in_devwalk(dip, &ap, NULL); 568 ASSERT(np); 569 dp = in_drvwalk(np, (char *)ddi_driver_name(dip)); 570 ASSERT(dp); 571 572 mutex_enter(&e_ddi_inst_state.ins_serial); 573 if (dp->ind_state == IN_PROVISIONAL) { 574 dp->ind_state = IN_PERMANENT; 575 i_log_devfs_instance_mod(); 576 e_ddi_inst_state.ins_dirty = 1; 577 } 578 mutex_exit(&e_ddi_inst_state.ins_serial); 579 e_ddi_exit_instance(); 580 } 581 582 /* 583 * A new major has been added to the system. Run through the orphan list 584 * and try to attach each one to a driver's list. 585 */ 586 void 587 e_ddi_unorphan_instance_nos() 588 { 589 in_drv_t *dp, *ndp; 590 591 /* 592 * disconnect the orphan list, and call in_hashdrv for each item 593 * on it 594 */ 595 596 /* 597 * Only one thread is allowed to change the state of the instance 598 * number assignments on the system at any given time. 599 */ 600 e_ddi_enter_instance(); 601 if (e_ddi_inst_state.ins_no_major == NULL) { 602 e_ddi_exit_instance(); 603 return; 604 } 605 /* 606 * Hash instance list to devnames structure of major. 607 * Note that if there is not a valid major number for the 608 * node, in_hashdrv will put it back on the no_major list. 609 */ 610 dp = e_ddi_inst_state.ins_no_major; 611 e_ddi_inst_state.ins_no_major = NULL; 612 while (dp) { 613 ndp = dp->ind_next; 614 ASSERT(dp->ind_state != IN_UNKNOWN); 615 dp->ind_next = NULL; 616 in_hashdrv(dp); 617 dp = ndp; 618 } 619 e_ddi_exit_instance(); 620 } 621 622 static void 623 in_removenode(struct devnames *dnp, in_node_t *mp, in_node_t *ap) 624 { 625 in_node_t *np; 626 627 ASSERT(e_ddi_inst_state.ins_busy); 628 /* 629 * Assertion: parents are always instantiated by the framework 630 * before their children, destroyed after them 631 */ 632 ASSERT(mp->in_child == NULL); 633 /* 634 * Assertion: drv entries are always removed before their owning nodes 635 */ 636 ASSERT(mp->in_drivers == NULL); 637 /* 638 * Take the node out of the tree 639 */ 640 if (ap->in_child == mp) { 641 ap->in_child = mp->in_sibling; 642 in_dealloc_node(mp); 643 return; 644 } else { 645 for (np = ap->in_child; np; np = np->in_sibling) { 646 if (np->in_sibling == mp) { 647 np->in_sibling = mp->in_sibling; 648 in_dealloc_node(mp); 649 return; 650 } 651 } 652 } 653 panic("in_removenode dnp %p mp %p", (void *)dnp, (void *)mp); 654 } 655 656 /* 657 * Recursive ascent 658 * 659 * This now only does half the job. It finds the node, then the caller 660 * has to search the node for the binding name 661 */ 662 static in_node_t * 663 in_devwalk(dev_info_t *dip, in_node_t **ap, char *addr) 664 { 665 in_node_t *np; 666 char *name; 667 668 ASSERT(dip); 669 ASSERT(e_ddi_inst_state.ins_busy); 670 if (dip == ddi_root_node()) { 671 *ap = NULL; 672 return (e_ddi_inst_state.ins_root); 673 } 674 /* 675 * call up to find parent, then look through the list of kids 676 * for a match 677 */ 678 np = in_devwalk(ddi_get_parent(dip), ap, NULL); 679 if (np == NULL) 680 return (np); 681 *ap = np; 682 np = np->in_child; 683 name = ddi_node_name(dip); 684 if (addr == NULL) 685 addr = ddi_get_name_addr(dip); 686 687 while (np) { 688 if (in_eqstr(np->in_node_name, name) && 689 in_eqstr(np->in_unit_addr, addr)) { 690 return (np); 691 } 692 np = np->in_sibling; 693 } 694 return (np); 695 } 696 697 /* 698 * Create a node specified by cp and assign it the given instance no. 699 */ 700 static int 701 in_pathin(char *cp, int instance, char *bname, struct bind **args) 702 { 703 in_node_t *np; 704 in_drv_t *dp; 705 char *name; 706 707 ASSERT(e_ddi_inst_state.ins_busy); 708 ASSERT(args == NULL); 709 710 /* 711 * Give a warning to the console. 712 * return value ignored 713 */ 714 if (cp[0] != '/' || instance == -1 || bname == NULL) { 715 cmn_err(CE_WARN, 716 "invalid instance file entry %s %d", 717 cp, instance); 718 719 return (0); 720 } 721 722 if ((name = i_binding_to_drv_name(bname)) != NULL) 723 bname = name; 724 725 np = in_make_path(cp); 726 ASSERT(np); 727 if (in_inuse(instance, bname)) { 728 cmn_err(CE_WARN, 729 "instance already in use: %s %d", cp, instance); 730 return (0); 731 } 732 dp = in_drvwalk(np, bname); 733 if (dp != NULL) { 734 cmn_err(CE_WARN, 735 "multiple instance number assignments for " 736 "'%s' (driver %s), %d used", 737 cp, bname, dp->ind_instance); 738 return (0); 739 } 740 dp = in_alloc_drv(bname); 741 in_endrv(np, dp); 742 dp->ind_instance = instance; 743 dp->ind_state = IN_PERMANENT; 744 in_hashdrv(dp); 745 746 return (0); 747 } 748 749 /* 750 * Create (or find) the node named by path by recursively descending from the 751 * root's first child (we ignore the root, which is never named) 752 */ 753 static in_node_t * 754 in_make_path(char *path) 755 { 756 in_node_t *ap; /* ancestor pointer */ 757 in_node_t *np; /* working node pointer */ 758 in_node_t *rp; /* return node pointer */ 759 char buf[MAXPATHLEN]; /* copy of string so we can change it */ 760 char *cp, *name, *addr; 761 762 ASSERT(e_ddi_inst_state.ins_busy); 763 if (path == NULL || path[0] != '/') 764 return (NULL); 765 (void) snprintf(buf, sizeof (buf), "%s", path); 766 cp = buf + 1; /* skip over initial '/' in path */ 767 name = in_name_addr(&cp, &addr); 768 769 /* 770 * In S9 and earlier releases, the path_to_inst file 771 * SunCluster was prepended with "/node@#". This was 772 * removed in S10. We skip the prefix if the prefix 773 * still exists in /etc/path_to_inst. It is needed for 774 * various forms of Solaris upgrade to work properly 775 * in the SunCluster environment. 776 */ 777 if ((cluster_bootflags & CLUSTER_CONFIGURED) && 778 (strcmp(name, "node") == 0)) 779 name = in_name_addr(&cp, &addr); 780 781 ap = e_ddi_inst_state.ins_root; 782 rp = np = e_ddi_inst_state.ins_root->in_child; 783 while (name) { 784 while (name && np) { 785 if (in_eqstr(name, np->in_node_name) && 786 in_eqstr(addr, np->in_unit_addr)) { 787 name = in_name_addr(&cp, &addr); 788 if (name == NULL) 789 return (np); 790 ap = np; 791 np = np->in_child; 792 continue; 793 } else { 794 np = np->in_sibling; 795 } 796 } 797 np = in_alloc_node(name, addr); 798 in_enlist(ap, np); /* insert into tree */ 799 rp = np; /* value to return if we quit */ 800 ap = np; /* new parent */ 801 np = NULL; /* can have no children */ 802 name = in_name_addr(&cp, &addr); 803 } 804 return (rp); 805 } 806 807 /* 808 * Insert node np into the tree as one of ap's children. 809 */ 810 static void 811 in_enlist(in_node_t *ap, in_node_t *np) 812 { 813 in_node_t *mp; 814 ASSERT(e_ddi_inst_state.ins_busy); 815 /* 816 * Make this node some other node's child or child's sibling 817 */ 818 ASSERT(ap && np); 819 if (ap->in_child == NULL) { 820 ap->in_child = np; 821 } else { 822 for (mp = ap->in_child; mp; mp = mp->in_sibling) 823 if (mp->in_sibling == NULL) { 824 mp->in_sibling = np; 825 break; 826 } 827 } 828 np->in_parent = ap; 829 } 830 831 /* 832 * Insert drv entry dp onto a node's driver list 833 */ 834 static void 835 in_endrv(in_node_t *np, in_drv_t *dp) 836 { 837 in_drv_t *mp; 838 ASSERT(e_ddi_inst_state.ins_busy); 839 ASSERT(np && dp); 840 mp = np->in_drivers; 841 np->in_drivers = dp; 842 dp->ind_next_drv = mp; 843 dp->ind_node = np; 844 } 845 846 /* 847 * Parse the next name out of the path, null terminate it and update cp. 848 * caller has copied string so we can mess with it. 849 * Upon return *cpp points to the next section to be parsed, *addrp points 850 * to the current address substring (or NULL if none) and we return the 851 * current name substring (or NULL if none). name and address substrings 852 * are null terminated in place. 853 */ 854 855 static char * 856 in_name_addr(char **cpp, char **addrp) 857 { 858 char *namep; /* return value holder */ 859 char *ap; /* pointer to '@' in string */ 860 char *sp; /* pointer to '/' in string */ 861 862 if (*cpp == NULL || **cpp == '\0') { 863 *addrp = NULL; 864 return (NULL); 865 } 866 namep = *cpp; 867 sp = strchr(*cpp, '/'); 868 if (sp != NULL) { /* more to follow */ 869 *sp = '\0'; 870 *cpp = sp + 1; 871 } else { /* this is last component. */ 872 *cpp = NULL; 873 } 874 ap = strchr(namep, '@'); 875 if (ap == NULL) { 876 *addrp = NULL; 877 } else { 878 *ap = '\0'; /* terminate the name */ 879 *addrp = ap + 1; 880 } 881 return (namep); 882 } 883 884 /* 885 * Allocate a node and storage for name and addr strings, and fill them in. 886 */ 887 static in_node_t * 888 in_alloc_node(char *name, char *addr) 889 { 890 in_node_t *np; 891 char *cp; 892 size_t namelen; 893 894 ASSERT(e_ddi_inst_state.ins_busy); 895 /* 896 * Has name or will become root 897 */ 898 ASSERT(name || e_ddi_inst_state.ins_root == NULL); 899 if (addr == NULL) 900 addr = ""; 901 if (name == NULL) 902 namelen = 0; 903 else 904 namelen = strlen(name) + 1; 905 cp = kmem_zalloc(sizeof (in_node_t) + namelen + strlen(addr) + 1, 906 KM_SLEEP); 907 np = (in_node_t *)cp; 908 if (name) { 909 np->in_node_name = cp + sizeof (in_node_t); 910 (void) strcpy(np->in_node_name, name); 911 } 912 np->in_unit_addr = cp + sizeof (in_node_t) + namelen; 913 (void) strcpy(np->in_unit_addr, addr); 914 return (np); 915 } 916 917 /* 918 * Allocate a drv entry and storage for binding name string, and fill it in. 919 */ 920 static in_drv_t * 921 in_alloc_drv(char *bindingname) 922 { 923 in_drv_t *dp; 924 char *cp; 925 size_t namelen; 926 927 ASSERT(e_ddi_inst_state.ins_busy); 928 /* 929 * Has name or will become root 930 */ 931 ASSERT(bindingname || e_ddi_inst_state.ins_root == NULL); 932 if (bindingname == NULL) 933 namelen = 0; 934 else 935 namelen = strlen(bindingname) + 1; 936 cp = kmem_zalloc(sizeof (in_drv_t) + namelen, KM_SLEEP); 937 dp = (in_drv_t *)cp; 938 if (bindingname) { 939 dp->ind_driver_name = cp + sizeof (in_drv_t); 940 (void) strcpy(dp->ind_driver_name, bindingname); 941 } 942 dp->ind_state = IN_UNKNOWN; 943 dp->ind_instance = -1; 944 return (dp); 945 } 946 947 static void 948 in_dealloc_node(in_node_t *np) 949 { 950 /* 951 * The root node can never be de-allocated 952 */ 953 ASSERT(np->in_node_name && np->in_unit_addr); 954 ASSERT(e_ddi_inst_state.ins_busy); 955 kmem_free(np, sizeof (in_node_t) + strlen(np->in_node_name) 956 + strlen(np->in_unit_addr) + 2); 957 } 958 959 static void 960 in_dealloc_drv(in_drv_t *dp) 961 { 962 ASSERT(dp->ind_driver_name); 963 ASSERT(e_ddi_inst_state.ins_busy); 964 kmem_free(dp, sizeof (in_drv_t) + strlen(dp->ind_driver_name) 965 + 1); 966 } 967 968 /* 969 * Handle the various possible versions of "no address" 970 */ 971 static int 972 in_eqstr(char *a, char *b) 973 { 974 if (a == b) /* covers case where both are nulls */ 975 return (1); 976 if (a == NULL && *b == 0) 977 return (1); 978 if (b == NULL && *a == 0) 979 return (1); 980 if (a == NULL || b == NULL) 981 return (0); 982 return (strcmp(a, b) == 0); 983 } 984 985 /* 986 * Returns true if instance no. is already in use by named driver 987 */ 988 static int 989 in_inuse(int instance, char *name) 990 { 991 major_t major; 992 in_drv_t *dp; 993 struct devnames *dnp; 994 995 ASSERT(e_ddi_inst_state.ins_busy); 996 /* 997 * For now, if we've never heard of this device we assume it is not 998 * in use, since we can't tell 999 * XXX could do the weaker search through the nomajor list checking 1000 * XXX for the same name 1001 */ 1002 if ((major = ddi_name_to_major(name)) == (major_t)-1) 1003 return (0); 1004 dnp = &devnamesp[major]; 1005 1006 dp = dnp->dn_inlist; 1007 while (dp) { 1008 if (dp->ind_instance == instance) 1009 return (1); 1010 dp = dp->ind_next; 1011 } 1012 return (0); 1013 } 1014 1015 static void 1016 in_hashdrv(in_drv_t *dp) 1017 { 1018 struct devnames *dnp; 1019 in_drv_t *mp, *pp; 1020 major_t major; 1021 1022 /* hash to no major list */ 1023 if ((major = ddi_name_to_major(dp->ind_driver_name)) == (major_t)-1) { 1024 dp->ind_next = e_ddi_inst_state.ins_no_major; 1025 e_ddi_inst_state.ins_no_major = dp; 1026 return; 1027 } 1028 1029 /* 1030 * dnp->dn_inlist is sorted by instance number. 1031 * Adding a new instance entry may introduce holes, 1032 * set dn_instance to IN_SEARCHME so the next instance 1033 * assignment may fill in holes. 1034 */ 1035 dnp = &devnamesp[major]; 1036 pp = mp = dnp->dn_inlist; 1037 if (mp == NULL || dp->ind_instance < mp->ind_instance) { 1038 /* prepend as the first entry, turn on IN_SEARCHME */ 1039 dnp->dn_instance = IN_SEARCHME; 1040 dp->ind_next = mp; 1041 dnp->dn_inlist = dp; 1042 return; 1043 } 1044 1045 ASSERT(mp->ind_instance != dp->ind_instance); 1046 while (mp->ind_instance < dp->ind_instance && mp->ind_next) { 1047 pp = mp; 1048 mp = mp->ind_next; 1049 ASSERT(mp->ind_instance != dp->ind_instance); 1050 } 1051 1052 if (mp->ind_instance < dp->ind_instance) { /* end of list */ 1053 dp->ind_next = NULL; 1054 mp->ind_next = dp; 1055 } else { 1056 ASSERT(dnp->dn_instance == IN_SEARCHME); 1057 dp->ind_next = pp->ind_next; 1058 pp->ind_next = dp; 1059 } 1060 } 1061 1062 /* 1063 * Remove a driver entry from the list, given a previous pointer 1064 */ 1065 static void 1066 in_removedrv(struct devnames *dnp, in_drv_t *mp) 1067 { 1068 in_drv_t *dp; 1069 in_drv_t *prevp; 1070 1071 if (dnp->dn_inlist == mp) { /* head of list */ 1072 dnp->dn_inlist = mp->ind_next; 1073 dnp->dn_instance = IN_SEARCHME; 1074 in_dq_drv(mp); 1075 in_dealloc_drv(mp); 1076 return; 1077 } 1078 prevp = dnp->dn_inlist; 1079 for (dp = prevp->ind_next; dp; dp = dp->ind_next) { 1080 if (dp == mp) { /* found it */ 1081 break; 1082 } 1083 prevp = dp; 1084 } 1085 1086 ASSERT(dp == mp); 1087 dnp->dn_instance = IN_SEARCHME; 1088 prevp->ind_next = mp->ind_next; 1089 in_dq_drv(mp); 1090 in_dealloc_drv(mp); 1091 } 1092 1093 static void 1094 in_dq_drv(in_drv_t *mp) 1095 { 1096 struct in_node *node = mp->ind_node; 1097 in_drv_t *ptr, *prev; 1098 1099 if (mp == node->in_drivers) { 1100 node->in_drivers = mp->ind_next_drv; 1101 return; 1102 } 1103 prev = node->in_drivers; 1104 for (ptr = prev->ind_next_drv; ptr != (struct in_drv *)NULL; 1105 ptr = ptr->ind_next_drv) { 1106 if (ptr == mp) { 1107 prev->ind_next_drv = ptr->ind_next_drv; 1108 return; 1109 } 1110 } 1111 panic("in_dq_drv: in_drv not found on node driver list"); 1112 } 1113 1114 1115 in_drv_t * 1116 in_drvwalk(in_node_t *np, char *binding_name) 1117 { 1118 char *name; 1119 in_drv_t *dp = np->in_drivers; 1120 while (dp) { 1121 if ((name = i_binding_to_drv_name(dp->ind_driver_name)) 1122 == NULL) { 1123 name = dp->ind_driver_name; 1124 } 1125 if (strcmp(binding_name, name) == 0) { 1126 break; 1127 } 1128 dp = dp->ind_next_drv; 1129 } 1130 return (dp); 1131 } 1132 1133 1134 1135 static void 1136 i_log_devfs_instance_mod(void) 1137 { 1138 sysevent_t *ev; 1139 sysevent_id_t eid; 1140 1141 /* 1142 * Prevent unnecessary event generation. Do not need to generate 1143 * events during boot. 1144 */ 1145 if (!i_ddi_io_initialized()) 1146 return; 1147 1148 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_INSTANCE_MOD, EP_DDI, 1149 SE_NOSLEEP); 1150 if (ev == NULL) { 1151 return; 1152 } 1153 if (log_sysevent(ev, SE_NOSLEEP, &eid) != 0) { 1154 cmn_err(CE_WARN, "i_log_devfs_instance_mod: failed to post " 1155 "event"); 1156 } 1157 sysevent_free(ev); 1158 } 1159 1160 void 1161 e_ddi_enter_instance() 1162 { 1163 mutex_enter(&e_ddi_inst_state.ins_serial); 1164 if (e_ddi_inst_state.ins_thread == curthread) 1165 e_ddi_inst_state.ins_busy++; 1166 else { 1167 while (e_ddi_inst_state.ins_busy) 1168 cv_wait(&e_ddi_inst_state.ins_serial_cv, 1169 &e_ddi_inst_state.ins_serial); 1170 e_ddi_inst_state.ins_thread = curthread; 1171 e_ddi_inst_state.ins_busy = 1; 1172 } 1173 mutex_exit(&e_ddi_inst_state.ins_serial); 1174 } 1175 1176 void 1177 e_ddi_exit_instance() 1178 { 1179 mutex_enter(&e_ddi_inst_state.ins_serial); 1180 e_ddi_inst_state.ins_busy--; 1181 if (e_ddi_inst_state.ins_busy == 0) { 1182 cv_broadcast(&e_ddi_inst_state.ins_serial_cv); 1183 e_ddi_inst_state.ins_thread = NULL; 1184 } 1185 mutex_exit(&e_ddi_inst_state.ins_serial); 1186 } 1187 1188 int 1189 e_ddi_instance_is_clean() 1190 { 1191 return (e_ddi_inst_state.ins_dirty == 0); 1192 } 1193 1194 void 1195 e_ddi_instance_set_clean() 1196 { 1197 e_ddi_inst_state.ins_dirty = 0; 1198 } 1199 1200 in_node_t * 1201 e_ddi_instance_root() 1202 { 1203 return (e_ddi_inst_state.ins_root); 1204 } 1205 1206 /* 1207 * Visit a node in the instance tree 1208 */ 1209 static int 1210 in_walk_instances(in_node_t *np, char *path, char *this, 1211 int (*f)(const char *, in_node_t *, in_drv_t *, void *), void *arg) 1212 { 1213 in_drv_t *dp; 1214 int rval = INST_WALK_CONTINUE; 1215 char *next; 1216 1217 while (np != NULL) { 1218 1219 if (np->in_unit_addr[0] == 0) 1220 (void) sprintf(this, "/%s", np->in_node_name); 1221 else 1222 (void) sprintf(this, "/%s@%s", np->in_node_name, 1223 np->in_unit_addr); 1224 next = this + strlen(this); 1225 1226 for (dp = np->in_drivers; dp; dp = dp->ind_next_drv) { 1227 if (dp->ind_state == IN_PERMANENT) { 1228 rval = (*f)(path, np, dp, arg); 1229 if (rval == INST_WALK_TERMINATE) 1230 break; 1231 } 1232 } 1233 if (np->in_child) { 1234 rval = in_walk_instances(np->in_child, 1235 path, next, f, arg); 1236 if (rval == INST_WALK_TERMINATE) 1237 break; 1238 } 1239 1240 np = np->in_sibling; 1241 } 1242 1243 return (rval); 1244 } 1245 1246 /* 1247 * A general interface for walking the instance tree, 1248 * calling a user-supplied callback for each node. 1249 */ 1250 int 1251 e_ddi_walk_instances(int (*f)(const char *, 1252 in_node_t *, in_drv_t *, void *), void *arg) 1253 { 1254 in_node_t *root; 1255 int rval; 1256 char *path; 1257 1258 path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1259 1260 e_ddi_enter_instance(); 1261 root = e_ddi_instance_root(); 1262 rval = in_walk_instances(root->in_child, path, path, f, arg); 1263 e_ddi_exit_instance(); 1264 1265 kmem_free(path, MAXPATHLEN); 1266 return (rval); 1267 } 1268