1227569Sphilip/*- 2227569Sphilip * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3227569Sphilip * 4227569Sphilip * Redistribution and use in source and binary forms, with or without 5227569Sphilip * modification, are permitted provided that the following conditions 6227569Sphilip * are met: 7227569Sphilip * 1. Redistributions of source code must retain the above copyright 8227569Sphilip * notice, this list of conditions and the following disclaimer. 9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 10227569Sphilip * notice, this list of conditions and the following disclaimer in the 11227569Sphilip * documentation and/or other materials provided with the distribution. 12227569Sphilip * 13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227569Sphilip * SUCH DAMAGE. 24227569Sphilip */ 25228100Sphilip 26228100Sphilip#include <sys/cdefs.h> 27228100Sphilip__FBSDID("$FreeBSD$"); 28228100Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_impl.h" 32227569Sphilip 33227569Sphilip#if EFSYS_OPT_MON_SIENA 34227569Sphilip 35227569Sphilip __checkReturn int 36227569Sphilipsiena_mon_reset( 37227569Sphilip __in efx_nic_t *enp) 38227569Sphilip{ 39227569Sphilip _NOTE(ARGUNUSED(enp)) 40227569Sphilip EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 41227569Sphilip 42227569Sphilip return (0); 43227569Sphilip} 44227569Sphilip 45227569Sphilip __checkReturn int 46227569Sphilipsiena_mon_reconfigure( 47227569Sphilip __in efx_nic_t *enp) 48227569Sphilip{ 49227569Sphilip _NOTE(ARGUNUSED(enp)) 50227569Sphilip EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 51227569Sphilip 52227569Sphilip return (0); 53227569Sphilip} 54227569Sphilip 55227569Sphilip#if EFSYS_OPT_MON_STATS 56227569Sphilip 57227569Sphilip#define SIENA_MON_WRONG_PORT (uint16_t)0xffff 58227569Sphilip 59227569Sphilipstatic __cs uint16_t __siena_mon_port0_map[] = { 60227569Sphilip EFX_MON_STAT_INT_TEMP, /* MC_CMD_SENSOR_CONTROLLER_TEMP */ 61227569Sphilip EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY_COMMON_TEMP */ 62227569Sphilip EFX_MON_STAT_INT_COOLING, /* MC_CMD_SENSOR_CONTROLLER_COOLING */ 63227569Sphilip EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY0_TEMP */ 64227569Sphilip EFX_MON_STAT_EXT_COOLING, /* MC_CMD_SENSOR_PHY0_COOLING */ 65227569Sphilip SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY1_TEMP */ 66227569Sphilip SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY1_COOLING */ 67227569Sphilip EFX_MON_STAT_1V, /* MC_CMD_SENSOR_IN_1V0 */ 68227569Sphilip EFX_MON_STAT_1_2V, /* MC_CMD_SENSOR_IN_1V2 */ 69227569Sphilip EFX_MON_STAT_1_8V, /* MC_CMD_SENSOR_IN_1V8 */ 70227569Sphilip EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */ 71227569Sphilip EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */ 72227569Sphilip EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */ 73227569Sphilip}; 74227569Sphilip 75227569Sphilipstatic __cs uint16_t __siena_mon_port1_map[] = { 76227569Sphilip EFX_MON_STAT_INT_TEMP, /* MC_CMD_SENSOR_CONTROLLER_TEMP */ 77227569Sphilip EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY_COMMON_TEMP */ 78227569Sphilip EFX_MON_STAT_INT_COOLING, /* MC_CMD_SENSOR_CONTROLLER_COOLING */ 79227569Sphilip SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY0_TEMP */ 80227569Sphilip SIENA_MON_WRONG_PORT, /* MC_CMD_SENSOR_PHY0_COOLING */ 81227569Sphilip EFX_MON_STAT_EXT_TEMP, /* MC_CMD_SENSOR_PHY1_TEMP */ 82227569Sphilip EFX_MON_STAT_EXT_COOLING, /* MC_CMD_SENSOR_PHY1_COOLING */ 83227569Sphilip EFX_MON_STAT_1V, /* MC_CMD_SENSOR_IN_1V0 */ 84227569Sphilip EFX_MON_STAT_1_2V, /* MC_CMD_SENSOR_IN_1V2 */ 85227569Sphilip EFX_MON_STAT_1_8V, /* MC_CMD_SENSOR_IN_1V8 */ 86227569Sphilip EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */ 87227569Sphilip EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */ 88227569Sphilip EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */ 89227569Sphilip}; 90227569Sphilip 91227569Sphilip#define SIENA_STATIC_SENSOR_ASSERT(_field) \ 92227569Sphilip EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \ 93227569Sphilip == EFX_MON_STAT_STATE_ ## _field) 94227569Sphilip 95227569Sphilip void 96227569Sphilipsiena_mon_decode_stats( 97227569Sphilip __in efx_nic_t *enp, 98227569Sphilip __in uint32_t dmask, 99227569Sphilip __in_opt efsys_mem_t *esmp, 100227569Sphilip __out_opt uint32_t *vmaskp, 101227569Sphilip __out_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *value) 102227569Sphilip{ 103227569Sphilip efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); 104227569Sphilip uint16_t *sensor_map; 105227569Sphilip uint16_t mc_sensor; 106227569Sphilip size_t mc_sensor_max; 107227569Sphilip uint32_t vmask = 0; 108227569Sphilip 109227569Sphilip /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */ 110227569Sphilip SIENA_STATIC_SENSOR_ASSERT(OK); 111227569Sphilip SIENA_STATIC_SENSOR_ASSERT(WARNING); 112227569Sphilip SIENA_STATIC_SENSOR_ASSERT(FATAL); 113227569Sphilip SIENA_STATIC_SENSOR_ASSERT(BROKEN); 114227569Sphilip 115227569Sphilip EFX_STATIC_ASSERT(sizeof (__siena_mon_port1_map) 116227569Sphilip == sizeof (__siena_mon_port0_map)); 117227569Sphilip mc_sensor_max = EFX_ARRAY_SIZE(__siena_mon_port0_map); 118227569Sphilip sensor_map = (emip->emi_port == 1) 119227569Sphilip ? __siena_mon_port0_map 120227569Sphilip : __siena_mon_port1_map; 121227569Sphilip 122227569Sphilip /* 123227569Sphilip * dmask may legitimately contain sensors not understood by the driver 124227569Sphilip */ 125227569Sphilip for (mc_sensor = 0; mc_sensor < mc_sensor_max; ++mc_sensor) { 126227569Sphilip uint16_t efx_sensor = sensor_map[mc_sensor]; 127227569Sphilip 128227569Sphilip if (efx_sensor == SIENA_MON_WRONG_PORT) 129227569Sphilip continue; 130227569Sphilip EFSYS_ASSERT(efx_sensor < EFX_MON_NSTATS); 131227569Sphilip 132227569Sphilip if (~dmask & (1 << mc_sensor)) 133227569Sphilip continue; 134227569Sphilip 135227569Sphilip vmask |= (1 << efx_sensor); 136227569Sphilip if (value != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 137227569Sphilip efx_mon_stat_value_t *emsvp = value + efx_sensor; 138227569Sphilip efx_dword_t dword; 139227569Sphilip EFSYS_MEM_READD(esmp, 4 * mc_sensor, &dword); 140227569Sphilip emsvp->emsv_value = 141227569Sphilip (uint16_t)EFX_DWORD_FIELD( 142227569Sphilip dword, 143227569Sphilip MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); 144227569Sphilip emsvp->emsv_state = 145227569Sphilip (uint16_t)EFX_DWORD_FIELD( 146227569Sphilip dword, 147227569Sphilip MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 148227569Sphilip } 149227569Sphilip } 150227569Sphilip 151227569Sphilip if (vmaskp != NULL) 152227569Sphilip *vmaskp = vmask; 153227569Sphilip} 154227569Sphilip 155227569Sphilip __checkReturn int 156227569Sphilipsiena_mon_ev( 157227569Sphilip __in efx_nic_t *enp, 158227569Sphilip __in efx_qword_t *eqp, 159227569Sphilip __out efx_mon_stat_t *idp, 160227569Sphilip __out efx_mon_stat_value_t *valuep) 161227569Sphilip{ 162227569Sphilip efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); 163227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 164227569Sphilip uint16_t ev_monitor; 165227569Sphilip uint16_t ev_state; 166227569Sphilip uint16_t ev_value; 167227569Sphilip uint16_t *sensor_map; 168227569Sphilip efx_mon_stat_t id; 169227569Sphilip int rc; 170227569Sphilip 171227569Sphilip sensor_map = (emip->emi_port == 1) 172227569Sphilip ? __siena_mon_port0_map 173227569Sphilip : __siena_mon_port1_map; 174227569Sphilip 175227569Sphilip ev_monitor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR); 176227569Sphilip ev_state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE); 177227569Sphilip ev_value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE); 178227569Sphilip 179227569Sphilip /* Hardware must support this statistic */ 180227569Sphilip EFSYS_ASSERT((1 << ev_monitor) & encp->enc_siena_mon_stat_mask); 181227569Sphilip 182227569Sphilip /* But we don't have to understand it */ 183227569Sphilip if (ev_monitor >= EFX_ARRAY_SIZE(__siena_mon_port0_map)) { 184227569Sphilip rc = ENOTSUP; 185227569Sphilip goto fail1; 186227569Sphilip } 187227569Sphilip 188227569Sphilip id = sensor_map[ev_monitor]; 189227569Sphilip if (id == SIENA_MON_WRONG_PORT) 190227569Sphilip return (ENODEV); 191227569Sphilip EFSYS_ASSERT(id < EFX_MON_NSTATS); 192227569Sphilip 193227569Sphilip *idp = id; 194227569Sphilip valuep->emsv_value = ev_value; 195227569Sphilip valuep->emsv_state = ev_state; 196227569Sphilip 197227569Sphilip return (0); 198227569Sphilip 199227569Sphilipfail1: 200227569Sphilip EFSYS_PROBE1(fail1, int, rc); 201227569Sphilip 202227569Sphilip return (rc); 203227569Sphilip} 204227569Sphilip 205227569Sphilip __checkReturn int 206227569Sphilipsiena_mon_stats_update( 207227569Sphilip __in efx_nic_t *enp, 208227569Sphilip __in efsys_mem_t *esmp, 209227569Sphilip __out_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values) 210227569Sphilip{ 211227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 212227569Sphilip uint32_t dmask = encp->enc_siena_mon_stat_mask; 213227569Sphilip uint32_t vmask; 214227569Sphilip uint8_t payload[MC_CMD_READ_SENSORS_IN_LEN]; 215227569Sphilip efx_mcdi_req_t req; 216227569Sphilip int rc; 217227569Sphilip 218227569Sphilip EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA); 219227569Sphilip 220227569Sphilip req.emr_cmd = MC_CMD_READ_SENSORS; 221227569Sphilip req.emr_in_buf = payload; 222227569Sphilip req.emr_in_length = sizeof (payload); 223227569Sphilip EFX_STATIC_ASSERT(MC_CMD_READ_SENSORS_OUT_LEN == 0); 224227569Sphilip req.emr_out_buf = NULL; 225227569Sphilip req.emr_out_length = 0; 226227569Sphilip 227227569Sphilip MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_LO, 228227569Sphilip EFSYS_MEM_ADDR(esmp) & 0xffffffff); 229227569Sphilip MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_HI, 230227569Sphilip EFSYS_MEM_ADDR(esmp) >> 32); 231227569Sphilip 232227569Sphilip efx_mcdi_execute(enp, &req); 233227569Sphilip 234227569Sphilip if (req.emr_rc != 0) { 235227569Sphilip rc = req.emr_rc; 236227569Sphilip goto fail1; 237227569Sphilip } 238227569Sphilip 239227569Sphilip siena_mon_decode_stats(enp, dmask, esmp, &vmask, values); 240227569Sphilip EFSYS_ASSERT(vmask == encp->enc_mon_stat_mask); 241227569Sphilip 242227569Sphilip return (0); 243227569Sphilip 244227569Sphilipfail1: 245227569Sphilip EFSYS_PROBE1(fail1, int, rc); 246227569Sphilip 247227569Sphilip return (rc); 248227569Sphilip} 249227569Sphilip 250227569Sphilip#endif /* EFSYS_OPT_MON_STATS */ 251227569Sphilip 252227569Sphilip#endif /* EFSYS_OPT_MON_SIENA */ 253