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