diff options
Diffstat (limited to 'usr/src/lib')
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/hc_canon.h | 2 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/mem.c | 66 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/topo_protocol.c | 103 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip.c | 675 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip.h | 17 |
5 files changed, 549 insertions, 314 deletions
diff --git a/usr/src/lib/fm/topo/libtopo/common/hc_canon.h b/usr/src/lib/fm/topo/libtopo/common/hc_canon.h index 8da0c69c59..3edb066d32 100644 --- a/usr/src/lib/fm/topo/libtopo/common/hc_canon.h +++ b/usr/src/lib/fm/topo/libtopo/common/hc_canon.h @@ -45,12 +45,14 @@ static const char *Hc_canon[] = { "chip-select", "cpu", "dimm", + "rank", "disk", "hostbridge", "interconnect", "chassis", "ioboard", "memory-controller", + "dram-channel", "motherboard", "pcibus", "pcidev", diff --git a/usr/src/lib/fm/topo/libtopo/common/mem.c b/usr/src/lib/fm/topo/libtopo/common/mem.c index c228ff28b3..6d89042372 100644 --- a/usr/src/lib/fm/topo/libtopo/common/mem.c +++ b/usr/src/lib/fm/topo/libtopo/common/mem.c @@ -51,8 +51,6 @@ static int mem_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, nvlist_t **); static int mem_expand(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, nvlist_t **); -static int mem_asru(topo_mod_t *, tnode_t *, topo_version_t, - nvlist_t *, nvlist_t **); #define MEM_VERSION TOPO_VERSION @@ -69,8 +67,6 @@ static const topo_method_t mem_methods[] = { TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, mem_unusable }, { TOPO_METH_EXPAND, TOPO_METH_UNUSABLE_DESC, TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL, mem_expand }, - { TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC, - TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL, mem_asru }, { NULL } }; @@ -138,15 +134,21 @@ mem_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, * PA then use that. Otherwise just format the unum element. */ if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val) == 0) { - format = FM_FMRI_SCHEME_MEM ":///" - FM_FMRI_MEM_UNUM "=%1$s/" FM_FMRI_MEM_OFFSET "=%2$llx"; + format = FM_FMRI_SCHEME_MEM ":///%1$s/" + FM_FMRI_MEM_OFFSET "=%2$llx"; } else if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val) == 0) { - format = FM_FMRI_SCHEME_MEM ":///" - FM_FMRI_MEM_UNUM "=%1$s/" FM_FMRI_MEM_PHYSADDR "=%2$llx"; + format = FM_FMRI_SCHEME_MEM ":///%1$s/" + FM_FMRI_MEM_PHYSADDR "=%2$llx"; } else - format = FM_FMRI_SCHEME_MEM ":///" FM_FMRI_MEM_UNUM "=%1$s"; + format = FM_FMRI_SCHEME_MEM ":///" "%1$s"; - len = snprintf(NULL, 0, format, unum, val); + /* + * If we have a well-formed unum we step over the hc:/// prefix + */ + if (strncmp(unum, "hc:///", 6) == 0) + unum += 6; + + len = snprintf(NULL, 0, format, unum, val) + 1; buf = topo_mod_zalloc(mod, len); if (buf == NULL) { @@ -206,47 +208,3 @@ mem_expand(topo_mod_t *mod, tnode_t *node, topo_version_t version, { return (-1); } - -/*ARGSUSED*/ -static int -mem_asru(topo_mod_t *mod, tnode_t *node, topo_version_t version, - nvlist_t *in, nvlist_t **out) -{ - int err; - uint64_t pa = 0, offset = 0; - int incl_pa = 0, incl_offset = 0; - nvlist_t *hcsp = NULL; - nvlist_t *asru; - char *cstr; - - if (nvlist_lookup_nvlist(in, FM_FMRI_HC_SPECIFIC, &hcsp) == 0) { - incl_pa = (nvlist_lookup_uint64(hcsp, - "asru-"FM_FMRI_MEM_PHYSADDR, &pa) == 0); - incl_offset = (nvlist_lookup_uint64(hcsp, - "asru-"FM_FMRI_MEM_OFFSET, &offset) == 0); - } - - if (topo_fmri_nvl2str(topo_mod_handle(mod), in, &cstr, &err) < 0) - return (topo_mod_seterrno(mod, err)); - - if (topo_mod_nvalloc(mod, &asru, NV_UNIQUE_NAME) != 0) { - topo_mod_strfree(mod, cstr); - return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); - } - err = nvlist_add_uint8(asru, FM_VERSION, FM_MEM_SCHEME_VERSION); - err |= nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM); - err |= nvlist_add_string(asru, FM_FMRI_MEM_UNUM, cstr); - if (incl_pa) - err |= nvlist_add_uint64(asru, FM_FMRI_MEM_PHYSADDR, pa); - if (incl_offset) - err |= nvlist_add_uint64(asru, FM_FMRI_MEM_OFFSET, offset); - topo_mod_strfree(mod, cstr); - if (err != 0) { - nvlist_free(asru); - return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); - } - - *out = asru; - - return (0); -} diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c b/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c index 81ae45e3ca..85ced6fa43 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -39,35 +38,41 @@ #include <libtopo.h> static int -topo_asru_compute(topo_hdl_t *thp, const char *scheme, nvlist_t *rsrc, - nvlist_t **asru) +topo_compute(tnode_t *node, nvlist_t *stub, const char *method, + topo_version_t version, nvlist_t *rsrc, nvlist_t **asru, int *err) { - int err; + int rc; + char *scheme; + topo_hdl_t *thp = node->tn_hdl; tnode_t *rnode; - if ((rnode = topo_hdl_root(thp, scheme)) == NULL) - return (ETOPO_METHOD_NOTSUP); - - if (topo_method_invoke(rnode, TOPO_METH_ASRU_COMPUTE, - TOPO_METH_ASRU_COMPUTE_VERSION, rsrc, asru, &err) != 0) - return (err); + /* + * First try the originating enumerator for + * a compute method. If none is supported, try the + * node's scheme-specific enumerator. + */ + if (topo_method_invoke(node, method, version, rsrc, asru, err) == 0) + return (0); - return (0); -} + if (*err != ETOPO_METHOD_NOTSUP) + return (-1); -static int -topo_fru_compute(topo_hdl_t *thp, const char *scheme, nvlist_t *rsrc, - nvlist_t **fru) -{ - int err; - tnode_t *rnode; + if ((rc = nvlist_lookup_string(stub, FM_FMRI_SCHEME, &scheme)) != 0) { + if (rc == ENOENT) { + *err = ETOPO_FMRI_MALFORM; + } else { + *err = ETOPO_FMRI_NVL; + } + return (-1); + } - if ((rnode = topo_hdl_root(thp, scheme)) == NULL) - return (ETOPO_METHOD_NOTSUP); + if ((rnode = topo_hdl_root(thp, scheme)) == NULL) { + *err = ETOPO_METHOD_NOTSUP; + return (-1); + } - if (topo_method_invoke(rnode, TOPO_METH_FRU_COMPUTE, - TOPO_METH_FRU_COMPUTE_VERSION, rsrc, fru, &err) != 0) - return (err); + if (topo_method_invoke(rnode, method, version, rsrc, asru, err) != 0) + return (-1); return (0); } @@ -77,35 +82,20 @@ topo_node_asru(tnode_t *node, nvlist_t **asru, nvlist_t *priv, int *err) { int rc; nvlist_t *ap; - char *scheme; if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU, &ap, err) != 0) return (-1); if (node->tn_fflags & TOPO_ASRU_COMPUTE) { - if ((rc = nvlist_lookup_string(ap, FM_FMRI_SCHEME, &scheme)) - != 0) { - if (rc == ENOENT) - *err = ETOPO_FMRI_MALFORM; - else - *err = ETOPO_FMRI_NVL; - nvlist_free(ap); - return (-1); - } - if ((rc = topo_asru_compute(node->tn_hdl, scheme, priv, asru)) - != 0) { - nvlist_free(ap); - *err = rc; - return (-1); - } + rc = topo_compute(node, ap, TOPO_METH_ASRU_COMPUTE, + TOPO_METH_ASRU_COMPUTE_VERSION, priv, asru, err); nvlist_free(ap); - return (0); + return (rc); } else { *asru = ap; + return (0); } - - return (0); } int @@ -113,36 +103,20 @@ topo_node_fru(tnode_t *node, nvlist_t **fru, nvlist_t *priv, int *err) { int rc; nvlist_t *fp; - char *scheme; if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, &fp, err) != 0) return (-1); if (node->tn_fflags & TOPO_FRU_COMPUTE) { - if ((rc = nvlist_lookup_string(fp, FM_FMRI_SCHEME, &scheme)) - != 0) { - if (rc == ENOENT) - *err = ETOPO_FMRI_MALFORM; - else - *err = ETOPO_FMRI_NVL; - - nvlist_free(fp); - return (-1); - } - if ((rc = topo_fru_compute(node->tn_hdl, scheme, priv, fru)) - != 0) { - nvlist_free(fp); - *err = rc; - return (-1); - } + rc = topo_compute(node, fp, TOPO_METH_FRU_COMPUTE, + TOPO_METH_FRU_COMPUTE_VERSION, priv, fru, err); nvlist_free(fp); - return (0); + return (rc); } else { *fru = fp; + return (0); } - - return (0); } int @@ -220,7 +194,6 @@ topo_node_fru_set(tnode_t *node, nvlist_t *fru, int flag, int *err) int topo_node_label_set(tnode_t *node, char *label, int *err) { - /* * Inherit FRU property from our parent if * not specified */ diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c index 869abce891..9563120b61 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c @@ -29,6 +29,7 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <stdarg.h> #include <string.h> #include <strings.h> #include <limits.h> @@ -44,6 +45,7 @@ #include <sys/fm/protocol.h> #include <sys/systeminfo.h> #include <sys/mc.h> +#include <sys/mc_amd.h> #include <fm/topo_mod.h> #include "chip.h" @@ -64,22 +66,74 @@ static int chip_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, topo_instance_t, void *); +static int mem_asru_compute(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); + const topo_modinfo_t chip_info = { "chip", CHIP_VERSION, chip_enum, NULL}; +const topo_method_t rank_methods[] = { + { TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC, + TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL, + mem_asru_compute }, + { NULL } +}; + +static const struct debugopt { + const char *optname; + int optval; +} debugopts[] = { + { "err", TOPO_DBG_ERR }, + { "mod", TOPO_DBG_MOD }, + { "log", TOPO_DBG_LOG }, + { "walk", TOPO_DBG_WALK }, + { "tree", TOPO_DBG_TREE }, + { "all", TOPO_DBG_ALL } +}; + +static nvlist_t *cs_fmri[MC_CHIP_NCS]; + +static void +whinge(topo_mod_t *mod, int *nerr, const char *fmt, ...) +{ + va_list ap; + char buf[160]; + + if (nerr != NULL) + ++*nerr; + + va_start(ap, fmt); + (void) vsnprintf(buf, sizeof (buf), fmt, ap); + va_end(ap); + + topo_mod_dprintf(mod, "%s", buf); +} + int _topo_init(topo_mod_t *mod) { + const char *debugstr = getenv("TOPOCHPDBG"); chip_t *chip; + int i; + + if (debugstr != NULL) { + for (i = 0; i < sizeof (debugopts) / sizeof (struct debugopt); + i++) { + if (strncmp(debugstr, debugopts[i].optname, 4) == 0) { + topo_mod_clrdebug(mod); + topo_mod_setdebug(mod, debugopts[i].optval); + break; /* handle a single option only */ + } + } + } - topo_mod_setdebug(mod, TOPO_DBG_ALL); topo_mod_dprintf(mod, "initializing chip enumerator\n"); if ((chip = topo_mod_zalloc(mod, sizeof (chip_t))) == NULL) return (topo_mod_seterrno(mod, EMOD_NOMEM)); if ((chip->chip_kc = kstat_open()) == NULL) { - topo_mod_dprintf(mod, "kstat_open failed: %s\n", + whinge(mod, NULL, "kstat_open failed: %s\n", strerror(errno)); topo_mod_free(mod, chip, sizeof (chip_t)); return (topo_mod_seterrno(mod, errno)); @@ -94,7 +148,7 @@ _topo_init(topo_mod_t *mod) } if (topo_mod_register(mod, &chip_info, (void *)chip) != 0) { - topo_mod_dprintf(mod, "failed to register hc: " + whinge(mod, NULL, "failed to register hc: " "%s\n", topo_mod_errmsg(mod)); topo_mod_free(mod, chip->chip_cpustats, (chip->chip_ncpustats + 1) * sizeof (kstat_t *)); @@ -151,6 +205,29 @@ chip_longprop(tnode_t *cnode, kstat_t *ksp, const char *name) return (-1); } +static int +mkrsrc(topo_mod_t *mod, tnode_t *pnode, const char *name, int inst, + nvlist_t **nvl) +{ + nvlist_t *args = NULL, *pfmri = NULL; + topo_hdl_t *thp = topo_mod_handle(mod); + int err; + + if (topo_node_resource(pnode, &pfmri, &err) < 0 || + topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || + nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { + nvlist_free(pfmri); + nvlist_free(args); + return (-1); + } + + *nvl = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, inst, args, &err); + nvlist_free(pfmri); + nvlist_free(args); + + return (nvl != NULL ? 0 : -1); /* caller must free nvlist */ +} + static nvlist_t * cpu_fmri_create(topo_mod_t *mod, uint32_t cpuid, char *s, uint8_t cpumask) { @@ -175,86 +252,110 @@ cpu_fmri_create(topo_mod_t *mod, uint32_t cpuid, char *s, uint8_t cpumask) return (asru); } +static nvlist_t * +mem_fmri_create(topo_mod_t *mod) +{ + nvlist_t *asru; + + if (topo_mod_nvalloc(mod, &asru, NV_UNIQUE_NAME) != 0) + return (NULL); + + if (nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM) != 0 || + nvlist_add_uint8(asru, FM_VERSION, FM_MEM_SCHEME_VERSION) != 0) { + nvlist_free(asru); + return (NULL); + } + + return (asru); +} + static int cpu_create(topo_mod_t *mod, tnode_t *pnode, const char *name, int chipid, chip_t *chip) { kstat_named_t *k; - topo_hdl_t *thp; - nvlist_t *fmri, *pfmri, *asru, *args; + nvlist_t *fmri, *asru; tnode_t *cnode; int i, err, nerr = 0; + int coreid, cpuid; if (topo_node_range_create(mod, pnode, name, 0, chip->chip_ncpustats) < 0) return (-1); - thp = topo_mod_handle(mod); - for (i = 0; i <= chip->chip_ncpustats; i++) { - if (chip->chip_cpustats[i] == NULL) continue; + /* + * The chip_id in the cpu_info kstat numbers the individual + * chips from 0 to #chips - 1. + */ if ((k = kstat_data_lookup(chip->chip_cpustats[i], "chip_id")) - == NULL || k->value.l != chipid) { - ++nerr; + == NULL) { + whinge(mod, &nerr, "cpu_create: chip_id lookup via " + "kstats failed\n"); continue; } + if (k->value.l != chipid) + continue; /* not an error */ + + /* + * The clog_id in the cpu_info kstat numbers the processor + * cores of a single chip from 0 to #chips - 1. + */ if ((k = kstat_data_lookup(chip->chip_cpustats[i], "clog_id")) == NULL) { - ++nerr; + whinge(mod, &nerr, "cpu_create: clog_id lookup via " + "kstats failed\n"); continue; } + coreid = k->value.l; - args = pfmri = NULL; - if (topo_node_resource(pnode, &pfmri, &err) < 0 || - topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || - nvlist_add_nvlist(args, - TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { - nvlist_free(pfmri); - nvlist_free(args); - ++nerr; - continue; - } + if (mkrsrc(mod, pnode, name, coreid, &fmri) != 0) { + whinge(mod, &nerr, "cpu_create: mkrsrc failed\n"); + continue; + } - fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, - (topo_instance_t)k->value.l, args, &err); - nvlist_free(pfmri); - nvlist_free(args); - if (fmri == NULL) { - ++nerr; + /* + * The core_id in the cpu_info kstat corresponds to the + * processor id used in psradm etc - ie cpuid as used + * in a cpu scheme fmri. I'm not making this up! + */ + if ((k = kstat_data_lookup(chip->chip_cpustats[i], "core_id")) + == NULL) { + whinge(mod, &nerr, "cpu_create: core_id lookup via " + "kstats failed\n"); continue; } + cpuid = k->value.l; - if ((cnode = topo_node_bind(mod, pnode, name, i, fmri, + if ((cnode = topo_node_bind(mod, pnode, name, cpuid, fmri, NULL)) == NULL) { - ++nerr; + whinge(mod, &nerr, "cpu_create: node bind failed\n"); nvlist_free(fmri); continue; } nvlist_free(fmri); - if ((asru = cpu_fmri_create(mod, i, NULL, 0)) != NULL) { + if ((asru = cpu_fmri_create(mod, cpuid, NULL, 0)) != NULL) { (void) topo_node_asru_set(cnode, asru, 0, &err); nvlist_free(asru); } else { - ++nerr; + whinge(mod, &nerr, "cpu_create: cpu_fmri_create " + "failed\n"); } (void) topo_node_fru_set(cnode, NULL, 0, &err); } - if (nerr != 0) - return (-1); - else - return (0); + return (nerr == 0 ? 0 : -1); } static int -nvprop_add(nvpair_t *nvp, const char *pgname, tnode_t *node) +nvprop_add(topo_mod_t *mod, nvpair_t *nvp, const char *pgname, tnode_t *node) { - int err; + int err = 0; char *pname = nvpair_name(nvp); switch (nvpair_type(nvp)) { @@ -288,25 +389,66 @@ nvprop_add(nvpair_t *nvp, const char *pgname, tnode_t *node) } default: - return (-1); + whinge(mod, &err, "nvprop_add: Can't handle type %d for " + "'%s' in property group %s of %s node\n", + nvpair_type(nvp), pname, pgname, topo_node_name(node)); + return (1); } } -nvlist_t * -mem_fmri_create(topo_mod_t *mod) +static int +dramchan_create(topo_mod_t *mod, tnode_t *pnode, const char *name) { - nvlist_t *asru; + tnode_t *chnode; + nvlist_t *fmri; + char *socket; + int i, nchan; + int err, nerr = 0; - if (topo_mod_nvalloc(mod, &asru, NV_UNIQUE_NAME) != 0) - return (NULL); + /* + * We will enumerate the number of channels present even if only + * channel A is in use (i.e., running in 64-bit mode). Only + * the socket 754 package has a single channel. + */ + if (topo_prop_get_string(pnode, MCT_PGROUP, "socket", + &socket, &err) != 0) + return (-1); - if (nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM) != 0 || - nvlist_add_uint8(asru, FM_VERSION, FM_MEM_SCHEME_VERSION) != 0) { - nvlist_free(asru); - return (NULL); + if (strcmp(socket, "Socket 754") == 0) + nchan = 1; + else + nchan = 2; + + topo_mod_strfree(mod, socket); + + if (topo_node_range_create(mod, pnode, name, 0, nchan - 1) < 0) + return (-1); + + for (i = 0; i < nchan; i++) { + if (mkrsrc(mod, pnode, name, i, &fmri) != 0) { + whinge(mod, &nerr, "dramchan_create: mkrsrc " + "failed\n"); + continue; + } + + if ((chnode = topo_node_bind(mod, pnode, name, i, fmri, + NULL)) == NULL) { + nvlist_free(fmri); + whinge(mod, &nerr, "dramchan_create: node bind " + "failed\n"); + continue; + } + + nvlist_free(fmri); + + (void) topo_pgroup_create(chnode, CHAN_PGROUP, + TOPO_STABILITY_PRIVATE, &err); + + (void) topo_prop_set_string(chnode, CHAN_PGROUP, "channel", + TOPO_PROP_SET_ONCE, i == 0 ? "A" : "B", &err); } - return (asru); + return (nerr == 0 ? 0 : -1); } static int @@ -315,67 +457,218 @@ cs_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc) int i, err, nerr = 0; nvpair_t *nvp; tnode_t *csnode; - topo_hdl_t *thp; nvlist_t *fmri, **csarr = NULL; - nvlist_t *pfmri, *args; uint64_t csnum; uint_t ncs; - if (nvlist_lookup_nvlist_array(mc, "cslist", &csarr, &ncs) != 0 || - ncs == 0) + if (nvlist_lookup_nvlist_array(mc, "cslist", &csarr, &ncs) != 0) return (-1); + if (ncs == 0) + return (0); /* no chip-selects configured on this node */ + if (topo_node_range_create(mod, pnode, name, 0, MAX_CSNUM) < 0) return (-1); - thp = topo_mod_handle(mod); for (i = 0; i < ncs; i++) { if (nvlist_lookup_uint64(csarr[i], "num", &csnum) != 0) { - ++nerr; + whinge(mod, &nerr, "cs_create: cs num property " + "missing\n"); continue; } - args = pfmri = NULL; - if (topo_node_resource(pnode, &pfmri, &err) < 0 || - topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || - nvlist_add_nvlist(args, - TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { - nvlist_free(pfmri); - nvlist_free(args); - ++nerr; - continue; - } - fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, - csnum, args, &err); - nvlist_free(pfmri); - nvlist_free(args); - if (fmri == NULL) { - ++nerr; + if (mkrsrc(mod, pnode, name, csnum, &fmri) != 0) { + whinge(mod, &nerr, "cs_create: mkrsrc failed\n"); continue; } if ((csnode = topo_node_bind(mod, pnode, name, csnum, fmri, NULL)) == NULL) { nvlist_free(fmri); - ++nerr; + whinge(mod, &nerr, "cs_create: node bind failed\n"); continue; } - nvlist_free(fmri); + cs_fmri[csnum] = fmri; /* nvlist will be freed in mc_create */ + + (void) topo_node_asru_set(csnode, fmri, 0, &err); (void) topo_pgroup_create(csnode, CS_PGROUP, TOPO_STABILITY_PRIVATE, &err); for (nvp = nvlist_next_nvpair(csarr[i], NULL); nvp != NULL; nvp = nvlist_next_nvpair(csarr[i], nvp)) { - (void) nvprop_add(nvp, CS_PGROUP, csnode); + nerr += nvprop_add(mod, nvp, CS_PGROUP, csnode); } } - if (nerr != 0) - return (-1); - else - return (0); + return (nerr == 0 ? 0 : -1); +} + +/* + * Registered method for asru computation for rank nodes. The 'node' + * argument identifies the node for which we seek an asru. The 'in' + * argument is used to select which asru we will return, as follows: + * + * - the node name must be "dimm" or "rank" + * - if 'in' is NULL then return any statically defined asru for this node + * - if 'in' is an "hc" scheme fmri then we construct a "mem" scheme asru + * with unum being the hc path to the dimm or rank (this method is called + * as part of dynamic asru computation for rank nodes only, but dimm_create + * also calls it directly to construct a "mem" scheme asru for a dimm node) + * - if 'in' in addition includes an hc-specific member which specifies + * asru-physaddr or asru-offset then these are includes in the "mem" scheme + * asru as additional membersl physaddr and offset + */ +/*ARGSUSED*/ +static int +mem_asru_compute(topo_mod_t *mod, tnode_t *node, topo_version_t version, + nvlist_t *in, nvlist_t **out) +{ + int incl_pa = 0, incl_offset = 0; + nvlist_t *hcsp, *asru; + uint64_t pa, offset; + char *scheme, *unum; + int err; + + if (strcmp(topo_node_name(node), RANK_NODE_NAME) != 0 && + strcmp(topo_node_name(node), DIMM_NODE_NAME) != 0) + return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL)); + + if (in == NULL) { + if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, + TOPO_PROP_ASRU, out, &err) == 0) + return (0); + else + return (topo_mod_seterrno(mod, err)); + } else { + if (nvlist_lookup_string(in, FM_FMRI_SCHEME, &scheme) != 0 || + strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) + return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL)); + } + + if (nvlist_lookup_nvlist(in, FM_FMRI_HC_SPECIFIC, &hcsp) == 0) { + if (nvlist_lookup_uint64(hcsp, "asru-"FM_FMRI_MEM_PHYSADDR, + &pa) == 0) + incl_pa = 1; + + if (nvlist_lookup_uint64(hcsp, "asru-"FM_FMRI_MEM_OFFSET, + &offset) == 0) + incl_offset = 1; + } + + /* use 'in' to obtain resource path; could use node resource */ + if (topo_fmri_nvl2str(topo_mod_handle(mod), in, &unum, &err) < 0) + return (topo_mod_seterrno(mod, err)); + + if ((asru = mem_fmri_create(mod)) == NULL) { + topo_mod_strfree(mod, unum); + return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); + } + + err = nvlist_add_string(asru, FM_FMRI_MEM_UNUM, unum); + if (incl_pa) + err |= nvlist_add_uint64(asru, FM_FMRI_MEM_PHYSADDR, pa); + if (incl_offset) + err |= nvlist_add_uint64(asru, FM_FMRI_MEM_OFFSET, offset); + + topo_mod_strfree(mod, unum); + if (err != 0) { + nvlist_free(asru); + return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); + } + + *out = asru; + return (0); +} + +static int +rank_create(topo_mod_t *mod, tnode_t *pnode, nvlist_t *dimmnvl) +{ + uint64_t *csnumarr; + char **csnamearr; + uint_t ncs, ncsname; + tnode_t *ranknode; + nvlist_t *fmri, *pfmri = NULL; + uint64_t dsz, rsz; + int nerr = 0; + int err; + int i; + + if (nvlist_lookup_uint64_array(dimmnvl, "csnums", &csnumarr, + &ncs) != 0 || nvlist_lookup_string_array(dimmnvl, "csnames", + &csnamearr, &ncsname) != 0 || ncs != ncsname) { + whinge(mod, &nerr, "rank_create: " + "csnums/csnames extraction failed\n"); + return (nerr); + } + + if (topo_node_resource(pnode, &pfmri, &err) < 0) { + whinge(mod, &nerr, "rank_create: parent fmri lookup " + "failed\n"); + return (nerr); + } + + if (topo_node_range_create(mod, pnode, RANK_NODE_NAME, 0, ncs) < 0) { + whinge(mod, &nerr, "rank_create: range create failed\n"); + nvlist_free(pfmri); + return (nerr); + } + + if (topo_prop_get_uint64(pnode, DIMM_PGROUP, "size", &dsz, &err) == 0) { + rsz = dsz / ncs; + } else { + whinge(mod, &nerr, "rank_create: parent dimm has no size\n"); + return (nerr); + } + + for (i = 0; i < ncs; i++) { + if (mkrsrc(mod, pnode, RANK_NODE_NAME, i, &fmri) < 0) { + whinge(mod, &nerr, "rank_create: mkrsrc failed\n"); + continue; + } + + if ((ranknode = topo_node_bind(mod, pnode, RANK_NODE_NAME, i, + fmri, NULL)) == NULL) { + nvlist_free(fmri); + whinge(mod, &nerr, "rank_create: node bind " + "failed\n"); + continue; + } + + nvlist_free(fmri); + + (void) topo_node_fru_set(ranknode, pfmri, 0, &err); + + /* + * If a rank is faulted the asru is the associated + * chip-select, but if a page within a rank is faulted + * the asru is just that page. Hence the dual preconstructed + * and computed ASRU. + */ + (void) topo_node_asru_set(ranknode, cs_fmri[csnumarr[i]], + TOPO_ASRU_COMPUTE, &err); + + if (topo_method_register(mod, ranknode, rank_methods) < 0) + whinge(mod, &nerr, "rank_create: " + "topo_method_register failed"); + + (void) topo_pgroup_create(ranknode, RANK_PGROUP, + TOPO_STABILITY_PRIVATE, &err); + + (void) topo_prop_set_uint64(ranknode, RANK_PGROUP, "size", + TOPO_PROP_SET_ONCE, rsz, &err); + + (void) topo_prop_set_string(ranknode, RANK_PGROUP, "csname", + TOPO_PROP_SET_ONCE, csnamearr[i], &err); + + (void) topo_prop_set_uint64(ranknode, RANK_PGROUP, "csnum", + TOPO_PROP_SET_ONCE, csnumarr[i], &err); + } + + nvlist_free(pfmri); + + return (nerr); } static int @@ -385,59 +678,61 @@ dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc) nvpair_t *nvp; tnode_t *dimmnode; nvlist_t *fmri, *asru, **dimmarr = NULL; - nvlist_t *pfmri, *args; - uint64_t ldimmnum; + uint64_t num; uint_t ndimm; - topo_hdl_t *thp; - - thp = topo_mod_handle(mod); - if (nvlist_lookup_nvlist_array(mc, "dimmlist", &dimmarr, &ndimm) != 0 || - ndimm == 0) + if (nvlist_lookup_nvlist_array(mc, "dimmlist", &dimmarr, &ndimm) != 0) { + whinge(mod, NULL, "dimm_create: dimmlist lookup failed\n"); return (-1); + } + + if (ndimm == 0) + return (0); /* no dimms present on this node */ - if (topo_node_range_create(mod, pnode, name, 0, MAX_DIMMNUM) < 0) + if (topo_node_range_create(mod, pnode, name, 0, MAX_DIMMNUM) < 0) { + whinge(mod, NULL, "dimm_create: range create failed\n"); return (-1); + } for (i = 0; i < ndimm; i++) { - if (nvlist_lookup_uint64(dimmarr[i], "num", &ldimmnum) != 0) { - ++nerr; + if (nvlist_lookup_uint64(dimmarr[i], "num", &num) != 0) { + whinge(mod, &nerr, "dimm_create: dimm num property " + "missing\n"); continue; } - args = pfmri = NULL; - if (topo_node_resource(pnode, &pfmri, &err) < 0 || - topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || - nvlist_add_nvlist(args, - TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { - nvlist_free(pfmri); - nvlist_free(args); - ++nerr; - continue; - } - fmri = topo_fmri_create(thp, - FM_FMRI_SCHEME_HC, name, ldimmnum, args, &err); - nvlist_free(pfmri); - nvlist_free(args); - if (fmri == NULL) { - ++nerr; + if (mkrsrc(mod, pnode, name, num, &fmri) < 0) { + whinge(mod, &nerr, "dimm_create: mkrsrc failed\n"); continue; } - if ((dimmnode = topo_node_bind(mod, pnode, name, ldimmnum, fmri, + if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri, NULL)) == NULL) { nvlist_free(fmri); - ++nerr; + whinge(mod, &nerr, "dimm_create: node bind " + "failed\n"); continue; } - (void) topo_node_fru_set(dimmnode, fmri, 0, &err); - if ((asru = mem_fmri_create(mod)) != NULL) { - (void) topo_node_asru_set(dimmnode, asru, - TOPO_ASRU_COMPUTE, &err); + /* + * The asru is static but we prefer to publish it in the + * "mem" scheme so call the compute method directly to + * perform the conversion. + */ + if (mem_asru_compute(mod, dimmnode, + TOPO_METH_ASRU_COMPUTE_VERSION, fmri, &asru) == 0) { + (void) topo_node_asru_set(dimmnode, asru, 0, &err); nvlist_free(asru); + } else { + + nvlist_free(fmri); + whinge(mod, &nerr, "dimm_create: mem_asru_compute " + "failed\n"); + continue; } + (void) topo_node_fru_set(dimmnode, fmri, 0, &err); + nvlist_free(fmri); (void) topo_pgroup_create(dimmnode, DIMM_PGROUP, @@ -445,35 +740,19 @@ dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc) for (nvp = nvlist_next_nvpair(dimmarr[i], NULL); nvp != NULL; nvp = nvlist_next_nvpair(dimmarr[i], nvp)) { - if (nvprop_add(nvp, DIMM_PGROUP, dimmnode) == 0) { - continue; - } else if (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY) { - uint64_t *csnumarr; - uint_t ncs; - int i; - - if (strcmp(nvpair_name(nvp), "csnums") != 0 || - nvpair_value_uint64_array(nvp, &csnumarr, - &ncs) != 0) - continue; - - for (i = 0; i < ncs; i++) { - char name[7]; - (void) snprintf(name, sizeof (name), - "csnum%d", i); - (void) topo_prop_set_uint64(dimmnode, - DIMM_PGROUP, name, - TOPO_PROP_SET_ONCE, - csnumarr[i], &err); - } - } + if (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY && + strcmp(nvpair_name(nvp), "csnums") == 0 || + nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY && + strcmp(nvpair_name(nvp), "csnames") == 0) + continue; /* used in rank_create() */ + + nerr += nvprop_add(mod, nvp, DIMM_PGROUP, dimmnode); } + + nerr += rank_create(mod, dimmnode, dimmarr[i]); } - if (nerr != 0) - return (-1); - else - return (0); + return (nerr == 0 ? 0 : -1); } static nvlist_t * @@ -481,6 +760,7 @@ mc_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id) { mc_snapshot_info_t mcs; void *buf = NULL; + uint8_t ver; nvlist_t *nvl; char path[64]; @@ -490,7 +770,19 @@ mc_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id) fd = open(path, O_RDONLY); if (fd == -1) { - topo_mod_dprintf(mod, "mc failed to open %s: %s\n", + /* + * Some v20z and v40z systems may have had the 3rd-party + * NWSnps packagae installed which installs a /dev/mc + * link. So try again via /devices. + */ + (void) snprintf(path, sizeof (path), + "/devices/pci@0,0/pci1022,1102@%x,2:mc-amd", + MC_AMD_DEV_OFFSET + id); + fd = open(path, O_RDONLY); + } + + if (fd == -1) { + whinge(mod, NULL, "mc failed to open %s: %s\n", path, strerror(errno)); return (NULL); } @@ -499,7 +791,7 @@ mc_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id) (buf = topo_mod_alloc(mod, mcs.mcs_size)) == NULL || ioctl(fd, MC_IOC_SNAPSHOT, buf) == -1) { - topo_mod_dprintf(mod, "mc failed to snapshot %s: %s\n", + whinge(mod, NULL, "mc failed to snapshot %s: %s\n", path, strerror(errno)); free(buf); @@ -510,6 +802,17 @@ mc_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id) (void) close(fd); err = nvlist_unpack(buf, mcs.mcs_size, &nvl, 0); topo_mod_free(mod, buf, mcs.mcs_size); + + if (nvlist_lookup_uint8(nvl, MC_NVLIST_VERSTR, &ver) != 0) { + whinge(mod, NULL, "mc nvlist is not versioned\n"); + nvlist_free(nvl); + return (NULL); + } else if (ver != MC_NVLIST_VERS1) { + whinge(mod, NULL, "mc nvlist version mismatch\n"); + nvlist_free(nvl); + return (NULL); + } + return (err ? NULL : nvl); } @@ -521,26 +824,16 @@ mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name) nvlist_t *fmri; nvpair_t *nvp; nvlist_t *mc = NULL; - nvlist_t *pfmri, *args; - topo_hdl_t *thp; + int i; - thp = topo_mod_handle(mod); - args = pfmri = NULL; - if (topo_node_resource(pnode, &pfmri, &err) < 0 || - topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || - nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { - nvlist_free(pfmri); - nvlist_free(args); + if (mkrsrc(mod, pnode, name, 0, &fmri) != 0) { + whinge(mod, NULL, "mc_create: mkrsrc failed\n"); return (-1); } - fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, 0, args, &err); - nvlist_free(pfmri); - nvlist_free(args); - if (fmri == NULL) - return (-1); if (topo_node_range_create(mod, pnode, name, 0, 0) < 0) { nvlist_free(fmri); + whinge(mod, NULL, "mc_create: node range create failed\n"); return (-1); } @@ -554,6 +847,7 @@ mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name) nvlist_free(mc); topo_node_range_destroy(pnode, name); nvlist_free(fmri); + whinge(mod, NULL, "mc_create: mc lookup or bind failed\n"); return (-1); } @@ -563,21 +857,39 @@ mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name) /* * Add memory controller properties */ - (void) topo_pgroup_create(mcnode, MC_PGROUP, + (void) topo_pgroup_create(mcnode, MCT_PGROUP, TOPO_STABILITY_PRIVATE, &err); for (nvp = nvlist_next_nvpair(mc, NULL); nvp != NULL; nvp = nvlist_next_nvpair(mc, nvp)) { - if (nvprop_add(nvp, MC_PGROUP, mcnode) == 0) + if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY && + (strcmp(nvpair_name(nvp), "cslist") == 0 || + strcmp(nvpair_name(nvp), "dimmlist") == 0)) { continue; - else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) - break; + } else if (nvpair_type(nvp) == DATA_TYPE_UINT8 && + strcmp(nvpair_name(nvp), MC_NVLIST_VERSTR) == 0) { + continue; + } else { + if (nvprop_add(mod, nvp, MCT_PGROUP, mcnode) != 0) + rc = -1; + } } - if (dimm_create(mod, mcnode, DIMM_NODE_NAME, mc) != 0 || - cs_create(mod, mcnode, CS_NODE_NAME, mc) != 0) + if (dramchan_create(mod, mcnode, CHAN_NODE_NAME) != 0 || + cs_create(mod, mcnode, CS_NODE_NAME, mc) != 0 || + dimm_create(mod, mcnode, DIMM_NODE_NAME, mc) != 0) rc = -1; + /* + * Free the fmris for the chip-selects allocated in cs_create + */ + for (i = 0; i < MC_CHIP_NCS; i++) { + if (cs_fmri[i] != NULL) { + nvlist_free(cs_fmri[i]); + cs_fmri[i] = NULL; + } + } + nvlist_free(mc); return (rc); } @@ -590,12 +902,9 @@ chip_create(topo_mod_t *mod, tnode_t *pnode, const char *name, kstat_t *ksp; ulong_t *chipmap; tnode_t *cnode; - nvlist_t *pfmri, *fmri, *args; - topo_hdl_t *thp; - - thp = topo_mod_handle(mod); + nvlist_t *fmri; - if ((chipmap = topo_mod_zalloc(mod, BT_BITOUL(chip->chip_ncpustats) * + if ((chipmap = topo_mod_zalloc(mod, BT_BITOUL(max) * sizeof (ulong_t))) == NULL) return (topo_mod_seterrno(mod, EMOD_NOMEM)); @@ -619,7 +928,8 @@ chip_create(topo_mod_t *mod, tnode_t *pnode, const char *name, continue; if ((k = kstat_data_lookup(ksp, "chip_id")) == NULL) { - ++nerr; + whinge(mod, &nerr, "chip_create: chip_id lookup " + "via kstats failed\n"); continue; } @@ -630,31 +940,19 @@ chip_create(topo_mod_t *mod, tnode_t *pnode, const char *name, if (chipid < min || chipid > max) continue; - args = pfmri = NULL; - if (topo_node_resource(pnode, &pfmri, &err) < 0 || - topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 || - nvlist_add_nvlist(args, - TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) { - nvlist_free(pfmri); - nvlist_free(args); - ++nerr; - continue; - } - fmri = topo_fmri_create(thp, - FM_FMRI_SCHEME_HC, name, chipid, args, &err); - nvlist_free(pfmri); - nvlist_free(args); - if (fmri == NULL) { - ++nerr; + if (mkrsrc(mod, pnode, name, chipid, &fmri) != 0) { + whinge(mod, &nerr, "chip_create: mkrsrc failed\n"); continue; } if ((cnode = topo_node_bind(mod, pnode, name, chipid, fmri, NULL)) == NULL) { - ++nerr; nvlist_free(fmri); + whinge(mod, &nerr, "chip_create: node bind " + "failed for chipid %d\n", chipid); continue; } + BT_SET(chipmap, chipid); (void) topo_node_fru_set(cnode, fmri, 0, &err); @@ -667,18 +965,19 @@ chip_create(topo_mod_t *mod, tnode_t *pnode, const char *name, (void) chip_longprop(cnode, ksp, CHIP_MODEL); (void) chip_longprop(cnode, ksp, CHIP_STEPPING); - if (mc_create(mod, cnode, MC_NODE_NAME) != 0 || - cpu_create(mod, cnode, CPU_NODE_NAME, chipid, chip) != 0) - ++nerr; + if (cpu_create(mod, cnode, CPU_NODE_NAME, chipid, chip) != 0 || + mc_create(mod, cnode, MCT_NODE_NAME) != 0) + nerr++; /* have whinged elsewhere */ } - topo_mod_free(mod, chipmap, BT_BITOUL(chip->chip_ncpustats) * - sizeof (ulong_t)); + topo_mod_free(mod, chipmap, BT_BITOUL(max) * sizeof (ulong_t)); - if (nerr != 0) + if (nerr == 0) { + return (0); + } else { (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM); - - return (0); + return (-1); + } } static int diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h index 269dfa4f37..d1ff5ca3b4 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -39,15 +38,19 @@ extern "C" { #define CHIP_VERSION TOPO_VERSION -#define MC_NODE_NAME "memory-controller" +#define MCT_NODE_NAME "memory-controller" +#define CHAN_NODE_NAME "dram-channel" #define CPU_NODE_NAME "cpu" #define CS_NODE_NAME "chip-select" #define DIMM_NODE_NAME "dimm" +#define RANK_NODE_NAME "rank" #define CHIP_PGROUP "chip-properties" -#define CS_PGROUP "chip-select-properties" -#define MC_PGROUP "memory-contoller-properties" -#define DIMM_PGROUP "dimm-properties" +#define MCT_PGROUP MCT_NODE_NAME "-properties" +#define CHAN_PGROUP CHAN_NODE_NAME "-properties" +#define CS_PGROUP CS_NODE_NAME "-properties" +#define DIMM_PGROUP DIMM_NODE_NAME "-properties" +#define RANK_PGROUP RANK_NODE_NAME "-properties" /* * CHIP_PGROUP properties |