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 36siena_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 46siena_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 59static __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 75static __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 96siena_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 156siena_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 199fail1: 200 EFSYS_PROBE1(fail1, int, rc); 201 202 return (rc); 203} 204 205 __checkReturn int 206siena_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 244fail1: 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 */ 253