1 /*
   2  * Copyright (c) 2009-2015 Solarflare Communications Inc.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright notice,
   9  *    this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11  *    this list of conditions and the following disclaimer in the documentation
  12  *    and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  *
  26  * The views and conclusions contained in the software and documentation are
  27  * those of the authors and should not be interpreted as representing official
  28  * policies, either expressed or implied, of the FreeBSD Project.
  29  */
  30 
  31 #include "efx.h"
  32 #include "efx_impl.h"
  33 
  34 #if EFSYS_OPT_MON_MCDI
  35 
  36 #if EFSYS_OPT_MON_STATS
  37 
  38 #define MCDI_MON_NEXT_PAGE  (uint16_t)0xfffe
  39 #define MCDI_MON_INVALID_SENSOR (uint16_t)0xfffd
  40 #define MCDI_MON_PAGE_SIZE 0x20
  41 
  42 /* Bitmasks of valid port(s) for each sensor */
  43 #define MCDI_MON_PORT_NONE      (0x00)
  44 #define MCDI_MON_PORT_P1        (0x01)
  45 #define MCDI_MON_PORT_P2        (0x02)
  46 #define MCDI_MON_PORT_P3        (0x04)
  47 #define MCDI_MON_PORT_P4        (0x08)
  48 #define MCDI_MON_PORT_Px        (0xFFFF)
  49 
  50 /* Entry for MCDI sensor in sensor map */
  51 #define STAT(portmask, stat)    \
  52         { (MCDI_MON_PORT_##portmask), (EFX_MON_STAT_##stat) }
  53 
  54 /* Entry for sensor next page flag in sensor map */
  55 #define STAT_NEXT_PAGE()        \
  56         { MCDI_MON_PORT_NONE, MCDI_MON_NEXT_PAGE }
  57 
  58 /* Placeholder for gaps in the array */
  59 #define STAT_NO_SENSOR()        \
  60         { MCDI_MON_PORT_NONE, MCDI_MON_INVALID_SENSOR }
  61 
  62 /* Map from MC sensors to monitor statistics */
  63 static const struct mcdi_sensor_map_s {
  64         uint16_t        msm_port_mask;
  65         uint16_t        msm_stat;
  66 } mcdi_sensor_map[] = {
  67         /* Sensor page 0                MC_CMD_SENSOR_xxx */
  68         STAT(Px, INT_TEMP),             /* 0x00 CONTROLLER_TEMP */
  69         STAT(Px, EXT_TEMP),             /* 0x01 PHY_COMMON_TEMP */
  70         STAT(Px, INT_COOLING),          /* 0x02 CONTROLLER_COOLING */
  71         STAT(P1, EXT_TEMP),             /* 0x03 PHY0_TEMP */
  72         STAT(P1, EXT_COOLING),          /* 0x04 PHY0_COOLING */
  73         STAT(P2, EXT_TEMP),             /* 0x05 PHY1_TEMP */
  74         STAT(P2, EXT_COOLING),          /* 0x06 PHY1_COOLING */
  75         STAT(Px, 1V),                   /* 0x07 IN_1V0 */
  76         STAT(Px, 1_2V),                 /* 0x08 IN_1V2 */
  77         STAT(Px, 1_8V),                 /* 0x09 IN_1V8 */
  78         STAT(Px, 2_5V),                 /* 0x0a IN_2V5 */
  79         STAT(Px, 3_3V),                 /* 0x0b IN_3V3 */
  80         STAT(Px, 12V),                  /* 0x0c IN_12V0 */
  81         STAT(Px, 1_2VA),                /* 0x0d IN_1V2A */
  82         STAT(Px, VREF),                 /* 0x0e IN_VREF */
  83         STAT(Px, VAOE),                 /* 0x0f OUT_VAOE */
  84         STAT(Px, AOE_TEMP),             /* 0x10 AOE_TEMP */
  85         STAT(Px, PSU_AOE_TEMP),         /* 0x11 PSU_AOE_TEMP */
  86         STAT(Px, PSU_TEMP),             /* 0x12 PSU_TEMP */
  87         STAT(Px, FAN0),                 /* 0x13 FAN_0 */
  88         STAT(Px, FAN1),                 /* 0x14 FAN_1 */
  89         STAT(Px, FAN2),                 /* 0x15 FAN_2 */
  90         STAT(Px, FAN3),                 /* 0x16 FAN_3 */
  91         STAT(Px, FAN4),                 /* 0x17 FAN_4 */
  92         STAT(Px, VAOE_IN),              /* 0x18 IN_VAOE */
  93         STAT(Px, IAOE),                 /* 0x19 OUT_IAOE */
  94         STAT(Px, IAOE_IN),              /* 0x1a IN_IAOE */
  95         STAT(Px, NIC_POWER),            /* 0x1b NIC_POWER */
  96         STAT(Px, 0_9V),                 /* 0x1c IN_0V9 */
  97         STAT(Px, I0_9V),                /* 0x1d IN_I0V9 */
  98         STAT(Px, I1_2V),                /* 0x1e IN_I1V2 */
  99         STAT_NEXT_PAGE(),               /* 0x1f Next page flag (not a sensor) */
 100 
 101         /* Sensor page 1                MC_CMD_SENSOR_xxx */
 102         STAT(Px, 0_9V_ADC),             /* 0x20 IN_0V9_ADC */
 103         STAT(Px, INT_TEMP2),            /* 0x21 CONTROLLER_2_TEMP */
 104         STAT(Px, VREG_TEMP),            /* 0x22 VREG_INTERNAL_TEMP */
 105         STAT(Px, VREG_0_9V_TEMP),       /* 0x23 VREG_0V9_TEMP */
 106         STAT(Px, VREG_1_2V_TEMP),       /* 0x24 VREG_1V2_TEMP */
 107         STAT(Px, INT_VPTAT),            /* 0x25 CTRLR. VPTAT */
 108         STAT(Px, INT_ADC_TEMP),         /* 0x26 CTRLR. INTERNAL_TEMP */
 109         STAT(Px, EXT_VPTAT),            /* 0x27 CTRLR. VPTAT_EXTADC */
 110         STAT(Px, EXT_ADC_TEMP),         /* 0x28 CTRLR. INTERNAL_TEMP_EXTADC */
 111         STAT(Px, AMBIENT_TEMP),         /* 0x29 AMBIENT_TEMP */
 112         STAT(Px, AIRFLOW),              /* 0x2a AIRFLOW */
 113         STAT(Px, VDD08D_VSS08D_CSR),    /* 0x2b VDD08D_VSS08D_CSR */
 114         STAT(Px, VDD08D_VSS08D_CSR_EXTADC), /* 0x2c VDD08D_VSS08D_CSR_EXTADC */
 115         STAT(Px, HOTPOINT_TEMP),        /* 0x2d HOTPOINT_TEMP */
 116         STAT(P1, PHY_POWER_SWITCH_PORT0),   /* 0x2e PHY_POWER_SWITCH_PORT0 */
 117         STAT(P2, PHY_POWER_SWITCH_PORT1),   /* 0x2f PHY_POWER_SWITCH_PORT1 */
 118         STAT(Px, MUM_VCC),              /* 0x30 MUM_VCC */
 119         STAT(Px, 0V9_A),                /* 0x31 0V9_A */
 120         STAT(Px, I0V9_A),               /* 0x32 I0V9_A */
 121         STAT(Px, 0V9_A_TEMP),           /* 0x33 0V9_A_TEMP */
 122         STAT(Px, 0V9_B),                /* 0x34 0V9_B */
 123         STAT(Px, I0V9_B),               /* 0x35 I0V9_B */
 124         STAT(Px, 0V9_B_TEMP),           /* 0x36 0V9_B_TEMP */
 125         STAT(Px, CCOM_AVREG_1V2_SUPPLY),  /* 0x37 CCOM_AVREG_1V2_SUPPLY */
 126         STAT(Px, CCOM_AVREG_1V2_SUPPLY_EXT_ADC),
 127                                         /* 0x38 CCOM_AVREG_1V2_SUPPLY_EXT_ADC */
 128         STAT(Px, CCOM_AVREG_1V8_SUPPLY),  /* 0x39 CCOM_AVREG_1V8_SUPPLY */
 129         STAT(Px, CCOM_AVREG_1V8_SUPPLY_EXT_ADC),
 130                                         /* 0x3a CCOM_AVREG_1V8_SUPPLY_EXT_ADC */
 131         STAT_NO_SENSOR(),               /* 0x3b (no sensor) */
 132         STAT_NO_SENSOR(),               /* 0x3c (no sensor) */
 133         STAT_NO_SENSOR(),               /* 0x3d (no sensor) */
 134         STAT_NO_SENSOR(),               /* 0x3e (no sensor) */
 135         STAT_NEXT_PAGE(),               /* 0x3f Next page flag (not a sensor) */
 136 
 137         /* Sensor page 2                MC_CMD_SENSOR_xxx */
 138         STAT(Px, CONTROLLER_MASTER_VPTAT),         /* 0x40 MASTER_VPTAT */
 139         STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP), /* 0x41 MASTER_INT_TEMP */
 140         STAT(Px, CONTROLLER_MASTER_VPTAT_EXT_ADC), /* 0x42 MAST_VPTAT_EXT_ADC */
 141         STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP_EXT_ADC),
 142                                         /* 0x43 MASTER_INTERNAL_TEMP_EXT_ADC */
 143         STAT(Px, CONTROLLER_SLAVE_VPTAT),         /* 0x44 SLAVE_VPTAT */
 144         STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP), /* 0x45 SLAVE_INTERNAL_TEMP */
 145         STAT(Px, CONTROLLER_SLAVE_VPTAT_EXT_ADC), /* 0x46 SLAVE_VPTAT_EXT_ADC */
 146         STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP_EXT_ADC),
 147                                         /* 0x47 SLAVE_INTERNAL_TEMP_EXT_ADC */
 148         STAT_NO_SENSOR(),               /* 0x48 (no sensor) */
 149         STAT(Px, SODIMM_VOUT),          /* 0x49 SODIMM_VOUT */
 150         STAT(Px, SODIMM_0_TEMP),        /* 0x4a SODIMM_0_TEMP */
 151         STAT(Px, SODIMM_1_TEMP),        /* 0x4b SODIMM_1_TEMP */
 152         STAT(Px, PHY0_VCC),             /* 0x4c PHY0_VCC */
 153         STAT(Px, PHY1_VCC),             /* 0x4d PHY1_VCC */
 154         STAT(Px, CONTROLLER_TDIODE_TEMP), /* 0x4e CONTROLLER_TDIODE_TEMP */
 155         STAT(Px, BOARD_FRONT_TEMP),     /* 0x4f BOARD_FRONT_TEMP */
 156         STAT(Px, BOARD_BACK_TEMP),      /* 0x50 BOARD_BACK_TEMP */
 157 };
 158 
 159 #define MCDI_STATIC_SENSOR_ASSERT(_field)                               \
 160         EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field                \
 161                             == EFX_MON_STAT_STATE_ ## _field)
 162 
 163 static                                          void
 164 mcdi_mon_decode_stats(
 165         __in                                    efx_nic_t *enp,
 166         __in_ecount(sensor_mask_size)           uint32_t *sensor_mask,
 167         __in                                    size_t sensor_mask_size,
 168         __in_opt                                efsys_mem_t *esmp,
 169         __out_ecount_opt(sensor_mask_size)      uint32_t *stat_maskp,
 170         __inout_ecount_opt(EFX_MON_NSTATS)      efx_mon_stat_value_t *stat)
 171 {
 172         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
 173         uint16_t port_mask;
 174         uint16_t sensor;
 175         size_t sensor_max;
 176         uint32_t stat_mask[(EFX_ARRAY_SIZE(mcdi_sensor_map) + 31) / 32];
 177         uint32_t idx = 0;
 178         uint32_t page = 0;
 179 
 180         /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
 181         MCDI_STATIC_SENSOR_ASSERT(OK);
 182         MCDI_STATIC_SENSOR_ASSERT(WARNING);
 183         MCDI_STATIC_SENSOR_ASSERT(FATAL);
 184         MCDI_STATIC_SENSOR_ASSERT(BROKEN);
 185         MCDI_STATIC_SENSOR_ASSERT(NO_READING);
 186 
 187         EFX_STATIC_ASSERT(sizeof (stat_mask[0]) * 8 ==
 188             EFX_MON_MASK_ELEMENT_SIZE);
 189         sensor_max =
 190             MIN((8 * sensor_mask_size), EFX_ARRAY_SIZE(mcdi_sensor_map));
 191 
 192         port_mask = 1U << emip->emi_port;
 193 
 194         (void) memset(stat_mask, 0, sizeof (stat_mask));
 195 
 196         /*
 197          * The MCDI sensor readings in the DMA buffer are a packed array of
 198          * MC_CMD_SENSOR_VALUE_ENTRY structures, which only includes entries for
 199          * supported sensors (bit set in sensor_mask). The sensor_mask and
 200          * sensor readings do not include entries for the per-page NEXT_PAGE
 201          * flag.
 202          *
 203          * sensor_mask may legitimately contain MCDI sensors that the driver
 204          * does not understand.
 205          */
 206         for (sensor = 0; sensor < sensor_max; ++sensor) {
 207                 efx_mon_stat_t id = mcdi_sensor_map[sensor].msm_stat;
 208 
 209                 if ((sensor % MCDI_MON_PAGE_SIZE) == MC_CMD_SENSOR_PAGE0_NEXT) {
 210                         EFSYS_ASSERT3U(id, ==, MCDI_MON_NEXT_PAGE);
 211                         page++;
 212                         continue;
 213                 }
 214                 if (~(sensor_mask[page]) & (1U << sensor))
 215                         continue;
 216                 idx++;
 217 
 218                 if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0)
 219                         continue;
 220                 EFSYS_ASSERT(id < EFX_MON_NSTATS);
 221 
 222                 /*
 223                  * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic
 224                  * identifiers from efx_mon_stat_t (without NEXT_PAGE bits).
 225                  *
 226                  * If there is an entry in the MCDI sensor to monitor statistic
 227                  * map then the sensor reading is used for the value of the
 228                  * monitor statistic.
 229                  */
 230                 stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |=
 231                     (1U << (id % EFX_MON_MASK_ELEMENT_SIZE));
 232 
 233                 if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
 234                         efx_dword_t dword;
 235 
 236                         /* Get MCDI sensor reading from DMA buffer */
 237                         EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
 238 
 239                         /* Update EFX monitor stat from MCDI sensor reading */
 240                         stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword,
 241                             MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
 242 
 243                         stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword,
 244                             MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
 245                 }
 246         }
 247 
 248         if (stat_maskp != NULL) {
 249                 (void) memcpy(stat_maskp, stat_mask, sizeof (stat_mask));
 250         }
 251 }
 252 
 253         __checkReturn                   efx_rc_t
 254 mcdi_mon_ev(
 255         __in                            efx_nic_t *enp,
 256         __in                            efx_qword_t *eqp,
 257         __out                           efx_mon_stat_t *idp,
 258         __out                           efx_mon_stat_value_t *valuep)
 259 {
 260         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
 261         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 262         uint16_t port_mask;
 263         uint16_t sensor;
 264         uint16_t state;
 265         uint16_t value;
 266         efx_mon_stat_t id;
 267         efx_rc_t rc;
 268 
 269         port_mask = (emip->emi_port == 1)
 270             ? MCDI_MON_PORT_P1
 271             : MCDI_MON_PORT_P2;
 272 
 273         sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
 274         state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
 275         value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
 276 
 277         /* Hardware must support this MCDI sensor */
 278         EFSYS_ASSERT3U(sensor, <, (8 * encp->enc_mcdi_sensor_mask_size));
 279         EFSYS_ASSERT((sensor % MCDI_MON_PAGE_SIZE) != MC_CMD_SENSOR_PAGE0_NEXT);
 280         EFSYS_ASSERT(encp->enc_mcdi_sensor_maskp != NULL);
 281         EFSYS_ASSERT((encp->enc_mcdi_sensor_maskp[sensor / MCDI_MON_PAGE_SIZE] &
 282                 (1U << (sensor % MCDI_MON_PAGE_SIZE))) != 0);
 283 
 284         /* But we don't have to understand it */
 285         if (sensor >= EFX_ARRAY_SIZE(mcdi_sensor_map)) {
 286                 rc = ENOTSUP;
 287                 goto fail1;
 288         }
 289         id = mcdi_sensor_map[sensor].msm_stat;
 290         if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0)
 291                 return (ENODEV);
 292         EFSYS_ASSERT(id < EFX_MON_NSTATS);
 293 
 294         *idp = id;
 295         valuep->emsv_value = value;
 296         valuep->emsv_state = state;
 297 
 298         return (0);
 299 
 300 fail1:
 301         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 302 
 303         return (rc);
 304 }
 305 
 306 
 307 static  __checkReturn   efx_rc_t
 308 efx_mcdi_read_sensors(
 309         __in            efx_nic_t *enp,
 310         __in            efsys_mem_t *esmp,
 311         __in            uint32_t size)
 312 {
 313         efx_mcdi_req_t req;
 314         uint8_t payload[MAX(MC_CMD_READ_SENSORS_EXT_IN_LEN,
 315                             MC_CMD_READ_SENSORS_EXT_OUT_LEN)];
 316         uint32_t addr_lo, addr_hi;
 317 
 318         req.emr_cmd = MC_CMD_READ_SENSORS;
 319         req.emr_in_buf = payload;
 320         req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN;
 321         req.emr_out_buf = payload;
 322         req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN;
 323 
 324         addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff);
 325         addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32);
 326 
 327         MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo);
 328         MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi);
 329         MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size);
 330 
 331         efx_mcdi_execute(enp, &req);
 332 
 333         return (req.emr_rc);
 334 }
 335 
 336 static  __checkReturn   efx_rc_t
 337 efx_mcdi_sensor_info_npages(
 338         __in            efx_nic_t *enp,
 339         __out           uint32_t *npagesp)
 340 {
 341         efx_mcdi_req_t req;
 342         uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
 343                             MC_CMD_SENSOR_INFO_OUT_LENMAX)];
 344         int page;
 345         efx_rc_t rc;
 346 
 347         EFSYS_ASSERT(npagesp != NULL);
 348 
 349         page = 0;
 350         do {
 351                 (void) memset(payload, 0, sizeof (payload));
 352                 req.emr_cmd = MC_CMD_SENSOR_INFO;
 353                 req.emr_in_buf = payload;
 354                 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
 355                 req.emr_out_buf = payload;
 356                 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
 357 
 358                 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++);
 359 
 360                 efx_mcdi_execute_quiet(enp, &req);
 361 
 362                 if (req.emr_rc != 0) {
 363                         rc = req.emr_rc;
 364                         goto fail1;
 365                 }
 366         } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) &
 367             (1U << MC_CMD_SENSOR_PAGE0_NEXT));
 368 
 369         *npagesp = page;
 370 
 371         return (0);
 372 
 373 fail1:
 374         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 375 
 376         return (rc);
 377 }
 378 
 379 static  __checkReturn           efx_rc_t
 380 efx_mcdi_sensor_info(
 381         __in                    efx_nic_t *enp,
 382         __out_ecount(npages)    uint32_t *sensor_maskp,
 383         __in                    size_t npages)
 384 {
 385         efx_mcdi_req_t req;
 386         uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
 387                             MC_CMD_SENSOR_INFO_OUT_LENMAX)];
 388         uint32_t page;
 389         efx_rc_t rc;
 390 
 391         EFSYS_ASSERT(sensor_maskp != NULL);
 392 
 393         for (page = 0; page < npages; page++) {
 394                 uint32_t mask;
 395 
 396                 (void) memset(payload, 0, sizeof (payload));
 397                 req.emr_cmd = MC_CMD_SENSOR_INFO;
 398                 req.emr_in_buf = payload;
 399                 req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
 400                 req.emr_out_buf = payload;
 401                 req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
 402 
 403                 MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
 404 
 405                 efx_mcdi_execute(enp, &req);
 406 
 407                 if (req.emr_rc != 0) {
 408                         rc = req.emr_rc;
 409                         goto fail1;
 410                 }
 411 
 412                 mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
 413 
 414                 if ((page != (npages - 1)) &&
 415                     ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) {
 416                         rc = EINVAL;
 417                         goto fail2;
 418                 }
 419                 sensor_maskp[page] = mask;
 420         }
 421 
 422         if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
 423                 rc = EINVAL;
 424                 goto fail3;
 425         }
 426 
 427         return (0);
 428 
 429 fail3:
 430         EFSYS_PROBE(fail3);
 431 fail2:
 432         EFSYS_PROBE(fail2);
 433 fail1:
 434         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 435 
 436         return (rc);
 437 }
 438 
 439         __checkReturn                   efx_rc_t
 440 mcdi_mon_stats_update(
 441         __in                            efx_nic_t *enp,
 442         __in                            efsys_mem_t *esmp,
 443         __inout_ecount(EFX_MON_NSTATS)  efx_mon_stat_value_t *values)
 444 {
 445         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 446         uint32_t size = encp->enc_mon_stat_dma_buf_size;
 447         efx_rc_t rc;
 448 
 449         if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0)
 450                 goto fail1;
 451 
 452         EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size);
 453 
 454         mcdi_mon_decode_stats(enp,
 455             encp->enc_mcdi_sensor_maskp,
 456             encp->enc_mcdi_sensor_mask_size,
 457             esmp, NULL, values);
 458 
 459         return (0);
 460 
 461 fail1:
 462         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 463 
 464         return (rc);
 465 }
 466 
 467         __checkReturn   efx_rc_t
 468 mcdi_mon_cfg_build(
 469         __in            efx_nic_t *enp)
 470 {
 471         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 472         uint32_t npages;
 473         efx_rc_t rc;
 474 
 475         switch (enp->en_family) {
 476 #if EFSYS_OPT_SIENA
 477         case EFX_FAMILY_SIENA:
 478                 encp->enc_mon_type = EFX_MON_SFC90X0;
 479                 break;
 480 #endif
 481 #if EFSYS_OPT_HUNTINGTON
 482         case EFX_FAMILY_HUNTINGTON:
 483                 encp->enc_mon_type = EFX_MON_SFC91X0;
 484                 break;
 485 #endif
 486 #if EFSYS_OPT_MEDFORD
 487         case EFX_FAMILY_MEDFORD:
 488                 encp->enc_mon_type = EFX_MON_SFC92X0;
 489                 break;
 490 #endif
 491         default:
 492                 rc = EINVAL;
 493                 goto fail1;
 494         }
 495 
 496         /* Get mc sensor mask size */
 497         npages = 0;
 498         if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0)
 499                 goto fail2;
 500 
 501         encp->enc_mon_stat_dma_buf_size      = npages * EFX_MON_STATS_PAGE_SIZE;
 502         encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t);
 503 
 504         /* Allocate mc sensor mask */
 505         EFSYS_KMEM_ALLOC(enp->en_esip,
 506             encp->enc_mcdi_sensor_mask_size,
 507             encp->enc_mcdi_sensor_maskp);
 508 
 509         if (encp->enc_mcdi_sensor_maskp == NULL) {
 510                 rc = ENOMEM;
 511                 goto fail3;
 512         }
 513 
 514         /* Read mc sensor mask */
 515         if ((rc = efx_mcdi_sensor_info(enp,
 516                     encp->enc_mcdi_sensor_maskp,
 517                     npages)) != 0)
 518                 goto fail4;
 519 
 520         /* Build monitor statistics mask */
 521         mcdi_mon_decode_stats(enp,
 522             encp->enc_mcdi_sensor_maskp,
 523             encp->enc_mcdi_sensor_mask_size,
 524             NULL, encp->enc_mon_stat_mask, NULL);
 525 
 526         return (0);
 527 
 528 fail4:
 529         EFSYS_PROBE(fail4);
 530         EFSYS_KMEM_FREE(enp->en_esip,
 531             encp->enc_mcdi_sensor_mask_size,
 532             encp->enc_mcdi_sensor_maskp);
 533 
 534 fail3:
 535         EFSYS_PROBE(fail3);
 536 
 537 fail2:
 538         EFSYS_PROBE(fail2);
 539 
 540 fail1:
 541         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 542 
 543         return (rc);
 544 }
 545 
 546                         void
 547 mcdi_mon_cfg_free(
 548         __in            efx_nic_t *enp)
 549 {
 550         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 551 
 552         if (encp->enc_mcdi_sensor_maskp != NULL) {
 553                 EFSYS_KMEM_FREE(enp->en_esip,
 554                     encp->enc_mcdi_sensor_mask_size,
 555                     encp->enc_mcdi_sensor_maskp);
 556         }
 557 }
 558 
 559 
 560 #endif  /* EFSYS_OPT_MON_STATS */
 561 
 562 #endif  /* EFSYS_OPT_MON_MCDI */