1283514Sarybchik/*- 2301388Sarybchik * Copyright (c) 2009-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7283514Sarybchik * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29283514Sarybchik */ 30283514Sarybchik 31283514Sarybchik#include <sys/cdefs.h> 32283514Sarybchik__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/mcdi_mon.c 342516 2018-12-26 10:25:01Z arybchik $"); 33283514Sarybchik 34283514Sarybchik#include "efx.h" 35283514Sarybchik#include "efx_impl.h" 36342513Sarybchik#include "mcdi_mon.h" 37283514Sarybchik 38283514Sarybchik#if EFSYS_OPT_MON_MCDI 39283514Sarybchik 40283514Sarybchik#if EFSYS_OPT_MON_STATS 41283514Sarybchik 42311061Sarybchik#define MCDI_MON_NEXT_PAGE ((uint16_t)0xfffe) 43311061Sarybchik#define MCDI_MON_INVALID_SENSOR ((uint16_t)0xfffd) 44283514Sarybchik#define MCDI_MON_PAGE_SIZE 0x20 45283514Sarybchik 46283514Sarybchik/* Bitmasks of valid port(s) for each sensor */ 47283514Sarybchik#define MCDI_MON_PORT_NONE (0x00) 48283514Sarybchik#define MCDI_MON_PORT_P1 (0x01) 49283514Sarybchik#define MCDI_MON_PORT_P2 (0x02) 50283514Sarybchik#define MCDI_MON_PORT_P3 (0x04) 51283514Sarybchik#define MCDI_MON_PORT_P4 (0x08) 52283514Sarybchik#define MCDI_MON_PORT_Px (0xFFFF) 53283514Sarybchik 54311082Sarybchik/* Get port mask from one-based MCDI port number */ 55311082Sarybchik#define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1)) 56311082Sarybchik 57283514Sarybchik/* Entry for MCDI sensor in sensor map */ 58283514Sarybchik#define STAT(portmask, stat) \ 59283514Sarybchik { (MCDI_MON_PORT_##portmask), (EFX_MON_STAT_##stat) } 60283514Sarybchik 61283514Sarybchik/* Entry for sensor next page flag in sensor map */ 62283514Sarybchik#define STAT_NEXT_PAGE() \ 63283514Sarybchik { MCDI_MON_PORT_NONE, MCDI_MON_NEXT_PAGE } 64283514Sarybchik 65283514Sarybchik/* Placeholder for gaps in the array */ 66283514Sarybchik#define STAT_NO_SENSOR() \ 67283514Sarybchik { MCDI_MON_PORT_NONE, MCDI_MON_INVALID_SENSOR } 68283514Sarybchik 69283514Sarybchik/* Map from MC sensors to monitor statistics */ 70283514Sarybchikstatic const struct mcdi_sensor_map_s { 71283514Sarybchik uint16_t msm_port_mask; 72283514Sarybchik uint16_t msm_stat; 73283514Sarybchik} mcdi_sensor_map[] = { 74283514Sarybchik /* Sensor page 0 MC_CMD_SENSOR_xxx */ 75283514Sarybchik STAT(Px, INT_TEMP), /* 0x00 CONTROLLER_TEMP */ 76283514Sarybchik STAT(Px, EXT_TEMP), /* 0x01 PHY_COMMON_TEMP */ 77283514Sarybchik STAT(Px, INT_COOLING), /* 0x02 CONTROLLER_COOLING */ 78283514Sarybchik STAT(P1, EXT_TEMP), /* 0x03 PHY0_TEMP */ 79283514Sarybchik STAT(P1, EXT_COOLING), /* 0x04 PHY0_COOLING */ 80283514Sarybchik STAT(P2, EXT_TEMP), /* 0x05 PHY1_TEMP */ 81283514Sarybchik STAT(P2, EXT_COOLING), /* 0x06 PHY1_COOLING */ 82283514Sarybchik STAT(Px, 1V), /* 0x07 IN_1V0 */ 83283514Sarybchik STAT(Px, 1_2V), /* 0x08 IN_1V2 */ 84283514Sarybchik STAT(Px, 1_8V), /* 0x09 IN_1V8 */ 85283514Sarybchik STAT(Px, 2_5V), /* 0x0a IN_2V5 */ 86283514Sarybchik STAT(Px, 3_3V), /* 0x0b IN_3V3 */ 87283514Sarybchik STAT(Px, 12V), /* 0x0c IN_12V0 */ 88283514Sarybchik STAT(Px, 1_2VA), /* 0x0d IN_1V2A */ 89283514Sarybchik STAT(Px, VREF), /* 0x0e IN_VREF */ 90283514Sarybchik STAT(Px, VAOE), /* 0x0f OUT_VAOE */ 91283514Sarybchik STAT(Px, AOE_TEMP), /* 0x10 AOE_TEMP */ 92283514Sarybchik STAT(Px, PSU_AOE_TEMP), /* 0x11 PSU_AOE_TEMP */ 93283514Sarybchik STAT(Px, PSU_TEMP), /* 0x12 PSU_TEMP */ 94283514Sarybchik STAT(Px, FAN0), /* 0x13 FAN_0 */ 95283514Sarybchik STAT(Px, FAN1), /* 0x14 FAN_1 */ 96283514Sarybchik STAT(Px, FAN2), /* 0x15 FAN_2 */ 97283514Sarybchik STAT(Px, FAN3), /* 0x16 FAN_3 */ 98283514Sarybchik STAT(Px, FAN4), /* 0x17 FAN_4 */ 99283514Sarybchik STAT(Px, VAOE_IN), /* 0x18 IN_VAOE */ 100283514Sarybchik STAT(Px, IAOE), /* 0x19 OUT_IAOE */ 101283514Sarybchik STAT(Px, IAOE_IN), /* 0x1a IN_IAOE */ 102283514Sarybchik STAT(Px, NIC_POWER), /* 0x1b NIC_POWER */ 103283514Sarybchik STAT(Px, 0_9V), /* 0x1c IN_0V9 */ 104283514Sarybchik STAT(Px, I0_9V), /* 0x1d IN_I0V9 */ 105283514Sarybchik STAT(Px, I1_2V), /* 0x1e IN_I1V2 */ 106283514Sarybchik STAT_NEXT_PAGE(), /* 0x1f Next page flag (not a sensor) */ 107283514Sarybchik 108283514Sarybchik /* Sensor page 1 MC_CMD_SENSOR_xxx */ 109283514Sarybchik STAT(Px, 0_9V_ADC), /* 0x20 IN_0V9_ADC */ 110283514Sarybchik STAT(Px, INT_TEMP2), /* 0x21 CONTROLLER_2_TEMP */ 111283514Sarybchik STAT(Px, VREG_TEMP), /* 0x22 VREG_INTERNAL_TEMP */ 112283514Sarybchik STAT(Px, VREG_0_9V_TEMP), /* 0x23 VREG_0V9_TEMP */ 113283514Sarybchik STAT(Px, VREG_1_2V_TEMP), /* 0x24 VREG_1V2_TEMP */ 114283514Sarybchik STAT(Px, INT_VPTAT), /* 0x25 CTRLR. VPTAT */ 115283514Sarybchik STAT(Px, INT_ADC_TEMP), /* 0x26 CTRLR. INTERNAL_TEMP */ 116283514Sarybchik STAT(Px, EXT_VPTAT), /* 0x27 CTRLR. VPTAT_EXTADC */ 117283514Sarybchik STAT(Px, EXT_ADC_TEMP), /* 0x28 CTRLR. INTERNAL_TEMP_EXTADC */ 118283514Sarybchik STAT(Px, AMBIENT_TEMP), /* 0x29 AMBIENT_TEMP */ 119283514Sarybchik STAT(Px, AIRFLOW), /* 0x2a AIRFLOW */ 120283514Sarybchik STAT(Px, VDD08D_VSS08D_CSR), /* 0x2b VDD08D_VSS08D_CSR */ 121283514Sarybchik STAT(Px, VDD08D_VSS08D_CSR_EXTADC), /* 0x2c VDD08D_VSS08D_CSR_EXTADC */ 122283514Sarybchik STAT(Px, HOTPOINT_TEMP), /* 0x2d HOTPOINT_TEMP */ 123283514Sarybchik STAT(P1, PHY_POWER_SWITCH_PORT0), /* 0x2e PHY_POWER_SWITCH_PORT0 */ 124283514Sarybchik STAT(P2, PHY_POWER_SWITCH_PORT1), /* 0x2f PHY_POWER_SWITCH_PORT1 */ 125283514Sarybchik STAT(Px, MUM_VCC), /* 0x30 MUM_VCC */ 126283514Sarybchik STAT(Px, 0V9_A), /* 0x31 0V9_A */ 127283514Sarybchik STAT(Px, I0V9_A), /* 0x32 I0V9_A */ 128283514Sarybchik STAT(Px, 0V9_A_TEMP), /* 0x33 0V9_A_TEMP */ 129283514Sarybchik STAT(Px, 0V9_B), /* 0x34 0V9_B */ 130283514Sarybchik STAT(Px, I0V9_B), /* 0x35 I0V9_B */ 131283514Sarybchik STAT(Px, 0V9_B_TEMP), /* 0x36 0V9_B_TEMP */ 132283514Sarybchik STAT(Px, CCOM_AVREG_1V2_SUPPLY), /* 0x37 CCOM_AVREG_1V2_SUPPLY */ 133283514Sarybchik STAT(Px, CCOM_AVREG_1V2_SUPPLY_EXT_ADC), 134283514Sarybchik /* 0x38 CCOM_AVREG_1V2_SUPPLY_EXT_ADC */ 135283514Sarybchik STAT(Px, CCOM_AVREG_1V8_SUPPLY), /* 0x39 CCOM_AVREG_1V8_SUPPLY */ 136283514Sarybchik STAT(Px, CCOM_AVREG_1V8_SUPPLY_EXT_ADC), 137283514Sarybchik /* 0x3a CCOM_AVREG_1V8_SUPPLY_EXT_ADC */ 138283514Sarybchik STAT_NO_SENSOR(), /* 0x3b (no sensor) */ 139283514Sarybchik STAT_NO_SENSOR(), /* 0x3c (no sensor) */ 140283514Sarybchik STAT_NO_SENSOR(), /* 0x3d (no sensor) */ 141283514Sarybchik STAT_NO_SENSOR(), /* 0x3e (no sensor) */ 142283514Sarybchik STAT_NEXT_PAGE(), /* 0x3f Next page flag (not a sensor) */ 143283514Sarybchik 144283514Sarybchik /* Sensor page 2 MC_CMD_SENSOR_xxx */ 145283514Sarybchik STAT(Px, CONTROLLER_MASTER_VPTAT), /* 0x40 MASTER_VPTAT */ 146283514Sarybchik STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP), /* 0x41 MASTER_INT_TEMP */ 147283514Sarybchik STAT(Px, CONTROLLER_MASTER_VPTAT_EXT_ADC), /* 0x42 MAST_VPTAT_EXT_ADC */ 148283514Sarybchik STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP_EXT_ADC), 149283514Sarybchik /* 0x43 MASTER_INTERNAL_TEMP_EXT_ADC */ 150283514Sarybchik STAT(Px, CONTROLLER_SLAVE_VPTAT), /* 0x44 SLAVE_VPTAT */ 151283514Sarybchik STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP), /* 0x45 SLAVE_INTERNAL_TEMP */ 152283514Sarybchik STAT(Px, CONTROLLER_SLAVE_VPTAT_EXT_ADC), /* 0x46 SLAVE_VPTAT_EXT_ADC */ 153283514Sarybchik STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP_EXT_ADC), 154283514Sarybchik /* 0x47 SLAVE_INTERNAL_TEMP_EXT_ADC */ 155293994Sarybchik STAT_NO_SENSOR(), /* 0x48 (no sensor) */ 156293994Sarybchik STAT(Px, SODIMM_VOUT), /* 0x49 SODIMM_VOUT */ 157293994Sarybchik STAT(Px, SODIMM_0_TEMP), /* 0x4a SODIMM_0_TEMP */ 158293994Sarybchik STAT(Px, SODIMM_1_TEMP), /* 0x4b SODIMM_1_TEMP */ 159293994Sarybchik STAT(Px, PHY0_VCC), /* 0x4c PHY0_VCC */ 160293994Sarybchik STAT(Px, PHY1_VCC), /* 0x4d PHY1_VCC */ 161293994Sarybchik STAT(Px, CONTROLLER_TDIODE_TEMP), /* 0x4e CONTROLLER_TDIODE_TEMP */ 162311056Sarybchik STAT(Px, BOARD_FRONT_TEMP), /* 0x4f BOARD_FRONT_TEMP */ 163311056Sarybchik STAT(Px, BOARD_BACK_TEMP), /* 0x50 BOARD_BACK_TEMP */ 164283514Sarybchik}; 165283514Sarybchik 166283514Sarybchik#define MCDI_STATIC_SENSOR_ASSERT(_field) \ 167283514Sarybchik EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \ 168283514Sarybchik == EFX_MON_STAT_STATE_ ## _field) 169283514Sarybchik 170283514Sarybchikstatic void 171283514Sarybchikmcdi_mon_decode_stats( 172283514Sarybchik __in efx_nic_t *enp, 173311082Sarybchik __in_bcount(sensor_mask_size) uint32_t *sensor_mask, 174283514Sarybchik __in size_t sensor_mask_size, 175283514Sarybchik __in_opt efsys_mem_t *esmp, 176311082Sarybchik __out_bcount_opt(sensor_mask_size) uint32_t *stat_maskp, 177293921Sarybchik __inout_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *stat) 178283514Sarybchik{ 179283514Sarybchik efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 180283514Sarybchik uint16_t port_mask; 181283514Sarybchik uint16_t sensor; 182283514Sarybchik size_t sensor_max; 183283514Sarybchik uint32_t stat_mask[(EFX_ARRAY_SIZE(mcdi_sensor_map) + 31) / 32]; 184283514Sarybchik uint32_t idx = 0; 185283514Sarybchik uint32_t page = 0; 186283514Sarybchik 187283514Sarybchik /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */ 188283514Sarybchik MCDI_STATIC_SENSOR_ASSERT(OK); 189283514Sarybchik MCDI_STATIC_SENSOR_ASSERT(WARNING); 190283514Sarybchik MCDI_STATIC_SENSOR_ASSERT(FATAL); 191283514Sarybchik MCDI_STATIC_SENSOR_ASSERT(BROKEN); 192283514Sarybchik MCDI_STATIC_SENSOR_ASSERT(NO_READING); 193283514Sarybchik 194283514Sarybchik EFX_STATIC_ASSERT(sizeof (stat_mask[0]) * 8 == 195283514Sarybchik EFX_MON_MASK_ELEMENT_SIZE); 196283514Sarybchik sensor_max = 197283514Sarybchik MIN((8 * sensor_mask_size), EFX_ARRAY_SIZE(mcdi_sensor_map)); 198283514Sarybchik 199311082Sarybchik EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */ 200311082Sarybchik port_mask = MCDI_MON_PORT_MASK(emip); 201283514Sarybchik 202283514Sarybchik memset(stat_mask, 0, sizeof (stat_mask)); 203283514Sarybchik 204283514Sarybchik /* 205283514Sarybchik * The MCDI sensor readings in the DMA buffer are a packed array of 206283514Sarybchik * MC_CMD_SENSOR_VALUE_ENTRY structures, which only includes entries for 207283514Sarybchik * supported sensors (bit set in sensor_mask). The sensor_mask and 208283514Sarybchik * sensor readings do not include entries for the per-page NEXT_PAGE 209283514Sarybchik * flag. 210283514Sarybchik * 211283514Sarybchik * sensor_mask may legitimately contain MCDI sensors that the driver 212283514Sarybchik * does not understand. 213283514Sarybchik */ 214283514Sarybchik for (sensor = 0; sensor < sensor_max; ++sensor) { 215283514Sarybchik efx_mon_stat_t id = mcdi_sensor_map[sensor].msm_stat; 216283514Sarybchik 217283514Sarybchik if ((sensor % MCDI_MON_PAGE_SIZE) == MC_CMD_SENSOR_PAGE0_NEXT) { 218283514Sarybchik EFSYS_ASSERT3U(id, ==, MCDI_MON_NEXT_PAGE); 219283514Sarybchik page++; 220283514Sarybchik continue; 221283514Sarybchik } 222283514Sarybchik if (~(sensor_mask[page]) & (1U << sensor)) 223283514Sarybchik continue; 224283514Sarybchik idx++; 225283514Sarybchik 226283514Sarybchik if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0) 227283514Sarybchik continue; 228283514Sarybchik EFSYS_ASSERT(id < EFX_MON_NSTATS); 229283514Sarybchik 230283514Sarybchik /* 231283514Sarybchik * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic 232283514Sarybchik * identifiers from efx_mon_stat_t (without NEXT_PAGE bits). 233283514Sarybchik * 234283514Sarybchik * If there is an entry in the MCDI sensor to monitor statistic 235283514Sarybchik * map then the sensor reading is used for the value of the 236283514Sarybchik * monitor statistic. 237283514Sarybchik */ 238283514Sarybchik stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |= 239283514Sarybchik (1U << (id % EFX_MON_MASK_ELEMENT_SIZE)); 240283514Sarybchik 241283514Sarybchik if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 242283514Sarybchik efx_dword_t dword; 243283514Sarybchik 244283514Sarybchik /* Get MCDI sensor reading from DMA buffer */ 245283514Sarybchik EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword); 246283514Sarybchik 247283514Sarybchik /* Update EFX monitor stat from MCDI sensor reading */ 248283514Sarybchik stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword, 249283514Sarybchik MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); 250283514Sarybchik 251283514Sarybchik stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword, 252283514Sarybchik MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 253283514Sarybchik } 254283514Sarybchik } 255283514Sarybchik 256283514Sarybchik if (stat_maskp != NULL) { 257283514Sarybchik memcpy(stat_maskp, stat_mask, sizeof (stat_mask)); 258283514Sarybchik } 259283514Sarybchik} 260283514Sarybchik 261293927Sarybchik __checkReturn efx_rc_t 262283514Sarybchikmcdi_mon_ev( 263283514Sarybchik __in efx_nic_t *enp, 264283514Sarybchik __in efx_qword_t *eqp, 265283514Sarybchik __out efx_mon_stat_t *idp, 266283514Sarybchik __out efx_mon_stat_value_t *valuep) 267283514Sarybchik{ 268283514Sarybchik efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 269283514Sarybchik uint16_t port_mask; 270283514Sarybchik uint16_t sensor; 271283514Sarybchik uint16_t state; 272283514Sarybchik uint16_t value; 273283514Sarybchik efx_mon_stat_t id; 274293927Sarybchik efx_rc_t rc; 275283514Sarybchik 276311082Sarybchik EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */ 277311082Sarybchik port_mask = MCDI_MON_PORT_MASK(emip); 278283514Sarybchik 279283514Sarybchik sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR); 280283514Sarybchik state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE); 281283514Sarybchik value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE); 282283514Sarybchik 283283514Sarybchik /* Hardware must support this MCDI sensor */ 284342502Sarybchik EFSYS_ASSERT3U(sensor, <, 285342502Sarybchik (8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size)); 286283514Sarybchik EFSYS_ASSERT((sensor % MCDI_MON_PAGE_SIZE) != MC_CMD_SENSOR_PAGE0_NEXT); 287342502Sarybchik EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL); 288342502Sarybchik EFSYS_ASSERT( 289342502Sarybchik (enp->en_nic_cfg.enc_mcdi_sensor_maskp[sensor/MCDI_MON_PAGE_SIZE] & 290342502Sarybchik (1U << (sensor % MCDI_MON_PAGE_SIZE))) != 0); 291283514Sarybchik 292283514Sarybchik /* But we don't have to understand it */ 293283514Sarybchik if (sensor >= EFX_ARRAY_SIZE(mcdi_sensor_map)) { 294283514Sarybchik rc = ENOTSUP; 295283514Sarybchik goto fail1; 296283514Sarybchik } 297283514Sarybchik id = mcdi_sensor_map[sensor].msm_stat; 298283514Sarybchik if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0) 299283514Sarybchik return (ENODEV); 300283514Sarybchik EFSYS_ASSERT(id < EFX_MON_NSTATS); 301283514Sarybchik 302283514Sarybchik *idp = id; 303283514Sarybchik valuep->emsv_value = value; 304283514Sarybchik valuep->emsv_state = state; 305283514Sarybchik 306283514Sarybchik return (0); 307283514Sarybchik 308283514Sarybchikfail1: 309293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 310283514Sarybchik 311283514Sarybchik return (rc); 312283514Sarybchik} 313283514Sarybchik 314283514Sarybchik 315293927Sarybchikstatic __checkReturn efx_rc_t 316283514Sarybchikefx_mcdi_read_sensors( 317283514Sarybchik __in efx_nic_t *enp, 318283514Sarybchik __in efsys_mem_t *esmp, 319283514Sarybchik __in uint32_t size) 320283514Sarybchik{ 321283514Sarybchik efx_mcdi_req_t req; 322342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN, 323342516Sarybchik MC_CMD_READ_SENSORS_EXT_OUT_LEN); 324283514Sarybchik uint32_t addr_lo, addr_hi; 325342514Sarybchik efx_rc_t rc; 326283514Sarybchik 327342514Sarybchik if (EFSYS_MEM_SIZE(esmp) < size) { 328342514Sarybchik rc = EINVAL; 329342514Sarybchik goto fail1; 330342514Sarybchik } 331342514Sarybchik 332283514Sarybchik req.emr_cmd = MC_CMD_READ_SENSORS; 333283514Sarybchik req.emr_in_buf = payload; 334283514Sarybchik req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN; 335283514Sarybchik req.emr_out_buf = payload; 336283514Sarybchik req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN; 337283514Sarybchik 338283514Sarybchik addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff); 339283514Sarybchik addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32); 340283514Sarybchik 341283514Sarybchik MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo); 342283514Sarybchik MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi); 343283514Sarybchik MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size); 344283514Sarybchik 345283514Sarybchik efx_mcdi_execute(enp, &req); 346283514Sarybchik 347283514Sarybchik return (req.emr_rc); 348342514Sarybchik 349342514Sarybchikfail1: 350342514Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 351342514Sarybchik 352342514Sarybchik return (rc); 353283514Sarybchik} 354283514Sarybchik 355293927Sarybchikstatic __checkReturn efx_rc_t 356283514Sarybchikefx_mcdi_sensor_info_npages( 357283514Sarybchik __in efx_nic_t *enp, 358283514Sarybchik __out uint32_t *npagesp) 359283514Sarybchik{ 360283514Sarybchik efx_mcdi_req_t req; 361342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 362342516Sarybchik MC_CMD_SENSOR_INFO_OUT_LENMAX); 363283514Sarybchik int page; 364293927Sarybchik efx_rc_t rc; 365283514Sarybchik 366283514Sarybchik EFSYS_ASSERT(npagesp != NULL); 367283514Sarybchik 368283514Sarybchik page = 0; 369283514Sarybchik do { 370283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 371283514Sarybchik req.emr_cmd = MC_CMD_SENSOR_INFO; 372283514Sarybchik req.emr_in_buf = payload; 373283514Sarybchik req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 374283514Sarybchik req.emr_out_buf = payload; 375283514Sarybchik req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 376283514Sarybchik 377283514Sarybchik MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++); 378283514Sarybchik 379283514Sarybchik efx_mcdi_execute_quiet(enp, &req); 380283514Sarybchik 381283514Sarybchik if (req.emr_rc != 0) { 382283514Sarybchik rc = req.emr_rc; 383283514Sarybchik goto fail1; 384283514Sarybchik } 385283514Sarybchik } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) & 386301398Sarybchik (1U << MC_CMD_SENSOR_PAGE0_NEXT)); 387283514Sarybchik 388283514Sarybchik *npagesp = page; 389283514Sarybchik 390283514Sarybchik return (0); 391283514Sarybchik 392283514Sarybchikfail1: 393293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 394283514Sarybchik 395283514Sarybchik return (rc); 396283514Sarybchik} 397283514Sarybchik 398293927Sarybchikstatic __checkReturn efx_rc_t 399283514Sarybchikefx_mcdi_sensor_info( 400283514Sarybchik __in efx_nic_t *enp, 401283514Sarybchik __out_ecount(npages) uint32_t *sensor_maskp, 402283514Sarybchik __in size_t npages) 403283514Sarybchik{ 404283514Sarybchik efx_mcdi_req_t req; 405342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN, 406342516Sarybchik MC_CMD_SENSOR_INFO_OUT_LENMAX); 407283514Sarybchik uint32_t page; 408293927Sarybchik efx_rc_t rc; 409283514Sarybchik 410283514Sarybchik EFSYS_ASSERT(sensor_maskp != NULL); 411283514Sarybchik 412342506Sarybchik if (npages < 1) { 413342506Sarybchik rc = EINVAL; 414342506Sarybchik goto fail1; 415342506Sarybchik } 416342506Sarybchik 417283514Sarybchik for (page = 0; page < npages; page++) { 418283514Sarybchik uint32_t mask; 419283514Sarybchik 420283514Sarybchik (void) memset(payload, 0, sizeof (payload)); 421283514Sarybchik req.emr_cmd = MC_CMD_SENSOR_INFO; 422283514Sarybchik req.emr_in_buf = payload; 423283514Sarybchik req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN; 424283514Sarybchik req.emr_out_buf = payload; 425283514Sarybchik req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX; 426283514Sarybchik 427283514Sarybchik MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page); 428283514Sarybchik 429283514Sarybchik efx_mcdi_execute(enp, &req); 430283514Sarybchik 431283514Sarybchik if (req.emr_rc != 0) { 432283514Sarybchik rc = req.emr_rc; 433342506Sarybchik goto fail2; 434283514Sarybchik } 435283514Sarybchik 436283514Sarybchik mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 437283514Sarybchik 438283514Sarybchik if ((page != (npages - 1)) && 439283514Sarybchik ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) { 440283514Sarybchik rc = EINVAL; 441342506Sarybchik goto fail3; 442283514Sarybchik } 443283514Sarybchik sensor_maskp[page] = mask; 444283514Sarybchik } 445283514Sarybchik 446283514Sarybchik if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) { 447283514Sarybchik rc = EINVAL; 448342506Sarybchik goto fail4; 449283514Sarybchik } 450283514Sarybchik 451283514Sarybchik return (0); 452283514Sarybchik 453342506Sarybchikfail4: 454342506Sarybchik EFSYS_PROBE(fail4); 455283514Sarybchikfail3: 456283514Sarybchik EFSYS_PROBE(fail3); 457283514Sarybchikfail2: 458283514Sarybchik EFSYS_PROBE(fail2); 459283514Sarybchikfail1: 460293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 461283514Sarybchik 462283514Sarybchik return (rc); 463283514Sarybchik} 464283514Sarybchik 465293927Sarybchik __checkReturn efx_rc_t 466283514Sarybchikmcdi_mon_stats_update( 467283514Sarybchik __in efx_nic_t *enp, 468283514Sarybchik __in efsys_mem_t *esmp, 469293921Sarybchik __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values) 470283514Sarybchik{ 471283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 472283514Sarybchik uint32_t size = encp->enc_mon_stat_dma_buf_size; 473293927Sarybchik efx_rc_t rc; 474283514Sarybchik 475283514Sarybchik if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0) 476283514Sarybchik goto fail1; 477283514Sarybchik 478283514Sarybchik EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size); 479283514Sarybchik 480283514Sarybchik mcdi_mon_decode_stats(enp, 481283514Sarybchik encp->enc_mcdi_sensor_maskp, 482283514Sarybchik encp->enc_mcdi_sensor_mask_size, 483283514Sarybchik esmp, NULL, values); 484283514Sarybchik 485283514Sarybchik return (0); 486283514Sarybchik 487283514Sarybchikfail1: 488293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 489283514Sarybchik 490283514Sarybchik return (rc); 491283514Sarybchik} 492283514Sarybchik 493293927Sarybchik __checkReturn efx_rc_t 494283514Sarybchikmcdi_mon_cfg_build( 495283514Sarybchik __in efx_nic_t *enp) 496283514Sarybchik{ 497283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 498283514Sarybchik uint32_t npages; 499293927Sarybchik efx_rc_t rc; 500283514Sarybchik 501283514Sarybchik switch (enp->en_family) { 502283514Sarybchik#if EFSYS_OPT_SIENA 503283514Sarybchik case EFX_FAMILY_SIENA: 504283514Sarybchik encp->enc_mon_type = EFX_MON_SFC90X0; 505283514Sarybchik break; 506283514Sarybchik#endif 507283514Sarybchik#if EFSYS_OPT_HUNTINGTON 508283514Sarybchik case EFX_FAMILY_HUNTINGTON: 509283514Sarybchik encp->enc_mon_type = EFX_MON_SFC91X0; 510283514Sarybchik break; 511283514Sarybchik#endif 512293978Sarybchik#if EFSYS_OPT_MEDFORD 513293978Sarybchik case EFX_FAMILY_MEDFORD: 514293978Sarybchik encp->enc_mon_type = EFX_MON_SFC92X0; 515293978Sarybchik break; 516293978Sarybchik#endif 517283514Sarybchik default: 518283514Sarybchik rc = EINVAL; 519283514Sarybchik goto fail1; 520283514Sarybchik } 521283514Sarybchik 522283514Sarybchik /* Get mc sensor mask size */ 523283514Sarybchik npages = 0; 524283514Sarybchik if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0) 525283514Sarybchik goto fail2; 526283514Sarybchik 527283514Sarybchik encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE; 528283514Sarybchik encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t); 529283514Sarybchik 530283514Sarybchik /* Allocate mc sensor mask */ 531283514Sarybchik EFSYS_KMEM_ALLOC(enp->en_esip, 532283514Sarybchik encp->enc_mcdi_sensor_mask_size, 533283514Sarybchik encp->enc_mcdi_sensor_maskp); 534283514Sarybchik 535283514Sarybchik if (encp->enc_mcdi_sensor_maskp == NULL) { 536283514Sarybchik rc = ENOMEM; 537283514Sarybchik goto fail3; 538283514Sarybchik } 539283514Sarybchik 540283514Sarybchik /* Read mc sensor mask */ 541283514Sarybchik if ((rc = efx_mcdi_sensor_info(enp, 542283514Sarybchik encp->enc_mcdi_sensor_maskp, 543283514Sarybchik npages)) != 0) 544283514Sarybchik goto fail4; 545283514Sarybchik 546283514Sarybchik /* Build monitor statistics mask */ 547283514Sarybchik mcdi_mon_decode_stats(enp, 548283514Sarybchik encp->enc_mcdi_sensor_maskp, 549283514Sarybchik encp->enc_mcdi_sensor_mask_size, 550283514Sarybchik NULL, encp->enc_mon_stat_mask, NULL); 551283514Sarybchik 552283514Sarybchik return (0); 553283514Sarybchik 554283514Sarybchikfail4: 555283514Sarybchik EFSYS_PROBE(fail4); 556283514Sarybchik EFSYS_KMEM_FREE(enp->en_esip, 557283514Sarybchik encp->enc_mcdi_sensor_mask_size, 558283514Sarybchik encp->enc_mcdi_sensor_maskp); 559283514Sarybchik 560283514Sarybchikfail3: 561283514Sarybchik EFSYS_PROBE(fail3); 562283514Sarybchik 563283514Sarybchikfail2: 564283514Sarybchik EFSYS_PROBE(fail2); 565283514Sarybchik 566283514Sarybchikfail1: 567293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 568283514Sarybchik 569283514Sarybchik return (rc); 570283514Sarybchik} 571283514Sarybchik 572283514Sarybchik void 573283514Sarybchikmcdi_mon_cfg_free( 574283514Sarybchik __in efx_nic_t *enp) 575283514Sarybchik{ 576283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 577283514Sarybchik 578283514Sarybchik if (encp->enc_mcdi_sensor_maskp != NULL) { 579283514Sarybchik EFSYS_KMEM_FREE(enp->en_esip, 580283514Sarybchik encp->enc_mcdi_sensor_mask_size, 581283514Sarybchik encp->enc_mcdi_sensor_maskp); 582283514Sarybchik } 583283514Sarybchik} 584283514Sarybchik 585283514Sarybchik 586283514Sarybchik#endif /* EFSYS_OPT_MON_STATS */ 587283514Sarybchik 588283514Sarybchik#endif /* EFSYS_OPT_MON_MCDI */ 589