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 #include "efsys.h"
26 #include "efx.h"
27 #include "efx_impl.h"
28
29 #if EFSYS_OPT_MON_SIENA
30
31 __checkReturn int
32 siena_mon_reset(
33 __in efx_nic_t *enp)
34 {
35 _NOTE(ARGUNUSED(enp))
36 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
37
38 return (0);
39 }
40
41 __checkReturn int
42 siena_mon_reconfigure(
43 __in efx_nic_t *enp)
44 {
45 _NOTE(ARGUNUSED(enp))
46 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
47
48 return (0);
49 }
50
51 #if EFSYS_OPT_MON_STATS
52
53 #define SIENA_MON_WRONG_PORT (uint16_t)0xffff
54
55 static __cs uint16_t __siena_mon_port0_map[] = {
56 EFX_MON_STAT_INT_TEMP, /* MC_CMD_SENSOR_CONTROLLER_TEMP */
57 EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY_COMMON_TEMP */
58 EFX_MON_STAT_INT_COOLING, /* MC_CMD_SENSOR_CONTROLLER_COOLING */
59 EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY0_TEMP */
60 EFX_MON_STAT_EXT_COOLING, /* MC_CMD_SENSOR_PHY0_COOLING */
61 SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY1_TEMP */
62 SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY1_COOLING */
63 EFX_MON_STAT_1V, /* MC_CMD_SENSOR_IN_1V0 */
64 EFX_MON_STAT_1_2V, /* MC_CMD_SENSOR_IN_1V2 */
65 EFX_MON_STAT_1_8V, /* MC_CMD_SENSOR_IN_1V8 */
66 EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */
67 EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */
68 EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */
69 EFX_MON_STAT_1_2VA, /* MC_CMD_SENSOR_IN_1V2A */
70 EFX_MON_STAT_VREF, /* MC_CMD_SENSOR_IN_VREF */
71 };
72
73 static __cs uint16_t __siena_mon_port1_map[] = {
74 EFX_MON_STAT_INT_TEMP, /* MC_CMD_SENSOR_CONTROLLER_TEMP */
75 EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY_COMMON_TEMP */
76 EFX_MON_STAT_INT_COOLING, /* MC_CMD_SENSOR_CONTROLLER_COOLING */
77 SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY0_TEMP */
78 SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY0_COOLING */
79 EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY1_TEMP */
80 EFX_MON_STAT_EXT_COOLING, /* MC_CMD_SENSOR_PHY1_COOLING */
81 EFX_MON_STAT_1V, /* MC_CMD_SENSOR_IN_1V0 */
82 EFX_MON_STAT_1_2V, /* MC_CMD_SENSOR_IN_1V2 */
83 EFX_MON_STAT_1_8V, /* MC_CMD_SENSOR_IN_1V8 */
84 EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */
85 EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */
86 EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */
87 EFX_MON_STAT_1_2VA, /* MC_CMD_SENSOR_IN_1V2A */
88 EFX_MON_STAT_VREF, /* MC_CMD_SENSOR_IN_VREF */
89 };
90
91 #define SIENA_STATIC_SENSOR_ASSERT(_field) \
92 EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \
93 == EFX_MON_STAT_STATE_ ## _field)
94
95 void
96 siena_mon_decode_stats(
97 __in efx_nic_t *enp,
98 __in uint32_t dmask,
99 __in_opt efsys_mem_t *esmp,
100 __out_opt uint32_t *vmaskp,
101 __out_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *value)
102 {
103 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
104 uint16_t *sensor_map;
105 uint16_t mc_sensor;
106 size_t mc_sensor_max;
107 uint32_t vmask = 0;
108 uint32_t idx = 0;
109
110 /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
111 SIENA_STATIC_SENSOR_ASSERT(OK);
112 SIENA_STATIC_SENSOR_ASSERT(WARNING);
113 SIENA_STATIC_SENSOR_ASSERT(FATAL);
114 SIENA_STATIC_SENSOR_ASSERT(BROKEN);
115
116 EFX_STATIC_ASSERT(sizeof (__siena_mon_port1_map)
117 == sizeof (__siena_mon_port0_map));
118 mc_sensor_max = EFX_ARRAY_SIZE(__siena_mon_port0_map);
119 sensor_map = (emip->emi_port == 1)
120 ? __siena_mon_port0_map
121 : __siena_mon_port1_map;
122
123 /*
124 * dmask may legitimately contain sensors not understood by the driver
125 */
126 for (mc_sensor = 0; mc_sensor < mc_sensor_max; ++mc_sensor) {
127 uint16_t efx_sensor = sensor_map[mc_sensor];
128
129 if (~dmask & (1 << mc_sensor))
130 continue;
131 idx++;
132
133 if (efx_sensor == SIENA_MON_WRONG_PORT)
134 continue;
135 EFSYS_ASSERT(efx_sensor < EFX_MON_NSTATS);
136
137 vmask |= (1 << efx_sensor);
138 if (value != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
139 efx_mon_stat_value_t *emsvp = value + efx_sensor;
140 efx_dword_t dword;
141 EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
142 emsvp->emsv_value =
143 (uint16_t)EFX_DWORD_FIELD(
144 dword,
145 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
146 emsvp->emsv_state =
147 (uint16_t)EFX_DWORD_FIELD(
148 dword,
149 MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
150 }
151 }
152
153 if (vmaskp != NULL)
154 *vmaskp = vmask;
155 }
156
157 __checkReturn int
158 siena_mon_ev(
159 __in efx_nic_t *enp,
160 __in efx_qword_t *eqp,
161 __out efx_mon_stat_t *idp,
162 __out efx_mon_stat_value_t *valuep)
163 {
164 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
165 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
166 uint16_t ev_monitor;
167 uint16_t ev_state;
168 uint16_t ev_value;
169 uint16_t *sensor_map;
170 efx_mon_stat_t id;
171 int rc;
172
173 sensor_map = (emip->emi_port == 1)
174 ? __siena_mon_port0_map
175 : __siena_mon_port1_map;
176
177 ev_monitor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
178 ev_state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
179 ev_value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
180
181 /* Hardware must support this statistic */
182 EFSYS_ASSERT((1 << ev_monitor) & encp->enc_siena_mon_stat_mask);
183
184 /* But we don't have to understand it */
185 if (ev_monitor >= EFX_ARRAY_SIZE(__siena_mon_port0_map)) {
186 rc = ENOTSUP;
187 goto fail1;
188 }
189
190 id = sensor_map[ev_monitor];
191 if (id == SIENA_MON_WRONG_PORT)
192 return (ENODEV);
193 EFSYS_ASSERT(id < EFX_MON_NSTATS);
194
195 *idp = id;
196 valuep->emsv_value = ev_value;
197 valuep->emsv_state = ev_state;
198
199 return (0);
200
201 fail1:
202 EFSYS_PROBE1(fail1, int, rc);
203
204 return (rc);
205 }
206
207 __checkReturn int
208 siena_mon_stats_update(
209 __in efx_nic_t *enp,
210 __in efsys_mem_t *esmp,
211 __out_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values)
212 {
213 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
214 uint32_t dmask = encp->enc_siena_mon_stat_mask;
215 uint32_t vmask;
216 uint8_t payload[MC_CMD_READ_SENSORS_IN_LEN];
217 efx_mcdi_req_t req;
218 int rc;
219
220 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
221
222 req.emr_cmd = MC_CMD_READ_SENSORS;
223 req.emr_in_buf = payload;
224 req.emr_in_length = sizeof (payload);
225 EFX_STATIC_ASSERT(MC_CMD_READ_SENSORS_OUT_LEN == 0);
226 req.emr_out_buf = NULL;
227 req.emr_out_length = 0;
228
229 MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_LO,
230 EFSYS_MEM_ADDR(esmp) & 0xffffffff);
231 MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_HI,
232 EFSYS_MEM_ADDR(esmp) >> 32);
233
234 efx_mcdi_execute(enp, &req);
235
236 if (req.emr_rc != 0) {
237 rc = req.emr_rc;
238 goto fail1;
239 }
240
241 siena_mon_decode_stats(enp, dmask, esmp, &vmask, values);
242 EFSYS_ASSERT(vmask == encp->enc_mon_stat_mask);
243
244 return (0);
245
246 fail1:
247 EFSYS_PROBE1(fail1, int, rc);
248
249 return (rc);
250 }
251
252 #endif /* EFSYS_OPT_MON_STATS */
253
254 #endif /* EFSYS_OPT_MON_SIENA */