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