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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
38 #include <fm/fmd_api.h>
39 #include <sys/fm/protocol.h>
41 #include <sys/nvpair.h>
44 cmd_bank_add_dimm(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
, cmd_dimm_t
*dimm
)
48 fmd_hdl_debug(hdl
, "attaching dimm %s to bank %s\n", dimm
->dimm_unum
,
51 dimm
->dimm_bank
= bank
;
53 bm
= fmd_hdl_zalloc(hdl
, sizeof (cmd_bank_memb_t
), FMD_SLEEP
);
55 cmd_list_append(&bank
->bank_dimms
, bm
);
59 cmd_bank_remove_dimm(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
, cmd_dimm_t
*dimm
)
63 fmd_hdl_debug(hdl
, "detaching dimm %s from bank %s\n", dimm
->dimm_unum
,
66 for (bm
= cmd_list_next(&bank
->bank_dimms
); bm
!= NULL
;
67 bm
= cmd_list_next(bm
)) {
68 if (bm
->bm_dimm
!= dimm
)
71 cmd_list_delete(&bank
->bank_dimms
, bm
);
72 dimm
->dimm_bank
= NULL
;
73 fmd_hdl_free(hdl
, bm
, sizeof (cmd_bank_memb_t
));
77 fmd_hdl_abort(hdl
, "attempt to disconnect dimm from non-parent bank\n");
81 bank_dimmlist_create(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
)
85 for (dimm
= cmd_list_next(&cmd
.cmd_dimms
); dimm
!= NULL
;
86 dimm
= cmd_list_next(dimm
)) {
87 if (fmd_nvl_fmri_contains(hdl
, bank
->bank_asru_nvl
,
89 cmd_bank_add_dimm(hdl
, bank
, dimm
);
94 bank_dimmlist_free(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
)
98 while ((bm
= cmd_list_next(&bank
->bank_dimms
)) != NULL
) {
99 cmd_list_delete(&bank
->bank_dimms
, bm
);
100 bm
->bm_dimm
->dimm_bank
= NULL
;
101 fmd_hdl_free(hdl
, bm
, sizeof (cmd_bank_memb_t
));
106 cmd_bank_fru(cmd_bank_t
*bank
)
108 return (bank
->bank_asru_nvl
);
112 cmd_bank_create_fault(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
, const char *fltnm
,
115 return (cmd_nvl_create_fault(hdl
, fltnm
, cert
, bank
->bank_asru_nvl
,
116 bank
->bank_asru_nvl
, NULL
));
120 bank_free(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
, int destroy
)
122 if (bank
->bank_case
.cc_cp
!= NULL
)
123 cmd_case_fini(hdl
, bank
->bank_case
.cc_cp
, destroy
);
125 bank_dimmlist_free(hdl
, bank
);
126 cmd_fmri_fini(hdl
, &bank
->bank_asru
, destroy
);
129 fmd_buf_destroy(hdl
, NULL
, bank
->bank_bufname
);
130 cmd_list_delete(&cmd
.cmd_banks
, bank
);
131 fmd_hdl_free(hdl
, bank
, sizeof (cmd_bank_t
));
135 cmd_bank_destroy(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
)
137 fmd_stat_destroy(hdl
, 1, &(bank
->bank_retstat
));
138 bank_free(hdl
, bank
, FMD_B_TRUE
);
142 bank_lookup_by_unum(const char *unum
)
146 for (bank
= cmd_list_next(&cmd
.cmd_banks
); bank
!= NULL
;
147 bank
= cmd_list_next(bank
)) {
148 if (strcmp(bank
->bank_unum
, unum
) == 0)
156 cmd_bank_create(fmd_hdl_t
*hdl
, nvlist_t
*asru
)
161 if (!fmd_nvl_fmri_present(hdl
, asru
)) {
162 fmd_hdl_debug(hdl
, "dimm_lookup: discarding old ereport\n");
166 if ((unum
= cmd_fmri_get_unum(asru
)) == NULL
) {
167 CMD_STAT_BUMP(bad_mem_asru
);
171 fmd_hdl_debug(hdl
, "bank_create: creating new bank %s\n", unum
);
172 CMD_STAT_BUMP(bank_creat
);
174 bank
= fmd_hdl_zalloc(hdl
, sizeof (cmd_bank_t
), FMD_SLEEP
);
175 bank
->bank_nodetype
= CMD_NT_BANK
;
176 bank
->bank_version
= CMD_BANK_VERSION
;
178 cmd_bufname(bank
->bank_bufname
, sizeof (bank
->bank_bufname
), "bank_%s",
180 cmd_fmri_init(hdl
, &bank
->bank_asru
, asru
, "bank_asru_%s", unum
);
182 (void) nvlist_lookup_string(bank
->bank_asru_nvl
, FM_FMRI_MEM_UNUM
,
183 (char **)&bank
->bank_unum
);
185 bank_dimmlist_create(hdl
, bank
);
187 cmd_mem_retirestat_create(hdl
, &bank
->bank_retstat
, bank
->bank_unum
, 0,
188 CMD_BANK_STAT_PREFIX
);
190 cmd_list_append(&cmd
.cmd_banks
, bank
);
191 cmd_bank_dirty(hdl
, bank
);
197 cmd_bank_lookup(fmd_hdl_t
*hdl
, nvlist_t
*asru
)
202 if ((unum
= cmd_fmri_get_unum(asru
)) == NULL
) {
203 CMD_STAT_BUMP(bad_mem_asru
);
207 bank
= bank_lookup_by_unum(unum
);
209 if (bank
!= NULL
&& !fmd_nvl_fmri_present(hdl
, bank
->bank_asru_nvl
)) {
210 fmd_hdl_debug(hdl
, "bank_lookup: discarding old bank\n");
211 cmd_bank_destroy(hdl
, bank
);
219 bank_v0tov1(fmd_hdl_t
*hdl
, cmd_bank_0_t
*old
, size_t oldsz
)
223 if (oldsz
!= sizeof (cmd_bank_0_t
)) {
224 fmd_hdl_abort(hdl
, "size of state doesn't match size of "
225 "version 0 state (%u bytes).\n", sizeof (cmd_bank_0_t
));
228 new = fmd_hdl_zalloc(hdl
, sizeof (cmd_bank_t
), FMD_SLEEP
);
229 new->bank_header
= old
->bank0_header
;
230 new->bank_version
= CMD_BANK_VERSION
;
231 new->bank_asru
= old
->bank0_asru
;
232 new->bank_nretired
= old
->bank0_nretired
;
234 fmd_hdl_free(hdl
, old
, oldsz
);
239 bank_wrapv1(fmd_hdl_t
*hdl
, cmd_bank_pers_t
*pers
, size_t psz
)
243 if (psz
!= sizeof (cmd_bank_pers_t
)) {
244 fmd_hdl_abort(hdl
, "size of state doesn't match size of "
245 "version 1 state (%u bytes).\n", sizeof (cmd_bank_pers_t
));
248 bank
= fmd_hdl_zalloc(hdl
, sizeof (cmd_bank_t
), FMD_SLEEP
);
249 bcopy(pers
, bank
, sizeof (cmd_bank_pers_t
));
250 fmd_hdl_free(hdl
, pers
, psz
);
255 cmd_bank_restore(fmd_hdl_t
*hdl
, fmd_case_t
*cp
, cmd_case_ptr_t
*ptr
)
259 for (bank
= cmd_list_next(&cmd
.cmd_banks
); bank
!= NULL
;
260 bank
= cmd_list_next(bank
)) {
261 if (strcmp(bank
->bank_bufname
, ptr
->ptr_name
) == 0)
269 fmd_hdl_debug(hdl
, "restoring bank from %s\n", ptr
->ptr_name
);
271 if ((banksz
= fmd_buf_size(hdl
, NULL
, ptr
->ptr_name
)) == 0) {
272 fmd_hdl_abort(hdl
, "bank referenced by case %s does "
273 "not exist in saved state\n",
274 fmd_case_uuid(hdl
, cp
));
275 } else if (banksz
> CMD_BANK_MAXSIZE
||
276 banksz
< CMD_BANK_MINSIZE
) {
277 fmd_hdl_abort(hdl
, "bank buffer referenced by case %s "
278 "is out of bounds (is %u bytes, max %u, min %u)\n",
279 fmd_case_uuid(hdl
, cp
), banksz
,
280 CMD_BANK_MAXSIZE
, CMD_BANK_MAXSIZE
);
283 if ((bank
= cmd_buf_read(hdl
, NULL
, ptr
->ptr_name
,
285 fmd_hdl_abort(hdl
, "failed to read bank buf %s",
289 fmd_hdl_debug(hdl
, "found %d in version field\n",
292 if (CMD_BANK_VERSIONED(bank
)) {
293 switch (bank
->bank_version
) {
294 case CMD_BANK_VERSION_1
:
295 bank
= bank_wrapv1(hdl
, (cmd_bank_pers_t
*)bank
,
299 fmd_hdl_abort(hdl
, "unknown version (found %d) "
300 "for bank state referenced by case %s.\n",
301 bank
->bank_version
, fmd_case_uuid(hdl
, cp
));
305 bank
= bank_v0tov1(hdl
, (cmd_bank_0_t
*)bank
, banksz
);
310 CMD_STAT_BUMP(bank_migrat
);
311 cmd_bank_dirty(hdl
, bank
);
314 cmd_fmri_restore(hdl
, &bank
->bank_asru
);
316 if ((errno
= nvlist_lookup_string(bank
->bank_asru_nvl
,
317 FM_FMRI_MEM_UNUM
, (char **)&bank
->bank_unum
)) != 0)
318 fmd_hdl_abort(hdl
, "failed to retrieve nuum from asru");
320 bank_dimmlist_create(hdl
, bank
);
322 cmd_mem_retirestat_create(hdl
, &bank
->bank_retstat
,
323 bank
->bank_unum
, bank
->bank_nretired
, CMD_BANK_STAT_PREFIX
);
325 cmd_list_append(&cmd
.cmd_banks
, bank
);
328 switch (ptr
->ptr_subtype
) {
329 case BUG_PTR_BANK_CASE
:
330 fmd_hdl_debug(hdl
, "recovering from out of order page ptr\n");
331 cmd_case_redirect(hdl
, cp
, CMD_PTR_BANK_CASE
);
333 case CMD_PTR_BANK_CASE
:
334 cmd_mem_case_restore(hdl
, &bank
->bank_case
, cp
, "bank",
338 fmd_hdl_abort(hdl
, "invalid %s subtype %d\n",
339 ptr
->ptr_name
, ptr
->ptr_subtype
);
346 cmd_bank_validate(fmd_hdl_t
*hdl
)
348 cmd_bank_t
*bank
, *next
;
350 for (bank
= cmd_list_next(&cmd
.cmd_banks
); bank
!= NULL
; bank
= next
) {
351 next
= cmd_list_next(bank
);
353 if (!fmd_nvl_fmri_present(hdl
, bank
->bank_asru_nvl
))
354 cmd_bank_destroy(hdl
, bank
);
359 cmd_bank_dirty(fmd_hdl_t
*hdl
, cmd_bank_t
*bank
)
361 if (fmd_buf_size(hdl
, NULL
, bank
->bank_bufname
) !=
362 sizeof (cmd_bank_pers_t
))
363 fmd_buf_destroy(hdl
, NULL
, bank
->bank_bufname
);
365 /* No need to rewrite the FMRIs in the bank - they don't change */
366 fmd_buf_write(hdl
, NULL
, bank
->bank_bufname
, &bank
->bank_pers
,
367 sizeof (cmd_bank_pers_t
));
371 cmd_bank_gc(fmd_hdl_t
*hdl
)
373 cmd_bank_validate(hdl
);
377 cmd_bank_fini(fmd_hdl_t
*hdl
)
381 while ((bank
= cmd_list_next(&cmd
.cmd_banks
)) != NULL
)
382 bank_free(hdl
, bank
, FMD_B_FALSE
);