11529f52Scott Davenport/*
21529f52Scott Davenport * CDDL HEADER START
31529f52Scott Davenport *
41529f52Scott Davenport * The contents of this file are subject to the terms of the
51529f52Scott Davenport * Common Development and Distribution License (the "License").
61529f52Scott Davenport * You may not use this file except in compliance with the License.
71529f52Scott Davenport *
81529f52Scott Davenport * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91529f52Scott Davenport * or http://www.opensolaris.org/os/licensing.
101529f52Scott Davenport * See the License for the specific language governing permissions
111529f52Scott Davenport * and limitations under the License.
121529f52Scott Davenport *
131529f52Scott Davenport * When distributing Covered Code, include this CDDL HEADER in each
141529f52Scott Davenport * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151529f52Scott Davenport * If applicable, add the following below this CDDL HEADER, with the
161529f52Scott Davenport * fields enclosed by brackets "[]" replaced with your own identifying
171529f52Scott Davenport * information: Portions Copyright [yyyy] [name of copyright owner]
181529f52Scott Davenport *
191529f52Scott Davenport * CDDL HEADER END
201529f52Scott Davenport */
211529f52Scott Davenport/*
221529f52Scott Davenport * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
231529f52Scott Davenport * Use is subject to license terms.
241529f52Scott Davenport */
251529f52Scott Davenport
261529f52Scott Davenport/*
271529f52Scott Davenport * Case management and saved state restoration
281529f52Scott Davenport */
291529f52Scott Davenport
301529f52Scott Davenport#include <gmem_state.h>
311529f52Scott Davenport#include <gmem_mem.h>
321529f52Scott Davenport#include <gmem_page.h>
331529f52Scott Davenport#include <gmem_dimm.h>
341529f52Scott Davenport#include <gmem.h>
351529f52Scott Davenport
361529f52Scott Davenport#include <string.h>
371529f52Scott Davenport#include <fm/fmd_api.h>
381529f52Scott Davenport
391529f52Scott Davenport/* Must be in sync with gmem_ptrsubtype_t */
401529f52Scott Davenportstatic gmem_case_closer_f *const gmem_case_closers[] = {
411529f52Scott Davenport	NULL,
421529f52Scott Davenport	gmem_dimm_close,		/* GMEM_PTR_DIMM_CASE */
431529f52Scott Davenport	gmem_page_close,		/* GMEM_PTR_PAGE_CASE */
441529f52Scott Davenport};
451529f52Scott Davenport
461529f52Scott Davenportfmd_case_t *
471529f52Scott Davenportgmem_case_create(fmd_hdl_t *hdl, gmem_header_t *hdr,
481529f52Scott Davenport    gmem_ptrsubtype_t ptrsubtype, const char **uuidp)
491529f52Scott Davenport{
501529f52Scott Davenport	gmem_case_ptr_t ptr;
511529f52Scott Davenport	gmem_case_closer_t *cl;
521529f52Scott Davenport	fmd_case_t *cp;
531529f52Scott Davenport
541529f52Scott Davenport	cl = fmd_hdl_alloc(hdl, sizeof (gmem_case_closer_t), FMD_SLEEP);
551529f52Scott Davenport	cl->cl_func = gmem_case_closers[ptrsubtype];
561529f52Scott Davenport	cl->cl_arg = hdr;
571529f52Scott Davenport
581529f52Scott Davenport	cp = fmd_case_open(hdl, cl);
591529f52Scott Davenport
601529f52Scott Davenport	ptr.ptr_type = hdr->hdr_nodetype;
611529f52Scott Davenport	ptr.ptr_subtype = ptrsubtype;
621529f52Scott Davenport	(void) strcpy(ptr.ptr_name, hdr->hdr_bufname);
631529f52Scott Davenport
641529f52Scott Davenport	*uuidp = fmd_case_uuid(hdl, cp);
651529f52Scott Davenport	fmd_buf_write(hdl, cp, *uuidp, &ptr, sizeof (gmem_case_ptr_t));
661529f52Scott Davenport
671529f52Scott Davenport	return (cp);
681529f52Scott Davenport}
691529f52Scott Davenport
701529f52Scott Davenportvoid
711529f52Scott Davenportgmem_case_redirect(fmd_hdl_t *hdl, fmd_case_t *cp, gmem_ptrsubtype_t newsubtype)
721529f52Scott Davenport{
731529f52Scott Davenport	const char *uuid = fmd_case_uuid(hdl, cp);
741529f52Scott Davenport	gmem_case_ptr_t ptr;
751529f52Scott Davenport
761529f52Scott Davenport	fmd_buf_read(hdl, cp, uuid, &ptr, sizeof (gmem_case_ptr_t));
771529f52Scott Davenport	fmd_hdl_debug(hdl, "redirecting case %s from %d to %d\n", uuid,
781529f52Scott Davenport	    ptr.ptr_subtype, newsubtype);
791529f52Scott Davenport	ptr.ptr_subtype = newsubtype;
801529f52Scott Davenport	fmd_buf_write(hdl, cp, uuid, &ptr, sizeof (gmem_case_ptr_t));
811529f52Scott Davenport}
821529f52Scott Davenport
831529f52Scott Davenportvoid
841529f52Scott Davenportgmem_case_fini(fmd_hdl_t *hdl, fmd_case_t *cp, int close)
851529f52Scott Davenport{
861529f52Scott Davenport	const char *uuid = fmd_case_uuid(hdl, cp);
871529f52Scott Davenport	gmem_case_closer_t *cl = fmd_case_getspecific(hdl, cp);
881529f52Scott Davenport
891529f52Scott Davenport	if (close) {
901529f52Scott Davenport		fmd_hdl_debug(hdl, "closing case %s\n", uuid);
911529f52Scott Davenport
921529f52Scott Davenport		if (fmd_serd_exists(hdl, uuid))
931529f52Scott Davenport			fmd_serd_destroy(hdl, uuid);
941529f52Scott Davenport
951529f52Scott Davenport		if (fmd_buf_size(hdl, cp, uuid) != 0)
961529f52Scott Davenport			fmd_buf_destroy(hdl, cp, uuid);
971529f52Scott Davenport
981529f52Scott Davenport		fmd_case_setspecific(hdl, cp, NULL);
991529f52Scott Davenport		fmd_case_close(hdl, cp);
1001529f52Scott Davenport	}
1011529f52Scott Davenport
1021529f52Scott Davenport	if (cl != NULL)
1031529f52Scott Davenport		fmd_hdl_free(hdl, cl, sizeof (gmem_case_closer_t));
1041529f52Scott Davenport}
1051529f52Scott Davenport
1061529f52Scott Davenport/* Must be in sync with gmem_nodetype_t */
1071529f52Scott Davenportstatic gmem_case_restorer_f *const gmem_case_restorers[] = {
1081529f52Scott Davenport	NULL,
1091529f52Scott Davenport	gmem_dimm_restore,	/* CMD_NT_DIMM */
1101529f52Scott Davenport	gmem_page_restore,	/* CMD_NT_PAGE */
1111529f52Scott Davenport};
1121529f52Scott Davenport
1131529f52Scott Davenportint
1141529f52Scott Davenportgmem_state_restore(fmd_hdl_t *hdl)
1151529f52Scott Davenport{
1161529f52Scott Davenport	fmd_case_t *cp = NULL;
1171529f52Scott Davenport
1181529f52Scott Davenport	while ((cp = fmd_case_next(hdl, cp)) != NULL) {
1191529f52Scott Davenport		const char *uuid = fmd_case_uuid(hdl, cp);
1201529f52Scott Davenport		gmem_case_closer_t *cl;
1211529f52Scott Davenport		gmem_case_ptr_t ptr;
1221529f52Scott Davenport		void *thing;
1231529f52Scott Davenport		size_t sz;
1241529f52Scott Davenport
1251529f52Scott Davenport		if ((sz = fmd_buf_size(hdl, cp, uuid)) == 0)
1261529f52Scott Davenport			continue;
1271529f52Scott Davenport		else if (sz != sizeof (gmem_case_ptr_t))
1281529f52Scott Davenport			return (gmem_set_errno(EINVAL));
1291529f52Scott Davenport
1301529f52Scott Davenport		fmd_buf_read(hdl, cp, fmd_case_uuid(hdl, cp), &ptr,
1311529f52Scott Davenport		    sizeof (gmem_case_ptr_t));
1321529f52Scott Davenport
1331529f52Scott Davenport		if (ptr.ptr_type == 0 || ptr.ptr_type >
1341529f52Scott Davenport		    sizeof (gmem_case_restorers) /
1351529f52Scott Davenport		    sizeof (gmem_case_restorer_f *))
1361529f52Scott Davenport			return (gmem_set_errno(EINVAL));
1371529f52Scott Davenport
1381529f52Scott Davenport		if ((thing = gmem_case_restorers[ptr.ptr_type](hdl,
1391529f52Scott Davenport		    cp, &ptr)) == NULL) {
1401529f52Scott Davenport			fmd_hdl_debug(hdl, "Unable to restore case %s\n", uuid);
1411529f52Scott Davenport			continue;
1421529f52Scott Davenport		}
1431529f52Scott Davenport
1441529f52Scott Davenport		cl = fmd_hdl_alloc(hdl, sizeof (gmem_case_closer_t), FMD_SLEEP);
1451529f52Scott Davenport		cl->cl_func = gmem_case_closers[ptr.ptr_subtype];
1461529f52Scott Davenport		cl->cl_arg = thing;
1471529f52Scott Davenport		fmd_case_setspecific(hdl, cp, cl);
1481529f52Scott Davenport	}
1491529f52Scott Davenport
1501529f52Scott Davenport	gmem_dimm_validate(hdl);
1511529f52Scott Davenport	gmem_page_validate(hdl);
1521529f52Scott Davenport
1531529f52Scott Davenport	return (0);
1541529f52Scott Davenport}
1551529f52Scott Davenport
1561529f52Scott Davenportvoid
1571529f52Scott Davenportgmem_case_restore(fmd_hdl_t *hdl, gmem_case_t *cc, fmd_case_t *cp, char *serdnm)
1581529f52Scott Davenport{
1591529f52Scott Davenport	if (!fmd_serd_exists(hdl, serdnm)) {
1601529f52Scott Davenport		fmd_hdl_strfree(hdl, serdnm);
1611529f52Scott Davenport		serdnm = NULL;
1621529f52Scott Davenport	}
1631529f52Scott Davenport
1641529f52Scott Davenport	cc->cc_cp = cp;
1651529f52Scott Davenport	cc->cc_serdnm = serdnm;
1661529f52Scott Davenport}