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 */