diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/fm/modules/common/fdd-msg/Makefile | 10 | ||||
-rw-r--r-- | usr/src/cmd/fm/modules/common/fdd-msg/fdd-msg.conf | 15 | ||||
-rw-r--r-- | usr/src/cmd/fm/modules/common/fdd-msg/fdd_msg.c | 231 |
3 files changed, 193 insertions, 63 deletions
diff --git a/usr/src/cmd/fm/modules/common/fdd-msg/Makefile b/usr/src/cmd/fm/modules/common/fdd-msg/Makefile index da07c3ff28..be3a173e7f 100644 --- a/usr/src/cmd/fm/modules/common/fdd-msg/Makefile +++ b/usr/src/cmd/fm/modules/common/fdd-msg/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # MODULE = fdd-msg @@ -29,4 +28,9 @@ SRCS = fdd_msg.c include ../../Makefile.plugin -LDLIBS += -lipmi +LDLIBS_sparc = -lipmi +LDLIBS_i386 = -L$(ROOT)/usr/lib/fm -lipmi -lumem -lfmd_agent +LDFLAGS_sparc = +LDFLAGS_i386 = -R/usr/lib/fm +LDLIBS += $(LDLIBS_$(MACH)) +LDFLAGS += $(LDFLAGS_$(MACH)) diff --git a/usr/src/cmd/fm/modules/common/fdd-msg/fdd-msg.conf b/usr/src/cmd/fm/modules/common/fdd-msg/fdd-msg.conf index 673f715efe..d4c974e871 100644 --- a/usr/src/cmd/fm/modules/common/fdd-msg/fdd-msg.conf +++ b/usr/src/cmd/fm/modules/common/fdd-msg/fdd-msg.conf @@ -19,6 +19,15 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# +setprop default_fma_cap 0x3 + +# vendor=GenuineIntel, family=6, model=26 +setprop NHMEP_fma_cap 0x3 +# vendor=GenuineIntel, family=6, model=46 +setprop NHMEX_fma_cap 0x2 +# vendor=GenuineIntel, family=6, model=44 +setprop WSMEP_fma_cap 0x3 +# vendor=GenuineIntel, family=6, model=47 +setprop INTLN_fma_cap 0x2 diff --git a/usr/src/cmd/fm/modules/common/fdd-msg/fdd_msg.c b/usr/src/cmd/fm/modules/common/fdd-msg/fdd_msg.c index 3d643deb52..7137297c0b 100644 --- a/usr/src/cmd/fm/modules/common/fdd-msg/fdd_msg.c +++ b/usr/src/cmd/fm/modules/common/fdd-msg/fdd_msg.c @@ -20,22 +20,25 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * fdd messenger + * FMA capability messenger * - * This module sends fdd running on service processor a message which - * indicates the Solaris host FMA capability when fmd is started. The - * message is sent via the BMC driver (KCS interface) to the IPMI stack - * of ILOM using the IPMI Sun OEM core tunnel command. The sub-command - * is CORE_TUNNEL_SUBCMD_HOSTCAP. The IPMI stack posts an host FMA - * capability event to the event manager upon receiving this message. - * fdd subscribes to the event manager for this event. Upon receving - * this event, fdd will adjust its configuration. + * fdd-msg module is called once when fmd starts up. It does the following + * based on different scenarios * + * 1. If it's on a x86 platform, fdd-msg module sends fdd running on service + * processor a message (ILOM) which indicates the Solaris host FMA capability. + * The message is sent via the BMC driver (KCS interface) to the IPMI stack + * of ILOM using the IPMI Sun OEM core tunnel command. The sub-command is + * CORE_TUNNEL_SUBCMD_HOSTCAP. The IPMI stack posts an host FMA capability + * event to the event manager upon receiving this message. fdd subscribes to + * the event manager for this event. Upon receving this event, fdd will adjust + * its configuration. + * + * 2. If it's on a Sparc platform, fdd-msg module just exit for now. */ #include <errno.h> @@ -43,13 +46,35 @@ #include <strings.h> #include <sys/systeminfo.h> #include <libipmi.h> +#include <sys/devfm.h> #include <fm/fmd_api.h> +#if defined(__x86) +#include <sys/x86_archext.h> +#include <fm/fmd_agent.h> +#include <libnvpair.h> +#endif #define CMD_SUNOEM_CORE_TUNNEL 0x44 #define CORE_TUNNEL_SUBCMD_HOSTFMACAP 2 #define OEM_DATA_LENGTH 3 #define VERSION 0x10 -#define HOST_CAPABILITY 2 + +#if defined(__x86) +typedef struct cpu_tbl { + char vendor[X86_VENDOR_STRLEN]; + int32_t family; + int32_t model; + char *propname; +} cpu_tbl_t; + +static cpu_tbl_t fma_cap_list[] = { + {"GenuineIntel", 6, 26, "NHMEP_fma_cap"}, + {"GenuineIntel", 6, 46, "NHMEX_fma_cap"}, + {"GenuineIntel", 6, 44, "WSMEP_fma_cap"}, + {"GenuineIntel", 6, 47, "INTLN_fma_cap"}, + {NULL, 0, 0, NULL} +}; +#endif static int check_sunoem(ipmi_handle_t *ipmi_hdl) @@ -65,19 +90,127 @@ check_sunoem(ipmi_handle_t *ipmi_hdl) return (0); } -/*ARGSUSED*/ +#if defined(__x86) +static int32_t +fma_cap_cpu_info(cpu_tbl_t *ci) +{ + nvlist_t **cpus, *nvl; + uint_t ncpu, i; + fmd_agent_hdl_t *hdl; + char *ven; + int32_t family, model; + + if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) + return (-1); + if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) { + fmd_agent_close(hdl); + return (-1); + } + fmd_agent_close(hdl); + + if (cpus == NULL) + return (-1); + + /* + * There is no mixed CPU type on x86 systems, it's ok to + * just pick the first one + */ + nvl = cpus[0]; + if (nvlist_lookup_string(nvl, FM_PHYSCPU_INFO_VENDOR_ID, &ven) != 0 || + nvlist_lookup_int32(nvl, FM_PHYSCPU_INFO_FAMILY, &family) != 0 || + nvlist_lookup_int32(nvl, FM_PHYSCPU_INFO_MODEL, &model) != 0) { + for (i = 0; i < ncpu; i++) + nvlist_free(cpus[i]); + umem_free(cpus, sizeof (nvlist_t *) * ncpu); + return (-1); + } + + (void) snprintf(ci->vendor, X86_VENDOR_STRLEN, "%s", ven); + ci->family = family; + ci->model = model; + + for (i = 0; i < ncpu; i++) + nvlist_free(cpus[i]); + umem_free(cpus, sizeof (nvlist_t *) * ncpu); + return (0); +} +#endif + +static uint32_t +get_cap_conf(fmd_hdl_t *hdl) +{ + uint32_t fma_cap; +#if defined(__x86) + int found = 0; + cpu_tbl_t *cl, ci; + + if (fma_cap_cpu_info(&ci) == 0) { + fmd_hdl_debug(hdl, "Got CPU info: vendor=%s, family=%d, " + "model=%d\n", ci.vendor, ci.family, ci.model); + for (cl = fma_cap_list; cl->propname != NULL; cl++) { + if (strncmp(ci.vendor, cl->vendor, + X86_VENDOR_STRLEN) == 0 && + ci.family == cl->family && + ci.model == cl->model) { + found++; + break; + } + } + } else { + fmd_hdl_debug(hdl, "Failed to get CPU info"); + } + + if (found) { + fma_cap = fmd_prop_get_int32(hdl, cl->propname); + fmd_hdl_debug(hdl, "Found property, FMA capability=0x%x", + fma_cap); + } else { +#endif + fma_cap = fmd_prop_get_int32(hdl, "default_fma_cap"); + fmd_hdl_debug(hdl, "Didn't find FMA capability property, " + "use default=0x%x", fma_cap); +#if defined(__x86) + } +#endif + + return (fma_cap); +} + static void -send_fma_cap(fmd_hdl_t *hdl, id_t id, void *data) +send_fma_cap_to_ilom(fmd_hdl_t *hdl, uint32_t fma_cap) { + int error; + char *msg; ipmi_handle_t *ipmi_hdl; ipmi_cmd_t cmd; uint8_t oem_data[OEM_DATA_LENGTH]; - ipmi_hdl = fmd_hdl_getspecific(hdl); + if ((ipmi_hdl = ipmi_open(&error, &msg, IPMI_TRANSPORT_BMC, NULL)) + == NULL) { + /* + * If /dev/bmc doesn't exist on the system, then return + * without doing anything. + */ + if (error != EIPMI_BMC_OPEN_FAILED) + fmd_hdl_abort(hdl, "Failed to initialize IPMI " + "connection: %s\n", msg); + fmd_hdl_debug(hdl, "Failed: no IPMI connection present"); + return; + } + + /* + * Check if it's Sun ILOM + */ + if (check_sunoem(ipmi_hdl) != 0) { + fmd_hdl_debug(hdl, "Service Processor does not run " + "Sun ILOM"); + ipmi_close(ipmi_hdl); + return; + } oem_data[0] = CORE_TUNNEL_SUBCMD_HOSTFMACAP; oem_data[1] = VERSION; - oem_data[2] = HOST_CAPABILITY; + oem_data[2] = fma_cap; cmd.ic_netfn = IPMI_NETFN_OEM; cmd.ic_lun = 0; @@ -87,17 +220,27 @@ send_fma_cap(fmd_hdl_t *hdl, id_t id, void *data) if (ipmi_send(ipmi_hdl, &cmd) == NULL) { fmd_hdl_debug(hdl, "Failed to send Solaris FMA " - "capability to fdd: %s", ipmi_errmsg(ipmi_hdl)); + "capability to ilom: %s", ipmi_errmsg(ipmi_hdl)); } ipmi_close(ipmi_hdl); - fmd_hdl_setspecific(hdl, NULL); +} + +/*ARGSUSED*/ +static void +fma_cap_init(fmd_hdl_t *hdl, id_t id, void *data) +{ + uint32_t fma_cap; + + fma_cap = get_cap_conf(hdl); + send_fma_cap_to_ilom(hdl, fma_cap); + fmd_hdl_unregister(hdl); } static const fmd_hdl_ops_t fmd_ops = { NULL, /* fmdo_recv */ - send_fma_cap, /* fmdo_timeout */ + fma_cap_init, /* fmdo_timeout */ NULL, /* fmdo_close */ NULL, /* fmdo_stats */ NULL, /* fmdo_gc */ @@ -107,22 +250,28 @@ static const fmd_hdl_ops_t fmd_ops = { static const fmd_prop_t fmd_props[] = { { "interval", FMD_TYPE_TIME, "1s" }, + { "default_fma_cap", FMD_TYPE_UINT32, "0x3" }, + { "NHMEP_fma_cap", FMD_TYPE_UINT32, "0x3" }, + { "NHMEX_fma_cap", FMD_TYPE_UINT32, "0x2" }, + { "WSMEP_fma_cap", FMD_TYPE_UINT32, "0x3" }, + { "INTLN_fma_cap", FMD_TYPE_UINT32, "0x2" }, { NULL, 0, NULL } }; static const fmd_hdl_info_t fmd_info = { - "fdd Messenger", "1.0", &fmd_ops, fmd_props + "FMA Capability Messenger", "1.1", &fmd_ops, fmd_props }; void _fmd_init(fmd_hdl_t *hdl) { - ipmi_handle_t *ipmi_hdl; - int error; - char *msg; char isa[8]; - /* For now the module only sends message to ILOM on i386 platforms */ + /* + * For now the module only sends message to ILOM on i386 platforms + * till CR 6933053 is fixed. Module unregister may cause etm module + * core dump due to 6933053. + */ if ((sysinfo(SI_ARCHITECTURE, isa, sizeof (isa)) == -1) || (strncmp(isa, "i386", 4) != 0)) return; @@ -130,46 +279,14 @@ _fmd_init(fmd_hdl_t *hdl) if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) return; - if ((ipmi_hdl = ipmi_open(&error, &msg, IPMI_TRANSPORT_BMC, NULL)) - == NULL) { - /* - * If /dev/bmc doesn't exist on the system, then unload the - * module without doing anything. - */ - if (error != EIPMI_BMC_OPEN_FAILED) - fmd_hdl_abort(hdl, "Failed to initialize IPMI " - "connection: %s\n", msg); - fmd_hdl_debug(hdl, "Failed to load: no IPMI connection " - "present"); - fmd_hdl_unregister(hdl); - return; - } - - /* - * Check if it's Sun ILOM - */ - if (check_sunoem(ipmi_hdl) != 0) { - fmd_hdl_debug(hdl, "Service Processor does not run " - "Sun ILOM"); - ipmi_close(ipmi_hdl); - fmd_hdl_unregister(hdl); - return; - } - - fmd_hdl_setspecific(hdl, ipmi_hdl); - /* * Setup the timer. */ (void) fmd_timer_install(hdl, NULL, NULL, 2000000000ULL); } +/*ARGSUSED*/ void _fmd_fini(fmd_hdl_t *hdl) { - ipmi_handle_t *ipmi_hdl = fmd_hdl_getspecific(hdl); - - if (ipmi_hdl) { - ipmi_close(ipmi_hdl); - } } |