1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * CDDL HEADER START
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * The contents of this file are subject to the terms of the
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Common Development and Distribution License (the "License").
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * You may not use this file except in compliance with the License.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * or http://www.opensolaris.org/os/licensing.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * See the License for the specific language governing permissions
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * and limitations under the License.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * When distributing Covered Code, include this CDDL HEADER in each
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * If applicable, add the following below this CDDL HEADER, with the
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * fields enclosed by brackets "[]" replaced with your own identifying
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * information: Portions Copyright [yyyy] [name of copyright owner]
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * CDDL HEADER END
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Ereport-handling routines for memory errors
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <gmem_mem.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <gmem_dimm.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <gmem_page.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <gmem.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <strings.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <string.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <errno.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <assert.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <fm/fmd_api.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <fm/libtopo.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <sys/fm/protocol.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <sys/async.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport#include <sys/errclassify.h>
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do#define OFFBIT 0xFFFFFFFFFFFC07FFULL
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do#define BIT28_32 0x00000001F0000000ULL
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do#define BIT13_17 0x000000000003E000ULL
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do#define BIT18_19 0x00000000000C0000ULL
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do#define BIT11_12 0x0000000000001800ULL
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportstruct ce_name2type {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport const char *name;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ce_dispact_t type;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport};
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Donvlist_t *fru_nvl;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportstatic ce_dispact_t
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_mem_name2type(const char *name)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport static const struct ce_name2type new[] = {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport { "mem-unk", CE_DISP_UNKNOWN },
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport { "mem-is", CE_DISP_INTERMITTENT },
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport { "mem-cs", CE_DISP_PERS },
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport { "mem-ss", CE_DISP_STICKY },
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport { NULL }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport };
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport const struct ce_name2type *names = &new[0];
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport const struct ce_name2type *tp;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (tp = names; tp->name != NULL; tp++) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (strcasecmp(name, tp->name) == 0)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (tp->type);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (CE_DISP_UNKNOWN);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*ARGSUSED*/
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic int
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dofind_fault_fru(topo_hdl_t *thp, tnode_t *node, void *arg)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *nvl = (nvlist_t *)arg;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *rsc = NULL, *fru = NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t **hcl, **topo_hcl;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint_t n1, n2;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do char *name, *name1, *name2;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do char *id1, *id2;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int err, i;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (topo_node_resource(node, &rsc, &err) < 0)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_NEXT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do err = nvlist_lookup_nvlist_array(rsc, FM_FMRI_HC_LIST, &topo_hcl, &n1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (err != 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_NEXT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(topo_hcl[n1 - 1], FM_FMRI_HC_NAME, &name);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (strcmp(name, "chip") != 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_NEXT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcl, &n2);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (n1 != n2) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_NEXT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n1; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(topo_hcl[i], FM_FMRI_HC_NAME,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do &name1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(topo_hcl[i], FM_FMRI_HC_ID, &id1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name2);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id2);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (strcmp(name1, name2) != 0 || strcmp(id1, id2) != 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_NEXT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) topo_node_fru(node, &fru, NULL, &err);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (fru != NULL) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_dup(fru, &fru_nvl, NV_UNIQUE_NAME);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(fru);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (TOPO_WALK_TERMINATE);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Donvlist_t *
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dogmem_find_fault_fru(fmd_hdl_t *hdl, nvlist_t *nvl) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do topo_hdl_t *thp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do topo_walk_t *twp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int err;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fru_nvl = NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (NULL);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do find_fault_fru, nvl, &err)) == NULL) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_topo_rele(hdl, thp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (NULL);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) topo_walk_step(twp, TOPO_WALK_CHILD);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do topo_walk_fini(twp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_topo_rele(hdl, thp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (fru_nvl);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * fault the FRU of the common detector between two DIMMs
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dovoid
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dogmem_gen_datapath_fault(fmd_hdl_t *hdl, nvlist_t *det)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do char *name, *id;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t **hcl1, **hcl;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint_t n;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int i, j;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_t *cp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *fltlist, *rsrc;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *fru = NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nvlist_lookup_nvlist_array(det, FM_FMRI_HC_LIST, &hcl1, &n) < 0)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(hcl1[i], FM_FMRI_HC_NAME, &name);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (strcmp(name, "chip") == 0)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do break;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do n = i + 1;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do hcl = fmd_hdl_zalloc(hdl, sizeof (nvlist_t *) * n, FMD_SLEEP);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (hcl == NULL)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_alloc(&hcl[i],
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE, 0);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0, j = 0; i < n; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(hcl1[i], FM_FMRI_HC_NAME, &name);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_lookup_string(hcl1[i], FM_FMRI_HC_ID, &id);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_add_string(hcl[j], FM_FMRI_HC_NAME, name);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) nvlist_add_string(hcl[j], FM_FMRI_HC_ID, id);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do j++;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (strcmp(name, "chip") == 0)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do break;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nvlist_alloc(&rsrc, NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE, 0) != 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n; i++) {
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(hcl[i]);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_free(hdl, hcl, sizeof (nvlist_t *) * n);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nvlist_add_uint8(rsrc, FM_VERSION, FM_HC_SCHEME_VERSION) != 0 ||
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_add_string(rsrc, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0 ||
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_add_string(rsrc, FM_FMRI_HC_ROOT, "") != 0 ||
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_add_uint32(rsrc, FM_FMRI_HC_LIST_SZ, n) != 0 ||
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_add_nvlist_array(rsrc, FM_FMRI_HC_LIST, hcl, n) != 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n; i++) {
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(hcl[i]);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_free(hdl, hcl, sizeof (nvlist_t *) * n);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fru = gmem_find_fault_fru(hdl, rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (fru != NULL) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do cp = fmd_case_open(hdl, NULL);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fltlist = fmd_nvl_create_fault(hdl, "fault.memory.datapath",
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do 100, fru, fru, fru);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_add_suspect(hdl, cp, fltlist);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_solve(hdl, cp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(fru);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < n; i++) {
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(hcl[i]);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_free(hdl, hcl, sizeof (nvlist_t *) * n);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * formula to conver an unhashed address to hashed address
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * PA[17:11] = (PA[32:28] xor PA[17:13]) :: ((PA[19:18] xor PA[12:11])
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic void
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dogmem_to_hashed_addr(uint64_t *addr, uint64_t afar)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do *addr = (afar & OFFBIT) | ((afar & BIT28_32) >> 15) ^ (afar & BIT13_17)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do | ((afar & BIT18_19) >> 7) ^ (afar & BIT11_12);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * check if a dimm has n CEs that have the same symbol-in-error
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Doint
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Doupos_thresh_check(gmem_dimm_t *dimm, uint16_t upos, uint32_t threshold)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int i;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_mq_t *ip, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int count = 0;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < GMEM_MAX_CKWDS; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (ip = gmem_list_next(&dimm->mq_root[i]); ip != NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(ip);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (ip->mq_unit_position == upos) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do count++;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (count >= threshold)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (0);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * check if smaller number of retired pages > 1/16 of larger number of
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * retired pages
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Doint
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Docheck_bad_rw_retired_pages(fmd_hdl_t *hdl, gmem_dimm_t *d1, gmem_dimm_t *d2)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint_t sret, lret;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do double ratio;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do sret = lret = 0;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (d2->dimm_nretired < d1->dimm_nretired) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do sret = d2->dimm_nretired;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do lret = d1->dimm_nretired;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do } else if (d2->dimm_nretired > d1->dimm_nretired) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do sret = d1->dimm_nretired;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do lret = d2->dimm_nretired;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do } else
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (0);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ratio = lret * GMEM_MQ_RATIO;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (sret > ratio) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_debug(hdl, "sret=%d lret=%d ratio=%.3f",
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do sret, lret, ratio);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (0);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * check bad rw on any two DIMMs. The check succeeds if
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * - each DIMM has a n CEs which have the same symbol-in-error,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * - the smaller number of retired pages > 1/16 larger number of retired pages
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic int
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Docheck_bad_rw_between_dimms(fmd_hdl_t *hdl, gmem_dimm_t *d1, gmem_dimm_t *d2,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint16_t *rupos)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int i;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_mq_t *ip, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint16_t upos;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (i = 0; i < GMEM_MAX_CKWDS; i++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (ip = gmem_list_next(&d1->mq_root[i]); ip != NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(ip);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do upos = ip->mq_unit_position;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (upos_thresh_check(d1, upos, gmem.gm_nupos)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (upos_thresh_check(d2, upos,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem.gm_nupos)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (check_bad_rw_retired_pages(hdl,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do d1, d2)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do *rupos = upos;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (1);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (0);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic void
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dobad_reader_writer_check(fmd_hdl_t *hdl, nvlist_t *det, gmem_dimm_t *ce_dimm)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_dimm_t *d, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint16_t upos;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (d = gmem_list_next(&gmem.gm_dimms); d != NULL; d = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(d);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (d == ce_dimm)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do continue;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (!gmem_same_datapath_dimms(hdl, ce_dimm, d))
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do continue;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (check_bad_rw_between_dimms(hdl, ce_dimm, d, &upos)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_gen_datapath_fault(hdl, det);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_save_symbol_error(hdl, ce_dimm, upos);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_debug(hdl,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do "check_bad_rw_dimms succeeded: %s %s\n",
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ce_dimm->dimm_serial, d->dimm_serial);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * rule 5a checking. The check succeeds if
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * - nretired >= 512
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * - nretired >= 128 and (addr_hi - addr_low) / (nretired -1 ) > 512KB
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportstatic void
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportce_thresh_check(fmd_hdl_t *hdl, gmem_dimm_t *dimm)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *flt, *rsrc;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_t *cp;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport uint_t nret;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint64_t delta_addr = 0;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (dimm->dimm_flags & GMEM_F_FAULTING)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nret = dimm->dimm_nretired;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nret < gmem.gm_low_ce_thresh)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (dimm->dimm_phys_addr_hi >= dimm->dimm_phys_addr_low)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do delta_addr =
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (dimm->dimm_phys_addr_hi - dimm->dimm_phys_addr_low) /
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (nret - 1);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nret >= gmem.gm_max_retired_pages || delta_addr > GMEM_MQ_512KB) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_debug(hdl, "ce_thresh_check succeeded nret=%d", nret);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do dimm->dimm_flags |= GMEM_F_FAULTING;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_dimm_dirty(hdl, dimm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do cp = fmd_case_open(hdl, NULL);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do rsrc = gmem_find_dimm_rsc(hdl, dimm->dimm_serial);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do flt = fmd_nvl_create_fault(hdl, GMEM_FAULT_DIMM_PAGES,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do GMEM_FLTMAXCONF, NULL, gmem_dimm_fru(dimm), rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_add_suspect(hdl, cp, flt);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_solve(hdl, cp);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * rule 5b checking. The check succeeds if more than 120
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * non-intermittent CEs are reported against one symbol
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * position of one afar in 72 hours
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic void
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Domq_5b_check(fmd_hdl_t *hdl, gmem_dimm_t *dimm)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *flt, *rsrc;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_t *cp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_mq_t *ip, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int cw;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (cw = 0; cw < GMEM_MAX_CKWDS; cw++) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (ip = gmem_list_next(&dimm->mq_root[cw]);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip != NULL; ip = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(ip);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (ip->mq_dupce_count >= gmem.gm_dupce) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_debug(hdl,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do "mq_5b_check succeeded: duplicate CE=%d",
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip->mq_dupce_count);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do cp = fmd_case_open(hdl, NULL);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do rsrc = gmem_find_dimm_rsc(hdl,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do dimm->dimm_serial);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do flt = fmd_nvl_create_fault(hdl,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do GMEM_FAULT_DIMM_PAGES, GMEM_FLTMAXCONF,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do NULL, gmem_dimm_fru(dimm), rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do dimm->dimm_flags |= GMEM_F_FAULTING;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_dimm_dirty(hdl, dimm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_add_suspect(hdl, cp, flt);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_case_solve(hdl, cp);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(rsrc);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do/*
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * delete the expired duplicate CE time stamps
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic void
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Domq_prune_dup(fmd_hdl_t *hdl, gmem_mq_t *ip, uint64_t now)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tstamp_t *tsp, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (tsp = gmem_list_next(&ip->mq_dupce_tstamp); tsp != NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(tsp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (tsp->tstamp < now - GMEM_MQ_TIMELIM) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_list_delete(&ip->mq_dupce_tstamp, &tsp->ts_l);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_free(hdl, tsp, sizeof (tstamp_t));
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip->mq_dupce_count--;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do}
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Dostatic void
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Domq_update(fmd_hdl_t *hdl, fmd_event_t *ep, gmem_mq_t *ip, uint64_t now)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do{
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tstamp_t *tsp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip->mq_tstamp = now;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip->mq_ep = ep;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (fmd_serd_exists(hdl, ip->mq_serdnm))
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_serd_destroy(hdl, ip->mq_serdnm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_serd_create(hdl, ip->mq_serdnm, GMEM_MQ_SERDN, GMEM_MQ_SERDT);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do (void) fmd_serd_record(hdl, ip->mq_serdnm, ep);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp = fmd_hdl_zalloc(hdl, sizeof (tstamp_t), FMD_SLEEP);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp->tstamp = now;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_list_append(&ip->mq_dupce_tstamp, tsp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do ip->mq_dupce_count++;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Create a fresh index block for MQSC CE correlation.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_mq_t *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportmq_create(fmd_hdl_t *hdl, fmd_event_t *ep,
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien uint64_t afar, uint16_t upos, uint16_t ckwd, uint64_t now)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *cp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tstamp_t *tsp;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp = fmd_hdl_zalloc(hdl, sizeof (gmem_mq_t), FMD_SLEEP);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_tstamp = now;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_ckwd = ckwd;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_phys_addr = afar;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_unit_position = upos;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_ep = ep;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport cp->mq_serdnm =
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_serdnm_create(hdl, "mq", afar, ckwd, upos);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp = fmd_hdl_zalloc(hdl, sizeof (tstamp_t), FMD_SLEEP);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp->tstamp = now;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_list_append(&cp->mq_dupce_tstamp, tsp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do cp->mq_dupce_count = 1;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Create SERD to keep this event from being removed
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * by fmd which may not know there is an event pointer
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * saved here. This SERD is *never* meant to fire.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (fmd_serd_exists(hdl, cp->mq_serdnm))
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_serd_destroy(hdl, cp->mq_serdnm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_serd_create(hdl, cp->mq_serdnm, GMEM_MQ_SERDN, GMEM_MQ_SERDT);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport (void) fmd_serd_record(hdl, cp->mq_serdnm, ep);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (cp);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_mq_t *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportmq_destroy(fmd_hdl_t *hdl, gmem_list_t *lp, gmem_mq_t *ip)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *jp = gmem_list_next(ip);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tstamp_t *tsp, *next;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (ip->mq_serdnm != NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (fmd_serd_exists(hdl, ip->mq_serdnm))
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_serd_destroy(hdl, ip->mq_serdnm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_strfree(hdl, ip->mq_serdnm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip->mq_serdnm = NULL;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do for (tsp = gmem_list_next(&ip->mq_dupce_tstamp); tsp != NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do tsp = next) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do next = gmem_list_next(tsp);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_list_delete(&ip->mq_dupce_tstamp, &tsp->ts_l);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_free(hdl, tsp, sizeof (tstamp_t));
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_list_delete(lp, &ip->mq_l);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_free(hdl, ip, sizeof (gmem_mq_t));
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (jp);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Add an index block for a new CE, sorted
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * a) by ascending unit position
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * b) order of arrival (~= time order)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportvoid
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportmq_add(fmd_hdl_t *hdl, gmem_dimm_t *dimm, fmd_event_t *ep,
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien uint64_t afar, uint16_t unit_position, uint16_t ckwd,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport uint64_t now)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *ip, *jp;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport int cw = (int)ckwd;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (ip = gmem_list_next(&dimm->mq_root[cw]); ip != NULL; ) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (ip->mq_unit_position > unit_position) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /* list is in unit position order */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport break;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } else if (ip->mq_unit_position == unit_position &&
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip->mq_phys_addr == afar) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Found a duplicate cw, unit_position, and afar.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Delete this node, to be superseded by the new
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * node added below.
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do * update the mq_t structure
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do mq_update(hdl, ep, ip, now);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } else {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip = gmem_list_next(ip);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien jp = mq_create(hdl, ep, afar, unit_position, cw, now);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (ip == NULL)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_list_append(&dimm->mq_root[cw], jp);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport else
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_list_insert_before(&dimm->mq_root[cw], ip, jp);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Prune the MQSC index lists (one for each checkword), by deleting
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * outdated index blocks from each list.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportvoid
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportmq_prune(fmd_hdl_t *hdl, gmem_dimm_t *dimm, uint64_t now)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *ip;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport int cw;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (cw = 0; cw < GMEM_MAX_CKWDS; cw++) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (ip = gmem_list_next(&dimm->mq_root[cw]); ip != NULL; ) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (ip->mq_tstamp < now - GMEM_MQ_TIMELIM) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * This event has timed out - delete the
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * mq block as well as serd for the event.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip = mq_destroy(hdl, &dimm->mq_root[cw], ip);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } else {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do mq_prune_dup(hdl, ip, now);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /* tstamp < now - ce_t */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip = gmem_list_next(ip);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } /* per checkword */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } /* cw = 0...3 */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Check the MQSC index lists (one for each checkword) by making a
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien * complete pass through each list, checking if the criteria for
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien * Rule 4A has been met. Rule 4A checking is done for each checkword.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport *
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Rule 4A: fault a DIMM "whenever Solaris reports two or more CEs from
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * two or more different physical addresses on each of two or more different
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * bit positions from the same DIMM within 72 hours of each other, and all
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * the addresses are in the same relative checkword (that is, the AFARs
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * are all the same modulo 64). [Note: This means at least 4 CEs; two
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * from one bit position, with unique addresses, and two from another,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * also with unique addresses, and the lower 6 bits of all the addresses
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * are the same."
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportvoid
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsienmq_check(fmd_hdl_t *hdl, gmem_dimm_t *dimm)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien int upos_pairs, curr_upos, cw, i, j;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_t *flt, *rsc;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport typedef struct upos_pair {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport int upos;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *mq1;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *mq2;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } upos_pair_t;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_pair_t upos_array[16]; /* max per cw = 2, * 8 cw's */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_mq_t *ip;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Each upos_array[] member represents a pair of CEs for the same
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * unit position (symbol) which is a 4 bit nibble.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * MQSC rule 4 requires pairs of CEs from the same symbol (same DIMM
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * for rule 4A, and same DRAM for rule 4B) for a violation - this
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * is why CE pairs are tracked.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_pairs = 0;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[0].mq1 = NULL;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (cw = 0; cw < GMEM_MAX_CKWDS; cw++) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport i = upos_pairs;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport curr_upos = -1;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * mq_root[] is an array of cumulative lists of CEs
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * indexed by checkword where the list is in unit position
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * order. Loop through checking for duplicate unit position
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * entries (filled in at mq_create()).
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * The upos_array[] is filled in each time a duplicate
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * unit position is found; the first time through the loop
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * of a unit position sets curr_upos but does not fill in
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * upos_array[] until the second symbol is found.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (ip = gmem_list_next(&dimm->mq_root[cw]); ip != NULL;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ip = gmem_list_next(ip)) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (curr_upos != ip->mq_unit_position) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /* Set initial current position */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport curr_upos = ip->mq_unit_position;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } else if (i > upos_pairs &&
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport curr_upos == upos_array[i-1].upos) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Only keep track of CE pairs; skip
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * triples, quads, etc...
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport continue;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport } else if (upos_array[i].mq1 == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /* Have a pair. Add to upos_array[] */
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien fmd_hdl_debug(hdl, "pair:upos=%d",
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien curr_upos);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[i].upos = curr_upos;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[i].mq1 = gmem_list_prev(ip);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[i].mq2 = ip;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[++i].mq1 = NULL;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (i - upos_pairs >= 2) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /* Rule 4A violation */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport rsc = gmem_find_dimm_rsc(hdl, dimm->dimm_serial);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport flt = fmd_nvl_create_fault(hdl, GMEM_FAULT_DIMM_4A,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport GMEM_FLTMAXCONF, NULL, gmem_dimm_fru(dimm), rsc);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport for (j = upos_pairs; j < i; j++) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_add_ereport(hdl,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_case.cc_cp,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[j].mq1->mq_ep);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_add_ereport(hdl,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_case.cc_cp,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_array[j].mq2->mq_ep);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_flags |= GMEM_F_FAULTING;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_dimm_dirty(hdl, dimm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_add_suspect(hdl, dimm->dimm_case.cc_cp, flt);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_solve(hdl, dimm->dimm_case.cc_cp);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(rsc);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport upos_pairs = i;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport assert(upos_pairs < 16);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport/*ARGSUSED*/
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_evdisp_t
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_ce(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien uint16_t symbol_pos, cw;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint64_t phyaddr, offset, addr;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport uint32_t filter_ratio = 0;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_dimm_t *dimm;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_page_t *page;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_t *fru = NULL;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_t *topo_rsc = NULL;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_t *rsrc, *det;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport const char *uuid;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ce_dispact_t type;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport boolean_t diagnose;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport char *sn;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport int err, rc;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint64_t *now;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do uint_t nelem;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do int skip_error = 0;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport err = nvlist_lookup_boolean_value(nvl, GMEM_ERPT_PAYLOAD_DIAGNOSE,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &diagnose);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (err != 0 || diagnose == 0)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if ((nvlist_lookup_uint64(nvl, GMEM_ERPT_PAYLOAD_PHYSADDR,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &phyaddr) != 0) ||
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport (nvlist_lookup_uint64(nvl, GMEM_ERPT_PAYLOAD_OFFSET,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &offset) != 0)) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "Can't get page phyaddr or offset");
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_BAD);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "phyaddr %llx offset %llx", phyaddr, offset);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if ((page = gmem_page_lookup(phyaddr)) != NULL &&
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport page->page_case.cc_cp != NULL &&
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_solved(hdl, page->page_case.cc_cp))
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_REDUND);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (nvlist_lookup_nvlist(nvl, GMEM_ERPT_PAYLOAD_RESOURCE,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &rsrc) != 0 ||
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_lookup_string(rsrc, FM_FMRI_HC_SERIAL_ID, &sn) != 0) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "Can't get dimm serial\n");
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_BAD);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "serial %s", sn);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (nvlist_lookup_nvlist(nvl, GMEM_ERPT_PAYLOAD_DETECTOR, &det) != 0)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (GMEM_EVD_BAD);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Find dimm fru by serial number.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fru = gmem_find_dimm_fru(hdl, sn);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (fru == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "Dimm is not present\n");
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if ((dimm = gmem_dimm_lookup(hdl, fru)) == NULL &&
8f6658897e88431fedd1dbcecab56535cb8a6ebfTrang Do (dimm = gmem_dimm_create(hdl, fru, det)) == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (dimm->dimm_case.cc_cp == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_case.cc_cp = gmem_case_create(hdl,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &dimm->dimm_header, GMEM_PTR_DIMM_CASE, &uuid);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport /*
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * Add to MQSC correlation lists all CEs which pass validity
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport * checks above. If there is no symbol_pos & relative ckword
cfb7311ca709ca6f4d930977c7498455556b5312Louis Tsien * in the ereport, skip rule 4A checking.
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport err = nvlist_lookup_uint16(nvl, GMEM_ERPT_PAYLOAD_SYMBOLPOS,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &symbol_pos);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport err |= nvlist_lookup_uint16(nvl, GMEM_ERPT_PAYLOAD_CKW, &cw);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (err == 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do fmd_hdl_debug(hdl, "symbol_pos=%d cw=%d", symbol_pos, cw);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (nvlist_lookup_uint64_array(nvl,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport "__tod", &now, &nelem) == 0) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do skip_error = gmem_check_symbol_error(hdl, dimm,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do symbol_pos);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (!skip_error ||
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do !(dimm->dimm_flags & GMEM_F_FAULTING))
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do mq_add(hdl, dimm, ep, phyaddr, symbol_pos,
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do cw, *now);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport mq_prune(hdl, dimm, *now);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (!skip_error)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do bad_reader_writer_check(hdl, det, dimm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (!(dimm->dimm_flags & GMEM_F_FAULTING)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do mq_check(hdl, dimm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do mq_5b_check(hdl, dimm);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport type = gmem_mem_name2type(strstr(class, "mem"));
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport switch (type) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_UNKNOWN:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport GMEM_STAT_BUMP(ce_unknown);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_INTERMITTENT:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport GMEM_STAT_BUMP(ce_interm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_PERS:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport GMEM_STAT_BUMP(ce_clearable_persis);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport break;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_STICKY:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport GMEM_STAT_BUMP(ce_sticky);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport break;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport default:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_BAD);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (gmem_check_symbol_error(hdl, dimm, symbol_pos)) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do nvlist_free(fru);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do return (GMEM_EVD_REDUND);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do }
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (page == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport page = gmem_page_create(hdl, fru, phyaddr, offset);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (page == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_UNUSED);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport nvlist_free(fru);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (page->page_case.cc_cp == NULL) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport page->page_case.cc_cp = gmem_case_create(hdl,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport &page->page_header, GMEM_PTR_PAGE_CASE, &uuid);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport switch (type) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_PERS:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "adding persistent event to CE serd");
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (page->page_case.cc_serdnm == NULL)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_page_serd_create(hdl, page, nvl);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport filter_ratio = gmem_get_serd_filter_ratio(nvl);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "filter_ratio %d\n", filter_ratio);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (gmem_serd_record(hdl, page->page_case.cc_serdnm,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport filter_ratio, ep) == FMD_B_FALSE) {
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_OK); /* engine hasn't fired */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_hdl_debug(hdl, "ce page serd fired\n");
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_add_serd(hdl, page->page_case.cc_cp,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport page->page_case.cc_serdnm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_serd_reset(hdl, page->page_case.cc_serdnm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport break; /* to retire */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport case CE_DISP_STICKY:
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport fmd_case_add_ereport(hdl, page->page_case.cc_cp, ep);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport break; /* to retire */
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport topo_rsc = gmem_find_dimm_rsc(hdl, dimm->dimm_serial);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport rc = gmem_page_fault(hdl, gmem_dimm_fru(dimm), topo_rsc,
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ep, phyaddr, offset);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport if (rc) {
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do gmem_to_hashed_addr(&addr, phyaddr);
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (addr > dimm->dimm_phys_addr_hi)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do dimm->dimm_phys_addr_hi = addr;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do if (addr < dimm->dimm_phys_addr_low)
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do dimm->dimm_phys_addr_low = addr;
d4ac42a1cd3016618a9ba0330862d410f0058f89Trang Do
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_nretired++;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport dimm->dimm_retstat.fmds_value.ui64++;
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_dimm_dirty(hdl, dimm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport ce_thresh_check(hdl, dimm);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport }
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport return (GMEM_EVD_OK);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportvoid
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenportgmem_dimm_close(fmd_hdl_t *hdl, void *arg)
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport{
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport gmem_dimm_destroy(hdl, arg);
1529f529004c61fcfd0d95ab79b0f257d6ad4451Scott Davenport}