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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <sys/types.h> 30 #include <libnvpair.h> 31 #include <sys/fcntl.h> 32 #include <sys/devfm.h> 33 #include <fmd_agent_impl.h> 34 35 static int 36 cleanup_set_errno(fmd_agent_hdl_t *hdl, nvlist_t *innvl, nvlist_t *outnvl, 37 int err) 38 { 39 if (innvl != NULL) 40 nvlist_free(innvl); 41 if (outnvl != NULL) 42 nvlist_free(outnvl); 43 return (fmd_agent_seterrno(hdl, err)); 44 } 45 46 static int 47 fmd_agent_physcpu_info_v1(fmd_agent_hdl_t *hdl, nvlist_t ***cpusp, 48 uint_t *ncpup) 49 { 50 int err; 51 nvlist_t *nvl, **nvl_array, **cpus; 52 uint_t i, n; 53 54 if ((err = fmd_agent_nvl_ioctl(hdl, FM_IOC_PHYSCPU_INFO, 1, 55 NULL, &nvl)) != 0) 56 return (cleanup_set_errno(hdl, NULL, NULL, err)); 57 if ((err = nvlist_lookup_nvlist_array(nvl, FM_PHYSCPU_INFO_CPUS, 58 &cpus, &n)) != 0) 59 return (cleanup_set_errno(hdl, NULL, nvl, err)); 60 61 if ((nvl_array = umem_alloc(sizeof (nvlist_t *) * n, UMEM_DEFAULT)) 62 == NULL) 63 return (cleanup_set_errno(hdl, NULL, nvl, errno)); 64 for (i = 0; i < n; i++) { 65 if ((err = nvlist_dup(cpus[i], nvl_array + i, 0)) != 0) { 66 while (i > 0) 67 nvlist_free(nvl_array[--i]); 68 umem_free(nvl_array, sizeof (nvlist_t *) * n); 69 return (cleanup_set_errno(hdl, NULL, nvl, err)); 70 } 71 } 72 73 nvlist_free(nvl); 74 *cpusp = nvl_array; 75 *ncpup = n; 76 return (0); 77 } 78 79 int 80 fmd_agent_physcpu_info(fmd_agent_hdl_t *hdl, nvlist_t ***cpusp, uint_t *ncpu) 81 { 82 uint32_t ver; 83 84 if (fmd_agent_version(hdl, FM_CPU_INFO_VERSION, &ver) == -1) 85 return (fmd_agent_seterrno(hdl, errno)); 86 87 switch (ver) { 88 case 1: 89 return (fmd_agent_physcpu_info_v1(hdl, cpusp, ncpu)); 90 91 default: 92 return (fmd_agent_seterrno(hdl, ENOTSUP)); 93 } 94 } 95 96 static int 97 fmd_agent_cpuop_v1(fmd_agent_hdl_t *hdl, int cmd, int chipid, int coreid, 98 int strandid, int *old_status) 99 { 100 int err; 101 nvlist_t *nvl = NULL, *outnvl = NULL; 102 int32_t status; 103 104 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) != 0 || 105 (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_CHIP_ID, chipid)) != 0 || 106 (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_CORE_ID, coreid)) != 0 || 107 (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_STRAND_ID, strandid)) 108 != 0 || (err = fmd_agent_nvl_ioctl(hdl, cmd, 1, nvl, &outnvl)) != 0) 109 return (cleanup_set_errno(hdl, nvl, NULL, err)); 110 111 nvlist_free(nvl); 112 if (outnvl != NULL) { 113 if (old_status != NULL) { 114 (void) nvlist_lookup_int32(outnvl, 115 FM_CPU_RETIRE_OLDSTATUS, &status); 116 *old_status = status; 117 } 118 nvlist_free(outnvl); 119 } 120 121 return (0); 122 } 123 124 static int 125 fmd_agent_cpuop(fmd_agent_hdl_t *hdl, int cmd, int chipid, int coreid, 126 int strandid, int *old_status) 127 { 128 uint32_t ver; 129 130 if (fmd_agent_version(hdl, FM_CPU_OP_VERSION, &ver) == -1) 131 return (cleanup_set_errno(hdl, NULL, NULL, errno)); 132 133 switch (ver) { 134 case 1: 135 return (fmd_agent_cpuop_v1(hdl, cmd, chipid, coreid, strandid, 136 old_status)); 137 138 default: 139 return (fmd_agent_seterrno(hdl, ENOTSUP)); 140 } 141 } 142 143 int 144 fmd_agent_cpu_retire(fmd_agent_hdl_t *hdl, int chipid, int coreid, int strandid) 145 { 146 int ret; 147 148 ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_RETIRE, chipid, coreid, strandid, 149 NULL); 150 151 return (ret == 0 ? FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL); 152 } 153 154 int 155 fmd_agent_cpu_isretired(fmd_agent_hdl_t *hdl, int chipid, int coreid, 156 int strandid) 157 { 158 int ret, status; 159 160 ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_STATUS, chipid, coreid, strandid, 161 &status); 162 163 return (ret == 0 && status != P_ONLINE ? 164 FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL); 165 } 166 167 int 168 fmd_agent_cpu_unretire(fmd_agent_hdl_t *hdl, int chipid, int coreid, 169 int strandid) 170 { 171 int ret; 172 173 ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_UNRETIRE, chipid, coreid, 174 strandid, NULL); 175 176 return (ret == 0 ? FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL); 177 } 178