xref: /trueos/sys/dev/sfxge/common/siena_mon.c (revision 8cee81c05db1904906f988fe4ecb93dd8565cf85)
1 /*-
2  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include "efsys.h"
30 #include "efx.h"
31 #include "efx_impl.h"
32 
33 #if EFSYS_OPT_MON_SIENA
34 
35 	__checkReturn	int
siena_mon_reset(__in efx_nic_t * enp)36 siena_mon_reset(
37 	__in		efx_nic_t *enp)
38 {
39 	_NOTE(ARGUNUSED(enp))
40 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
41 
42 	return (0);
43 }
44 
45 	__checkReturn	int
siena_mon_reconfigure(__in efx_nic_t * enp)46 siena_mon_reconfigure(
47 	__in		efx_nic_t *enp)
48 {
49 	_NOTE(ARGUNUSED(enp))
50 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
51 
52 	return (0);
53 }
54 
55 #if EFSYS_OPT_MON_STATS
56 
57 #define	SIENA_MON_WRONG_PORT (uint16_t)0xffff
58 
59 static __cs uint16_t __siena_mon_port0_map[] = {
60 	EFX_MON_STAT_INT_TEMP,		/* MC_CMD_SENSOR_CONTROLLER_TEMP */
61 	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY_COMMON_TEMP */
62 	EFX_MON_STAT_INT_COOLING,	/* MC_CMD_SENSOR_CONTROLLER_COOLING */
63 	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY0_TEMP */
64 	EFX_MON_STAT_EXT_COOLING,	/* MC_CMD_SENSOR_PHY0_COOLING */
65 	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY1_TEMP */
66 	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY1_COOLING */
67 	EFX_MON_STAT_1V,		/* MC_CMD_SENSOR_IN_1V0 */
68 	EFX_MON_STAT_1_2V,		/* MC_CMD_SENSOR_IN_1V2 */
69 	EFX_MON_STAT_1_8V,		/* MC_CMD_SENSOR_IN_1V8 */
70 	EFX_MON_STAT_2_5V,		/* MC_CMD_SENSOR_IN_2V5 */
71 	EFX_MON_STAT_3_3V,		/* MC_CMD_SENSOR_IN_3V3 */
72 	EFX_MON_STAT_12V,		/* MC_CMD_SENSOR_IN_12V0 */
73 	EFX_MON_STAT_1_2VA,		/* MC_CMD_SENSOR_IN_1V2A */
74 	EFX_MON_STAT_VREF,		/* MC_CMD_SENSOR_IN_VREF */
75 	EFX_MON_STAT_VAOE,		/* MC_CMD_SENSOR_OUT_VAOE */
76 	EFX_MON_STAT_AOE_TEMP,		/* MC_CMD_SENSOR_AOE_TEMP */
77 	EFX_MON_STAT_PSU_AOE_TEMP,	/* MC_CMD_SENSOR_PSU_AOE_TEMP */
78 	EFX_MON_STAT_PSU_TEMP,		/* MC_CMD_SENSOR_PSE_TEMP */
79 	EFX_MON_STAT_FAN0,		/* MC_CMD_SENSOR_FAN_0 */
80 	EFX_MON_STAT_FAN1,		/* MC_CMD_SENSOR_FAN_1 */
81 	EFX_MON_STAT_FAN2,		/* MC_CMD_SENSOR_FAN_2 */
82 	EFX_MON_STAT_FAN3,		/* MC_CMD_SENSOR_FAN_3 */
83 	EFX_MON_STAT_FAN4,		/* MC_CMD_SENSOR_FAN_4 */
84 	EFX_MON_STAT_VAOE_IN,		/* MC_CMD_SENSOR_IN_VAOE */
85 	EFX_MON_STAT_IAOE,		/* MC_CMD_SENSOR_OUT_IAOE */
86 	EFX_MON_STAT_IAOE_IN,		/* MC_CMD_SENSOR_IN_IAOE */
87 
88 };
89 
90 static __cs uint16_t __siena_mon_port1_map[] = {
91 	EFX_MON_STAT_INT_TEMP,		/* MC_CMD_SENSOR_CONTROLLER_TEMP */
92 	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY_COMMON_TEMP */
93 	EFX_MON_STAT_INT_COOLING,	/* MC_CMD_SENSOR_CONTROLLER_COOLING */
94 	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY0_TEMP */
95 	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY0_COOLING */
96 	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY1_TEMP */
97 	EFX_MON_STAT_EXT_COOLING,	/* MC_CMD_SENSOR_PHY1_COOLING */
98 	EFX_MON_STAT_1V,		/* MC_CMD_SENSOR_IN_1V0 */
99 	EFX_MON_STAT_1_2V,		/* MC_CMD_SENSOR_IN_1V2 */
100 	EFX_MON_STAT_1_8V,		/* MC_CMD_SENSOR_IN_1V8 */
101 	EFX_MON_STAT_2_5V,		/* MC_CMD_SENSOR_IN_2V5 */
102 	EFX_MON_STAT_3_3V,		/* MC_CMD_SENSOR_IN_3V3 */
103 	EFX_MON_STAT_12V,		/* MC_CMD_SENSOR_IN_12V0 */
104 	EFX_MON_STAT_1_2VA,		/* MC_CMD_SENSOR_IN_1V2A */
105 	EFX_MON_STAT_VREF,		/* MC_CMD_SENSOR_IN_VREF */
106 	EFX_MON_STAT_VAOE,		/* MC_CMD_SENSOR_OUT_VAOE */
107 	EFX_MON_STAT_AOE_TEMP,		/* MC_CMD_SENSOR_AOE_TEMP */
108 	EFX_MON_STAT_PSU_AOE_TEMP,	/* MC_CMD_SENSOR_PSU_AOE_TEMP */
109 	EFX_MON_STAT_PSU_TEMP,		/* MC_CMD_SENSOR_PSE_TEMP */
110 	EFX_MON_STAT_FAN0,		/* MC_CMD_SENSOR_FAN_0 */
111 	EFX_MON_STAT_FAN1,		/* MC_CMD_SENSOR_FAN_1 */
112 	EFX_MON_STAT_FAN2,		/* MC_CMD_SENSOR_FAN_2 */
113 	EFX_MON_STAT_FAN3,		/* MC_CMD_SENSOR_FAN_3 */
114 	EFX_MON_STAT_FAN4,		/* MC_CMD_SENSOR_FAN_4 */
115 	EFX_MON_STAT_VAOE_IN,		/* MC_CMD_SENSOR_IN_VAOE */
116 	EFX_MON_STAT_IAOE,		/* MC_CMD_SENSOR_OUT_IAOE */
117 	EFX_MON_STAT_IAOE_IN,		/* MC_CMD_SENSOR_IN_IAOE */
118 
119 };
120 
121 #define	SIENA_STATIC_SENSOR_ASSERT(_field)				\
122 	EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field		\
123 			    == EFX_MON_STAT_STATE_ ## _field)
124 
125 					void
siena_mon_decode_stats(__in efx_nic_t * enp,__in uint32_t dmask,__in_opt efsys_mem_t * esmp,__out_opt uint32_t * vmaskp,__out_ecount_opt (EFX_MON_NSTATS)efx_mon_stat_value_t * value)126 siena_mon_decode_stats(
127 	__in				efx_nic_t *enp,
128 	__in				uint32_t dmask,
129 	__in_opt			efsys_mem_t *esmp,
130 	__out_opt			uint32_t *vmaskp,
131 	__out_ecount_opt(EFX_MON_NSTATS)	efx_mon_stat_value_t *value)
132 {
133 	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
134 	uint16_t *sensor_map;
135 	uint16_t mc_sensor;
136 	size_t mc_sensor_max;
137 	uint32_t vmask = 0;
138 	uint32_t idx = 0;
139 
140 	/* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
141 	SIENA_STATIC_SENSOR_ASSERT(OK);
142 	SIENA_STATIC_SENSOR_ASSERT(WARNING);
143 	SIENA_STATIC_SENSOR_ASSERT(FATAL);
144 	SIENA_STATIC_SENSOR_ASSERT(BROKEN);
145 
146 	EFX_STATIC_ASSERT(sizeof (__siena_mon_port1_map)
147 			    == sizeof (__siena_mon_port0_map));
148 	mc_sensor_max = EFX_ARRAY_SIZE(__siena_mon_port0_map);
149 	sensor_map = (emip->emi_port == 1)
150 		? __siena_mon_port0_map
151 		: __siena_mon_port1_map;
152 
153 	/*
154 	 * dmask may legitimately contain sensors not understood by the driver
155 	 */
156 	for (mc_sensor = 0; mc_sensor < mc_sensor_max; ++mc_sensor) {
157 		uint16_t efx_sensor = sensor_map[mc_sensor];
158 
159 		if (~dmask & (1 << mc_sensor))
160 			continue;
161 		idx++;
162 
163 		if (efx_sensor == SIENA_MON_WRONG_PORT)
164 			continue;
165 		EFSYS_ASSERT(efx_sensor < EFX_MON_NSTATS);
166 
167 		vmask |= (1 << efx_sensor);
168 		if (value != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
169 			efx_mon_stat_value_t *emsvp = value + efx_sensor;
170 			efx_dword_t dword;
171 			EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
172 			emsvp->emsv_value =
173 			    (uint16_t)EFX_DWORD_FIELD(
174 				dword,
175 				MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
176 			emsvp->emsv_state =
177 			    (uint16_t)EFX_DWORD_FIELD(
178 				dword,
179 				MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
180 		}
181 	}
182 
183 	if (vmaskp != NULL)
184 		*vmaskp = vmask;
185 }
186 
187 	__checkReturn			int
siena_mon_ev(__in efx_nic_t * enp,__in efx_qword_t * eqp,__out efx_mon_stat_t * idp,__out efx_mon_stat_value_t * valuep)188 siena_mon_ev(
189 	__in				efx_nic_t *enp,
190 	__in				efx_qword_t *eqp,
191 	__out				efx_mon_stat_t *idp,
192 	__out				efx_mon_stat_value_t *valuep)
193 {
194 	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
195 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
196 	uint16_t ev_monitor;
197 	uint16_t ev_state;
198 	uint16_t ev_value;
199 	uint16_t *sensor_map;
200 	efx_mon_stat_t id;
201 	int rc;
202 
203 	sensor_map = (emip->emi_port == 1)
204 		? __siena_mon_port0_map
205 		: __siena_mon_port1_map;
206 
207 	ev_monitor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
208 	ev_state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
209 	ev_value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
210 
211 	/* Hardware must support this statistic */
212 	EFSYS_ASSERT((1 << ev_monitor) & encp->enc_siena_mon_stat_mask);
213 
214 	/* But we don't have to understand it */
215 	if (ev_monitor >= EFX_ARRAY_SIZE(__siena_mon_port0_map)) {
216 		rc = ENOTSUP;
217 		goto fail1;
218 	}
219 
220 	id = sensor_map[ev_monitor];
221 	if (id == SIENA_MON_WRONG_PORT)
222 		return (ENODEV);
223 	EFSYS_ASSERT(id < EFX_MON_NSTATS);
224 
225 	*idp = id;
226 	valuep->emsv_value = ev_value;
227 	valuep->emsv_state = ev_state;
228 
229 	return (0);
230 
231 fail1:
232 	EFSYS_PROBE1(fail1, int, rc);
233 
234 	return (rc);
235 }
236 
237 	__checkReturn			int
siena_mon_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__out_ecount (EFX_MON_NSTATS)efx_mon_stat_value_t * values)238 siena_mon_stats_update(
239 	__in				efx_nic_t *enp,
240 	__in				efsys_mem_t *esmp,
241 	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
242 {
243 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
244 	uint32_t dmask = encp->enc_siena_mon_stat_mask;
245 	uint32_t vmask;
246 	uint8_t payload[MC_CMD_READ_SENSORS_IN_LEN];
247 	efx_mcdi_req_t req;
248 	int rc;
249 
250 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
251 
252 	req.emr_cmd = MC_CMD_READ_SENSORS;
253 	req.emr_in_buf = payload;
254 	req.emr_in_length = sizeof (payload);
255 	EFX_STATIC_ASSERT(MC_CMD_READ_SENSORS_OUT_LEN == 0);
256 	req.emr_out_buf = NULL;
257 	req.emr_out_length = 0;
258 
259 	MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_LO,
260 			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
261 	MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_HI,
262 			    EFSYS_MEM_ADDR(esmp) >> 32);
263 
264 	efx_mcdi_execute(enp, &req);
265 
266 	if (req.emr_rc != 0) {
267 		rc = req.emr_rc;
268 		goto fail1;
269 	}
270 
271 	siena_mon_decode_stats(enp, dmask, esmp, &vmask, values);
272 	EFSYS_ASSERT(vmask == encp->enc_mon_stat_mask);
273 
274 	return (0);
275 
276 fail1:
277 	EFSYS_PROBE1(fail1, int, rc);
278 
279 	return (rc);
280 }
281 
282 #endif	/* EFSYS_OPT_MON_STATS */
283 
284 #endif	/* EFSYS_OPT_MON_SIENA */
285