dpdk/drivers/common/sfc_efx/base/mcdi_mon.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 *
   3 * Copyright(c) 2019-2021 Xilinx, Inc.
   4 * Copyright(c) 2009-2019 Solarflare Communications Inc.
   5 */
   6
   7#include "efx.h"
   8#include "efx_impl.h"
   9#include "mcdi_mon.h"
  10
  11#if EFSYS_OPT_MON_MCDI
  12
  13#if EFSYS_OPT_MON_STATS
  14
  15/* Get port mask from one-based MCDI port number */
  16#define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1))
  17
  18#define MCDI_STATIC_SENSOR_ASSERT(_field)                               \
  19        EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field                \
  20                            == EFX_MON_STAT_STATE_ ## _field)
  21
  22static                                          void
  23mcdi_mon_decode_stats(
  24        __in                                    efx_nic_t *enp,
  25        __in_bcount(sensor_mask_size)           uint32_t *sensor_mask,
  26        __in                                    size_t sensor_mask_size,
  27        __in_opt                                efsys_mem_t *esmp,
  28        __out_bcount_opt(sensor_mask_size)      uint32_t *stat_maskp,
  29        __inout_ecount_opt(EFX_MON_NSTATS)      efx_mon_stat_value_t *stat)
  30{
  31        efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
  32        efx_mon_stat_portmask_t port_mask;
  33        uint16_t sensor;
  34        size_t sensor_max;
  35        uint32_t stat_mask[(EFX_MON_NSTATS + 31) / 32];
  36        uint32_t idx = 0;
  37        uint32_t page = 0;
  38
  39        /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
  40        MCDI_STATIC_SENSOR_ASSERT(OK);
  41        MCDI_STATIC_SENSOR_ASSERT(WARNING);
  42        MCDI_STATIC_SENSOR_ASSERT(FATAL);
  43        MCDI_STATIC_SENSOR_ASSERT(BROKEN);
  44        MCDI_STATIC_SENSOR_ASSERT(NO_READING);
  45
  46        sensor_max = 8 * sensor_mask_size;
  47
  48        EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
  49        port_mask = (efx_mon_stat_portmask_t)MCDI_MON_PORT_MASK(emip);
  50
  51        memset(stat_mask, 0, sizeof (stat_mask));
  52
  53        /*
  54         * The MCDI sensor readings in the DMA buffer are a packed array of
  55         * MC_CMD_SENSOR_VALUE_ENTRY structures, which only includes entries for
  56         * supported sensors (bit set in sensor_mask). The sensor_mask and
  57         * sensor readings do not include entries for the per-page NEXT_PAGE
  58         * flag.
  59         *
  60         * sensor_mask may legitimately contain MCDI sensors that the driver
  61         * does not understand.
  62         */
  63        for (sensor = 0; sensor < sensor_max; ++sensor) {
  64                efx_mon_stat_t id;
  65                efx_mon_stat_portmask_t stat_portmask = 0;
  66                efx_mon_stat_unit_t stat_unit;
  67
  68                if ((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) ==
  69                    MC_CMD_SENSOR_PAGE0_NEXT) {
  70                        /* This sensor is one of the page boundary bits. */
  71                        page++;
  72                        continue;
  73                }
  74
  75                if (~(sensor_mask[page]) &
  76                    (1U << (sensor % (sizeof (sensor_mask[page]) * 8)))) {
  77                        /* This sensor is not supported. */
  78                        continue;
  79                }
  80
  81                /* Supported sensor, so it is present in the DMA buffer. */
  82                idx++;
  83
  84                if ((efx_mon_mcdi_to_efx_stat(sensor, &id) != B_TRUE) ||
  85                    (efx_mon_get_stat_portmap(id, &stat_portmask) != B_TRUE)) {
  86                        /* The sensor is not known to the driver. */
  87                        continue;
  88                }
  89
  90                if ((stat_portmask & port_mask) == 0) {
  91                        /* The sensor is not for this port. */
  92                        continue;
  93                }
  94
  95                EFSYS_ASSERT(id < EFX_MON_NSTATS);
  96
  97                /*
  98                 * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic
  99                 * identifiers from efx_mon_stat_t (without NEXT_PAGE bits).
 100                 *
 101                 * If there is an entry in the MCDI sensor to monitor statistic
 102                 * map then the sensor reading is used for the value of the
 103                 * monitor statistic.
 104                 */
 105                stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |=
 106                    (1U << (id % EFX_MON_MASK_ELEMENT_SIZE));
 107
 108                if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
 109                        efx_dword_t dword;
 110
 111                        /* Get MCDI sensor reading from DMA buffer */
 112                        EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
 113
 114                        /* Update EFX monitor stat from MCDI sensor reading */
 115                        stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword,
 116                            MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
 117
 118                        stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword,
 119                            MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
 120
 121                        stat[id].emsv_unit =
 122                            efx_mon_get_stat_unit(id, &stat_unit) ?
 123                            stat_unit : EFX_MON_STAT_UNIT_UNKNOWN;
 124                }
 125        }
 126
 127        if (stat_maskp != NULL) {
 128                memcpy(stat_maskp, stat_mask, sizeof (stat_mask));
 129        }
 130}
 131
 132        __checkReturn                   efx_rc_t
 133mcdi_mon_ev(
 134        __in                            efx_nic_t *enp,
 135        __in                            efx_qword_t *eqp,
 136        __out                           efx_mon_stat_t *idp,
 137        __out                           efx_mon_stat_value_t *valuep)
 138{
 139        efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
 140        efx_mon_stat_portmask_t port_mask, sensor_port_mask;
 141        uint16_t sensor;
 142        uint16_t state;
 143        uint16_t value;
 144        efx_mon_stat_t id;
 145        efx_rc_t rc;
 146
 147        EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
 148        port_mask = MCDI_MON_PORT_MASK(emip);
 149
 150        sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
 151        state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
 152        value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
 153
 154        /* Hardware must support this MCDI sensor */
 155        EFSYS_ASSERT3U(sensor, <,
 156            (8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size));
 157        EFSYS_ASSERT((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) !=
 158            MC_CMD_SENSOR_PAGE0_NEXT);
 159        EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL);
 160        EFSYS_ASSERT((enp->en_nic_cfg.enc_mcdi_sensor_maskp[
 161                    sensor / (MC_CMD_SENSOR_PAGE0_NEXT + 1)] &
 162                (1U << (sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)))) != 0);
 163
 164        /* And we need to understand it, to get port-map */
 165        if (!efx_mon_mcdi_to_efx_stat(sensor, &id)) {
 166                rc = ENOTSUP;
 167                goto fail1;
 168        }
 169        if (!(efx_mon_get_stat_portmap(id, &sensor_port_mask) &&
 170                (port_mask && sensor_port_mask))) {
 171                return (ENODEV);
 172        }
 173        EFSYS_ASSERT(id < EFX_MON_NSTATS);
 174
 175        *idp = id;
 176        valuep->emsv_value = value;
 177        valuep->emsv_state = state;
 178
 179        return (0);
 180
 181fail1:
 182        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 183
 184        return (rc);
 185}
 186
 187
 188static  __checkReturn   efx_rc_t
 189efx_mcdi_read_sensors(
 190        __in            efx_nic_t *enp,
 191        __in            efsys_mem_t *esmp,
 192        __in            uint32_t size)
 193{
 194        efx_mcdi_req_t req;
 195        EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN,
 196                MC_CMD_READ_SENSORS_EXT_OUT_LEN);
 197        uint32_t addr_lo, addr_hi;
 198        efx_rc_t rc;
 199
 200        if (EFSYS_MEM_SIZE(esmp) < size) {
 201                rc = EINVAL;
 202                goto fail1;
 203        }
 204
 205        req.emr_cmd = MC_CMD_READ_SENSORS;
 206        req.emr_in_buf = payload;
 207        req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN;
 208        req.emr_out_buf = payload;
 209        req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN;
 210
 211        addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff);
 212        addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32);
 213
 214        MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo);
 215        MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi);
 216        MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size);
 217
 218        efx_mcdi_execute(enp, &req);
 219
 220        return (req.emr_rc);
 221
 222fail1:
 223        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 224
 225        return (rc);
 226}
 227
 228static  __checkReturn   efx_rc_t
 229efx_mcdi_sensor_info_npages(
 230        __in            efx_nic_t *enp,
 231        __out           uint32_t *npagesp)
 232{
 233        efx_mcdi_req_t req;
 234        EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
 235                MC_CMD_SENSOR_INFO_OUT_LENMAX);
 236        int page;
 237        efx_rc_t rc;
 238
 239        EFSYS_ASSERT(npagesp != NULL);
 240
 241        page = 0;
 242        do {
 243                (void) memset(payload, 0, sizeof (payload));
 244                req.emr_cmd = MC_CMD_SENSOR_INFO;
 245                req.emr_in_buf = payload;
 246                req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
 247                req.emr_out_buf = payload;
 248                req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
 249
 250                MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++);
 251
 252                efx_mcdi_execute_quiet(enp, &req);
 253
 254                if (req.emr_rc != 0) {
 255                        rc = req.emr_rc;
 256                        goto fail1;
 257                }
 258        } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) &
 259            (1U << MC_CMD_SENSOR_PAGE0_NEXT));
 260
 261        *npagesp = page;
 262
 263        return (0);
 264
 265fail1:
 266        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 267
 268        return (rc);
 269}
 270
 271static  __checkReturn           efx_rc_t
 272efx_mcdi_sensor_info(
 273        __in                    efx_nic_t *enp,
 274        __out_ecount(npages)    uint32_t *sensor_maskp,
 275        __in                    size_t npages)
 276{
 277        efx_mcdi_req_t req;
 278        EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
 279                MC_CMD_SENSOR_INFO_OUT_LENMAX);
 280        uint32_t page;
 281        efx_rc_t rc;
 282
 283        EFSYS_ASSERT(sensor_maskp != NULL);
 284
 285        if (npages < 1) {
 286                rc = EINVAL;
 287                goto fail1;
 288        }
 289
 290        for (page = 0; page < npages; page++) {
 291                uint32_t mask;
 292
 293                (void) memset(payload, 0, sizeof (payload));
 294                req.emr_cmd = MC_CMD_SENSOR_INFO;
 295                req.emr_in_buf = payload;
 296                req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
 297                req.emr_out_buf = payload;
 298                req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
 299
 300                MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
 301
 302                efx_mcdi_execute(enp, &req);
 303
 304                if (req.emr_rc != 0) {
 305                        rc = req.emr_rc;
 306                        goto fail2;
 307                }
 308
 309                mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
 310
 311                if ((page != (npages - 1)) &&
 312                    ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) {
 313                        rc = EINVAL;
 314                        goto fail3;
 315                }
 316                sensor_maskp[page] = mask;
 317        }
 318
 319        if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
 320                rc = EINVAL;
 321                goto fail4;
 322        }
 323
 324        return (0);
 325
 326fail4:
 327        EFSYS_PROBE(fail4);
 328fail3:
 329        EFSYS_PROBE(fail3);
 330fail2:
 331        EFSYS_PROBE(fail2);
 332fail1:
 333        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 334
 335        return (rc);
 336}
 337
 338static  __checkReturn           efx_rc_t
 339efx_mcdi_sensor_info_page(
 340        __in                    efx_nic_t *enp,
 341        __in                    uint32_t page,
 342        __out                   uint32_t *mask_part,
 343        __out_ecount((sizeof (*mask_part) * 8) - 1)
 344                                efx_mon_stat_limits_t *limits)
 345{
 346        efx_mcdi_req_t req;
 347        EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
 348                MC_CMD_SENSOR_INFO_OUT_LENMAX);
 349        efx_rc_t rc;
 350        uint32_t mask_copy;
 351        efx_dword_t *maskp;
 352        efx_qword_t *limit_info;
 353
 354        EFSYS_ASSERT(mask_part != NULL);
 355        EFSYS_ASSERT(limits != NULL);
 356
 357        memset(limits, 0,
 358            ((sizeof (*mask_part) * 8) - 1) * sizeof (efx_mon_stat_limits_t));
 359
 360        req.emr_cmd = MC_CMD_SENSOR_INFO;
 361        req.emr_in_buf = payload;
 362        req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
 363        req.emr_out_buf = payload;
 364        req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
 365
 366        MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
 367
 368        efx_mcdi_execute(enp, &req);
 369
 370        rc = req.emr_rc;
 371
 372        if (rc != 0)
 373                goto fail1;
 374
 375        EFSYS_ASSERT(sizeof (*limit_info) ==
 376            MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN);
 377        maskp = MCDI_OUT2(req, efx_dword_t, SENSOR_INFO_OUT_MASK);
 378        limit_info = (efx_qword_t *)(maskp + 1);
 379
 380        *mask_part = maskp->ed_u32[0];
 381        mask_copy = *mask_part;
 382
 383        /* Copy an entry for all but the highest bit set. */
 384        while (mask_copy) {
 385
 386                if (mask_copy == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
 387                        /* Only next page bit set. */
 388                        mask_copy = 0;
 389                } else {
 390                        /* Clear lowest bit */
 391                        mask_copy = mask_copy & ~(mask_copy ^ (mask_copy - 1));
 392                        /* And copy out limit entry into buffer */
 393                        limits->emlv_warning_min = EFX_QWORD_FIELD(*limit_info,
 394                            MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1);
 395
 396                        limits->emlv_warning_max = EFX_QWORD_FIELD(*limit_info,
 397                            MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1);
 398
 399                        limits->emlv_fatal_min = EFX_QWORD_FIELD(*limit_info,
 400                            MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2);
 401
 402                        limits->emlv_fatal_max = EFX_QWORD_FIELD(*limit_info,
 403                            MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2);
 404
 405                        limits++;
 406                        limit_info++;
 407                }
 408        }
 409
 410        return (rc);
 411
 412fail1:
 413        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 414
 415        return (rc);
 416}
 417
 418        __checkReturn                   efx_rc_t
 419mcdi_mon_stats_update(
 420        __in                            efx_nic_t *enp,
 421        __in                            efsys_mem_t *esmp,
 422        __inout_ecount(EFX_MON_NSTATS)  efx_mon_stat_value_t *values)
 423{
 424        efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 425        uint32_t size = encp->enc_mon_stat_dma_buf_size;
 426        efx_rc_t rc;
 427
 428        if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0)
 429                goto fail1;
 430
 431        EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size);
 432
 433        mcdi_mon_decode_stats(enp,
 434            encp->enc_mcdi_sensor_maskp,
 435            encp->enc_mcdi_sensor_mask_size,
 436            esmp, NULL, values);
 437
 438        return (0);
 439
 440fail1:
 441        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 442
 443        return (rc);
 444}
 445
 446static          void
 447lowest_set_bit(
 448        __in    uint32_t input_mask,
 449        __out   uint32_t *lowest_bit_mask,
 450        __out   uint32_t *lowest_bit_num
 451)
 452{
 453        uint32_t x;
 454        uint32_t set_bit, bit_index;
 455
 456        x = (input_mask ^ (input_mask - 1));
 457        set_bit = (x + 1) >> 1;
 458        if (!set_bit)
 459                set_bit = (1U << 31U);
 460
 461        bit_index = 0;
 462        if (set_bit & 0xFFFF0000)
 463                bit_index += 16;
 464        if (set_bit & 0xFF00FF00)
 465                bit_index += 8;
 466        if (set_bit & 0xF0F0F0F0)
 467                bit_index += 4;
 468        if (set_bit & 0xCCCCCCCC)
 469                bit_index += 2;
 470        if (set_bit & 0xAAAAAAAA)
 471                bit_index += 1;
 472
 473        *lowest_bit_mask = set_bit;
 474        *lowest_bit_num = bit_index;
 475}
 476
 477        __checkReturn                   efx_rc_t
 478mcdi_mon_limits_update(
 479        __in                            efx_nic_t *enp,
 480        __inout_ecount(EFX_MON_NSTATS)  efx_mon_stat_limits_t *values)
 481{
 482        efx_rc_t rc;
 483        uint32_t page;
 484        uint32_t page_mask;
 485        uint32_t limit_index;
 486        efx_mon_stat_limits_t limits[sizeof (page_mask) * 8];
 487        efx_mon_stat_t stat;
 488
 489        page = 0;
 490        page--;
 491        do {
 492                page++;
 493
 494                rc = efx_mcdi_sensor_info_page(enp, page, &page_mask, limits);
 495                if (rc != 0)
 496                        goto fail1;
 497
 498                limit_index = 0;
 499                while (page_mask) {
 500                        uint32_t set_bit;
 501                        uint32_t page_index;
 502                        uint32_t mcdi_index;
 503
 504                        if (page_mask == (1U << MC_CMD_SENSOR_PAGE0_NEXT))
 505                                break;
 506
 507                        lowest_set_bit(page_mask, &set_bit, &page_index);
 508                        page_mask = page_mask & ~set_bit;
 509
 510                        mcdi_index =
 511                            page_index + (sizeof (page_mask) * 8 * page);
 512
 513                        /*
 514                         * This can fail if MCDI reports newer stats than the
 515                         * drivers understand, or the bit is the next page bit.
 516                         *
 517                         * Driver needs to be tolerant of this.
 518                         */
 519                        if (!efx_mon_mcdi_to_efx_stat(mcdi_index, &stat))
 520                                continue;
 521
 522                        values[stat] = limits[limit_index];
 523                        limit_index++;
 524                }
 525
 526        } while (page_mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT));
 527
 528        return (rc);
 529
 530fail1:
 531        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 532
 533        return (rc);
 534}
 535
 536        __checkReturn   efx_rc_t
 537mcdi_mon_cfg_build(
 538        __in            efx_nic_t *enp)
 539{
 540        efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 541        uint32_t npages;
 542        efx_rc_t rc;
 543
 544        switch (enp->en_family) {
 545#if EFSYS_OPT_SIENA
 546        case EFX_FAMILY_SIENA:
 547                encp->enc_mon_type = EFX_MON_SFC90X0;
 548                break;
 549#endif
 550#if EFSYS_OPT_HUNTINGTON
 551        case EFX_FAMILY_HUNTINGTON:
 552                encp->enc_mon_type = EFX_MON_SFC91X0;
 553                break;
 554#endif
 555#if EFSYS_OPT_MEDFORD
 556        case EFX_FAMILY_MEDFORD:
 557                encp->enc_mon_type = EFX_MON_SFC92X0;
 558                break;
 559#endif
 560#if EFSYS_OPT_MEDFORD2
 561        case EFX_FAMILY_MEDFORD2:
 562                encp->enc_mon_type = EFX_MON_SFC92X0;
 563                break;
 564#endif
 565        default:
 566                rc = EINVAL;
 567                goto fail1;
 568        }
 569
 570        /* Get mc sensor mask size */
 571        npages = 0;
 572        if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0)
 573                goto fail2;
 574
 575        encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE;
 576        encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t);
 577
 578        /* Allocate mc sensor mask */
 579        EFSYS_KMEM_ALLOC(enp->en_esip,
 580            encp->enc_mcdi_sensor_mask_size,
 581            encp->enc_mcdi_sensor_maskp);
 582
 583        if (encp->enc_mcdi_sensor_maskp == NULL) {
 584                rc = ENOMEM;
 585                goto fail3;
 586        }
 587
 588        /* Read mc sensor mask */
 589        if ((rc = efx_mcdi_sensor_info(enp,
 590                    encp->enc_mcdi_sensor_maskp,
 591                    npages)) != 0)
 592                goto fail4;
 593
 594        /* Build monitor statistics mask */
 595        mcdi_mon_decode_stats(enp,
 596            encp->enc_mcdi_sensor_maskp,
 597            encp->enc_mcdi_sensor_mask_size,
 598            NULL, encp->enc_mon_stat_mask, NULL);
 599
 600        return (0);
 601
 602fail4:
 603        EFSYS_PROBE(fail4);
 604        EFSYS_KMEM_FREE(enp->en_esip,
 605            encp->enc_mcdi_sensor_mask_size,
 606            encp->enc_mcdi_sensor_maskp);
 607
 608fail3:
 609        EFSYS_PROBE(fail3);
 610
 611fail2:
 612        EFSYS_PROBE(fail2);
 613
 614fail1:
 615        EFSYS_PROBE1(fail1, efx_rc_t, rc);
 616
 617        return (rc);
 618}
 619
 620                        void
 621mcdi_mon_cfg_free(
 622        __in            efx_nic_t *enp)
 623{
 624        efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 625
 626        if (encp->enc_mcdi_sensor_maskp != NULL) {
 627                EFSYS_KMEM_FREE(enp->en_esip,
 628                    encp->enc_mcdi_sensor_mask_size,
 629                    encp->enc_mcdi_sensor_maskp);
 630        }
 631}
 632
 633
 634#endif  /* EFSYS_OPT_MON_STATS */
 635
 636#endif  /* EFSYS_OPT_MON_MCDI */
 637