ipmi_enum.c revision e5dcf7beb7c949f9234713d5818b581ec3825443
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <assert.h>
#include <fm/topo_mod.h>
#include <string.h>
#define TOPO_PGROUP_IPMI "ipmi"
#define TOPO_PROP_IPMI_ENTITY_REF "entity_ref"
#define TOPO_PROP_IPMI_ENTITY_PRESENT "entity_present"
typedef struct ipmi_enum_data {
const char *ed_name;
char *ed_label;
nvlist_t **);
topo_instance_t, topo_instance_t, void *, void *);
static const topo_method_t ipmi_methods[] = {
{ "ipmi_fru_label", "Property method", 0,
{ "ipmi_fru_fmri", "Property method", 0,
{ NULL }
};
const topo_modinfo_t ipmi_info =
/*
* Determine if the entity is present.
*/
/*ARGSUSED*/
static int
{
int err;
char *name;
/*
* Some broken IPMI implementations don't export correct
* entities, so referring to an entity isn't sufficient.
* For these platforms, we allow the XML to specify a
* single SDR record that represents the current present
* state.
*/
"Failed to get present state of %s (%s)\n",
return (-1);
}
} else {
/*
* Not all nodes have an entity_ref attribute.
* For these cases, return ENOTSUP so that we
* fall back to the default hc presence
* detection.
*/
return (topo_mod_seterrno(mod,
}
"Failed to lookup ipmi entity "
return (-1);
}
}
}
"ipmi_entity_present() failed: %s",
ipmi_errmsg(ihp));
return (-1);
}
}
}
return (0);
}
/*
* This determines if the entity has a FRU locator record set, in which case we
* treat this as a FRU, even if it's part of an association.
*/
/*ARGSUSED*/
static int
{
return (0);
}
/*
* Main entity enumerator. If we find a matching entity type, then instantiate
* a topo node.
*/
static int
{
int err;
const char *labelname;
char label[64];
return (0);
/*
* The purpose of power and cooling domains is to group psus and fans
* together. Unfortunately, some broken IPMI implementations declare
* domains that don't contain other elements. Since the end goal is to
* only enumerate psus and fans, we'll just ignore such elements.
*/
ep->ie_children == 0)
return (0);
return (1);
}
return (1);
}
return (1);
}
/*
* We inherit our label from our parent, appending our label in the
* process. This results in defaults labels of the form "FM 1 FAN 0"
* by default when given a hierarchy.
*/
else
label[0] = '\0';
case IPMI_ET_POWER_DOMAIN:
labelname = "PM";
break;
case IPMI_ET_PSU:
labelname = "PSU";
break;
case IPMI_ET_COOLING_DOMAIN:
labelname = "FM";
break;
case IPMI_ET_FAN:
labelname = "FAN";
break;
}
edp->ed_instance++;
topo_strerror(err));
return (1);
}
/*
* Store IPMI entity details as properties on the node
*/
if (err != ETOPO_PROP_DEFD) {
return (1);
}
}
return (1);
}
/*
* If we are a child of a non-chassis node, and there isn't an explicit
* FRU locator record, then propagate the parent's FRU. Otherwise, set
* the FRU to be the same as the resource.
*/
topo_strerror(err));
return (1);
}
} else {
topo_strerror(err));
return (1);
}
}
topo_strerror(err));
return (1);
}
/*
* Iterate over children, once for recursive domains and once for
*/
if (ep->ie_children != 0 &&
cdata.ed_instance = 0;
ipmi_check_entity, &cdata) != 0)
return (1);
case IPMI_ET_POWER_DOMAIN:
break;
case IPMI_ET_COOLING_DOMAIN:
break;
}
ipmi_check_entity, &cdata) != 0)
return (1);
}
return (0);
}
/*
* libtopo enumeration point. This simply iterates over entities looking for
* the appropriate type.
*/
/*ARGSUSED*/
static int
{
int ret;
/*
* If the node being passed in ISN'T the chassis node, then we're being
* asked to post-process a statically defined node.
*/
return (-1);
}
return (0);
}
} else {
name);
return (-1);
}
return (0);
data.ed_instance = 0;
/*
* We don't return failure if IPMI enumeration fails. This may
* be due to the SP being unavailable or an otherwise transient
* event.
*/
if (ret < 0) {
"failed to enumerate entities: %s",
ipmi_errmsg(ihp));
} else {
return (-1);
}
}
return (0);
}
static int
{
return (1);
}
return (0);
}
/*ARGSUSED*/
int
{
return (-1); /* mod errno already set */
}
return (0);
}
void
{
}