1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Case management and saved state restoration 28 */ 29 30 #include <gmem_state.h> 31 #include <gmem_mem.h> 32 #include <gmem_page.h> 33 #include <gmem_dimm.h> 34 #include <gmem.h> 35 36 #include <string.h> 37 #include <fm/fmd_api.h> 38 39 /* Must be in sync with gmem_ptrsubtype_t */ 40 static gmem_case_closer_f *const gmem_case_closers[] = { 41 NULL, 42 gmem_dimm_close, /* GMEM_PTR_DIMM_CASE */ 43 gmem_page_close, /* GMEM_PTR_PAGE_CASE */ 44 }; 45 46 fmd_case_t * 47 gmem_case_create(fmd_hdl_t *hdl, gmem_header_t *hdr, 48 gmem_ptrsubtype_t ptrsubtype, const char **uuidp) 49 { 50 gmem_case_ptr_t ptr; 51 gmem_case_closer_t *cl; 52 fmd_case_t *cp; 53 54 cl = fmd_hdl_alloc(hdl, sizeof (gmem_case_closer_t), FMD_SLEEP); 55 cl->cl_func = gmem_case_closers[ptrsubtype]; 56 cl->cl_arg = hdr; 57 58 cp = fmd_case_open(hdl, cl); 59 60 ptr.ptr_type = hdr->hdr_nodetype; 61 ptr.ptr_subtype = ptrsubtype; 62 (void) strcpy(ptr.ptr_name, hdr->hdr_bufname); 63 64 *uuidp = fmd_case_uuid(hdl, cp); 65 fmd_buf_write(hdl, cp, *uuidp, &ptr, sizeof (gmem_case_ptr_t)); 66 67 return (cp); 68 } 69 70 void 71 gmem_case_redirect(fmd_hdl_t *hdl, fmd_case_t *cp, gmem_ptrsubtype_t newsubtype) 72 { 73 const char *uuid = fmd_case_uuid(hdl, cp); 74 gmem_case_ptr_t ptr; 75 76 fmd_buf_read(hdl, cp, uuid, &ptr, sizeof (gmem_case_ptr_t)); 77 fmd_hdl_debug(hdl, "redirecting case %s from %d to %d\n", uuid, 78 ptr.ptr_subtype, newsubtype); 79 ptr.ptr_subtype = newsubtype; 80 fmd_buf_write(hdl, cp, uuid, &ptr, sizeof (gmem_case_ptr_t)); 81 } 82 83 void 84 gmem_case_fini(fmd_hdl_t *hdl, fmd_case_t *cp, int close) 85 { 86 const char *uuid = fmd_case_uuid(hdl, cp); 87 gmem_case_closer_t *cl = fmd_case_getspecific(hdl, cp); 88 89 if (close) { 90 fmd_hdl_debug(hdl, "closing case %s\n", uuid); 91 92 if (fmd_serd_exists(hdl, uuid)) 93 fmd_serd_destroy(hdl, uuid); 94 95 if (fmd_buf_size(hdl, cp, uuid) != 0) 96 fmd_buf_destroy(hdl, cp, uuid); 97 98 fmd_case_setspecific(hdl, cp, NULL); 99 fmd_case_close(hdl, cp); 100 } 101 102 if (cl != NULL) 103 fmd_hdl_free(hdl, cl, sizeof (gmem_case_closer_t)); 104 } 105 106 /* Must be in sync with gmem_nodetype_t */ 107 static gmem_case_restorer_f *const gmem_case_restorers[] = { 108 NULL, 109 gmem_dimm_restore, /* CMD_NT_DIMM */ 110 gmem_page_restore, /* CMD_NT_PAGE */ 111 }; 112 113 int 114 gmem_state_restore(fmd_hdl_t *hdl) 115 { 116 fmd_case_t *cp = NULL; 117 118 while ((cp = fmd_case_next(hdl, cp)) != NULL) { 119 const char *uuid = fmd_case_uuid(hdl, cp); 120 gmem_case_closer_t *cl; 121 gmem_case_ptr_t ptr; 122 void *thing; 123 size_t sz; 124 125 if ((sz = fmd_buf_size(hdl, cp, uuid)) == 0) 126 continue; 127 else if (sz != sizeof (gmem_case_ptr_t)) 128 return (gmem_set_errno(EINVAL)); 129 130 fmd_buf_read(hdl, cp, fmd_case_uuid(hdl, cp), &ptr, 131 sizeof (gmem_case_ptr_t)); 132 133 if (ptr.ptr_type == 0 || ptr.ptr_type > 134 sizeof (gmem_case_restorers) / 135 sizeof (gmem_case_restorer_f *)) 136 return (gmem_set_errno(EINVAL)); 137 138 if ((thing = gmem_case_restorers[ptr.ptr_type](hdl, 139 cp, &ptr)) == NULL) { 140 fmd_hdl_debug(hdl, "Unable to restore case %s\n", uuid); 141 continue; 142 } 143 144 cl = fmd_hdl_alloc(hdl, sizeof (gmem_case_closer_t), FMD_SLEEP); 145 cl->cl_func = gmem_case_closers[ptr.ptr_subtype]; 146 cl->cl_arg = thing; 147 fmd_case_setspecific(hdl, cp, cl); 148 } 149 150 gmem_dimm_validate(hdl); 151 gmem_page_validate(hdl); 152 153 return (0); 154 } 155 156 void 157 gmem_case_restore(fmd_hdl_t *hdl, gmem_case_t *cc, fmd_case_t *cp, char *serdnm) 158 { 159 if (!fmd_serd_exists(hdl, serdnm)) { 160 fmd_hdl_strfree(hdl, serdnm); 161 serdnm = NULL; 162 } 163 164 cc->cc_cp = cp; 165 cc->cc_serdnm = serdnm; 166 } 167