13c838a9fSAndrew Rybchenko /*-
2929c7febSAndrew Rybchenko * Copyright (c) 2009-2016 Solarflare Communications Inc.
33c838a9fSAndrew Rybchenko * All rights reserved.
43c838a9fSAndrew Rybchenko *
53c838a9fSAndrew Rybchenko * Redistribution and use in source and binary forms, with or without
63c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
73c838a9fSAndrew Rybchenko *
83c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
93c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer.
103c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
123c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution.
133c838a9fSAndrew Rybchenko *
143c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
153c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
163c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
173c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
183c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
193c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
203c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
213c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
223c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
233c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
243c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
253c838a9fSAndrew Rybchenko *
263c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are
273c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official
283c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
293c838a9fSAndrew Rybchenko */
303c838a9fSAndrew Rybchenko
313c838a9fSAndrew Rybchenko #include <sys/cdefs.h>
323c838a9fSAndrew Rybchenko #include "efx.h"
333c838a9fSAndrew Rybchenko #include "efx_impl.h"
34b288270eSAndrew Rybchenko #include "mcdi_mon.h"
353c838a9fSAndrew Rybchenko
363c838a9fSAndrew Rybchenko #if EFSYS_OPT_MON_MCDI
373c838a9fSAndrew Rybchenko
383c838a9fSAndrew Rybchenko #if EFSYS_OPT_MON_STATS
393c838a9fSAndrew Rybchenko
40b5a84969SAndrew Rybchenko /* Get port mask from one-based MCDI port number */
41b5a84969SAndrew Rybchenko #define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1))
42b5a84969SAndrew Rybchenko
433c838a9fSAndrew Rybchenko #define MCDI_STATIC_SENSOR_ASSERT(_field) \
443c838a9fSAndrew Rybchenko EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \
453c838a9fSAndrew Rybchenko == EFX_MON_STAT_STATE_ ## _field)
463c838a9fSAndrew Rybchenko
473c838a9fSAndrew Rybchenko static void
mcdi_mon_decode_stats(__in efx_nic_t * enp,__in_bcount (sensor_mask_size)uint32_t * sensor_mask,__in size_t sensor_mask_size,__in_opt efsys_mem_t * esmp,__out_bcount_opt (sensor_mask_size)uint32_t * stat_maskp,__inout_ecount_opt (EFX_MON_NSTATS)efx_mon_stat_value_t * stat)483c838a9fSAndrew Rybchenko mcdi_mon_decode_stats(
493c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
50b5a84969SAndrew Rybchenko __in_bcount(sensor_mask_size) uint32_t *sensor_mask,
513c838a9fSAndrew Rybchenko __in size_t sensor_mask_size,
523c838a9fSAndrew Rybchenko __in_opt efsys_mem_t *esmp,
53b5a84969SAndrew Rybchenko __out_bcount_opt(sensor_mask_size) uint32_t *stat_maskp,
54536c03c2SAndrew Rybchenko __inout_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *stat)
553c838a9fSAndrew Rybchenko {
563c838a9fSAndrew Rybchenko efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
5721b72677SAndrew Rybchenko efx_mon_stat_portmask_t port_mask;
583c838a9fSAndrew Rybchenko uint16_t sensor;
593c838a9fSAndrew Rybchenko size_t sensor_max;
6021b72677SAndrew Rybchenko uint32_t stat_mask[(EFX_MON_NSTATS + 31) / 32];
613c838a9fSAndrew Rybchenko uint32_t idx = 0;
623c838a9fSAndrew Rybchenko uint32_t page = 0;
633c838a9fSAndrew Rybchenko
643c838a9fSAndrew Rybchenko /* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
653c838a9fSAndrew Rybchenko MCDI_STATIC_SENSOR_ASSERT(OK);
663c838a9fSAndrew Rybchenko MCDI_STATIC_SENSOR_ASSERT(WARNING);
673c838a9fSAndrew Rybchenko MCDI_STATIC_SENSOR_ASSERT(FATAL);
683c838a9fSAndrew Rybchenko MCDI_STATIC_SENSOR_ASSERT(BROKEN);
693c838a9fSAndrew Rybchenko MCDI_STATIC_SENSOR_ASSERT(NO_READING);
703c838a9fSAndrew Rybchenko
7121b72677SAndrew Rybchenko sensor_max = 8 * sensor_mask_size;
723c838a9fSAndrew Rybchenko
73b5a84969SAndrew Rybchenko EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
7421b72677SAndrew Rybchenko port_mask = (efx_mon_stat_portmask_t)MCDI_MON_PORT_MASK(emip);
753c838a9fSAndrew Rybchenko
763c838a9fSAndrew Rybchenko memset(stat_mask, 0, sizeof (stat_mask));
773c838a9fSAndrew Rybchenko
783c838a9fSAndrew Rybchenko /*
793c838a9fSAndrew Rybchenko * The MCDI sensor readings in the DMA buffer are a packed array of
803c838a9fSAndrew Rybchenko * MC_CMD_SENSOR_VALUE_ENTRY structures, which only includes entries for
813c838a9fSAndrew Rybchenko * supported sensors (bit set in sensor_mask). The sensor_mask and
823c838a9fSAndrew Rybchenko * sensor readings do not include entries for the per-page NEXT_PAGE
833c838a9fSAndrew Rybchenko * flag.
843c838a9fSAndrew Rybchenko *
853c838a9fSAndrew Rybchenko * sensor_mask may legitimately contain MCDI sensors that the driver
863c838a9fSAndrew Rybchenko * does not understand.
873c838a9fSAndrew Rybchenko */
883c838a9fSAndrew Rybchenko for (sensor = 0; sensor < sensor_max; ++sensor) {
8921b72677SAndrew Rybchenko efx_mon_stat_t id;
9021b72677SAndrew Rybchenko efx_mon_stat_portmask_t stat_portmask = 0;
9121b72677SAndrew Rybchenko boolean_t decode_ok;
9221b72677SAndrew Rybchenko efx_mon_stat_unit_t stat_unit;
933c838a9fSAndrew Rybchenko
9421b72677SAndrew Rybchenko if ((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) ==
9521b72677SAndrew Rybchenko MC_CMD_SENSOR_PAGE0_NEXT) {
963c838a9fSAndrew Rybchenko page++;
973c838a9fSAndrew Rybchenko continue;
9821b72677SAndrew Rybchenko /* This sensor is one of the page boundary bits. */
993c838a9fSAndrew Rybchenko }
10021b72677SAndrew Rybchenko
1013c838a9fSAndrew Rybchenko if (~(sensor_mask[page]) & (1U << sensor))
1023c838a9fSAndrew Rybchenko continue;
10321b72677SAndrew Rybchenko /* This sensor not in DMA buffer */
1043c838a9fSAndrew Rybchenko
10521b72677SAndrew Rybchenko idx++;
10621b72677SAndrew Rybchenko /*
10721b72677SAndrew Rybchenko * Valid stat in DMA buffer that we need to increment over, even
10821b72677SAndrew Rybchenko * if we couldn't look up the id
10921b72677SAndrew Rybchenko */
11021b72677SAndrew Rybchenko
11121b72677SAndrew Rybchenko decode_ok = efx_mon_mcdi_to_efx_stat(sensor, &id);
11221b72677SAndrew Rybchenko decode_ok =
11321b72677SAndrew Rybchenko decode_ok && efx_mon_get_stat_portmap(id, &stat_portmask);
11421b72677SAndrew Rybchenko
11521b72677SAndrew Rybchenko if (!(decode_ok && (stat_portmask & port_mask)))
1163c838a9fSAndrew Rybchenko continue;
11721b72677SAndrew Rybchenko /* Either bad decode, or don't know what port stat is on */
11821b72677SAndrew Rybchenko
1193c838a9fSAndrew Rybchenko EFSYS_ASSERT(id < EFX_MON_NSTATS);
1203c838a9fSAndrew Rybchenko
1213c838a9fSAndrew Rybchenko /*
1223c838a9fSAndrew Rybchenko * stat_mask is a bitmask indexed by EFX_MON_* monitor statistic
1233c838a9fSAndrew Rybchenko * identifiers from efx_mon_stat_t (without NEXT_PAGE bits).
1243c838a9fSAndrew Rybchenko *
1253c838a9fSAndrew Rybchenko * If there is an entry in the MCDI sensor to monitor statistic
1263c838a9fSAndrew Rybchenko * map then the sensor reading is used for the value of the
1273c838a9fSAndrew Rybchenko * monitor statistic.
1283c838a9fSAndrew Rybchenko */
1293c838a9fSAndrew Rybchenko stat_mask[id / EFX_MON_MASK_ELEMENT_SIZE] |=
1303c838a9fSAndrew Rybchenko (1U << (id % EFX_MON_MASK_ELEMENT_SIZE));
1313c838a9fSAndrew Rybchenko
1323c838a9fSAndrew Rybchenko if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
1333c838a9fSAndrew Rybchenko efx_dword_t dword;
1343c838a9fSAndrew Rybchenko
1353c838a9fSAndrew Rybchenko /* Get MCDI sensor reading from DMA buffer */
1363c838a9fSAndrew Rybchenko EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
1373c838a9fSAndrew Rybchenko
1383c838a9fSAndrew Rybchenko /* Update EFX monitor stat from MCDI sensor reading */
1393c838a9fSAndrew Rybchenko stat[id].emsv_value = (uint16_t)EFX_DWORD_FIELD(dword,
1403c838a9fSAndrew Rybchenko MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
1413c838a9fSAndrew Rybchenko
1423c838a9fSAndrew Rybchenko stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword,
1433c838a9fSAndrew Rybchenko MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
14421b72677SAndrew Rybchenko
14521b72677SAndrew Rybchenko stat[id].emsv_unit =
14621b72677SAndrew Rybchenko efx_mon_get_stat_unit(id, &stat_unit) ?
14721b72677SAndrew Rybchenko stat_unit : EFX_MON_STAT_UNIT_UNKNOWN;
1483c838a9fSAndrew Rybchenko }
1493c838a9fSAndrew Rybchenko }
1503c838a9fSAndrew Rybchenko
1513c838a9fSAndrew Rybchenko if (stat_maskp != NULL) {
1523c838a9fSAndrew Rybchenko memcpy(stat_maskp, stat_mask, sizeof (stat_mask));
1533c838a9fSAndrew Rybchenko }
1543c838a9fSAndrew Rybchenko }
1553c838a9fSAndrew Rybchenko
156460cb568SAndrew Rybchenko __checkReturn efx_rc_t
mcdi_mon_ev(__in efx_nic_t * enp,__in efx_qword_t * eqp,__out efx_mon_stat_t * idp,__out efx_mon_stat_value_t * valuep)1573c838a9fSAndrew Rybchenko mcdi_mon_ev(
1583c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
1593c838a9fSAndrew Rybchenko __in efx_qword_t *eqp,
1603c838a9fSAndrew Rybchenko __out efx_mon_stat_t *idp,
1613c838a9fSAndrew Rybchenko __out efx_mon_stat_value_t *valuep)
1623c838a9fSAndrew Rybchenko {
1633c838a9fSAndrew Rybchenko efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
16421b72677SAndrew Rybchenko efx_mon_stat_portmask_t port_mask, sensor_port_mask;
1653c838a9fSAndrew Rybchenko uint16_t sensor;
1663c838a9fSAndrew Rybchenko uint16_t state;
1673c838a9fSAndrew Rybchenko uint16_t value;
1683c838a9fSAndrew Rybchenko efx_mon_stat_t id;
169460cb568SAndrew Rybchenko efx_rc_t rc;
1703c838a9fSAndrew Rybchenko
171b5a84969SAndrew Rybchenko EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
172b5a84969SAndrew Rybchenko port_mask = MCDI_MON_PORT_MASK(emip);
1733c838a9fSAndrew Rybchenko
1743c838a9fSAndrew Rybchenko sensor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
1753c838a9fSAndrew Rybchenko state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
1763c838a9fSAndrew Rybchenko value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
1773c838a9fSAndrew Rybchenko
1783c838a9fSAndrew Rybchenko /* Hardware must support this MCDI sensor */
179cc8d2b23SAndrew Rybchenko EFSYS_ASSERT3U(sensor, <,
180cc8d2b23SAndrew Rybchenko (8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size));
18121b72677SAndrew Rybchenko EFSYS_ASSERT((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) !=
18221b72677SAndrew Rybchenko MC_CMD_SENSOR_PAGE0_NEXT);
183cc8d2b23SAndrew Rybchenko EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL);
18421b72677SAndrew Rybchenko EFSYS_ASSERT((enp->en_nic_cfg.enc_mcdi_sensor_maskp[
18521b72677SAndrew Rybchenko sensor / (MC_CMD_SENSOR_PAGE0_NEXT + 1)] &
18621b72677SAndrew Rybchenko (1U << (sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)))) != 0);
1873c838a9fSAndrew Rybchenko
18821b72677SAndrew Rybchenko /* And we need to understand it, to get port-map */
18921b72677SAndrew Rybchenko if (!efx_mon_mcdi_to_efx_stat(sensor, &id)) {
1903c838a9fSAndrew Rybchenko rc = ENOTSUP;
1913c838a9fSAndrew Rybchenko goto fail1;
1923c838a9fSAndrew Rybchenko }
19321b72677SAndrew Rybchenko if (!(efx_mon_get_stat_portmap(id, &sensor_port_mask) &&
19421b72677SAndrew Rybchenko (port_mask && sensor_port_mask))) {
1953c838a9fSAndrew Rybchenko return (ENODEV);
19621b72677SAndrew Rybchenko }
1973c838a9fSAndrew Rybchenko EFSYS_ASSERT(id < EFX_MON_NSTATS);
1983c838a9fSAndrew Rybchenko
1993c838a9fSAndrew Rybchenko *idp = id;
2003c838a9fSAndrew Rybchenko valuep->emsv_value = value;
2013c838a9fSAndrew Rybchenko valuep->emsv_state = state;
2023c838a9fSAndrew Rybchenko
2033c838a9fSAndrew Rybchenko return (0);
2043c838a9fSAndrew Rybchenko
2053c838a9fSAndrew Rybchenko fail1:
206460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2073c838a9fSAndrew Rybchenko
2083c838a9fSAndrew Rybchenko return (rc);
2093c838a9fSAndrew Rybchenko }
2103c838a9fSAndrew Rybchenko
211460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_read_sensors(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint32_t size)2123c838a9fSAndrew Rybchenko efx_mcdi_read_sensors(
2133c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
2143c838a9fSAndrew Rybchenko __in efsys_mem_t *esmp,
2153c838a9fSAndrew Rybchenko __in uint32_t size)
2163c838a9fSAndrew Rybchenko {
2173c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
218*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN,
219*315bbbaaSAndrew Rybchenko MC_CMD_READ_SENSORS_EXT_OUT_LEN);
2203c838a9fSAndrew Rybchenko uint32_t addr_lo, addr_hi;
2219d3487a6SAndrew Rybchenko efx_rc_t rc;
2229d3487a6SAndrew Rybchenko
2239d3487a6SAndrew Rybchenko if (EFSYS_MEM_SIZE(esmp) < size) {
2249d3487a6SAndrew Rybchenko rc = EINVAL;
2259d3487a6SAndrew Rybchenko goto fail1;
2269d3487a6SAndrew Rybchenko }
2273c838a9fSAndrew Rybchenko
2283c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_READ_SENSORS;
2293c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
2303c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_READ_SENSORS_EXT_IN_LEN;
2313c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
2323c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_READ_SENSORS_EXT_OUT_LEN;
2333c838a9fSAndrew Rybchenko
2343c838a9fSAndrew Rybchenko addr_lo = (uint32_t)(EFSYS_MEM_ADDR(esmp) & 0xffffffff);
2353c838a9fSAndrew Rybchenko addr_hi = (uint32_t)(EFSYS_MEM_ADDR(esmp) >> 32);
2363c838a9fSAndrew Rybchenko
2373c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_LO, addr_lo);
2383c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_DMA_ADDR_HI, addr_hi);
2393c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, READ_SENSORS_EXT_IN_LENGTH, size);
2403c838a9fSAndrew Rybchenko
2413c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
2423c838a9fSAndrew Rybchenko
2433c838a9fSAndrew Rybchenko return (req.emr_rc);
2449d3487a6SAndrew Rybchenko
2459d3487a6SAndrew Rybchenko fail1:
2469d3487a6SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2479d3487a6SAndrew Rybchenko
2489d3487a6SAndrew Rybchenko return (rc);
2493c838a9fSAndrew Rybchenko }
2503c838a9fSAndrew Rybchenko
251460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_sensor_info_npages(__in efx_nic_t * enp,__out uint32_t * npagesp)2523c838a9fSAndrew Rybchenko efx_mcdi_sensor_info_npages(
2533c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
2543c838a9fSAndrew Rybchenko __out uint32_t *npagesp)
2553c838a9fSAndrew Rybchenko {
2563c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
257*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
258*315bbbaaSAndrew Rybchenko MC_CMD_SENSOR_INFO_OUT_LENMAX);
2593c838a9fSAndrew Rybchenko int page;
260460cb568SAndrew Rybchenko efx_rc_t rc;
2613c838a9fSAndrew Rybchenko
2623c838a9fSAndrew Rybchenko EFSYS_ASSERT(npagesp != NULL);
2633c838a9fSAndrew Rybchenko
2643c838a9fSAndrew Rybchenko page = 0;
2653c838a9fSAndrew Rybchenko do {
2663c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload));
2673c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_SENSOR_INFO;
2683c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
2693c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
2703c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
2713c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
2723c838a9fSAndrew Rybchenko
2733c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page++);
2743c838a9fSAndrew Rybchenko
2753c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
2763c838a9fSAndrew Rybchenko
2773c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
2783c838a9fSAndrew Rybchenko rc = req.emr_rc;
2793c838a9fSAndrew Rybchenko goto fail1;
2803c838a9fSAndrew Rybchenko }
2813c838a9fSAndrew Rybchenko } while (MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK) &
2822ceb37acSAndrew Rybchenko (1U << MC_CMD_SENSOR_PAGE0_NEXT));
2833c838a9fSAndrew Rybchenko
2843c838a9fSAndrew Rybchenko *npagesp = page;
2853c838a9fSAndrew Rybchenko
2863c838a9fSAndrew Rybchenko return (0);
2873c838a9fSAndrew Rybchenko
2883c838a9fSAndrew Rybchenko fail1:
289460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
2903c838a9fSAndrew Rybchenko
2913c838a9fSAndrew Rybchenko return (rc);
2923c838a9fSAndrew Rybchenko }
2933c838a9fSAndrew Rybchenko
294460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_sensor_info(__in efx_nic_t * enp,__out_ecount (npages)uint32_t * sensor_maskp,__in size_t npages)2953c838a9fSAndrew Rybchenko efx_mcdi_sensor_info(
2963c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
2973c838a9fSAndrew Rybchenko __out_ecount(npages) uint32_t *sensor_maskp,
2983c838a9fSAndrew Rybchenko __in size_t npages)
2993c838a9fSAndrew Rybchenko {
3003c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
301*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
302*315bbbaaSAndrew Rybchenko MC_CMD_SENSOR_INFO_OUT_LENMAX);
3033c838a9fSAndrew Rybchenko uint32_t page;
304460cb568SAndrew Rybchenko efx_rc_t rc;
3053c838a9fSAndrew Rybchenko
3063c838a9fSAndrew Rybchenko EFSYS_ASSERT(sensor_maskp != NULL);
3073c838a9fSAndrew Rybchenko
3089a3efb21SAndrew Rybchenko if (npages < 1) {
3099a3efb21SAndrew Rybchenko rc = EINVAL;
3109a3efb21SAndrew Rybchenko goto fail1;
3119a3efb21SAndrew Rybchenko }
3129a3efb21SAndrew Rybchenko
3133c838a9fSAndrew Rybchenko for (page = 0; page < npages; page++) {
3143c838a9fSAndrew Rybchenko uint32_t mask;
3153c838a9fSAndrew Rybchenko
3163c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload));
3173c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_SENSOR_INFO;
3183c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
3193c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
3203c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
3213c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
3223c838a9fSAndrew Rybchenko
3233c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
3243c838a9fSAndrew Rybchenko
3253c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
3263c838a9fSAndrew Rybchenko
3273c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
3283c838a9fSAndrew Rybchenko rc = req.emr_rc;
3299a3efb21SAndrew Rybchenko goto fail2;
3303c838a9fSAndrew Rybchenko }
3313c838a9fSAndrew Rybchenko
3323c838a9fSAndrew Rybchenko mask = MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
3333c838a9fSAndrew Rybchenko
3343c838a9fSAndrew Rybchenko if ((page != (npages - 1)) &&
3353c838a9fSAndrew Rybchenko ((mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) == 0)) {
3363c838a9fSAndrew Rybchenko rc = EINVAL;
3379a3efb21SAndrew Rybchenko goto fail3;
3383c838a9fSAndrew Rybchenko }
3393c838a9fSAndrew Rybchenko sensor_maskp[page] = mask;
3403c838a9fSAndrew Rybchenko }
3413c838a9fSAndrew Rybchenko
3423c838a9fSAndrew Rybchenko if (sensor_maskp[npages - 1] & (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
3433c838a9fSAndrew Rybchenko rc = EINVAL;
3449a3efb21SAndrew Rybchenko goto fail4;
3453c838a9fSAndrew Rybchenko }
3463c838a9fSAndrew Rybchenko
3473c838a9fSAndrew Rybchenko return (0);
3483c838a9fSAndrew Rybchenko
3499a3efb21SAndrew Rybchenko fail4:
3509a3efb21SAndrew Rybchenko EFSYS_PROBE(fail4);
3513c838a9fSAndrew Rybchenko fail3:
3523c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
3533c838a9fSAndrew Rybchenko fail2:
3543c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
3553c838a9fSAndrew Rybchenko fail1:
356460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3573c838a9fSAndrew Rybchenko
3583c838a9fSAndrew Rybchenko return (rc);
3593c838a9fSAndrew Rybchenko }
3603c838a9fSAndrew Rybchenko
361b4d3f02eSAndrew Rybchenko static __checkReturn efx_rc_t
362b4d3f02eSAndrew Rybchenko efx_mcdi_sensor_info_page(
363b4d3f02eSAndrew Rybchenko __in efx_nic_t *enp,
364b4d3f02eSAndrew Rybchenko __in uint32_t page,
365b4d3f02eSAndrew Rybchenko __out uint32_t *mask_part,
366b4d3f02eSAndrew Rybchenko __out_ecount((sizeof (*mask_part) * 8) - 1)
367b4d3f02eSAndrew Rybchenko efx_mon_stat_limits_t *limits)
368b4d3f02eSAndrew Rybchenko {
369b4d3f02eSAndrew Rybchenko efx_mcdi_req_t req;
370*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
371*315bbbaaSAndrew Rybchenko MC_CMD_SENSOR_INFO_OUT_LENMAX);
372b4d3f02eSAndrew Rybchenko efx_rc_t rc;
373b4d3f02eSAndrew Rybchenko uint32_t mask_copy;
374b4d3f02eSAndrew Rybchenko efx_dword_t *maskp;
375b4d3f02eSAndrew Rybchenko efx_qword_t *limit_info;
376b4d3f02eSAndrew Rybchenko
377b4d3f02eSAndrew Rybchenko EFSYS_ASSERT(mask_part != NULL);
378b4d3f02eSAndrew Rybchenko EFSYS_ASSERT(limits != NULL);
379b4d3f02eSAndrew Rybchenko
380b4d3f02eSAndrew Rybchenko memset(limits, 0,
381b4d3f02eSAndrew Rybchenko ((sizeof (*mask_part) * 8) - 1) * sizeof (efx_mon_stat_limits_t));
382b4d3f02eSAndrew Rybchenko
383b4d3f02eSAndrew Rybchenko req.emr_cmd = MC_CMD_SENSOR_INFO;
384b4d3f02eSAndrew Rybchenko req.emr_in_buf = payload;
385b4d3f02eSAndrew Rybchenko req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
386b4d3f02eSAndrew Rybchenko req.emr_out_buf = payload;
387b4d3f02eSAndrew Rybchenko req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
388b4d3f02eSAndrew Rybchenko
389b4d3f02eSAndrew Rybchenko MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
390b4d3f02eSAndrew Rybchenko
391b4d3f02eSAndrew Rybchenko efx_mcdi_execute(enp, &req);
392b4d3f02eSAndrew Rybchenko
393b4d3f02eSAndrew Rybchenko rc = req.emr_rc;
394b4d3f02eSAndrew Rybchenko
395b4d3f02eSAndrew Rybchenko if (rc != 0)
396b4d3f02eSAndrew Rybchenko goto fail1;
397b4d3f02eSAndrew Rybchenko
398b4d3f02eSAndrew Rybchenko EFSYS_ASSERT(sizeof (*limit_info) ==
399b4d3f02eSAndrew Rybchenko MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN);
400b4d3f02eSAndrew Rybchenko maskp = MCDI_OUT2(req, efx_dword_t, SENSOR_INFO_OUT_MASK);
401b4d3f02eSAndrew Rybchenko limit_info = (efx_qword_t *)(maskp + 1);
402b4d3f02eSAndrew Rybchenko
403b4d3f02eSAndrew Rybchenko *mask_part = maskp->ed_u32[0];
404b4d3f02eSAndrew Rybchenko mask_copy = *mask_part;
405b4d3f02eSAndrew Rybchenko
406b4d3f02eSAndrew Rybchenko /* Copy an entry for all but the highest bit set. */
407b4d3f02eSAndrew Rybchenko while (mask_copy) {
408b4d3f02eSAndrew Rybchenko if (mask_copy == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
409b4d3f02eSAndrew Rybchenko /* Only next page bit set. */
410b4d3f02eSAndrew Rybchenko mask_copy = 0;
411b4d3f02eSAndrew Rybchenko } else {
412b4d3f02eSAndrew Rybchenko /* Clear lowest bit */
413b4d3f02eSAndrew Rybchenko mask_copy = mask_copy & ~(mask_copy ^ (mask_copy - 1));
414b4d3f02eSAndrew Rybchenko /* And copy out limit entry into buffer */
415b4d3f02eSAndrew Rybchenko limits->emlv_warning_min = EFX_QWORD_FIELD(*limit_info,
416b4d3f02eSAndrew Rybchenko MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1);
417b4d3f02eSAndrew Rybchenko
418b4d3f02eSAndrew Rybchenko limits->emlv_warning_max = EFX_QWORD_FIELD(*limit_info,
419b4d3f02eSAndrew Rybchenko MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1);
420b4d3f02eSAndrew Rybchenko
421b4d3f02eSAndrew Rybchenko limits->emlv_fatal_min = EFX_QWORD_FIELD(*limit_info,
422b4d3f02eSAndrew Rybchenko MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2);
423b4d3f02eSAndrew Rybchenko
424b4d3f02eSAndrew Rybchenko limits->emlv_fatal_max = EFX_QWORD_FIELD(*limit_info,
425b4d3f02eSAndrew Rybchenko MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2);
426b4d3f02eSAndrew Rybchenko
427b4d3f02eSAndrew Rybchenko limits++;
428b4d3f02eSAndrew Rybchenko limit_info++;
429b4d3f02eSAndrew Rybchenko }
430b4d3f02eSAndrew Rybchenko }
431b4d3f02eSAndrew Rybchenko
432b4d3f02eSAndrew Rybchenko return (rc);
433b4d3f02eSAndrew Rybchenko
434b4d3f02eSAndrew Rybchenko fail1:
435b4d3f02eSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
436b4d3f02eSAndrew Rybchenko
437b4d3f02eSAndrew Rybchenko return (rc);
438b4d3f02eSAndrew Rybchenko }
439b4d3f02eSAndrew Rybchenko
440460cb568SAndrew Rybchenko __checkReturn efx_rc_t
mcdi_mon_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MON_NSTATS)efx_mon_stat_value_t * values)4413c838a9fSAndrew Rybchenko mcdi_mon_stats_update(
4423c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
4433c838a9fSAndrew Rybchenko __in efsys_mem_t *esmp,
444536c03c2SAndrew Rybchenko __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values)
4453c838a9fSAndrew Rybchenko {
4463c838a9fSAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
4473c838a9fSAndrew Rybchenko uint32_t size = encp->enc_mon_stat_dma_buf_size;
448460cb568SAndrew Rybchenko efx_rc_t rc;
4493c838a9fSAndrew Rybchenko
4503c838a9fSAndrew Rybchenko if ((rc = efx_mcdi_read_sensors(enp, esmp, size)) != 0)
4513c838a9fSAndrew Rybchenko goto fail1;
4523c838a9fSAndrew Rybchenko
4533c838a9fSAndrew Rybchenko EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, size);
4543c838a9fSAndrew Rybchenko
4553c838a9fSAndrew Rybchenko mcdi_mon_decode_stats(enp,
4563c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp,
4573c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size,
4583c838a9fSAndrew Rybchenko esmp, NULL, values);
4593c838a9fSAndrew Rybchenko
4603c838a9fSAndrew Rybchenko return (0);
4613c838a9fSAndrew Rybchenko
4623c838a9fSAndrew Rybchenko fail1:
463460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4643c838a9fSAndrew Rybchenko
4653c838a9fSAndrew Rybchenko return (rc);
4663c838a9fSAndrew Rybchenko }
4673c838a9fSAndrew Rybchenko
468b4d3f02eSAndrew Rybchenko static void
lowest_set_bit(__in uint32_t input_mask,__out uint32_t * lowest_bit_mask,__out uint32_t * lowest_bit_num)469b4d3f02eSAndrew Rybchenko lowest_set_bit(
470b4d3f02eSAndrew Rybchenko __in uint32_t input_mask,
471b4d3f02eSAndrew Rybchenko __out uint32_t *lowest_bit_mask,
472b4d3f02eSAndrew Rybchenko __out uint32_t *lowest_bit_num
473b4d3f02eSAndrew Rybchenko )
474b4d3f02eSAndrew Rybchenko {
475b4d3f02eSAndrew Rybchenko uint32_t x;
476b4d3f02eSAndrew Rybchenko uint32_t set_bit, bit_index;
477b4d3f02eSAndrew Rybchenko
478b4d3f02eSAndrew Rybchenko x = (input_mask ^ (input_mask - 1));
479b4d3f02eSAndrew Rybchenko set_bit = (x + 1) >> 1;
480b4d3f02eSAndrew Rybchenko if (!set_bit)
481b4d3f02eSAndrew Rybchenko set_bit = (1U << 31U);
482b4d3f02eSAndrew Rybchenko
483b4d3f02eSAndrew Rybchenko bit_index = 0;
484b4d3f02eSAndrew Rybchenko if (set_bit & 0xFFFF0000)
485b4d3f02eSAndrew Rybchenko bit_index += 16;
486b4d3f02eSAndrew Rybchenko if (set_bit & 0xFF00FF00)
487b4d3f02eSAndrew Rybchenko bit_index += 8;
488b4d3f02eSAndrew Rybchenko if (set_bit & 0xF0F0F0F0)
489b4d3f02eSAndrew Rybchenko bit_index += 4;
490b4d3f02eSAndrew Rybchenko if (set_bit & 0xCCCCCCCC)
491b4d3f02eSAndrew Rybchenko bit_index += 2;
492b4d3f02eSAndrew Rybchenko if (set_bit & 0xAAAAAAAA)
493b4d3f02eSAndrew Rybchenko bit_index += 1;
494b4d3f02eSAndrew Rybchenko
495b4d3f02eSAndrew Rybchenko *lowest_bit_mask = set_bit;
496b4d3f02eSAndrew Rybchenko *lowest_bit_num = bit_index;
497b4d3f02eSAndrew Rybchenko }
498b4d3f02eSAndrew Rybchenko
499b4d3f02eSAndrew Rybchenko __checkReturn efx_rc_t
mcdi_mon_limits_update(__in efx_nic_t * enp,__inout_ecount (EFX_MON_NSTATS)efx_mon_stat_limits_t * values)500b4d3f02eSAndrew Rybchenko mcdi_mon_limits_update(
501b4d3f02eSAndrew Rybchenko __in efx_nic_t *enp,
502b4d3f02eSAndrew Rybchenko __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values)
503b4d3f02eSAndrew Rybchenko {
504b4d3f02eSAndrew Rybchenko efx_rc_t rc;
505b4d3f02eSAndrew Rybchenko uint32_t page;
506b4d3f02eSAndrew Rybchenko uint32_t page_mask;
507b4d3f02eSAndrew Rybchenko uint32_t limit_index;
508b4d3f02eSAndrew Rybchenko efx_mon_stat_limits_t limits[sizeof (page_mask) * 8];
509b4d3f02eSAndrew Rybchenko efx_mon_stat_t stat;
510b4d3f02eSAndrew Rybchenko
511b4d3f02eSAndrew Rybchenko page = 0;
512b4d3f02eSAndrew Rybchenko page--;
513b4d3f02eSAndrew Rybchenko do {
514b4d3f02eSAndrew Rybchenko page++;
515b4d3f02eSAndrew Rybchenko
516b4d3f02eSAndrew Rybchenko rc = efx_mcdi_sensor_info_page(enp, page, &page_mask, limits);
517b4d3f02eSAndrew Rybchenko if (rc != 0)
518b4d3f02eSAndrew Rybchenko goto fail1;
519b4d3f02eSAndrew Rybchenko
520b4d3f02eSAndrew Rybchenko limit_index = 0;
521b4d3f02eSAndrew Rybchenko while (page_mask) {
522b4d3f02eSAndrew Rybchenko uint32_t set_bit;
523b4d3f02eSAndrew Rybchenko uint32_t page_index;
524b4d3f02eSAndrew Rybchenko uint32_t mcdi_index;
525b4d3f02eSAndrew Rybchenko
526b4d3f02eSAndrew Rybchenko if (page_mask == (1U << MC_CMD_SENSOR_PAGE0_NEXT))
527b4d3f02eSAndrew Rybchenko break;
528b4d3f02eSAndrew Rybchenko
529b4d3f02eSAndrew Rybchenko lowest_set_bit(page_mask, &set_bit, &page_index);
530b4d3f02eSAndrew Rybchenko page_mask = page_mask & ~set_bit;
531b4d3f02eSAndrew Rybchenko
532b4d3f02eSAndrew Rybchenko mcdi_index =
533b4d3f02eSAndrew Rybchenko page_index + (sizeof (page_mask) * 8 * page);
534b4d3f02eSAndrew Rybchenko
535b4d3f02eSAndrew Rybchenko /*
536b4d3f02eSAndrew Rybchenko * This can fail if MCDI reports newer stats than the
537b4d3f02eSAndrew Rybchenko * drivers understand, or the bit is the next page bit.
538b4d3f02eSAndrew Rybchenko *
539b4d3f02eSAndrew Rybchenko * Driver needs to be tolerant of this.
540b4d3f02eSAndrew Rybchenko */
541b4d3f02eSAndrew Rybchenko if (!efx_mon_mcdi_to_efx_stat(mcdi_index, &stat))
542b4d3f02eSAndrew Rybchenko continue;
543b4d3f02eSAndrew Rybchenko
544b4d3f02eSAndrew Rybchenko values[stat] = limits[limit_index];
545b4d3f02eSAndrew Rybchenko limit_index++;
546b4d3f02eSAndrew Rybchenko }
547b4d3f02eSAndrew Rybchenko
548b4d3f02eSAndrew Rybchenko } while (page_mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT));
549b4d3f02eSAndrew Rybchenko
550b4d3f02eSAndrew Rybchenko return (rc);
551b4d3f02eSAndrew Rybchenko
552b4d3f02eSAndrew Rybchenko fail1:
553b4d3f02eSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
554b4d3f02eSAndrew Rybchenko
555b4d3f02eSAndrew Rybchenko return (rc);
556b4d3f02eSAndrew Rybchenko }
557b4d3f02eSAndrew Rybchenko
558460cb568SAndrew Rybchenko __checkReturn efx_rc_t
mcdi_mon_cfg_build(__in efx_nic_t * enp)5593c838a9fSAndrew Rybchenko mcdi_mon_cfg_build(
5603c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
5613c838a9fSAndrew Rybchenko {
5623c838a9fSAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
5633c838a9fSAndrew Rybchenko uint32_t npages;
564460cb568SAndrew Rybchenko efx_rc_t rc;
5653c838a9fSAndrew Rybchenko
5663c838a9fSAndrew Rybchenko switch (enp->en_family) {
5673c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
5683c838a9fSAndrew Rybchenko case EFX_FAMILY_SIENA:
5693c838a9fSAndrew Rybchenko encp->enc_mon_type = EFX_MON_SFC90X0;
5703c838a9fSAndrew Rybchenko break;
5713c838a9fSAndrew Rybchenko #endif
5723c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
5733c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
5743c838a9fSAndrew Rybchenko encp->enc_mon_type = EFX_MON_SFC91X0;
5753c838a9fSAndrew Rybchenko break;
5763c838a9fSAndrew Rybchenko #endif
577b13ad4deSAndrew Rybchenko #if EFSYS_OPT_MEDFORD
578b13ad4deSAndrew Rybchenko case EFX_FAMILY_MEDFORD:
579b13ad4deSAndrew Rybchenko encp->enc_mon_type = EFX_MON_SFC92X0;
580b13ad4deSAndrew Rybchenko break;
581b13ad4deSAndrew Rybchenko #endif
582bbefcb4cSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
583bbefcb4cSAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
584bbefcb4cSAndrew Rybchenko encp->enc_mon_type = EFX_MON_SFC92X0;
585bbefcb4cSAndrew Rybchenko break;
586bbefcb4cSAndrew Rybchenko #endif
5873c838a9fSAndrew Rybchenko default:
5883c838a9fSAndrew Rybchenko rc = EINVAL;
5893c838a9fSAndrew Rybchenko goto fail1;
5903c838a9fSAndrew Rybchenko }
5913c838a9fSAndrew Rybchenko
5923c838a9fSAndrew Rybchenko /* Get mc sensor mask size */
5933c838a9fSAndrew Rybchenko npages = 0;
5943c838a9fSAndrew Rybchenko if ((rc = efx_mcdi_sensor_info_npages(enp, &npages)) != 0)
5953c838a9fSAndrew Rybchenko goto fail2;
5963c838a9fSAndrew Rybchenko
5973c838a9fSAndrew Rybchenko encp->enc_mon_stat_dma_buf_size = npages * EFX_MON_STATS_PAGE_SIZE;
5983c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size = npages * sizeof (uint32_t);
5993c838a9fSAndrew Rybchenko
6003c838a9fSAndrew Rybchenko /* Allocate mc sensor mask */
6013c838a9fSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip,
6023c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size,
6033c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp);
6043c838a9fSAndrew Rybchenko
6053c838a9fSAndrew Rybchenko if (encp->enc_mcdi_sensor_maskp == NULL) {
6063c838a9fSAndrew Rybchenko rc = ENOMEM;
6073c838a9fSAndrew Rybchenko goto fail3;
6083c838a9fSAndrew Rybchenko }
6093c838a9fSAndrew Rybchenko
6103c838a9fSAndrew Rybchenko /* Read mc sensor mask */
6113c838a9fSAndrew Rybchenko if ((rc = efx_mcdi_sensor_info(enp,
6123c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp,
6133c838a9fSAndrew Rybchenko npages)) != 0)
6143c838a9fSAndrew Rybchenko goto fail4;
6153c838a9fSAndrew Rybchenko
6163c838a9fSAndrew Rybchenko /* Build monitor statistics mask */
6173c838a9fSAndrew Rybchenko mcdi_mon_decode_stats(enp,
6183c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp,
6193c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size,
6203c838a9fSAndrew Rybchenko NULL, encp->enc_mon_stat_mask, NULL);
6213c838a9fSAndrew Rybchenko
6223c838a9fSAndrew Rybchenko return (0);
6233c838a9fSAndrew Rybchenko
6243c838a9fSAndrew Rybchenko fail4:
6253c838a9fSAndrew Rybchenko EFSYS_PROBE(fail4);
6263c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip,
6273c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size,
6283c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp);
6293c838a9fSAndrew Rybchenko
6303c838a9fSAndrew Rybchenko fail3:
6313c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
6323c838a9fSAndrew Rybchenko
6333c838a9fSAndrew Rybchenko fail2:
6343c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
6353c838a9fSAndrew Rybchenko
6363c838a9fSAndrew Rybchenko fail1:
637460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
6383c838a9fSAndrew Rybchenko
6393c838a9fSAndrew Rybchenko return (rc);
6403c838a9fSAndrew Rybchenko }
6413c838a9fSAndrew Rybchenko
6423c838a9fSAndrew Rybchenko void
mcdi_mon_cfg_free(__in efx_nic_t * enp)6433c838a9fSAndrew Rybchenko mcdi_mon_cfg_free(
6443c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
6453c838a9fSAndrew Rybchenko {
6463c838a9fSAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
6473c838a9fSAndrew Rybchenko
6483c838a9fSAndrew Rybchenko if (encp->enc_mcdi_sensor_maskp != NULL) {
6493c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip,
6503c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_mask_size,
6513c838a9fSAndrew Rybchenko encp->enc_mcdi_sensor_maskp);
6523c838a9fSAndrew Rybchenko }
6533c838a9fSAndrew Rybchenko }
6543c838a9fSAndrew Rybchenko
6553c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_MON_STATS */
6563c838a9fSAndrew Rybchenko
6573c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_MON_MCDI */
658