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