8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / fm / modules / sun4 / cpumem-diagnosis / cmd_mem.c
blob176b515715fe7958c19104071e16e67c6d62e823
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Support routines for managing state related to memory modules.
30 #include <cmd_mem.h>
31 #include <cmd_dimm.h>
32 #include <cmd_bank.h>
33 #include <cmd.h>
34 #ifdef sun4u
35 #include <cmd_dp.h>
36 #endif
37 #ifdef sun4v
38 #include <cmd_branch.h>
39 #endif
41 #include <errno.h>
42 #include <strings.h>
43 #include <ctype.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <fm/fmd_api.h>
47 #include <sys/fm/protocol.h>
48 #include <sys/mem.h>
49 #include <sys/nvpair.h>
51 const char *
52 cmd_fmri_get_unum(nvlist_t *fmri)
54 const char *scheme, *unum;
55 uint8_t vers;
57 if (nvlist_lookup_pairs(fmri, 0,
58 FM_VERSION, DATA_TYPE_UINT8, &vers,
59 FM_FMRI_SCHEME, DATA_TYPE_STRING, &scheme,
60 FM_FMRI_MEM_UNUM, DATA_TYPE_STRING, &unum,
61 NULL) != 0 || vers > FM_MEM_SCHEME_VERSION ||
62 strcmp(scheme, FM_FMRI_SCHEME_MEM) != 0)
63 return (NULL);
65 return (unum);
68 char *
69 cmd_mem_serdnm_create(fmd_hdl_t *hdl, const char *serdbase, const char *unum)
71 const char *fmt = "%s_%s_serd";
72 size_t sz = snprintf(NULL, 0, fmt, serdbase, unum) + 1;
73 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
74 (void) snprintf(nm, sz, fmt, serdbase, unum);
76 return (nm);
79 char *
80 cmd_page_serdnm_create(fmd_hdl_t *hdl, const char *serdbase,
81 uint64_t phys_addr)
83 const char *fmt = "%s_%llXserd";
84 size_t sz = snprintf(NULL, 0, fmt, serdbase, phys_addr) + 1;
85 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
86 (void) snprintf(nm, sz, fmt, serdbase, phys_addr);
88 return (nm);
91 char *
92 cmd_mq_serdnm_create(fmd_hdl_t *hdl, const char *serdbase,
93 uint64_t phys_addr, uint16_t cw, uint16_t pos)
95 const char *fmt = "%s_%llX_%x_%x_serd";
96 size_t sz = snprintf(NULL, 0, fmt, serdbase, phys_addr, cw, pos) + 1;
97 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
98 (void) snprintf(nm, sz, fmt, serdbase, phys_addr, cw, pos);
100 return (nm);
103 void
104 cmd_mem_case_restore(fmd_hdl_t *hdl, cmd_case_t *cc, fmd_case_t *cp,
105 const char *serdbase, const char *unum)
107 cmd_case_restore(hdl, cc, cp, cmd_mem_serdnm_create(hdl, serdbase,
108 unum));
111 void
112 cmd_mem_retirestat_create(fmd_hdl_t *hdl, fmd_stat_t *st, const char *unum,
113 uint64_t value, const char *prefix)
115 char *c;
118 * Prior to Niagara-2, every bank had to have at least two dimms; it
119 * was therefore impossible for the retirestat of a bank to ever have
120 * the same name (strcmp() == 0) as that of a dimm.
122 * Niagara-2 and VF, in "single channel mode" , retrieve an entire
123 * cache line from a single dimm. We therefore use a different
124 * prefix to name the bank retirestat vs. the dimm retirestat,
125 * or else the DE will abort trying to register a duplicate stat name
126 * with fmd.
128 (void) snprintf(st->fmds_name, sizeof (st->fmds_name), "%s%s",
129 prefix, unum);
130 (void) snprintf(st->fmds_desc, sizeof (st->fmds_desc),
131 "retirements for %s", unum);
132 st->fmds_type = FMD_TYPE_UINT64;
133 st->fmds_value.ui64 = value;
136 * Sanitize the name of the statistic -- standard unums won't get
137 * by fmd's validity checker.
139 for (c = st->fmds_name; *c != '\0'; c++) {
140 if (!isupper(*c) && !islower(*c) &&
141 !isdigit(*c) && *c != '-' && *c != '_' && *c != '.')
142 *c = '_';
145 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, 1, st);
149 cmd_mem_thresh_check(fmd_hdl_t *hdl, uint_t nret)
151 ulong_t npages = cmd_mem_get_phys_pages(hdl);
152 ulong_t wrnpgs;
154 fmd_hdl_debug(hdl, "thresh_check: npages is %lu\n", npages);
155 if (npages == 0) {
156 return (0);
159 if (cmd.cmd_thresh_abs_sysmem != 0) {
160 wrnpgs = cmd.cmd_thresh_abs_sysmem;
161 } else {
162 /* threshold is in thousandths of a percent */
163 wrnpgs = npages * cmd.cmd_thresh_tpct_sysmem / 100000;
166 fmd_hdl_debug(hdl, "thresh_check: nret %u, wrn %lu\n", nret, wrnpgs);
168 return (nret > wrnpgs);
171 nvlist_t *
172 cmd_mem_fmri_create(const char *unum, char **serids, size_t nserids)
174 nvlist_t *fmri;
176 if ((errno = nvlist_alloc(&fmri, NV_UNIQUE_NAME, 0)) != 0)
177 return (NULL);
179 if ((errno = nvlist_add_uint8(fmri, FM_VERSION,
180 FM_MEM_SCHEME_VERSION)) != 0 || (errno = nvlist_add_string(fmri,
181 FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM)) != 0 || (errno =
182 nvlist_add_string(fmri, FM_FMRI_MEM_UNUM, unum)) != 0) {
183 nvlist_free(fmri);
184 return (NULL);
187 if ((nserids > 0) && (serids != NULL)) {
188 (void) nvlist_add_string_array(fmri, FM_FMRI_MEM_SERIAL_ID,
189 serids, nserids);
191 return (fmri);
194 nvlist_t *
195 cmd_mem_fmri_derive(fmd_hdl_t *hdl, uint64_t afar, uint64_t afsr, uint16_t synd)
197 mem_name_t mn;
198 nvlist_t *fmri;
199 int fd;
201 if ((fd = open("/dev/mem", O_RDONLY)) < 0)
202 return (NULL);
204 mn.m_addr = afar;
205 mn.m_synd = synd;
206 mn.m_type[0] = afsr;
207 mn.m_type[1] = 0;
208 mn.m_namelen = 100;
210 for (;;) {
211 mn.m_name = fmd_hdl_alloc(hdl, mn.m_namelen, FMD_SLEEP);
213 if (ioctl(fd, MEM_NAME, &mn) == 0)
214 break;
216 fmd_hdl_free(hdl, mn.m_name, mn.m_namelen);
218 if (errno != ENOSPC) {
219 (void) close(fd);
220 return (NULL);
223 mn.m_namelen *= 2;
226 (void) close(fd);
228 fmri = cmd_mem_fmri_create(mn.m_name, NULL, 0);
229 fmd_hdl_free(hdl, mn.m_name, mn.m_namelen);
231 return (fmri);
234 void
235 cmd_iorxefrx_queue(fmd_hdl_t *hdl, cmd_iorxefrx_t *rf)
238 fmd_hdl_debug(hdl, "queueing IOxE/RxE/FRx for matching\n");
240 rf->rf_expid = fmd_timer_install(hdl, (void *)CMD_TIMERTYPE_MEM, NULL,
241 cmd.cmd_iorxefrx_window);
242 cmd_list_append(&cmd.cmd_iorxefrx, rf);
245 void
246 cmd_iorxefrx_free(fmd_hdl_t *hdl, cmd_iorxefrx_t *rf)
248 /* It's not persisted, so just remove it */
249 cmd_list_delete(&cmd.cmd_iorxefrx, rf);
250 fmd_hdl_free(hdl, rf, sizeof (cmd_iorxefrx_t));
253 void
254 cmd_mem_timeout(fmd_hdl_t *hdl, id_t id)
256 cmd_iorxefrx_t *rf;
258 for (rf = cmd_list_next(&cmd.cmd_iorxefrx); rf != NULL;
259 rf = cmd_list_next(rf)) {
260 if (rf->rf_expid == id) {
261 fmd_hdl_debug(hdl, "reclaiming iorxefrx tid %d\n", id);
262 cmd_iorxefrx_free(hdl, rf);
263 return;
268 void
269 cmd_mem_gc(fmd_hdl_t *hdl)
271 cmd_dimm_gc(hdl);
272 cmd_bank_gc(hdl);
273 #ifdef sun4v
274 cmd_branch_gc(hdl);
275 #endif
278 void
279 cmd_mem_fini(fmd_hdl_t *hdl)
281 cmd_iorxefrx_t *rf;
283 cmd_dimm_fini(hdl);
284 cmd_bank_fini(hdl);
285 #ifdef sun4v
286 cmd_branch_fini(hdl);
287 #endif
289 while ((rf = cmd_list_next(&cmd.cmd_iorxefrx)) != NULL)
290 cmd_iorxefrx_free(hdl, rf);