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