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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <cma.h>
29 
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <fm/fmd_api.h>
36 #include <sys/fm/protocol.h>
37 #include <sys/bl.h>
38 #include <sys/processor.h>
39 
40 /* ARGSUSED */
41 static int
42 cpu_online(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, const char *uuid,
43     uint32_t cpuid)
44 {
45 	int err = CMA_RA_SUCCESS;
46 
47 	if (cma.cma_cpu_doonline) {
48 		err = cma_cpu_statechange(hdl, asru, uuid, P_ONLINE,
49 		    B_TRUE);
50 	} else {
51 		fmd_hdl_debug(hdl, "suppressed online of CPU %u\n",
52 		    cpuid);
53 		cma_stats.cpu_supp.fmds_value.ui64++;
54 	}
55 
56 	/* OPL performs the blacklist in the service processor */
57 #ifndef opl
58 	if (cma.cma_cpu_dounblacklist) {
59 		if (cma_cpu_blacklist(hdl, nvl, asru, B_TRUE) < 0)
60 			cma_stats.cpu_blfails.fmds_value.ui64++;
61 	} else {
62 		fmd_hdl_debug(hdl, "suppressed unblacklist of CPU %u\n", cpuid);
63 		cma_stats.cpu_blsupp.fmds_value.ui64++;
64 	}
65 #endif /* opl */
66 
67 	return (err);
68 }
69 
70 /* ARGSUSED */
71 static int
72 cpu_offline(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, const char *uuid,
73     uint32_t cpuid)
74 {
75 	int err = CMA_RA_FAILURE;
76 
77 	if (cma.cma_cpu_dooffline) {
78 		int cpustate = P_FAULTED;
79 
80 		if (cma.cma_cpu_forcedoffline)
81 			cpustate |= P_FORCED;
82 		err = cma_cpu_statechange(hdl, asru, uuid, cpustate,
83 		    B_FALSE);
84 	} else {
85 		fmd_hdl_debug(hdl, "suppressed offline of CPU %u\n",
86 		    cpuid);
87 		cma_stats.cpu_supp.fmds_value.ui64++;
88 	}
89 
90 	/* OPL performs the blacklist in the service processor */
91 #ifndef opl
92 	if (cma.cma_cpu_doblacklist) {
93 		if (cma_cpu_blacklist(hdl, nvl, asru, B_FALSE) < 0)
94 			cma_stats.cpu_blfails.fmds_value.ui64++;
95 	} else {
96 		fmd_hdl_debug(hdl, "suppressed blacklist of CPU %u\n",
97 		    cpuid);
98 		cma_stats.cpu_blsupp.fmds_value.ui64++;
99 	}
100 #endif /* opl */
101 
102 	return (err);
103 }
104 
105 static int
106 cpu_statechange(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, const char *uuid,
107     uint32_t cpuid, boolean_t repair)
108 {
109 	if (repair)
110 		return (cpu_online(hdl, nvl, asru, uuid, cpuid));
111 	else
112 		return (cpu_offline(hdl, nvl, asru, uuid, cpuid));
113 }
114 
115 const char *
116 p_online_state_fmt(int state)
117 {
118 	state &= ~P_FORCED;
119 	switch (state) {
120 	case P_OFFLINE:
121 		return (PS_OFFLINE);
122 	case P_ONLINE:
123 		return (PS_ONLINE);
124 	case P_FAULTED:
125 		return (PS_FAULTED);
126 	case P_POWEROFF:
127 		return (PS_POWEROFF);
128 	case P_NOINTR:
129 		return (PS_NOINTR);
130 	case P_SPARE:
131 		return (PS_SPARE);
132 	default:
133 		return ("unknown");
134 	}
135 }
136 
137 int
138 cma_cpu_retire(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru, const char *uuid,
139     boolean_t repair)
140 {
141 	uint_t cpuid;
142 
143 	if (nvlist_lookup_uint32(asru, FM_FMRI_CPU_ID, &cpuid) != 0) {
144 		fmd_hdl_debug(hdl, "cpu fault missing '%s'\n", FM_FMRI_CPU_ID);
145 		cma_stats.bad_flts.fmds_value.ui64++;
146 		return (CMA_RA_FAILURE);
147 	}
148 
149 	return (cpu_statechange(hdl, nvl, asru, uuid, cpuid, repair));
150 }
151 
152 #ifdef opl
153 /* ARGSUSED 4 */
154 int
155 cma_cpu_hc_retire(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *asru,
156     const char *uuid, boolean_t repair)
157 {
158 	uint_t cpuid;
159 	uint_t i, nprs;
160 	nvlist_t **hc_prs = NULL, *hc_spec_nvl;
161 
162 	if (nvlist_lookup_nvlist(asru, FM_FMRI_HC_SPECIFIC,
163 	    &hc_spec_nvl) != 0) {
164 		cma_stats.bad_flts.fmds_value.ui64++;
165 		fmd_hdl_debug(hdl,
166 		    "cma_cpu_hc_retire lookup hc_spec_nvl failed\n");
167 		return (CMA_RA_FAILURE);
168 	}
169 
170 	if (nvlist_lookup_nvlist_array(hc_spec_nvl, FM_FMRI_HC_CPUIDS,
171 	    &hc_prs, &nprs) != 0) {
172 		cma_stats.bad_flts.fmds_value.ui64++;
173 		fmd_hdl_debug(hdl,
174 		    "cma_cpu_hc_retire lookup cpuid array failed\n");
175 		return (CMA_RA_FAILURE);
176 	}
177 
178 	for (i = 0; i < nprs; i++) {
179 		if (nvlist_lookup_uint32(hc_prs[i],
180 		    FM_FMRI_CPU_ID, &cpuid) != 0) {
181 			cma_stats.bad_flts.fmds_value.ui64++;
182 			return (CMA_RA_FAILURE);
183 		}
184 
185 		if (cpu_statechange(hdl, nvl, hc_prs[i], uuid, cpuid, repair)
186 		    != CMA_RA_SUCCESS) {
187 			cma_stats.bad_flts.fmds_value.ui64++;
188 			return (CMA_RA_FAILURE);
189 		}
190 	}
191 
192 	return (CMA_RA_SUCCESS);
193 }
194 #endif /* opl */
195