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