Esempio n. 1
0
/*
 * During each register callback: totally rebuild the group list from a new
 * libdevinfo snapshot, and then update the registrants.
 */
static int
mpxio_register(rcm_handle_t *hdl)
{
	int nclients = 0;
	di_node_t devroot;

	rcm_log_message(RCM_TRACE1, "MPXIO: register()\n");

	(void) mutex_lock(&mpxio_lock);

	/* Destroy the previous group list */
	free_grouplist();

	/* Get a current libdevinfo snapshot */
	if ((devroot = di_init("/", DINFOCPYALL | DINFOPATH)) == DI_NODE_NIL) {
		rcm_log_message(RCM_ERROR,
		    "MPXIO: libdevinfo initialization failed (%s).\n",
		    strerror(errno));
		(void) mutex_unlock(&mpxio_lock);
		return (RCM_FAILURE);
	}

	/*
	 * First count the total number of clients.  This'll be a useful
	 * upper bound when allocating client arrays within each group.
	 */
	(void) di_walk_node(devroot, DI_WALK_CLDFIRST, &nclients, get_nclients);

	rcm_log_message(RCM_TRACE2, gettext("MPXIO: found %d clients.\n"),
	    nclients);

	/*
	 * Then walk the libdevinfo snapshot, building up the new group list
	 * along the way.  Pass in the total number of clients (from above) to
	 * assist in group construction.
	 */
	(void) di_walk_node(devroot, DI_WALK_CLDFIRST, &nclients, build_groups);

	/* Now with a new group list constructed, refresh the registrants */
	refresh_regs(hdl);

	/* Free the libdevinfo snapshot */
	di_fini(devroot);

	(void) mutex_unlock(&mpxio_lock);

	return (0);
}
Esempio n. 2
0
int
dev_list_gather(topo_mod_t *mod, topo_list_t *listp)
{
	di_node_t		devtree;
	di_devlink_handle_t	devhdl;
	disk_cbdata_t		dcb;

	if ((devtree = topo_mod_devinfo(mod)) == DI_NODE_NIL) {
		topo_mod_dprintf(mod, "disk_list_gather: "
		    "topo_mod_devinfo() failed");
		return (-1);
	}

	if ((devhdl = di_devlink_init(NULL, 0)) == DI_NODE_NIL) {
		topo_mod_dprintf(mod, "disk_list_gather: "
		    "di_devlink_init() failed");
		return (-1);
	}

	dcb.dcb_mod = mod;
	dcb.dcb_list = listp;
	dcb.dcb_devhdl = devhdl;

	/* walk the devinfo snapshot looking for disk nodes */
	(void) di_walk_node(devtree, DI_WALK_CLDFIRST, &dcb,
	    dev_walk_di_nodes);

	(void) di_devlink_fini(&devhdl);

	return (0);
}
Esempio n. 3
0
static int
destroy_console_devs(zlog_t *zlogp)
{
	char conspath[MAXPATHLEN];
	di_node_t root;
	struct cb_data cb;
	int masterfd;
	int slavefd;

	/*
	 * Signal the master side to release its handle on the slave side by
	 * issuing a ZC_RELEASESLAVE ioctl.
	 */
	(void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
	    zone_name, ZCONS_MASTER_NAME);
	if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) != -1) {
		(void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
		    zone_name, ZCONS_SLAVE_NAME);
		if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) != -1) {
			if (ioctl(masterfd, ZC_RELEASESLAVE,
			    (caddr_t)(intptr_t)slavefd) != 0)
				zerror(zlogp, B_TRUE, "WARNING: error while "
				    "releasing slave handle of zone console for"
				    " %s", zone_name);
			(void) close(slavefd);
		} else {
			zerror(zlogp, B_TRUE, "WARNING: could not open slave "
			    "side of zone console for %s to release slave "
			    "handle", zone_name);
		}
		(void) close(masterfd);
	} else {
		zerror(zlogp, B_TRUE, "WARNING: could not open master side of "
		    "zone console for %s to release slave handle", zone_name);
	}

	bzero(&cb, sizeof (cb));
	cb.zlogp = zlogp;

	if ((root = di_init(ZCONSNEX_DEVTREEPATH, DINFOCPYALL)) ==
	    DI_NODE_NIL) {
		zerror(zlogp, B_TRUE, "%s failed", "di_init");
		return (-1);
	}

	(void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, destroy_cb);
	if (cb.found > 1) {
		zerror(zlogp, B_FALSE, "WARNING: multiple zone console "
		    "instances detected for zone '%s'; %d of %d "
		    "successfully removed.",
		    zone_name, cb.killed, cb.found);
	}

	di_fini(root);
	return (0);
}
Esempio n. 4
0
/*
 * Map a device path to its matching di_node_t.
 */
static di_node_t
path2node(char *path)
{
	cb_t	cb;

	cb.cb_path = path;
	cb.cb_node = DI_NODE_NIL;

	(void) di_walk_node(root_node, DI_WALK_CLDFIRST, &cb, p2n_cb);

	return (cb.cb_node);
}
PUSBDEVICE USBProxyServiceSolaris::getDevices(void)
{
    USBDEVICELIST DevList;
    DevList.pHead = NULL;
    DevList.pTail = NULL;
    di_node_t RootNode = di_init("/", DINFOCPYALL);
    if (RootNode != DI_NODE_NIL)
        di_walk_node(RootNode, DI_WALK_CLDFIRST, &DevList, solarisWalkDeviceNode);

    di_fini(RootNode);
    return DevList.pHead;
}
Esempio n. 6
0
/*
 * checks if a fru is present under location using pdev-path and busaddr
 */
boolean_t
is_fru_present_under_location(frutree_locnode_t *locp)
{
	di_node_t		rnode;
	frutree_devinfo_t	*devinfo = NULL;
	char probe_path[PICL_PROPNAMELEN_MAX];

	if (locp == NULL) {
		return (B_FALSE);
	}

	if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_PROBE_PATH,
		probe_path, sizeof (probe_path)) != PICL_SUCCESS) {
		if (ptree_get_propval_by_name(locp->locnodeh,
			PICL_PROP_DEVFS_PATH, probe_path,
			sizeof (probe_path)) != PICL_SUCCESS) {
			return (B_FALSE);
		}
	}

	rnode = di_init(probe_path, DINFOSUBTREE);
	if (rnode == DI_NODE_NIL) {
		di_fini(rnode);
		return (B_FALSE);
	}

	devinfo = (frutree_devinfo_t *)malloc(sizeof (frutree_devinfo_t));
	if (devinfo == NULL) {
		di_fini(rnode);
		return (B_FALSE);
	}
	devinfo->rnode = rnode;
	devinfo->arg = (frutree_locnode_t **)&locp;
	devinfo->retval = PICL_FAILURE;

	if (di_walk_node(rnode, DI_WALK_SIBFIRST, &devinfo,
		find_fru_node) != 0) {
		di_fini(rnode);
		free(devinfo);
		return (B_FALSE);
	}
	di_fini(rnode);

	if (devinfo->retval == PICL_SUCCESS) {
		free(devinfo);
		return (B_TRUE);
	} else {
		free(devinfo);
		return (B_FALSE);
	}
}
Esempio n. 7
0
static int
count_zfd_devs(zlog_t *zlogp)
{
	di_node_t root;
	struct cb_data cb;

	bzero(&cb, sizeof (cb));
	cb.zlogp = zlogp;

	if ((root = di_init(ZFDNEX_DEVTREEPATH, DINFOCPYALL)) == DI_NODE_NIL) {
		zerror(zlogp, B_TRUE, "di_init failed");
		return (-1);
	}

	(void) di_walk_node(root, DI_WALK_CLDFIRST, (void *)&cb, count_cb);
	di_fini(root);
	return (cb.found);
}
Esempio n. 8
0
/*
 * Force all "network" drivers to be loaded.
 *
 * Returns: ICFG_SUCCESS or ICFG_FAILURE. In the case of
 *          ICFG_FAILURE, syserr will contain the errno.
 */
static int
nic_load_drivers(int *syserr)
{
	di_node_t root_node;
	di_prom_handle_t ph;
	int ret;

	root_node = di_init(NIC_DEVTREE_ROOT, DINFOCPYALL);
	if (root_node == DI_NODE_NIL) {
		*syserr = errno;
		return (ICFG_FAILURE);
	}

	/*
	 * Create handle to PROM
	 */
	if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) {
		*syserr = errno;
		di_fini(root_node);
		return (ICFG_FAILURE);
	}

	/*
	 * Walk nodes and make sure all network devices have
	 * drivers loaded so that devinfo has accurate data.
	 */
	ret = di_walk_node(root_node, DI_WALK_CLDFIRST, ph, process_node);
	if (ret != 0) {
		*syserr = errno;
		di_prom_fini(ph);
		di_fini(root_node);
		return (ICFG_FAILURE);
	}

	/*
	 * Clean up handles
	 */
	di_prom_fini(ph);
	di_fini(root_node);

	return (ICFG_SUCCESS);
}
Esempio n. 9
0
static picl_errno_t
load_drivers(char *path)
{
	di_node_t	rnode;
	if (path == NULL) {
		return (PICL_INVALIDARG);
	}

	rnode = di_init(path, DINFOSUBTREE|DINFOMINOR);
	if (rnode == DI_NODE_NIL) {
		return (PICL_FAILURE);
	}

	if (di_walk_node(rnode, DI_WALK_CLDFIRST, NULL, load_driver) != 0) {
		di_fini(rnode);
		return (PICL_FAILURE);
	}

	di_fini(rnode);
	return (PICL_SUCCESS);
}
Esempio n. 10
0
int
sunos_get_device_list(struct libusb_context * ctx,
	struct discovered_devs **discdevs)
{
	di_node_t root_node;
	struct node_args args;
	di_devlink_handle_t devlink_hdl;

	args.ctx = ctx;
	args.discdevs = discdevs;
	args.last_ugenpath = NULL;
	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
		usbi_dbg("di_int() failed: %s", strerror(errno));
		return (LIBUSB_ERROR_IO);
	}

	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
		di_fini(root_node);
		usbi_dbg("di_devlink_init() failed: %s", strerror(errno));

		return (LIBUSB_ERROR_IO);
	}
	args.dlink_hdl = devlink_hdl;

	/* walk each node to find USB devices */
	if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args,
	    sunos_walk_minor_node_link) == -1) {
		usbi_dbg("di_walk_node() failed: %s", strerror(errno));
		di_fini(root_node);

		return (LIBUSB_ERROR_IO);
	}

	di_fini(root_node);
	di_devlink_fini(&devlink_hdl);

	usbi_dbg("%d devices", (*discdevs)->len);

	return ((*discdevs)->len);
}
Esempio n. 11
0
int main()
{
    di_node_t root_node;

    int fd;

    if ((fd = open("/tmp/bootparams", O_RDONLY)) != -1) {
        /* If this file exists it acts as a replacement for the normal data */
        raw_cat(fd);
        close(fd);
    } else {
        /* We didn't have or couldn't open the file, so just get actual params */
        root_node = di_init("/", (DINFOSUBTREE | DINFOPROP));
        if (root_node == DI_NODE_NIL) {
            fprintf(stderr, "di_init() failed\n");
            exit(1);
        }
        di_walk_node(root_node, DI_WALK_CLDFIRST, NULL, prt_node);
        di_fini(root_node);
    }

    exit(EXIT_SUCCESS);
}
Esempio n. 12
0
static int
getpath(char *path, int instance, char *name, int pathlen)
{
	di_node_t node;
	struct walk_arg warg;

	warg.instance = instance;
	(void) strncpy(warg.name, name, MAXPATHLEN);
	warg.path = path;
	warg.pathlen = pathlen;
	warg.found = 0;
	if ((node = di_init("/", DINFOSUBTREE)) == DI_NODE_NIL)
		return (-1);
	if (di_walk_node(node, DI_WALK_CLDFIRST, &warg, walk_callback) == -1) {
		di_fini(node);
		return (-1);
	}
	if (warg.found == 0) {
		di_fini(node);
		return (-1);
	}
	di_fini(node);
	return (0);
}
/*
 * Solaris version
 */
static int
pci_device_solx_devfs_probe( struct pci_device * dev )
{
    int err = 0;
    di_node_t rnode = DI_NODE_NIL;
    i_devnode_t args = { 0, 0, 0, DI_NODE_NIL };
    int *regbuf;
    pci_regspec_t *reg;
    int i;
    int len = 0;
    uint ent = 0;
    nexus_t *nexus;

#ifdef __sparc
    if ( (nexus = find_nexus_for_dev(dev)) == NULL )
#else
    if ( (nexus = find_nexus_for_bus(dev->domain, dev->bus)) == NULL )
#endif
	return ENODEV;

    /*
     * starting to find if it is MEM/MEM64/IO
     * using libdevinfo
     */
    if ((rnode = di_init(nexus->dev_path, DINFOCPYALL)) == DI_NODE_NIL) {
	err = errno;
	(void) fprintf(stderr, "di_init failed: %s\n", strerror(errno));
    } else {
	args.bus = dev->bus;
	args.dev = dev->dev;
	args.func = dev->func;
	(void) di_walk_node(rnode, DI_WALK_CLDFIRST,
		(void *)&args, find_target_node);
    }

    if (args.node != DI_NODE_NIL) {
#ifdef __sparc
	di_minor_t minor;
#endif

#ifdef __sparc
	if (minor = di_minor_next(args.node, DI_MINOR_NIL))
	    MAPPING_DEV_PATH(dev) = di_devfs_minor_path (minor);
	else
	    MAPPING_DEV_PATH(dev) = NULL;
#endif

	/*
	 * It will succeed for sure, because it was
	 * successfully called in find_target_node
	 */
	len = di_prop_lookup_ints(DDI_DEV_T_ANY, args.node,
				  "assigned-addresses",
				  &regbuf);

#ifdef __sparc
	if ((len <= 0) && di_phdl) {
	    len = di_prom_prop_lookup_ints(di_phdl, args.node,
				"assigned-addresses", &regbuf);
	}
#endif
    }

    if (len <= 0)
	goto cleanup;


    /*
     * how to find the size of rom???
     * if the device has expansion rom,
     * it must be listed in the last
     * cells because solaris find probe
     * the base address from offset 0x10
     * to 0x30h. So only check the last
     * item.
     */
    reg = (pci_regspec_t *)&regbuf[len - CELL_NUMS_1275];
    if (PCI_REG_REG_G(reg->pci_phys_hi) == PCI_CONF_ROM) {
	/*
	 * rom can only be 32 bits
	 */
	dev->rom_size = reg->pci_size_low;
	len = len - CELL_NUMS_1275;
    }
    else {
	/*
	 * size default to 64K and base address
	 * default to 0xC0000
	 */
	dev->rom_size = 0x10000;
    }

    /*
     * Solaris has its own BAR index.
     * Linux give two region slot for 64 bit address.
     */
    for (i = 0; i < len; i = i + CELL_NUMS_1275) {

	reg = (pci_regspec_t *)&regbuf[i];
	ent = reg->pci_phys_hi & 0xff;
	/*
	 * G35 broken in BAR0
	 */
	ent = (ent - PCI_CONF_BASE0) >> 2;
	if (ent >= 6) {
	    fprintf(stderr, "error ent = %d\n", ent);
	    break;
	}

	/*
	 * non relocatable resource is excluded
	 * such like 0xa0000, 0x3b0. If it is met,
	 * the loop is broken;
	 */
	if (!PCI_REG_REG_G(reg->pci_phys_hi))
	    break;

	if (reg->pci_phys_hi & PCI_PREFETCH_B) {
	    dev->regions[ent].is_prefetchable = 1;
	}


	/*
	 * We split the shift count 32 into two 16 to
	 * avoid the complaining of the compiler
	 */
	dev->regions[ent].base_addr = reg->pci_phys_low +
	    ((reg->pci_phys_mid << 16) << 16);
	dev->regions[ent].size = reg->pci_size_low +
	    ((reg->pci_size_hi << 16) << 16);

	switch (reg->pci_phys_hi & PCI_REG_ADDR_M) {
	    case PCI_ADDR_IO:
		dev->regions[ent].is_IO = 1;
		break;
	    case PCI_ADDR_MEM32:
		break;
	    case PCI_ADDR_MEM64:
		dev->regions[ent].is_64 = 1;
		/*
		 * Skip one slot for 64 bit address
		 */
		break;
	}
    }

  cleanup:
    if (rnode != DI_NODE_NIL) {
	di_fini(rnode);
    }
    return (err);
}
Esempio n. 14
0
/* This routine probes libdevinfo for port nodes */
picl_errno_t
probe_libdevinfo(frutree_frunode_t *frup, frutree_device_args_t ** device,
	boolean_t load_drv)
{
	di_node_t	rnode;
	picl_errno_t	rc;
	plist_t	list;

	if (frup == NULL) {
		return (PICL_FAILURE);
	}
	FRUTREE_DEBUG1(EVENTS, "loading drivers for %s", frup->name);

	if (load_drv == B_TRUE) {
		if ((rc = load_drivers(frup->fru_path)) != PICL_SUCCESS) {
			return (rc);
		}
	}
	FRUTREE_DEBUG1(EVENTS, "done with loading drivers for %s", frup->name);

	rnode = di_init(frup->fru_path, DINFOSUBTREE|DINFOMINOR);
	if (rnode == DI_NODE_NIL) {
		return (PICL_FAILURE);
	}

	list.first = NULL;
	list.last = NULL;
	list.n_network = 0;
	list.n_serial = 0;
	list.n_parallel = 0;

	if (di_walk_node(rnode, DI_WALK_CLDFIRST, &list, probe_tree) != 0) {
		di_fini(rnode);
		free_list(&list);
		return (PICL_FAILURE);
	}

	if (list.n_serial > 0)
	if ((rc = assign_geo_addr(&list, SERIAL_PORT)) != PICL_SUCCESS) {
		di_fini(rnode);
		free_list(&list);
		return (rc);
	}

	if (list.n_network > 0)
	if ((rc = assign_geo_addr(&list, NETWORK_PORT)) != PICL_SUCCESS) {
		di_fini(rnode);
		free_list(&list);
		return (rc);
	}

	if (list.n_parallel > 0)
	if ((rc = assign_geo_addr(&list, PARALLEL_PORT)) != PICL_SUCCESS) {
		di_fini(rnode);
		free_list(&list);
		return (rc);
	}

	if ((rc = create_port_config_info(&list, *device)) != PICL_SUCCESS) {
		di_fini(rnode);
		free_list(&list);
		return (rc);
	}

	di_fini(rnode);
	free_list(&list);
	FRUTREE_DEBUG1(EVENTS, "done with probing %s", frup->name);
	return (PICL_SUCCESS);
}
Esempio n. 15
0
picl_errno_t
get_fru_path(char *parent_path, frutree_frunode_t *frup)
{
	picl_errno_t rc = 0;
	picl_nodehdl_t loch;
	di_node_t rnode;
	frutree_devinfo_t *devinfo = NULL;
	char slot_type[PICL_PROPNAMELEN_MAX];
	char probe_path[PICL_PROPNAMELEN_MAX];
	char bus_addr[PICL_PROPNAMELEN_MAX];

	if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT,
		&loch, sizeof (loch))) != PICL_SUCCESS) {
		return (rc);
	}

	if ((rc = ptree_get_propval_by_name(loch, PICL_PROP_SLOT_TYPE,
		slot_type, sizeof (slot_type))) != PICL_SUCCESS) {
		return (rc);
	}

	if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 ||
		strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) {
		if (ptree_get_propval_by_name(loch, PICL_PROP_PROBE_PATH,
			probe_path, sizeof (probe_path)) != PICL_SUCCESS) {
			return (rc);
		}
		(void) strncpy(frup->fru_path, probe_path,
			sizeof (frup->fru_path));
		return (PICL_SUCCESS);
	}

	prom_handle = di_prom_init();
	rnode = di_init(parent_path, DINFOSUBTREE|DINFOMINOR);
	if (rnode == DI_NODE_NIL) {
		di_prom_fini(prom_handle);
		return (PICL_FAILURE);
	}

	devinfo = (frutree_devinfo_t *)malloc(sizeof (frutree_devinfo_t));
	if (devinfo == NULL) {
		di_fini(rnode);
		di_prom_fini(prom_handle);
		return (PICL_NOSPACE);
	}

	if (ptree_get_propval_by_name(loch, PICL_PROP_BUS_ADDR,
		bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) {
		free(devinfo);
		di_fini(rnode);
		di_prom_fini(prom_handle);
		return (rc);
	}

	devinfo->rnode = rnode;
	(void) strncpy(devinfo->bus_addr, bus_addr, sizeof (devinfo->bus_addr));
	devinfo->path[0] = '\0';
	devinfo->arg = frup;

	if (di_walk_node(rnode, DI_WALK_SIBFIRST, &devinfo, walk_tree) != 0) {
		di_fini(rnode);
		di_prom_fini(prom_handle);
		free(devinfo);
		return (PICL_FAILURE);
	}
	di_fini(rnode);
	di_prom_fini(prom_handle);

	if (devinfo->path[0]) {
		(void) strncpy(frup->fru_path, devinfo->path,
			sizeof (frup->fru_path));
		free(devinfo);
		return (PICL_SUCCESS);
	} else {
		free(devinfo);
		return (PICL_NODENOTFOUND);
	}
}
Esempio n. 16
0
int
main(int argc, char *argv[])
{
	int c, i, ret;
	di_node_t root;
	ahciem_t ahci;

	ahciem_progname = basename(argv[0]);

	bzero(&ahci, sizeof (ahciem_t));
	while ((c = getopt(argc, argv, ":s:")) != -1) {
		switch (c) {
		case 's':
			ahci.ahci_set = B_TRUE;
			ahci.ahci_led = ahciem_parse(optarg);
			break;
		case ':':
			ahciem_usage("option -%c requires an operand\n",
			    optopt);
			return (EXIT_USAGE);
		case '?':
		default:
			ahciem_usage("unknown option: -%c\n", optopt);
			return (EXIT_USAGE);
		}
	}

	argc -= optind;
	argv += optind;
	ahci.ahci_argc = argc;
	ahci.ahci_argv = argv;
	if (argc > 0) {
		ahci.ahci_found = calloc(argc, sizeof (boolean_t));
		if (ahci.ahci_found == NULL) {
			err(EXIT_FAILURE, "failed to alloc memory for %d "
			    "booleans", argc);
		}
	}

	if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
		err(EXIT_FAILURE, "failed to open devinfo tree");
	}

	if (!ahci.ahci_set) {
		(void) printf("%-20s %-12s %s\n", "PORT", "ACTIVE",
		    "SUPPORTED");
	}

	if (di_walk_node(root, DI_WALK_CLDFIRST, &ahci,
	    ahciem_devinfo) != 0) {
		err(EXIT_FAILURE, "failed to walk devinfo tree");
	}

	ret = ahci.ahci_err;
	for (i = 0; i < argc; i++) {
		if (ahci.ahci_found[i])
			continue;
		warnx("failed to find ahci enclosure port \"%s\"",
		    ahci.ahci_argv[i]);
		ret = 1;
	}

	return (ret);
}
/*
 * Refreshes information about an HBA
 *
 * Note: This routine holds the locks in write mode
 *       during most of the processing, and as such, will cause
 *	 all other threads to block on entry into the library
 *	 until the refresh is complete.  An optimization would be
 *       to put fine-grain locking in for the open_handle structures.
 */
void
Sun_sasRefreshAdapterConfiguration()
{
	const char		    ROUTINE[] =
	    "Sun_sasRefreshAdapterConfiguration";
	struct sun_sas_hba	    *hba_ptr;
	di_node_t		    root;
	hrtime_t		    start;
	hrtime_t		    end;
	double			    duration;
	walkarg_t		    wa;

	/*
	 * We're going to be tweaking a lot of global lists, so write
	 * lock them.
	 */
	lock(&all_hbas_lock);
	lock(&open_handles_lock);

	start = gethrtime();
	/* Grab device tree */
	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
		log(LOG_DEBUG, ROUTINE,
		    "Unable to load device tree for reason \"%s\"",
		    strerror(errno));
		unlock(&open_handles_lock);
		unlock(&all_hbas_lock);
		return;
	}

	end = gethrtime();
	duration = end - start;
	duration /= HR_SECOND;
	log(LOG_DEBUG, ROUTINE, "Device tree init took "
	    "%.6f seconds", duration);

	for (hba_ptr = global_hba_head; hba_ptr != NULL;
	    hba_ptr = hba_ptr->next) {
		wa.devpath = hba_ptr->device_path;
		wa.flag = (boolean_t *)calloc(1, sizeof (boolean_t));
		*wa.flag = B_FALSE;

		if (di_walk_node(root, DI_WALK_SIBFIRST, &wa,
		    find_matching_hba) != 0) {
			log(LOG_DEBUG, ROUTINE, "di_walk_node failed.");
			unlock(&open_handles_lock);
			unlock(&all_hbas_lock);
			S_FREE(wa.flag);
			di_fini(root);
			return;
		}

		if (*wa.flag == B_FALSE) {
			/*
			 * Keep the HBA as it is including open handles
			 * per the SM-HBA standards. Just mark it as invalid.
			 */
			log(LOG_DEBUG, ROUTINE, "No matching HBA found. %s",
			    hba_ptr->device_path);
			hba_ptr->invalid = B_TRUE;
		}
		S_FREE(wa.flag);
	}

	/*
	 * Now we marked missing HBA(s). Redisoover hbas to refresh
	 * or add any new adapter to the hba list.
	 * Simply call devtree_get_all_hbas().
	 */
	if (devtree_get_all_hbas(root) != HBA_STATUS_OK) {
		log(LOG_DEBUG, ROUTINE, "devtree_get_all_hbas failed.");
	}
	di_fini(root);

	unlock(&open_handles_lock);
	unlock(&all_hbas_lock);
}