]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/sfxge/common/siena_mon.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / sfxge / common / siena_mon.c
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
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
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 };
74
75 static __cs uint16_t __siena_mon_port1_map[] = {
76         EFX_MON_STAT_INT_TEMP,          /* MC_CMD_SENSOR_CONTROLLER_TEMP */
77         EFX_MON_STAT_EXT_TEMP,          /* MC_CMD_SENSOR_PHY_COMMON_TEMP */
78         EFX_MON_STAT_INT_COOLING,       /* MC_CMD_SENSOR_CONTROLLER_COOLING */
79         SIENA_MON_WRONG_PORT,           /* MC_CMD_SENSOR_PHY0_TEMP */
80         SIENA_MON_WRONG_PORT,           /* MC_CMD_SENSOR_PHY0_COOLING */
81         EFX_MON_STAT_EXT_TEMP,          /* MC_CMD_SENSOR_PHY1_TEMP */
82         EFX_MON_STAT_EXT_COOLING,       /* MC_CMD_SENSOR_PHY1_COOLING */
83         EFX_MON_STAT_1V,                /* MC_CMD_SENSOR_IN_1V0 */
84         EFX_MON_STAT_1_2V,              /* MC_CMD_SENSOR_IN_1V2 */
85         EFX_MON_STAT_1_8V,              /* MC_CMD_SENSOR_IN_1V8 */
86         EFX_MON_STAT_2_5V,              /* MC_CMD_SENSOR_IN_2V5 */
87         EFX_MON_STAT_3_3V,              /* MC_CMD_SENSOR_IN_3V3 */
88         EFX_MON_STAT_12V,               /* MC_CMD_SENSOR_IN_12V0 */
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
109         /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
110         SIENA_STATIC_SENSOR_ASSERT(OK);
111         SIENA_STATIC_SENSOR_ASSERT(WARNING);
112         SIENA_STATIC_SENSOR_ASSERT(FATAL);
113         SIENA_STATIC_SENSOR_ASSERT(BROKEN);
114
115         EFX_STATIC_ASSERT(sizeof (__siena_mon_port1_map)
116                             == sizeof (__siena_mon_port0_map));
117         mc_sensor_max = EFX_ARRAY_SIZE(__siena_mon_port0_map);
118         sensor_map = (emip->emi_port == 1)
119                 ? __siena_mon_port0_map
120                 : __siena_mon_port1_map;
121
122         /*
123          * dmask may legitimately contain sensors not understood by the driver
124          */
125         for (mc_sensor = 0; mc_sensor < mc_sensor_max; ++mc_sensor) {
126                 uint16_t efx_sensor = sensor_map[mc_sensor];
127
128                 if (efx_sensor == SIENA_MON_WRONG_PORT)
129                         continue;
130                 EFSYS_ASSERT(efx_sensor < EFX_MON_NSTATS);
131
132                 if (~dmask & (1 << mc_sensor))
133                         continue;
134
135                 vmask |= (1 << efx_sensor);
136                 if (value != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
137                         efx_mon_stat_value_t *emsvp = value + efx_sensor;
138                         efx_dword_t dword;
139                         EFSYS_MEM_READD(esmp, 4 * mc_sensor, &dword);
140                         emsvp->emsv_value =
141                                 (uint16_t)EFX_DWORD_FIELD(
142                                         dword,
143                                         MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
144                         emsvp->emsv_state =
145                                 (uint16_t)EFX_DWORD_FIELD(
146                                         dword,
147                                         MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
148                 }
149         }
150
151         if (vmaskp != NULL)
152                 *vmaskp = vmask;
153 }
154
155         __checkReturn                   int
156 siena_mon_ev(
157         __in                            efx_nic_t *enp,
158         __in                            efx_qword_t *eqp,
159         __out                           efx_mon_stat_t *idp,
160         __out                           efx_mon_stat_value_t *valuep)
161 {
162         efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
163         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
164         uint16_t ev_monitor;
165         uint16_t ev_state;
166         uint16_t ev_value;
167         uint16_t *sensor_map;
168         efx_mon_stat_t id;
169         int rc;
170
171         sensor_map = (emip->emi_port == 1)
172                 ? __siena_mon_port0_map
173                 : __siena_mon_port1_map;
174
175         ev_monitor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
176         ev_state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
177         ev_value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
178
179         /* Hardware must support this statistic */
180         EFSYS_ASSERT((1 << ev_monitor) & encp->enc_siena_mon_stat_mask);
181
182         /* But we don't have to understand it */
183         if (ev_monitor >= EFX_ARRAY_SIZE(__siena_mon_port0_map)) {
184                 rc = ENOTSUP;
185                 goto fail1;
186         }
187
188         id = sensor_map[ev_monitor];
189         if (id == SIENA_MON_WRONG_PORT)
190                 return (ENODEV);
191         EFSYS_ASSERT(id < EFX_MON_NSTATS);
192
193         *idp = id;
194         valuep->emsv_value = ev_value;
195         valuep->emsv_state = ev_state;
196
197         return (0);
198
199 fail1:
200         EFSYS_PROBE1(fail1, int, rc);
201
202         return (rc);
203 }
204
205         __checkReturn                   int
206 siena_mon_stats_update(
207         __in                            efx_nic_t *enp,
208         __in                            efsys_mem_t *esmp,
209         __out_ecount(EFX_MON_NSTATS)    efx_mon_stat_value_t *values)
210 {
211         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
212         uint32_t dmask = encp->enc_siena_mon_stat_mask;
213         uint32_t vmask;
214         uint8_t payload[MC_CMD_READ_SENSORS_IN_LEN];
215         efx_mcdi_req_t req;
216         int rc;
217
218         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
219
220         req.emr_cmd = MC_CMD_READ_SENSORS;
221         req.emr_in_buf = payload;
222         req.emr_in_length = sizeof (payload);
223         EFX_STATIC_ASSERT(MC_CMD_READ_SENSORS_OUT_LEN == 0);
224         req.emr_out_buf = NULL;
225         req.emr_out_length = 0;
226
227         MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_LO,
228                             EFSYS_MEM_ADDR(esmp) & 0xffffffff);
229         MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_HI,
230                             EFSYS_MEM_ADDR(esmp) >> 32);
231
232         efx_mcdi_execute(enp, &req);
233
234         if (req.emr_rc != 0) {
235                 rc = req.emr_rc;
236                 goto fail1;
237         }
238
239         siena_mon_decode_stats(enp, dmask, esmp, &vmask, values);
240         EFSYS_ASSERT(vmask == encp->enc_mon_stat_mask);
241
242         return (0);
243
244 fail1:
245         EFSYS_PROBE1(fail1, int, rc);
246
247         return (rc);
248 }
249
250 #endif  /* EFSYS_OPT_MON_STATS */
251
252 #endif  /* EFSYS_OPT_MON_SIENA */