908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * CDDL HEADER START
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * The contents of this file are subject to the terms of the
908f1e1388f616898b4e515d343c0414f2a6472esd * Common Development and Distribution License (the "License").
908f1e1388f616898b4e515d343c0414f2a6472esd * You may not use this file except in compliance with the License.
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
908f1e1388f616898b4e515d343c0414f2a6472esd * or http://www.opensolaris.org/os/licensing.
908f1e1388f616898b4e515d343c0414f2a6472esd * See the License for the specific language governing permissions
908f1e1388f616898b4e515d343c0414f2a6472esd * and limitations under the License.
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * When distributing Covered Code, include this CDDL HEADER in each
908f1e1388f616898b4e515d343c0414f2a6472esd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
908f1e1388f616898b4e515d343c0414f2a6472esd * If applicable, add the following below this CDDL HEADER, with the
908f1e1388f616898b4e515d343c0414f2a6472esd * fields enclosed by brackets "[]" replaced with your own identifying
908f1e1388f616898b4e515d343c0414f2a6472esd * information: Portions Copyright [yyyy] [name of copyright owner]
908f1e1388f616898b4e515d343c0414f2a6472esd *
908f1e1388f616898b4e515d343c0414f2a6472esd * CDDL HEADER END
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
908f1e1388f616898b4e515d343c0414f2a6472esd * Use is subject to license terms.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * Some topology creation routines may need to defer completing enumeration
908f1e1388f616898b4e515d343c0414f2a6472esd * until after the entire PRI graph has been visited. This file includes
908f1e1388f616898b4e515d343c0414f2a6472esd * the interfaces necessary to permit these routines to do this in a general
908f1e1388f616898b4e515d343c0414f2a6472esd * way.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd#include <sys/types.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <sys/time.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <stddef.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <inttypes.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <strings.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <string.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <libuutil.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <libnvpair.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <sys/mdesc.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <fm/topo_mod.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include <fm/topo_hc.h>
908f1e1388f616898b4e515d343c0414f2a6472esd#include "pi_impl.h"
908f1e1388f616898b4e515d343c0414f2a6472esd
021ceb9857f712f245edda92c7eb82f0a3a83acbTom Pothierstatic uu_list_pool_t *defer_pool = NULL;
021ceb9857f712f245edda92c7eb82f0a3a83acbTom Pothierstatic uu_list_t *defer_list = NULL;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esdstruct pi_defernode_s {
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_node_t defer_node;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd mde_cookie_t mde_node; /* MDE node index */
908f1e1388f616898b4e515d343c0414f2a6472esd tnode_t *t_parent; /* Parent topology node */
908f1e1388f616898b4e515d343c0414f2a6472esd tnode_t *t_node; /* Topo node associated with MDE node */
908f1e1388f616898b4e515d343c0414f2a6472esd void *private; /* Private data for defer routine */
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd pi_deferenum_fn_t *func; /* Defered enumeration routine */
908f1e1388f616898b4e515d343c0414f2a6472esd};
908f1e1388f616898b4e515d343c0414f2a6472esdtypedef struct pi_defernode_s pi_defernode_t;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/* Routines to handle the list of topology parents and mde_nodes */
908f1e1388f616898b4e515d343c0414f2a6472esdstatic int pi_deferlist_create(topo_mod_t *);
908f1e1388f616898b4e515d343c0414f2a6472esdstatic int pi_deferlist_compare(const void *, const void *, void *);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * Add a new routine to the list of deferred enumeration routines
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esdint
908f1e1388f616898b4e515d343c0414f2a6472esdpi_defer_add(topo_mod_t *mod, mde_cookie_t mde_node, tnode_t *t_parent,
908f1e1388f616898b4e515d343c0414f2a6472esd tnode_t *t_node, pi_deferenum_fn_t func, void *private)
908f1e1388f616898b4e515d343c0414f2a6472esd{
908f1e1388f616898b4e515d343c0414f2a6472esd int result;
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_index_t idx;
908f1e1388f616898b4e515d343c0414f2a6472esd pi_defernode_t *dnp;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd if (defer_list == NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd result = pi_deferlist_create(mod);
908f1e1388f616898b4e515d343c0414f2a6472esd if (result != 0) {
908f1e1388f616898b4e515d343c0414f2a6472esd return (result);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /*
908f1e1388f616898b4e515d343c0414f2a6472esd * Create a data structure to store information about the node for
908f1e1388f616898b4e515d343c0414f2a6472esd * which to defer enumeration. The defer_pool is created by the
908f1e1388f616898b4e515d343c0414f2a6472esd * list creation routine, above.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd dnp = topo_mod_zalloc(mod, sizeof (pi_defernode_t));
908f1e1388f616898b4e515d343c0414f2a6472esd if (dnp == NULL) {
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_NOMEM);
908f1e1388f616898b4e515d343c0414f2a6472esd return (-1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_node_init(dnp, &(dnp->defer_node), defer_pool);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd dnp->mde_node = mde_node;
908f1e1388f616898b4e515d343c0414f2a6472esd dnp->t_parent = t_parent;
908f1e1388f616898b4e515d343c0414f2a6472esd dnp->t_node = t_node;
908f1e1388f616898b4e515d343c0414f2a6472esd dnp->private = private;
908f1e1388f616898b4e515d343c0414f2a6472esd dnp->func = func;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd (void) uu_list_find(defer_list, dnp, NULL, &idx);
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_insert(defer_list, dnp, idx);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd return (0);
908f1e1388f616898b4e515d343c0414f2a6472esd}
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/*
908f1e1388f616898b4e515d343c0414f2a6472esd * Execute the list of deferred enumeration routines, destroying the list as
908f1e1388f616898b4e515d343c0414f2a6472esd * we go.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esdint
908f1e1388f616898b4e515d343c0414f2a6472esdpi_defer_exec(topo_mod_t *mod, md_t *mdp)
908f1e1388f616898b4e515d343c0414f2a6472esd{
908f1e1388f616898b4e515d343c0414f2a6472esd int result;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd void *dvp;
908f1e1388f616898b4e515d343c0414f2a6472esd pi_defernode_t *dp;
908f1e1388f616898b4e515d343c0414f2a6472esd topo_instance_t inst;
908f1e1388f616898b4e515d343c0414f2a6472esd mde_cookie_t mde_node;
908f1e1388f616898b4e515d343c0414f2a6472esd tnode_t *t_parent;
908f1e1388f616898b4e515d343c0414f2a6472esd tnode_t *t_node;
908f1e1388f616898b4e515d343c0414f2a6472esd void *private;
908f1e1388f616898b4e515d343c0414f2a6472esd char *hc_name;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd pi_deferenum_fn_t *func;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod, "beginning deferred enumerator execution\n");
908f1e1388f616898b4e515d343c0414f2a6472esd if (defer_list == NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod, "no deferred enumerators. done.\n");
908f1e1388f616898b4e515d343c0414f2a6472esd return (0);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd while ((dvp = uu_list_first(defer_list)) != NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd /* Extract the necessary information from the defernode_t */
908f1e1388f616898b4e515d343c0414f2a6472esd dp = (pi_defernode_t *)dvp;
908f1e1388f616898b4e515d343c0414f2a6472esd mde_node = dp->mde_node;
908f1e1388f616898b4e515d343c0414f2a6472esd t_parent = dp->t_parent;
908f1e1388f616898b4e515d343c0414f2a6472esd t_node = dp->t_node;
908f1e1388f616898b4e515d343c0414f2a6472esd private = dp->private;
908f1e1388f616898b4e515d343c0414f2a6472esd func = dp->func;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /*
908f1e1388f616898b4e515d343c0414f2a6472esd * Remove the element from the list. Once we are done calling
908f1e1388f616898b4e515d343c0414f2a6472esd * the routine we do not need it any more.
908f1e1388f616898b4e515d343c0414f2a6472esd */
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_remove(defer_list, dvp);
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_node_fini(dp, &(dp->defer_node), defer_pool);
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_free(mod, dp, sizeof (pi_defernode_t));
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Get the instance value from the mde node */
908f1e1388f616898b4e515d343c0414f2a6472esd if (pi_get_instance(mod, mdp, mde_node, &inst) != 0) {
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod, "deferred node_0x%llx invalid\n",
908f1e1388f616898b4e515d343c0414f2a6472esd (uint64_t)mde_node);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Move on to the next node */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
908f1e1388f616898b4e515d343c0414f2a6472esd continue;
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Get the hc name from the mde node */
908f1e1388f616898b4e515d343c0414f2a6472esd hc_name = pi_get_topo_hc_name(mod, mdp, mde_node);
908f1e1388f616898b4e515d343c0414f2a6472esd if (hc_name == NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod,
908f1e1388f616898b4e515d343c0414f2a6472esd "deferred node_0x%llx has invalid NULL hc_name\n",
908f1e1388f616898b4e515d343c0414f2a6472esd (uint64_t)mde_node);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Move on to the next node */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
908f1e1388f616898b4e515d343c0414f2a6472esd continue;
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod,
908f1e1388f616898b4e515d343c0414f2a6472esd "calling deferred enumerator for node_0x%llx\n",
908f1e1388f616898b4e515d343c0414f2a6472esd (uint64_t)mde_node);
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Call the deferred enumeration function */
908f1e1388f616898b4e515d343c0414f2a6472esd result = (func)(mod, mdp, mde_node, inst, t_parent, hc_name,
908f1e1388f616898b4e515d343c0414f2a6472esd t_node, private);
908f1e1388f616898b4e515d343c0414f2a6472esd if (result != 0) {
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod,
908f1e1388f616898b4e515d343c0414f2a6472esd "deferred enumeration for node_0x%llx failed\n",
908f1e1388f616898b4e515d343c0414f2a6472esd (uint64_t)mde_node);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd /* Clean up from the deferred call */
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_strfree(mod, hc_name);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd topo_mod_dprintf(mod, "deferred enumeration completed.\n");
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_destroy(defer_list);
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_pool_destroy(defer_pool);
021ceb9857f712f245edda92c7eb82f0a3a83acbTom Pothier defer_list = NULL;
021ceb9857f712f245edda92c7eb82f0a3a83acbTom Pothier defer_pool = NULL;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd return (0);
908f1e1388f616898b4e515d343c0414f2a6472esd}
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esdstatic int
908f1e1388f616898b4e515d343c0414f2a6472esdpi_deferlist_create(topo_mod_t *mod)
908f1e1388f616898b4e515d343c0414f2a6472esd{
908f1e1388f616898b4e515d343c0414f2a6472esd /* Initialize the uutil list structure */
908f1e1388f616898b4e515d343c0414f2a6472esd defer_pool = uu_list_pool_create("pi_defer_pool",
908f1e1388f616898b4e515d343c0414f2a6472esd sizeof (pi_defernode_t), offsetof(pi_defernode_t, defer_node),
908f1e1388f616898b4e515d343c0414f2a6472esd pi_deferlist_compare, 0);
908f1e1388f616898b4e515d343c0414f2a6472esd if (defer_pool == NULL) {
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_NOMEM);
908f1e1388f616898b4e515d343c0414f2a6472esd return (-1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd defer_list = uu_list_create(defer_pool, NULL, 0);
908f1e1388f616898b4e515d343c0414f2a6472esd if (defer_list == NULL) {
908f1e1388f616898b4e515d343c0414f2a6472esd uu_list_pool_destroy(defer_pool);
021ceb9857f712f245edda92c7eb82f0a3a83acbTom Pothier defer_pool = NULL;
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, EMOD_NOMEM);
908f1e1388f616898b4e515d343c0414f2a6472esd return (-1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd return (0);
908f1e1388f616898b4e515d343c0414f2a6472esd}
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd/* ARGSUSED */
908f1e1388f616898b4e515d343c0414f2a6472esdstatic int
908f1e1388f616898b4e515d343c0414f2a6472esdpi_deferlist_compare(const void *l_arg, const void *r_arg, void *private)
908f1e1388f616898b4e515d343c0414f2a6472esd{
908f1e1388f616898b4e515d343c0414f2a6472esd pi_defernode_t *lp = (pi_defernode_t *)l_arg;
908f1e1388f616898b4e515d343c0414f2a6472esd pi_defernode_t *rp = (pi_defernode_t *)r_arg;
908f1e1388f616898b4e515d343c0414f2a6472esd
908f1e1388f616898b4e515d343c0414f2a6472esd if (lp->func != rp->func) {
908f1e1388f616898b4e515d343c0414f2a6472esd return (1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd if (lp->t_parent != rp->t_parent) {
908f1e1388f616898b4e515d343c0414f2a6472esd return (-1);
908f1e1388f616898b4e515d343c0414f2a6472esd }
908f1e1388f616898b4e515d343c0414f2a6472esd return (0);
908f1e1388f616898b4e515d343c0414f2a6472esd}