diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2020-01-09 07:48:58 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2020-03-27 15:41:55 +0000 |
commit | ae6d4bc342613e6a5dc7b84b03ecdb0cc9cf7d26 (patch) | |
tree | 2a66b7c2c43e8fd5f5c3e5d42fcb40691fcfab3a /usr/src | |
parent | cd62a92d4a964bfe61d35ba2301b69e65e22a509 (diff) | |
download | illumos-joyent-ae6d4bc342613e6a5dc7b84b03ecdb0cc9cf7d26.tar.gz |
12444 Intel v1 chip topo needs rank information
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Paul Winder <paul@winders.demon.co.uk>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c | 206 |
1 files changed, 178 insertions, 28 deletions
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c index 4c5da1e8cb..df6e2b6f95 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c @@ -73,6 +73,8 @@ #define DIMM_HDRL "hdrl-enabled" #define DIMM_HDRL_PARITY "hdrl-parity" #define DIMM_3DRANK "3d-subranks" +#define RANK_STATUS "dimm-rank-status" +#define RANK_SIZE "dimm-rank-size" static const topo_pgroup_info_t dimm_channel_pgroup = { PGNAME(CHAN), TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 }; @@ -156,7 +158,7 @@ mc_add_ranks(topo_mod_t *mod, tnode_t *dnode, nvlist_t *auth, int dimm, (void) topo_node_fru_set(rnode, NULL, 0, &err); if (topo_method_register(mod, rnode, rank_methods) < 0) - whinge(mod, &err, "rank_create: " + whinge(mod, &err, "mc_add_ranks: " "topo_method_register failed"); if (! is_xpv() && topo_method_register(mod, rnode, @@ -455,6 +457,102 @@ mc_nb_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode, } static int +mc_rank_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, + nvlist_t *dimm_nvl, uint64_t rsize, uint32_t id) +{ + nvlist_t *fmri; + tnode_t *rank; + int err; + boolean_t *disabled; + uint_t ndisabled; + const char *status; + + fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, RANK, id, + NULL, auth, NULL, NULL, NULL); + if (fmri == NULL) { + whinge(mod, NULL, "mc_rank_create_v1: topo_mod_hcfmri " + "failed\n"); + return (-1); + } + + if ((rank = topo_node_bind(mod, pnode, RANK, id, fmri)) == NULL) { + whinge(mod, NULL, "mc_rank_create_v1: node bind failed for " + "DIMM\n"); + nvlist_free(fmri); + return (-1); + } + + if (topo_method_register(mod, rank, rank_methods) < 0) { + whinge(mod, NULL, "mc_rank_create_v1: topo_method_register " + "failed for rank_methods: %d", topo_mod_errno(mod)); + } + + if (!is_xpv() && topo_method_register(mod, rank, + ntv_page_retire_methods) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: topo_method_register " + "failed for page retire: %d", topo_mod_errno(mod)); + } + + if (topo_node_asru_set(rank, fmri, TOPO_ASRU_COMPUTE, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set asru: %d", + err); + nvlist_free(fmri); + return (topo_mod_seterrno(mod, err)); + } + + if (topo_node_fru_set(rank, NULL, 0, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: fru set failed: " + "%d\n", err); + nvlist_free(fmri); + return (topo_mod_seterrno(mod, err)); + } + nvlist_free(fmri); + + if (topo_pgroup_create(rank, &rank_pgroup, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to create " + "property group: %d\n", err); + return (topo_mod_seterrno(mod, err)); + } + + /* + * The traditional northbridge driver broke down each rank into the + * interleave targets that led to it. At this time, the imc driver (the + * only v1 provider) does not supply that information and therefore we + * cannot set that. Instead we just set basic properties on this, the + * size of the rank and whether or not it is disabled. + */ + if (rsize != 0 && topo_prop_set_uint64(rank, PGNAME(RANK), RANK_SIZE, + TOPO_PROP_IMMUTABLE, rsize, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set %s " + "property: %d", RANK_SIZE, err); + return (topo_mod_seterrno(mod, err)); + } + + if (nvlist_lookup_boolean_array(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_RDIS, + &disabled, &ndisabled) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: Couldn't find disabled " + "ranks array"); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + + if (id >= ndisabled) { + whinge(mod, NULL, "mc_rank_create_v1: Found rank %u with id " + "larger than supported by hardware", id); + return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); + } + + status = disabled[id] ? "disabled" : "enabled"; + if (topo_prop_set_string(rank, PGNAME(RANK), RANK_STATUS, + TOPO_PROP_IMMUTABLE, status, &err) != 0) { + whinge(mod, NULL, "mc_rank_create_v1: failed to set %s " + "property: %d", RANK_STATUS, err); + return (topo_mod_seterrno(mod, err)); + } + + return (0); +} + +static int mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, nvlist_t *dimm_nvl, uint_t id) { @@ -462,8 +560,8 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, tnode_t *dimm; nvlist_t *fmri; boolean_t present; - uint64_t size, density; - uint32_t cols, rows, width, ranks, banks; + uint64_t size, density, rsize; + uint32_t cols, rows, width, ranks, banks, i; /* * First, figure out if this DIMM is present. If not, we don't bother @@ -510,8 +608,10 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, &size) == 0) { char buf[64]; const char *suffix; + uint64_t tsize; ret |= topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_SIZE, TOPO_PROP_IMMUTABLE, size, &err); + tsize = size; /* * We must manually cons up a dimm-size property which is the @@ -520,68 +620,115 @@ mc_dimm_create_v1(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, * controller drivers did this in the driver, but we instead opt * to do so in user land. */ - if (size >= (1ULL << 40)) { - size /= (1ULL << 40); + if (tsize >= (1ULL << 40)) { + tsize /= (1ULL << 40); suffix = "T"; - } else if (size >= (1ULL << 30)) { - size /= (1ULL << 30); + } else if (tsize >= (1ULL << 30)) { + tsize /= (1ULL << 30); suffix = "G"; - } else if (size >= (1ULL << 20)) { - size /= (1ULL << 20); + } else if (tsize >= (1ULL << 20)) { + tsize /= (1ULL << 20); suffix = "M"; } else { suffix = NULL; } if (suffix != NULL) { - if (snprintf(buf, sizeof (buf), "%"PRIu64"%s", size, + if (snprintf(buf, sizeof (buf), "%"PRIu64"%s", tsize, suffix) >= sizeof (buf)) { whinge(mod, NULL, "failed to construct DIMM " "size due to buffer overflow"); return (topo_mod_seterrno(mod, EMOD_UNKNOWN)); } - ret |= topo_prop_set_string(dimm, PGNAME(DIMM), + ret = topo_prop_set_string(dimm, PGNAME(DIMM), DIMM_STRING_SIZE, TOPO_PROP_IMMUTABLE, buf, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } + } else { + size = 0; } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_NCOLS, &cols) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_COL, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_COL, TOPO_PROP_IMMUTABLE, cols, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_NROWS, &rows) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_ROW, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_ROW, TOPO_PROP_IMMUTABLE, rows, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint64(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_DENSITY, &density) == 0) { - ret |= topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_DENSITY, + ret = topo_prop_set_uint64(dimm, PGNAME(DIMM), DIMM_DENSITY, TOPO_PROP_IMMUTABLE, density, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_WIDTH, &width) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_WIDTH, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_WIDTH, TOPO_PROP_IMMUTABLE, width, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_BANKS, &banks) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_BANKS, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_BANKS, TOPO_PROP_IMMUTABLE, banks, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } + } else { + banks = 0; } if (nvlist_lookup_uint32(dimm_nvl, MCINTEL_NVLIST_V1_DIMM_RANKS, &ranks) == 0) { - ret |= topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_RANKS, + ret = topo_prop_set_uint32(dimm, PGNAME(DIMM), DIMM_RANKS, TOPO_PROP_IMMUTABLE, ranks, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } + } + + if (ret != 0) { + return (-1); + } + + if (topo_node_range_create(mod, dimm, RANK, 0, ranks - 1) < 0) { + whinge(mod, NULL, "mc_dimm_create_v1: rank node range " + "create failed\n"); + return (-1); + } + + rsize = 0; + if (size != 0 && banks != 0) { + rsize = size / banks; } - return (ret != 0 ? -1 : 0); + for (i = 0; i < ranks; i++) { + if (mc_rank_create_v1(mod, dimm, auth, dimm_nvl, rsize, i) != + 0) { + return (-1); + } + } + + return (0); } static int @@ -657,12 +804,12 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, uint_t nchans, i; if (mkrsrc(mod, pnode, name, id, auth, &fmri) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: mkrsrc failed\n"); + whinge(mod, NULL, "mc_imc_create_v1: mkrsrc failed\n"); return (-1); } if ((mcnode = topo_node_bind(mod, pnode, name, id, fmri)) == NULL) { - whinge(mod, NULL, "mc_nb_create_v1: node bind failed" + whinge(mod, NULL, "mc_imc_create_v1: node bind failed" " for memory-controller\n"); nvlist_free(fmri); return (-1); @@ -670,13 +817,13 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_free(fmri); if (topo_node_fru_set(mcnode, NULL, 0, &err) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: fru set failed: " + whinge(mod, NULL, "mc_imc_create_v1: fru set failed: " "%d\n", err); return (topo_mod_seterrno(mod, err)); } if (topo_pgroup_create(mcnode, &mc_pgroup, &err) != 0) { - whinge(mod, NULL, "mc_nb_create_v1: failed to create " + whinge(mod, NULL, "mc_imc_create_v1: failed to create " "property group: %d\n", err); return (topo_mod_seterrno(mod, err)); } @@ -689,14 +836,20 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, if (nvlist_lookup_boolean_value(mc_nvl, MCINTEL_NVLIST_V1_MC_ECC, &ecc) == 0) { const char *pval = ecc ? "enabled" : "disabled"; - ret |= topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_ECC, + ret = topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_ECC, TOPO_PROP_IMMUTABLE, pval, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_string(mc_nvl, MCINTEL_NVLIST_V1_MC_POLICY, &page) == 0) { - ret |= topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_POLICY, + ret = topo_prop_set_string(mcnode, PGNAME(MCT), MC_PROP_POLICY, TOPO_PROP_IMMUTABLE, page, &err); + if (ret != 0) { + return (topo_mod_seterrno(mod, err)); + } } if (nvlist_lookup_string(mc_nvl, MCINTEL_NVLIST_V1_MC_CHAN_MODE, @@ -704,9 +857,6 @@ mc_imc_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, cmode = NULL; } - if (ret != 0) - return (-1); - if (nvlist_lookup_nvlist_array(mc_nvl, MCINTEL_NVLIST_V1_MC_CHANNELS, &channels, &nchans) != 0) { whinge(mod, NULL, "mc_imc_create_v1: missing channels entry"); @@ -746,7 +896,7 @@ mc_nb_create_v1(topo_mod_t *mod, tnode_t *pnode, const char *name, if (topo_node_range_create(mod, pnode, name, 0, nmc - 1) < 0) { whinge(mod, NULL, - "mc_nb_create: node range create failed\n"); + "mc_nb_create_v1: node range create failed\n"); return (-1); } |