1e4b86885SCheng Sean Ye /*
2e4b86885SCheng Sean Ye  * CDDL HEADER START
3e4b86885SCheng Sean Ye  *
4e4b86885SCheng Sean Ye  * The contents of this file are subject to the terms of the
5e4b86885SCheng Sean Ye  * Common Development and Distribution License (the "License").
6e4b86885SCheng Sean Ye  * You may not use this file except in compliance with the License.
7e4b86885SCheng Sean Ye  *
8e4b86885SCheng Sean Ye  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e4b86885SCheng Sean Ye  * or http://www.opensolaris.org/os/licensing.
10e4b86885SCheng Sean Ye  * See the License for the specific language governing permissions
11e4b86885SCheng Sean Ye  * and limitations under the License.
12e4b86885SCheng Sean Ye  *
13e4b86885SCheng Sean Ye  * When distributing Covered Code, include this CDDL HEADER in each
14e4b86885SCheng Sean Ye  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e4b86885SCheng Sean Ye  * If applicable, add the following below this CDDL HEADER, with the
16e4b86885SCheng Sean Ye  * fields enclosed by brackets "[]" replaced with your own identifying
17e4b86885SCheng Sean Ye  * information: Portions Copyright [yyyy] [name of copyright owner]
18e4b86885SCheng Sean Ye  *
19e4b86885SCheng Sean Ye  * CDDL HEADER END
20e4b86885SCheng Sean Ye  */
21e4b86885SCheng Sean Ye 
22e4b86885SCheng Sean Ye /*
23e4b86885SCheng Sean Ye  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24e4b86885SCheng Sean Ye  * Use is subject to license terms.
25e4b86885SCheng Sean Ye  */
26e4b86885SCheng Sean Ye 
27e4b86885SCheng Sean Ye #include <stdlib.h>
28e4b86885SCheng Sean Ye #include <errno.h>
29e4b86885SCheng Sean Ye #include <sys/types.h>
30e4b86885SCheng Sean Ye #include <libnvpair.h>
31e4b86885SCheng Sean Ye #include <sys/fcntl.h>
32e4b86885SCheng Sean Ye #include <sys/devfm.h>
33e4b86885SCheng Sean Ye #include <fmd_agent_impl.h>
34e4b86885SCheng Sean Ye 
35e4b86885SCheng Sean Ye static int
cleanup_set_errno(fmd_agent_hdl_t * hdl,nvlist_t * innvl,nvlist_t * outnvl,int err)36e4b86885SCheng Sean Ye cleanup_set_errno(fmd_agent_hdl_t *hdl, nvlist_t *innvl, nvlist_t *outnvl,
37e4b86885SCheng Sean Ye     int err)
38e4b86885SCheng Sean Ye {
39*aab83bb8SJosef 'Jeff' Sipek 	nvlist_free(innvl);
40*aab83bb8SJosef 'Jeff' Sipek 	nvlist_free(outnvl);
41e4b86885SCheng Sean Ye 	return (fmd_agent_seterrno(hdl, err));
42e4b86885SCheng Sean Ye }
43e4b86885SCheng Sean Ye 
44e4b86885SCheng Sean Ye static int
fmd_agent_physcpu_info_v1(fmd_agent_hdl_t * hdl,nvlist_t *** cpusp,uint_t * ncpup)45e4b86885SCheng Sean Ye fmd_agent_physcpu_info_v1(fmd_agent_hdl_t *hdl, nvlist_t ***cpusp,
46e4b86885SCheng Sean Ye     uint_t *ncpup)
47e4b86885SCheng Sean Ye {
48e4b86885SCheng Sean Ye 	int err;
49e4b86885SCheng Sean Ye 	nvlist_t *nvl, **nvl_array, **cpus;
50e4b86885SCheng Sean Ye 	uint_t i, n;
51e4b86885SCheng Sean Ye 
52e4b86885SCheng Sean Ye 	if ((err = fmd_agent_nvl_ioctl(hdl, FM_IOC_PHYSCPU_INFO, 1,
53e4b86885SCheng Sean Ye 	    NULL, &nvl)) != 0)
54e4b86885SCheng Sean Ye 		return (cleanup_set_errno(hdl, NULL, NULL, err));
55e4b86885SCheng Sean Ye 	if ((err = nvlist_lookup_nvlist_array(nvl, FM_PHYSCPU_INFO_CPUS,
56e4b86885SCheng Sean Ye 	    &cpus, &n)) != 0)
57e4b86885SCheng Sean Ye 		return (cleanup_set_errno(hdl, NULL, nvl, err));
58e4b86885SCheng Sean Ye 
59e4b86885SCheng Sean Ye 	if ((nvl_array = umem_alloc(sizeof (nvlist_t *) * n, UMEM_DEFAULT))
60e4b86885SCheng Sean Ye 	    == NULL)
61e4b86885SCheng Sean Ye 		return (cleanup_set_errno(hdl, NULL, nvl, errno));
62e4b86885SCheng Sean Ye 	for (i = 0; i < n; i++) {
63e4b86885SCheng Sean Ye 		if ((err = nvlist_dup(cpus[i], nvl_array + i, 0)) != 0) {
64e4b86885SCheng Sean Ye 			while (i > 0)
65e4b86885SCheng Sean Ye 				nvlist_free(nvl_array[--i]);
66e4b86885SCheng Sean Ye 			umem_free(nvl_array, sizeof (nvlist_t *) * n);
67e4b86885SCheng Sean Ye 			return (cleanup_set_errno(hdl, NULL, nvl, err));
68e4b86885SCheng Sean Ye 		}
69e4b86885SCheng Sean Ye 	}
70e4b86885SCheng Sean Ye 
71e4b86885SCheng Sean Ye 	nvlist_free(nvl);
72e4b86885SCheng Sean Ye 	*cpusp = nvl_array;
73e4b86885SCheng Sean Ye 	*ncpup = n;
74e4b86885SCheng Sean Ye 	return (0);
75e4b86885SCheng Sean Ye }
76e4b86885SCheng Sean Ye 
77e4b86885SCheng Sean Ye int
fmd_agent_physcpu_info(fmd_agent_hdl_t * hdl,nvlist_t *** cpusp,uint_t * ncpu)78e4b86885SCheng Sean Ye fmd_agent_physcpu_info(fmd_agent_hdl_t *hdl, nvlist_t ***cpusp, uint_t *ncpu)
79e4b86885SCheng Sean Ye {
80e4b86885SCheng Sean Ye 	uint32_t ver;
81e4b86885SCheng Sean Ye 
82e4b86885SCheng Sean Ye 	if (fmd_agent_version(hdl, FM_CPU_INFO_VERSION, &ver) == -1)
83e4b86885SCheng Sean Ye 		return (fmd_agent_seterrno(hdl, errno));
84e4b86885SCheng Sean Ye 
85e4b86885SCheng Sean Ye 	switch (ver) {
86e4b86885SCheng Sean Ye 	case 1:
87e4b86885SCheng Sean Ye 		return (fmd_agent_physcpu_info_v1(hdl, cpusp, ncpu));
88e4b86885SCheng Sean Ye 
89e4b86885SCheng Sean Ye 	default:
90e4b86885SCheng Sean Ye 		return (fmd_agent_seterrno(hdl, ENOTSUP));
91e4b86885SCheng Sean Ye 	}
92e4b86885SCheng Sean Ye }
93e4b86885SCheng Sean Ye 
94e4b86885SCheng Sean Ye static int
fmd_agent_cpuop_v1(fmd_agent_hdl_t * hdl,int cmd,int chipid,int coreid,int strandid,int * old_status)95e4b86885SCheng Sean Ye fmd_agent_cpuop_v1(fmd_agent_hdl_t *hdl, int cmd, int chipid, int coreid,
96e4b86885SCheng Sean Ye     int strandid, int *old_status)
97e4b86885SCheng Sean Ye {
98e4b86885SCheng Sean Ye 	int err;
99e4b86885SCheng Sean Ye 	nvlist_t *nvl = NULL, *outnvl = NULL;
100e4b86885SCheng Sean Ye 	int32_t status;
101e4b86885SCheng Sean Ye 
102e4b86885SCheng Sean Ye 	if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) != 0 ||
103e4b86885SCheng Sean Ye 	    (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_CHIP_ID, chipid)) != 0 ||
104e4b86885SCheng Sean Ye 	    (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_CORE_ID, coreid)) != 0 ||
105e4b86885SCheng Sean Ye 	    (err = nvlist_add_int32(nvl, FM_CPU_RETIRE_STRAND_ID, strandid))
106e4b86885SCheng Sean Ye 	    != 0 || (err = fmd_agent_nvl_ioctl(hdl, cmd, 1, nvl, &outnvl)) != 0)
107e4b86885SCheng Sean Ye 		return (cleanup_set_errno(hdl, nvl, NULL, err));
108e4b86885SCheng Sean Ye 
109e4b86885SCheng Sean Ye 	nvlist_free(nvl);
110e4b86885SCheng Sean Ye 	if (outnvl != NULL) {
111e4b86885SCheng Sean Ye 		if (old_status != NULL) {
112e4b86885SCheng Sean Ye 			(void) nvlist_lookup_int32(outnvl,
113e4b86885SCheng Sean Ye 			    FM_CPU_RETIRE_OLDSTATUS, &status);
114e4b86885SCheng Sean Ye 			*old_status = status;
115e4b86885SCheng Sean Ye 		}
116e4b86885SCheng Sean Ye 		nvlist_free(outnvl);
117e4b86885SCheng Sean Ye 	}
118e4b86885SCheng Sean Ye 
119e4b86885SCheng Sean Ye 	return (0);
120e4b86885SCheng Sean Ye }
121e4b86885SCheng Sean Ye 
122e4b86885SCheng Sean Ye static int
fmd_agent_cpuop(fmd_agent_hdl_t * hdl,int cmd,int chipid,int coreid,int strandid,int * old_status)123e4b86885SCheng Sean Ye fmd_agent_cpuop(fmd_agent_hdl_t *hdl, int cmd, int chipid, int coreid,
124e4b86885SCheng Sean Ye     int strandid, int *old_status)
125e4b86885SCheng Sean Ye {
126e4b86885SCheng Sean Ye 	uint32_t ver;
127e4b86885SCheng Sean Ye 
128e4b86885SCheng Sean Ye 	if (fmd_agent_version(hdl, FM_CPU_OP_VERSION, &ver) == -1)
129e4b86885SCheng Sean Ye 		return (cleanup_set_errno(hdl, NULL, NULL, errno));
130e4b86885SCheng Sean Ye 
131e4b86885SCheng Sean Ye 	switch (ver) {
132e4b86885SCheng Sean Ye 	case 1:
133e4b86885SCheng Sean Ye 		return (fmd_agent_cpuop_v1(hdl, cmd, chipid, coreid, strandid,
134e4b86885SCheng Sean Ye 		    old_status));
135e4b86885SCheng Sean Ye 
136e4b86885SCheng Sean Ye 	default:
137e4b86885SCheng Sean Ye 		return (fmd_agent_seterrno(hdl, ENOTSUP));
138e4b86885SCheng Sean Ye 	}
139e4b86885SCheng Sean Ye }
140e4b86885SCheng Sean Ye 
141e4b86885SCheng Sean Ye int
fmd_agent_cpu_retire(fmd_agent_hdl_t * hdl,int chipid,int coreid,int strandid)142e4b86885SCheng Sean Ye fmd_agent_cpu_retire(fmd_agent_hdl_t *hdl, int chipid, int coreid, int strandid)
143e4b86885SCheng Sean Ye {
144e4b86885SCheng Sean Ye 	int ret;
145e4b86885SCheng Sean Ye 
146e4b86885SCheng Sean Ye 	ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_RETIRE, chipid, coreid, strandid,
147e4b86885SCheng Sean Ye 	    NULL);
148e4b86885SCheng Sean Ye 
149e4b86885SCheng Sean Ye 	return (ret == 0 ? FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL);
150e4b86885SCheng Sean Ye }
151e4b86885SCheng Sean Ye 
152e4b86885SCheng Sean Ye int
fmd_agent_cpu_isretired(fmd_agent_hdl_t * hdl,int chipid,int coreid,int strandid)153e4b86885SCheng Sean Ye fmd_agent_cpu_isretired(fmd_agent_hdl_t *hdl, int chipid, int coreid,
154e4b86885SCheng Sean Ye     int strandid)
155e4b86885SCheng Sean Ye {
156e4b86885SCheng Sean Ye 	int ret, status;
157e4b86885SCheng Sean Ye 
158e4b86885SCheng Sean Ye 	ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_STATUS, chipid, coreid, strandid,
159e4b86885SCheng Sean Ye 	    &status);
160e4b86885SCheng Sean Ye 
161e4b86885SCheng Sean Ye 	return (ret == 0 && status != P_ONLINE ?
162e4b86885SCheng Sean Ye 	    FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL);
163e4b86885SCheng Sean Ye }
164e4b86885SCheng Sean Ye 
165e4b86885SCheng Sean Ye int
fmd_agent_cpu_unretire(fmd_agent_hdl_t * hdl,int chipid,int coreid,int strandid)166e4b86885SCheng Sean Ye fmd_agent_cpu_unretire(fmd_agent_hdl_t *hdl, int chipid, int coreid,
167e4b86885SCheng Sean Ye     int strandid)
168e4b86885SCheng Sean Ye {
169e4b86885SCheng Sean Ye 	int ret;
170e4b86885SCheng Sean Ye 
171e4b86885SCheng Sean Ye 	ret = fmd_agent_cpuop(hdl, FM_IOC_CPU_UNRETIRE, chipid, coreid,
172e4b86885SCheng Sean Ye 	    strandid, NULL);
173e4b86885SCheng Sean Ye 
174e4b86885SCheng Sean Ye 	return (ret == 0 ? FMD_AGENT_RETIRE_DONE : FMD_AGENT_RETIRE_FAIL);
175e4b86885SCheng Sean Ye }
176