summaryrefslogtreecommitdiff
path: root/usr/src/lib/fm/topo/modules/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/fm/topo/modules/common')
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c65
-rw-r--r--usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c51
-rw-r--r--usr/src/lib/fm/topo/modules/common/ipmi/Makefile5
-rw-r--r--usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c297
-rw-r--r--usr/src/lib/fm/topo/modules/common/ses/ses.c43
5 files changed, 441 insertions, 20 deletions
diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c b/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c
index db853c6695..beae89f9f1 100644
--- a/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c
@@ -32,11 +32,18 @@
#include "disk.h"
#include "disk_drivers.h"
+/*
+ * Request the SAS address of the disk (if any) attached to this mpt_sas
+ * instance at (Enclosure Number, Slot Number). The function returns
+ * -1 on error and sets errno to ENOENT _only_ if the /devices node
+ * (*devctl) does not exist.
+ */
static int
get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
uint32_t slot, char **sas_address)
{
- int fd, err, i;
+ int ret = -1, en = ENXIO;
+ int fd, i;
mptsas_get_disk_info_t gdi;
mptsas_disk_info_t *di;
size_t disz;
@@ -44,16 +51,19 @@ get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
bzero(&gdi, sizeof (gdi));
if ((fd = open(devctl, O_RDWR)) == -1) {
+ en = errno;
topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n",
devctl, strerror(errno));
+ errno = en;
return (-1);
}
if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
+ if (errno != ENOENT)
+ en = errno;
topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl,
strerror(errno));
- (void) close(fd);
- return (-1);
+ goto out;
}
gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) *
@@ -61,19 +71,19 @@ get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz);
if (di == NULL) {
topo_mod_dprintf(mod, "memory allocation failed\n");
- (void) close(fd);
- return (-1);
+ en = ENOMEM;
+ goto out;
}
if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
+ if (errno != ENOENT)
+ en = errno;
topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl,
strerror(errno));
topo_mod_free(mod, di, disz);
- (void) close(fd);
- return (-1);
+ goto out;
}
- err = -1;
for (i = 0; i < gdi.DiskCount; i++) {
if (di[i].Enclosure == enclosure && di[i].Slot == slot) {
char sas[17]; /* 16 hex digits and NUL */
@@ -81,14 +91,16 @@ get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) "
"with adddress %s\n", enclosure, slot, sas);
*sas_address = topo_mod_strdup(mod, sas);
- err = 0;
+ en = ret = 0;
break;
}
}
topo_mod_free(mod, di, disz);
+out:
(void) close(fd);
- return (err);
+ errno = en;
+ return (ret);
}
int
@@ -97,6 +109,8 @@ disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address)
char *devctl = NULL;
uint32_t enclosure, slot;
int err;
+ char *elem, *lastp;
+ int ret = -1;
/*
* Get the required properties from the node. These come from
@@ -115,6 +129,35 @@ disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address)
return (-1);
}
- return (get_sas_address(mod, devctl, enclosure, slot, sas_address));
+ /*
+ * devctl is a (potentially) pipe-separated list of different device
+ * paths to try.
+ */
+ if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) != NULL) {
+ boolean_t done = B_FALSE;
+ do {
+ topo_mod_dprintf(mod, "trying mpt_sas instance at %s\n",
+ elem);
+
+ ret = get_sas_address(mod, elem, enclosure,
+ slot, sas_address);
+
+ /*
+ * Only try further devctl paths from the list if this
+ * one was not found:
+ */
+ if (ret == 0 || errno != ENOENT) {
+ done = B_TRUE;
+ } else {
+ topo_mod_dprintf(mod, "instance not found\n");
+ }
+
+ topo_mod_strfree(mod, elem);
+
+ } while (!done && (elem = topo_mod_strsplit(mod, NULL, "|",
+ &lastp)) != NULL);
+ }
+ topo_mod_strfree(mod, devctl);
+ return (ret);
}
diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c
index a49a131811..115e3b801d 100644
--- a/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c
+++ b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c
@@ -72,6 +72,12 @@ _topo_fini(topo_mod_t *mod)
topo_mod_unregister(mod);
}
+/*
+ * Get or set LED state for a particular target attached to an mpt_sas
+ * instance at (Enclosure Number, Slot Number). The function returns
+ * -1 on error and sets errno to ENOENT _only_ if the /devices node
+ * (*devctl) does not exist.
+ */
static int
do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
uint16_t slot, uint8_t led, uint32_t *ledmode, boolean_t set)
@@ -88,8 +94,10 @@ do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
lc.LedStatus = *ledmode;
if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) {
+ int en = errno;
topo_mod_dprintf(mod, "devctl open failed: %s",
strerror(errno));
+ errno = en;
return (-1);
}
@@ -103,9 +111,11 @@ do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
*/
lc.LedStatus = 0;
} else {
+ int en = errno;
topo_mod_dprintf(mod, "led control ioctl failed: %s",
strerror(errno));
(void) close(fd);
+ errno = en;
return (-1);
}
}
@@ -113,6 +123,7 @@ do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
*ledmode = lc.LedStatus ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
(void) close(fd);
+ errno = 0;
return (0);
}
@@ -127,7 +138,8 @@ mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
char *driver = NULL, *devctl = NULL;
uint32_t enclosure, slot;
uint8_t mptsas_led;
- boolean_t set;
+ boolean_t set, done;
+ char *elem, *lastp;
if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION)
return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
@@ -197,8 +209,41 @@ mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__);
}
- if (do_led_control(mod, devctl, enclosure, slot, mptsas_led, &ledmode,
- set) != 0) {
+ /*
+ * devctl is a (potentially) pipe-separated list of different device
+ * paths to try.
+ */
+ if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) == NULL) {
+ topo_mod_dprintf(mod, "%s: could not parse devctl list",
+ __func__);
+ ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
+ goto out;
+ }
+ done = B_FALSE;
+ do {
+ topo_mod_dprintf(mod, "%s: trying mpt_sas instance at %s\n",
+ __func__, elem);
+
+ ret = do_led_control(mod, elem, enclosure, slot,
+ mptsas_led, &ledmode, set);
+
+ /*
+ * Only try further devctl paths from the list if this one
+ * was not found:
+ */
+ if (ret == 0 || errno != ENOENT) {
+ done = B_TRUE;
+ } else {
+ topo_mod_dprintf(mod, "%s: instance not found\n",
+ __func__);
+ }
+
+ topo_mod_strfree(mod, elem);
+
+ } while (!done && (elem = topo_mod_strsplit(mod, NULL, "|",
+ &lastp)) != NULL);
+
+ if (ret != 0) {
topo_mod_dprintf(mod, "%s: do_led_control failed", __func__);
ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
goto out;
diff --git a/usr/src/lib/fm/topo/modules/common/ipmi/Makefile b/usr/src/lib/fm/topo/modules/common/ipmi/Makefile
index b6f2839c42..4a0bf39401 100644
--- a/usr/src/lib/fm/topo/modules/common/ipmi/Makefile
+++ b/usr/src/lib/fm/topo/modules/common/ipmi/Makefile
@@ -22,7 +22,8 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 2018, Joyent, Inc.
+#
MODULE = ipmi
CLASS = common
@@ -31,4 +32,4 @@ MODULESRCS = ipmi_enum.c ipmi_methods.c
include ../../Makefile.plugin
-LDLIBS += -lipmi
+LDLIBS += -lipmi -lnsl
diff --git a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c
index e0a768462d..96149ccc2e 100644
--- a/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c
+++ b/usr/src/lib/fm/topo/modules/common/ipmi/ipmi_enum.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
* Copyright 2019 by Western Digital Corporation
*/
@@ -30,6 +30,9 @@
#include <fm/topo_mod.h>
#include <sys/fm/protocol.h>
#include <string.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#define TOPO_PGROUP_IPMI "ipmi"
#define TOPO_PROP_IPMI_ENTITY_REF "entity_ref"
@@ -599,6 +602,278 @@ ipmi_check_entity(ipmi_handle_t *ihp, ipmi_entity_t *ep, void *data)
return (0);
}
+static const char *
+ipmi2toposrc(uint8_t ipmi_ip_src)
+{
+ char *cfgtype;
+
+ switch (ipmi_ip_src) {
+ case (IPMI_LAN_SRC_STATIC):
+ case (IPMI_LAN_SRC_BIOS):
+ cfgtype = TOPO_NETCFG_TYPE_STATIC;
+ break;
+ case (IPMI_LAN_SRC_DHCP):
+ cfgtype = TOPO_NETCFG_TYPE_DHCP;
+ break;
+ default:
+ cfgtype = TOPO_NETCFG_TYPE_UNKNOWN;
+ break;
+ }
+ return (cfgtype);
+}
+
+/*
+ * Channel related IPMI commands reserve 4 bits for the channel number.
+ */
+#define IPMI_MAX_CHANNEL 0xf
+
+static int
+ipmi_enum_sp(topo_mod_t *mod, tnode_t *pnode)
+{
+ ipmi_handle_t *ihp;
+ ipmi_channel_info_t *chinfo;
+ ipmi_lan_config_t lancfg = { 0 };
+ boolean_t found_lan = B_TRUE;
+ char ipv4_addr[INET_ADDRSTRLEN], subnet[INET_ADDRSTRLEN];
+ char gateway[INET_ADDRSTRLEN], macaddr[18];
+ char ipv6_addr[INET6_ADDRSTRLEN];
+ char **ipv6_routes = NULL;
+ const char *sp_rev, *ipv4_cfgtype, *ipv6_cfgtype;
+ nvlist_t *auth, *fmri;
+ tnode_t *sp_node;
+ topo_pgroup_info_t pgi;
+ topo_ufm_slot_info_t slotinfo = { 0 };
+ int err, ch, i, ret = -1;
+
+ if ((ihp = topo_mod_ipmi_hold(mod)) == NULL)
+ return (0);
+
+ /*
+ * If we're able to successfully get the service processor version by
+ * issuing a GET_DEVICE_ID IPMI command over the KCS interface, then we
+ * can say with certainty that a service processor exists. If not,
+ * then either the SP is unresponsive or one isn't present. In either
+ * case, we bail.
+ */
+ if ((sp_rev = ipmi_firmware_version(ihp)) == NULL) {
+ topo_mod_dprintf(mod, "failed to query SP");
+ topo_mod_ipmi_rele(mod);
+ return (0);
+ }
+
+ if ((auth = topo_mod_auth(mod, pnode)) == NULL) {
+ topo_mod_dprintf(mod, "topo_mod_auth() failed: %s",
+ topo_mod_errmsg(mod));
+ /* errno set */
+ goto out;
+ }
+ if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION,
+ SP, 0, NULL, auth, NULL, sp_rev, NULL)) == NULL) {
+ nvlist_free(auth);
+ topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s",
+ topo_mod_errmsg(mod));
+ /* errno set */
+ goto out;
+ }
+ nvlist_free(auth);
+
+ if ((sp_node = topo_node_bind(mod, pnode, SP, 0, fmri)) == NULL) {
+ nvlist_free(fmri);
+ topo_mod_dprintf(mod, "topo_node_bind() failed: %s",
+ topo_mod_errmsg(mod));
+ /* errno set */
+ goto out;
+ }
+ nvlist_free(fmri);
+ fmri = NULL;
+
+ if (topo_node_label_set(sp_node, "service-processor", &err) != 0) {
+ topo_mod_dprintf(mod, "failed to set label on %s=%d: %s", SP,
+ 0, topo_strerror(err));
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+
+ if (topo_node_fru(pnode, &fmri, NULL, &err) != 0 ||
+ topo_node_fru_set(sp_node, fmri, 0, &err) != 0) {
+ topo_mod_dprintf(mod, "failed to set FRU on %s=%d: %s", SP, 0,
+ topo_strerror(err));
+ nvlist_free(fmri);
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+ nvlist_free(fmri);
+
+ /*
+ * Create UFM node to capture the SP LOM version
+ */
+ slotinfo.usi_version = sp_rev;
+ slotinfo.usi_active = B_TRUE;
+ slotinfo.usi_mode = TOPO_UFM_SLOT_MODE_NONE;
+ if (topo_node_range_create(mod, sp_node, UFM, 0, 0) != 0 ||
+ topo_mod_create_ufm(mod, sp_node,
+ "Baseboard Management Controller firmware", &slotinfo) == NULL) {
+ topo_mod_dprintf(mod, "failed to create %s node", UFM);
+ goto out;
+ }
+
+ /*
+ * Iterate through the channels to find the LAN channel.
+ */
+ for (ch = 0; ch <= IPMI_MAX_CHANNEL; ch++) {
+ if ((chinfo = ipmi_get_channel_info(ihp, ch)) != NULL &&
+ chinfo->ici_medium == IPMI_MEDIUM_8023LAN) {
+ found_lan = B_TRUE;
+ break;
+ }
+ }
+ /*
+ * If we found a LAN channel, look up its configuration so that we can
+ * expose it via node properties.
+ */
+ if (found_lan != B_TRUE ||
+ ipmi_lan_get_config(ihp, ch, &lancfg) != 0) {
+ (void) fprintf(stderr, "failed to get LAN config\n");
+ (void) topo_mod_seterrno(mod, EMOD_UNKNOWN);
+ goto out;
+ }
+
+ pgi.tpi_name = TOPO_PGROUP_NETCFG;
+ pgi.tpi_namestab = TOPO_STABILITY_PRIVATE;
+ pgi.tpi_datastab = TOPO_STABILITY_PRIVATE;
+ pgi.tpi_version = TOPO_VERSION;
+
+ if (topo_pgroup_create(sp_node, &pgi, &err) != 0) {
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+
+ /* Set MAC address property */
+ (void) sprintf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+ lancfg.ilc_macaddr[0], lancfg.ilc_macaddr[1],
+ lancfg.ilc_macaddr[2], lancfg.ilc_macaddr[3],
+ lancfg.ilc_macaddr[4], lancfg.ilc_macaddr[5]);
+ macaddr[17] = '\0';
+
+ if (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_MACADDR, TOPO_PROP_IMMUTABLE, macaddr,
+ &err) != 0) {
+ topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s",
+ SP, 0, topo_strerror(err));
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+
+ /* Set VLAN ID property, if VLAN is enabled */
+ if (lancfg.ilc_vlan_enabled == B_TRUE &&
+ topo_prop_set_uint32(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_VLAN_ID, TOPO_PROP_IMMUTABLE, lancfg.ilc_vlan_id,
+ &err) != 0) {
+ topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s",
+ SP, 0, topo_strerror(err));
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+
+ /* Set IPv4 configuration properties if IPv4 is enabled */
+ if (lancfg.ilc_ipv4_enabled == B_TRUE &&
+ (inet_ntop(AF_INET, &lancfg.ilc_ipaddr, ipv4_addr,
+ sizeof (ipv4_addr)) == NULL ||
+ inet_ntop(AF_INET, &lancfg.ilc_subnet, subnet,
+ sizeof (subnet)) == NULL ||
+ inet_ntop(AF_INET, &lancfg.ilc_gateway_addr, gateway,
+ sizeof (gateway)) == NULL)) {
+ (void) fprintf(stderr, "failed to convert IP addresses: %s\n",
+ strerror(errno));
+ (void) topo_mod_seterrno(mod, EMOD_UNKNOWN);
+ goto out;
+ }
+ ipv4_cfgtype = ipmi2toposrc(lancfg.ilc_ipaddr_source);
+ if (lancfg.ilc_ipv4_enabled == B_TRUE &&
+ (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV4_ADDR, TOPO_PROP_IMMUTABLE, ipv4_addr,
+ &err) != 0 ||
+ topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV4_SUBNET, TOPO_PROP_IMMUTABLE, subnet,
+ &err) != 0 ||
+ topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV4_GATEWAY, TOPO_PROP_IMMUTABLE, gateway,
+ &err) != 0 ||
+ topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV4_TYPE, TOPO_PROP_IMMUTABLE, ipv4_cfgtype,
+ &err) != 0)) {
+ topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s",
+ SP, 0, topo_strerror(err));
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+
+ /* Set IPv6 configuration properties if IPv6 is enabled */
+ if (lancfg.ilc_ipv6_enabled == B_TRUE) {
+ ipv6_cfgtype = ipmi2toposrc(lancfg.ilc_ipv6_source);
+
+ if (inet_ntop(AF_INET6, &lancfg.ilc_ipv6_addr, ipv6_addr,
+ sizeof (ipv6_addr)) == NULL) {
+ (void) fprintf(stderr, "failed to convert IPv6 "
+ "address: %s\n", strerror(errno));
+ (void) topo_mod_seterrno(mod, EMOD_UNKNOWN);
+ goto out;
+ }
+
+ /* allocate and populate ipv6-routes string array */
+ if ((ipv6_routes = topo_mod_zalloc(mod,
+ lancfg.ilc_ipv6_nroutes * sizeof (char *))) == NULL) {
+ /* errno set */
+ goto out;
+ }
+ for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) {
+ if ((ipv6_routes[i] = topo_mod_alloc(mod,
+ INET6_ADDRSTRLEN)) == NULL) {
+ /* errno set */
+ goto out;
+ }
+ }
+ for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) {
+ if (inet_ntop(AF_INET6, &lancfg.ilc_ipv6_routes[i],
+ ipv6_routes[i], sizeof (ipv6_routes[i])) == NULL) {
+ (void) fprintf(stderr, "failed to convert "
+ "IPv6 addresses: %s\n", strerror(errno));
+ (void) topo_mod_seterrno(mod, EMOD_UNKNOWN);
+ goto out;
+ }
+ }
+ }
+ if (lancfg.ilc_ipv6_enabled == B_TRUE &&
+ (topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV6_ADDR, TOPO_PROP_IMMUTABLE, ipv6_addr,
+ &err) != 0 ||
+ topo_prop_set_string_array(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV6_ROUTES, TOPO_PROP_IMMUTABLE,
+ (const char **)ipv6_routes, lancfg.ilc_ipv6_nroutes, &err) != 0 ||
+ topo_prop_set_string(sp_node, TOPO_PGROUP_NETCFG,
+ TOPO_PROP_NETCFG_IPV6_TYPE, TOPO_PROP_IMMUTABLE, ipv6_cfgtype,
+ &err) != 0)) {
+ topo_mod_dprintf(mod, "failed to set properties on %s=%d: %s",
+ SP, 0, topo_strerror(err));
+ (void) topo_mod_seterrno(mod, err);
+ goto out;
+ }
+ ret = 0;
+out:
+ if (lancfg.ilc_ipv6_nroutes > 0 && ipv6_routes != NULL) {
+ for (i = 0; i < lancfg.ilc_ipv6_nroutes; i++) {
+ if (ipv6_routes[i] != NULL) {
+ topo_mod_free(mod, ipv6_routes[i],
+ INET6_ADDRSTRLEN);
+ }
+ }
+ topo_mod_free(mod, ipv6_routes,
+ lancfg.ilc_ipv6_nroutes * sizeof (char *));
+ }
+ topo_mod_ipmi_rele(mod);
+ return (ret);
+}
+
/*
* libtopo enumeration point. This simply iterates over entities looking for
* the appropriate type.
@@ -613,10 +888,11 @@ ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
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.
+ * If the node being passed in ISN'T the chassis or motherboard node,
+ * then we're being asked to post-process a statically defined node.
*/
- if (strcmp(topo_node_name(rnode), CHASSIS) != 0) {
+ if (strcmp(topo_node_name(rnode), CHASSIS) != 0 &&
+ strcmp(topo_node_name(rnode), MOTHERBOARD) != 0) {
if (ipmi_post_process(mod, rnode) != 0) {
topo_mod_dprintf(mod, "post processing of node %s=%d "
"failed!", topo_node_name(rnode),
@@ -626,6 +902,19 @@ ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
return (0);
}
+ /*
+ * For service processor enumeration we vector off into a special code
+ * path.
+ */
+ if (strcmp(name, SP) == 0) {
+ if (ipmi_enum_sp(mod, rnode) != 0) {
+ topo_mod_dprintf(mod, "failed to enumerate the "
+ "service-processor");
+ return (-1);
+ }
+ return (0);
+ }
+
if (strcmp(name, POWERMODULE) == 0) {
data.ed_entity = IPMI_ET_POWER_DOMAIN;
} else if (strcmp(name, PSU) == 0) {
diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses.c b/usr/src/lib/fm/topo/modules/common/ses/ses.c
index 8d74b8aeb8..0273009bbe 100644
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.c
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c
@@ -340,6 +340,34 @@ static ses_open_fail_list_t *ses_sofh;
static pthread_mutex_t ses_sofmt;
static void ses_ct_print(char *ptr);
+/*
+ * Static list of enclosure manufacturers/models that we will skip enumerating.
+ * To skip all models from a particular vendor, set the seb_model field to "*".
+ */
+typedef struct ses_enc_blacklist {
+ const char *seb_manuf;
+ const char *seb_model;
+} ses_enc_blacklist_t;
+
+static const ses_enc_blacklist_t enc_blacklist[] = {
+ { "LSI", "VirtualSES" }
+};
+
+#define N_ENC_BLACKLIST (sizeof (enc_blacklist) / \
+ sizeof (enc_blacklist[0]))
+
+static boolean_t
+ses_is_blacklisted(ses_enc_blacklist_t *seb)
+{
+ for (uint_t i = 0; i < N_ENC_BLACKLIST; i++) {
+ if (strcmp(seb->seb_manuf, enc_blacklist[i].seb_manuf) == 0 &&
+ (strcmp(enc_blacklist[i].seb_model, "*") == 0 ||
+ strcmp(seb->seb_model, enc_blacklist[i].seb_model) == 0))
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
static void
ses_recheck_dir()
{
@@ -3298,9 +3326,24 @@ ses_enum_gather(ses_node_t *np, void *data)
uint64_t prevstatus, status;
boolean_t report;
uint64_t subchassis = NO_SUBCHASSIS;
+ ses_enc_blacklist_t seb;
if (ses_node_type(np) == SES_NODE_ENCLOSURE) {
/*
+ * Compare the enclosure identity against the entries in the SES
+ * enclosure blacklist and ignore it, if found.
+ */
+ verify(nvlist_lookup_string(props, SES_EN_PROP_VID,
+ (char **)&seb.seb_manuf) == 0);
+ verify(nvlist_lookup_string(props, SES_EN_PROP_PID,
+ (char **)&seb.seb_model) == 0);
+ if (ses_is_blacklisted(&seb) == B_TRUE) {
+ topo_mod_dprintf(mod, "Skipping enclosure %s-%s: is "
+ "blacklisted", seb.seb_manuf, seb.seb_model);
+ return (SES_WALK_ACTION_TERMINATE);
+ }
+
+ /*
* If we have already identified the chassis for this target,
* then this is a secondary enclosure and we should ignore it,
* along with the rest of the tree (since this is depth-first).