summaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/base/mcdi_mon.c
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@gmail.com>2018-11-01 11:59:50 +0000
committerLuca Boccassi <luca.boccassi@gmail.com>2018-11-01 12:00:19 +0000
commit8d01b9cd70a67cdafd5b965a70420c3bd7fb3f82 (patch)
tree208e3bc33c220854d89d010e3abf720a2e62e546 /drivers/net/sfc/base/mcdi_mon.c
parentb63264c8342e6a1b6971c79550d2af2024b6a4de (diff)
New upstream version 18.11-rc1upstream/18.11-rc1
Change-Id: Iaa71986dd6332e878d8f4bf493101b2bbc6313bb Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Diffstat (limited to 'drivers/net/sfc/base/mcdi_mon.c')
-rw-r--r--drivers/net/sfc/base/mcdi_mon.c381
1 files changed, 228 insertions, 153 deletions
diff --git a/drivers/net/sfc/base/mcdi_mon.c b/drivers/net/sfc/base/mcdi_mon.c
index 940bd026..b53de0d6 100644
--- a/drivers/net/sfc/base/mcdi_mon.c
+++ b/drivers/net/sfc/base/mcdi_mon.c
@@ -6,141 +6,15 @@
#include "efx.h"
#include "efx_impl.h"
+#include "mcdi_mon.h"
#if EFSYS_OPT_MON_MCDI
#if EFSYS_OPT_MON_STATS
-#define MCDI_MON_NEXT_PAGE ((uint16_t)0xfffe)
-#define MCDI_MON_INVALID_SENSOR ((uint16_t)0xfffd)
-#define MCDI_MON_PAGE_SIZE 0x20
-
-/* Bitmasks of valid port(s) for each sensor */
-#define MCDI_MON_PORT_NONE (0x00)
-#define MCDI_MON_PORT_P1 (0x01)
-#define MCDI_MON_PORT_P2 (0x02)
-#define MCDI_MON_PORT_P3 (0x04)
-#define MCDI_MON_PORT_P4 (0x08)
-#define MCDI_MON_PORT_Px (0xFFFF)
-
/* Get port mask from one-based MCDI port number */
#define MCDI_MON_PORT_MASK(_emip) (1U << ((_emip)->emi_port - 1))
-/* Entry for MCDI sensor in sensor map */
-#define STAT(portmask, stat) \
- { (MCDI_MON_PORT_##portmask), (EFX_MON_STAT_##stat) }
-
-/* Entry for sensor next page flag in sensor map */
-#define STAT_NEXT_PAGE() \
- { MCDI_MON_PORT_NONE, MCDI_MON_NEXT_PAGE }
-
-/* Placeholder for gaps in the array */
-#define STAT_NO_SENSOR() \
- { MCDI_MON_PORT_NONE, MCDI_MON_INVALID_SENSOR }
-
-/* Map from MC sensors to monitor statistics */
-static const struct mcdi_sensor_map_s {
- uint16_t msm_port_mask;
- uint16_t msm_stat;
-} mcdi_sensor_map[] = {
- /* Sensor page 0 MC_CMD_SENSOR_xxx */
- STAT(Px, INT_TEMP), /* 0x00 CONTROLLER_TEMP */
- STAT(Px, EXT_TEMP), /* 0x01 PHY_COMMON_TEMP */
- STAT(Px, INT_COOLING), /* 0x02 CONTROLLER_COOLING */
- STAT(P1, EXT_TEMP), /* 0x03 PHY0_TEMP */
- STAT(P1, EXT_COOLING), /* 0x04 PHY0_COOLING */
- STAT(P2, EXT_TEMP), /* 0x05 PHY1_TEMP */
- STAT(P2, EXT_COOLING), /* 0x06 PHY1_COOLING */
- STAT(Px, 1V), /* 0x07 IN_1V0 */
- STAT(Px, 1_2V), /* 0x08 IN_1V2 */
- STAT(Px, 1_8V), /* 0x09 IN_1V8 */
- STAT(Px, 2_5V), /* 0x0a IN_2V5 */
- STAT(Px, 3_3V), /* 0x0b IN_3V3 */
- STAT(Px, 12V), /* 0x0c IN_12V0 */
- STAT(Px, 1_2VA), /* 0x0d IN_1V2A */
- STAT(Px, VREF), /* 0x0e IN_VREF */
- STAT(Px, VAOE), /* 0x0f OUT_VAOE */
- STAT(Px, AOE_TEMP), /* 0x10 AOE_TEMP */
- STAT(Px, PSU_AOE_TEMP), /* 0x11 PSU_AOE_TEMP */
- STAT(Px, PSU_TEMP), /* 0x12 PSU_TEMP */
- STAT(Px, FAN0), /* 0x13 FAN_0 */
- STAT(Px, FAN1), /* 0x14 FAN_1 */
- STAT(Px, FAN2), /* 0x15 FAN_2 */
- STAT(Px, FAN3), /* 0x16 FAN_3 */
- STAT(Px, FAN4), /* 0x17 FAN_4 */
- STAT(Px, VAOE_IN), /* 0x18 IN_VAOE */
- STAT(Px, IAOE), /* 0x19 OUT_IAOE */
- STAT(Px, IAOE_IN), /* 0x1a IN_IAOE */
- STAT(Px, NIC_POWER), /* 0x1b NIC_POWER */
- STAT(Px, 0_9V), /* 0x1c IN_0V9 */
- STAT(Px, I0_9V), /* 0x1d IN_I0V9 */
- STAT(Px, I1_2V), /* 0x1e IN_I1V2 */
- STAT_NEXT_PAGE(), /* 0x1f Next page flag (not a sensor) */
-
- /* Sensor page 1 MC_CMD_SENSOR_xxx */
- STAT(Px, 0_9V_ADC), /* 0x20 IN_0V9_ADC */
- STAT(Px, INT_TEMP2), /* 0x21 CONTROLLER_2_TEMP */
- STAT(Px, VREG_TEMP), /* 0x22 VREG_INTERNAL_TEMP */
- STAT(Px, VREG_0_9V_TEMP), /* 0x23 VREG_0V9_TEMP */
- STAT(Px, VREG_1_2V_TEMP), /* 0x24 VREG_1V2_TEMP */
- STAT(Px, INT_VPTAT), /* 0x25 CTRLR. VPTAT */
- STAT(Px, INT_ADC_TEMP), /* 0x26 CTRLR. INTERNAL_TEMP */
- STAT(Px, EXT_VPTAT), /* 0x27 CTRLR. VPTAT_EXTADC */
- STAT(Px, EXT_ADC_TEMP), /* 0x28 CTRLR. INTERNAL_TEMP_EXTADC */
- STAT(Px, AMBIENT_TEMP), /* 0x29 AMBIENT_TEMP */
- STAT(Px, AIRFLOW), /* 0x2a AIRFLOW */
- STAT(Px, VDD08D_VSS08D_CSR), /* 0x2b VDD08D_VSS08D_CSR */
- STAT(Px, VDD08D_VSS08D_CSR_EXTADC), /* 0x2c VDD08D_VSS08D_CSR_EXTADC */
- STAT(Px, HOTPOINT_TEMP), /* 0x2d HOTPOINT_TEMP */
- STAT(P1, PHY_POWER_SWITCH_PORT0), /* 0x2e PHY_POWER_SWITCH_PORT0 */
- STAT(P2, PHY_POWER_SWITCH_PORT1), /* 0x2f PHY_POWER_SWITCH_PORT1 */
- STAT(Px, MUM_VCC), /* 0x30 MUM_VCC */
- STAT(Px, 0V9_A), /* 0x31 0V9_A */
- STAT(Px, I0V9_A), /* 0x32 I0V9_A */
- STAT(Px, 0V9_A_TEMP), /* 0x33 0V9_A_TEMP */
- STAT(Px, 0V9_B), /* 0x34 0V9_B */
- STAT(Px, I0V9_B), /* 0x35 I0V9_B */
- STAT(Px, 0V9_B_TEMP), /* 0x36 0V9_B_TEMP */
- STAT(Px, CCOM_AVREG_1V2_SUPPLY), /* 0x37 CCOM_AVREG_1V2_SUPPLY */
- STAT(Px, CCOM_AVREG_1V2_SUPPLY_EXT_ADC),
- /* 0x38 CCOM_AVREG_1V2_SUPPLY_EXT_ADC */
- STAT(Px, CCOM_AVREG_1V8_SUPPLY), /* 0x39 CCOM_AVREG_1V8_SUPPLY */
- STAT(Px, CCOM_AVREG_1V8_SUPPLY_EXT_ADC),
- /* 0x3a CCOM_AVREG_1V8_SUPPLY_EXT_ADC */
- STAT_NO_SENSOR(), /* 0x3b (no sensor) */
- STAT_NO_SENSOR(), /* 0x3c (no sensor) */
- STAT_NO_SENSOR(), /* 0x3d (no sensor) */
- STAT_NO_SENSOR(), /* 0x3e (no sensor) */
- STAT_NEXT_PAGE(), /* 0x3f Next page flag (not a sensor) */
-
- /* Sensor page 2 MC_CMD_SENSOR_xxx */
- STAT(Px, CONTROLLER_MASTER_VPTAT), /* 0x40 MASTER_VPTAT */
- STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP), /* 0x41 MASTER_INT_TEMP */
- STAT(Px, CONTROLLER_MASTER_VPTAT_EXT_ADC), /* 0x42 MAST_VPTAT_EXT_ADC */
- STAT(Px, CONTROLLER_MASTER_INTERNAL_TEMP_EXT_ADC),
- /* 0x43 MASTER_INTERNAL_TEMP_EXT_ADC */
- STAT(Px, CONTROLLER_SLAVE_VPTAT), /* 0x44 SLAVE_VPTAT */
- STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP), /* 0x45 SLAVE_INTERNAL_TEMP */
- STAT(Px, CONTROLLER_SLAVE_VPTAT_EXT_ADC), /* 0x46 SLAVE_VPTAT_EXT_ADC */
- STAT(Px, CONTROLLER_SLAVE_INTERNAL_TEMP_EXT_ADC),
- /* 0x47 SLAVE_INTERNAL_TEMP_EXT_ADC */
- STAT_NO_SENSOR(), /* 0x48 (no sensor) */
- STAT(Px, SODIMM_VOUT), /* 0x49 SODIMM_VOUT */
- STAT(Px, SODIMM_0_TEMP), /* 0x4a SODIMM_0_TEMP */
- STAT(Px, SODIMM_1_TEMP), /* 0x4b SODIMM_1_TEMP */
- STAT(Px, PHY0_VCC), /* 0x4c PHY0_VCC */
- STAT(Px, PHY1_VCC), /* 0x4d PHY1_VCC */
- STAT(Px, CONTROLLER_TDIODE_TEMP), /* 0x4e CONTROLLER_TDIODE_TEMP */
- STAT(Px, BOARD_FRONT_TEMP), /* 0x4f BOARD_FRONT_TEMP */
- STAT(Px, BOARD_BACK_TEMP), /* 0x50 BOARD_BACK_TEMP */
- STAT(Px, I1V8), /* 0x51 IN_I1V8 */
- STAT(Px, I2V5), /* 0x52 IN_I2V5 */
- STAT(Px, I3V3), /* 0x53 IN_I3V3 */
- STAT(Px, I12V0), /* 0x54 IN_I12V0 */
- STAT(Px, 1_3V), /* 0x55 IN_1V3 */
- STAT(Px, I1V3), /* 0x56 IN_I1V3 */
-};
-
#define MCDI_STATIC_SENSOR_ASSERT(_field) \
EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field \
== EFX_MON_STAT_STATE_ ## _field)
@@ -155,10 +29,10 @@ mcdi_mon_decode_stats(
__inout_ecount_opt(EFX_MON_NSTATS) efx_mon_stat_value_t *stat)
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
- uint16_t port_mask;
+ efx_mon_stat_portmask_t port_mask;
uint16_t sensor;
size_t sensor_max;
- uint32_t stat_mask[(EFX_ARRAY_SIZE(mcdi_sensor_map) + 31) / 32];
+ uint32_t stat_mask[(EFX_MON_NSTATS + 31) / 32];
uint32_t idx = 0;
uint32_t page = 0;
@@ -169,13 +43,10 @@ mcdi_mon_decode_stats(
MCDI_STATIC_SENSOR_ASSERT(BROKEN);
MCDI_STATIC_SENSOR_ASSERT(NO_READING);
- EFX_STATIC_ASSERT(sizeof (stat_mask[0]) * 8 ==
- EFX_MON_MASK_ELEMENT_SIZE);
- sensor_max =
- MIN((8 * sensor_mask_size), EFX_ARRAY_SIZE(mcdi_sensor_map));
+ sensor_max = 8 * sensor_mask_size;
EFSYS_ASSERT(emip->emi_port > 0); /* MCDI port number is one-based */
- port_mask = MCDI_MON_PORT_MASK(emip);
+ port_mask = (efx_mon_stat_portmask_t)MCDI_MON_PORT_MASK(emip);
memset(stat_mask, 0, sizeof (stat_mask));
@@ -190,19 +61,36 @@ mcdi_mon_decode_stats(
* does not understand.
*/
for (sensor = 0; sensor < sensor_max; ++sensor) {
- efx_mon_stat_t id = mcdi_sensor_map[sensor].msm_stat;
+ efx_mon_stat_t id;
+ efx_mon_stat_portmask_t stat_portmask = 0;
+ boolean_t decode_ok;
+ efx_mon_stat_unit_t stat_unit;
- if ((sensor % MCDI_MON_PAGE_SIZE) == MC_CMD_SENSOR_PAGE0_NEXT) {
- EFSYS_ASSERT3U(id, ==, MCDI_MON_NEXT_PAGE);
+ if ((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) ==
+ MC_CMD_SENSOR_PAGE0_NEXT) {
page++;
continue;
+ /* This sensor is one of the page boundary bits. */
}
+
if (~(sensor_mask[page]) & (1U << sensor))
continue;
+ /* This sensor not in DMA buffer */
+
idx++;
+ /*
+ * Valid stat in DMA buffer that we need to increment over, even
+ * if we couldn't look up the id
+ */
+
+ decode_ok = efx_mon_mcdi_to_efx_stat(sensor, &id);
+ decode_ok =
+ decode_ok && efx_mon_get_stat_portmap(id, &stat_portmask);
- if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0)
+ if (!(decode_ok && (stat_portmask & port_mask)))
continue;
+ /* Either bad decode, or don't know what port stat is on */
+
EFSYS_ASSERT(id < EFX_MON_NSTATS);
/*
@@ -228,6 +116,10 @@ mcdi_mon_decode_stats(
stat[id].emsv_state = (uint16_t)EFX_DWORD_FIELD(dword,
MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
+
+ stat[id].emsv_unit =
+ efx_mon_get_stat_unit(id, &stat_unit) ?
+ stat_unit : EFX_MON_STAT_UNIT_UNKNOWN;
}
}
@@ -244,7 +136,7 @@ mcdi_mon_ev(
__out efx_mon_stat_value_t *valuep)
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
- uint16_t port_mask;
+ efx_mon_stat_portmask_t port_mask, sensor_port_mask;
uint16_t sensor;
uint16_t state;
uint16_t value;
@@ -261,20 +153,22 @@ mcdi_mon_ev(
/* Hardware must support this MCDI sensor */
EFSYS_ASSERT3U(sensor, <,
(8 * enp->en_nic_cfg.enc_mcdi_sensor_mask_size));
- EFSYS_ASSERT((sensor % MCDI_MON_PAGE_SIZE) != MC_CMD_SENSOR_PAGE0_NEXT);
+ EFSYS_ASSERT((sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)) !=
+ MC_CMD_SENSOR_PAGE0_NEXT);
EFSYS_ASSERT(enp->en_nic_cfg.enc_mcdi_sensor_maskp != NULL);
- EFSYS_ASSERT(
- (enp->en_nic_cfg.enc_mcdi_sensor_maskp[sensor/MCDI_MON_PAGE_SIZE] &
- (1U << (sensor % MCDI_MON_PAGE_SIZE))) != 0);
+ EFSYS_ASSERT((enp->en_nic_cfg.enc_mcdi_sensor_maskp[
+ sensor / (MC_CMD_SENSOR_PAGE0_NEXT + 1)] &
+ (1U << (sensor % (MC_CMD_SENSOR_PAGE0_NEXT + 1)))) != 0);
- /* But we don't have to understand it */
- if (sensor >= EFX_ARRAY_SIZE(mcdi_sensor_map)) {
+ /* And we need to understand it, to get port-map */
+ if (!efx_mon_mcdi_to_efx_stat(sensor, &id)) {
rc = ENOTSUP;
goto fail1;
}
- id = mcdi_sensor_map[sensor].msm_stat;
- if ((port_mask & mcdi_sensor_map[sensor].msm_port_mask) == 0)
+ if (!(efx_mon_get_stat_portmap(id, &sensor_port_mask) &&
+ (port_mask && sensor_port_mask))) {
return (ENODEV);
+ }
EFSYS_ASSERT(id < EFX_MON_NSTATS);
*idp = id;
@@ -297,9 +191,15 @@ efx_mcdi_read_sensors(
__in uint32_t size)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_READ_SENSORS_EXT_IN_LEN,
- MC_CMD_READ_SENSORS_EXT_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_READ_SENSORS_EXT_IN_LEN,
+ MC_CMD_READ_SENSORS_EXT_OUT_LEN);
uint32_t addr_lo, addr_hi;
+ efx_rc_t rc;
+
+ if (EFSYS_MEM_SIZE(esmp) < size) {
+ rc = EINVAL;
+ goto fail1;
+ }
req.emr_cmd = MC_CMD_READ_SENSORS;
req.emr_in_buf = payload;
@@ -317,6 +217,11 @@ efx_mcdi_read_sensors(
efx_mcdi_execute(enp, &req);
return (req.emr_rc);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
}
static __checkReturn efx_rc_t
@@ -325,8 +230,8 @@ efx_mcdi_sensor_info_npages(
__out uint32_t *npagesp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
- MC_CMD_SENSOR_INFO_OUT_LENMAX)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
+ MC_CMD_SENSOR_INFO_OUT_LENMAX);
int page;
efx_rc_t rc;
@@ -369,8 +274,8 @@ efx_mcdi_sensor_info(
__in size_t npages)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_SENSOR_INFO_EXT_IN_LEN,
- MC_CMD_SENSOR_INFO_OUT_LENMAX)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
+ MC_CMD_SENSOR_INFO_OUT_LENMAX);
uint32_t page;
efx_rc_t rc;
@@ -429,6 +334,86 @@ fail1:
return (rc);
}
+static __checkReturn efx_rc_t
+efx_mcdi_sensor_info_page(
+ __in efx_nic_t *enp,
+ __in uint32_t page,
+ __out uint32_t *mask_part,
+ __out_ecount((sizeof (*mask_part) * 8) - 1)
+ efx_mon_stat_limits_t *limits)
+{
+ efx_mcdi_req_t req;
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SENSOR_INFO_EXT_IN_LEN,
+ MC_CMD_SENSOR_INFO_OUT_LENMAX);
+ efx_rc_t rc;
+ uint32_t mask_copy;
+ efx_dword_t *maskp;
+ efx_qword_t *limit_info;
+
+ EFSYS_ASSERT(mask_part != NULL);
+ EFSYS_ASSERT(limits != NULL);
+
+ memset(limits, 0,
+ ((sizeof (*mask_part) * 8) - 1) * sizeof (efx_mon_stat_limits_t));
+
+ req.emr_cmd = MC_CMD_SENSOR_INFO;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_SENSOR_INFO_EXT_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_SENSOR_INFO_OUT_LENMAX;
+
+ MCDI_IN_SET_DWORD(req, SENSOR_INFO_EXT_IN_PAGE, page);
+
+ efx_mcdi_execute(enp, &req);
+
+ rc = req.emr_rc;
+
+ if (rc != 0)
+ goto fail1;
+
+ EFSYS_ASSERT(sizeof (*limit_info) ==
+ MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN);
+ maskp = MCDI_OUT2(req, efx_dword_t, SENSOR_INFO_OUT_MASK);
+ limit_info = (efx_qword_t *)(maskp + 1);
+
+ *mask_part = maskp->ed_u32[0];
+ mask_copy = *mask_part;
+
+ /* Copy an entry for all but the highest bit set. */
+ while (mask_copy) {
+
+ if (mask_copy == (1U << MC_CMD_SENSOR_PAGE0_NEXT)) {
+ /* Only next page bit set. */
+ mask_copy = 0;
+ } else {
+ /* Clear lowest bit */
+ mask_copy = mask_copy & ~(mask_copy ^ (mask_copy - 1));
+ /* And copy out limit entry into buffer */
+ limits->emlv_warning_min = EFX_QWORD_FIELD(*limit_info,
+ MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1);
+
+ limits->emlv_warning_max = EFX_QWORD_FIELD(*limit_info,
+ MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1);
+
+ limits->emlv_fatal_min = EFX_QWORD_FIELD(*limit_info,
+ MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2);
+
+ limits->emlv_fatal_max = EFX_QWORD_FIELD(*limit_info,
+ MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2);
+
+ limits++;
+ limit_info++;
+ }
+ }
+
+ return (rc);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
__checkReturn efx_rc_t
mcdi_mon_stats_update(
__in efx_nic_t *enp,
@@ -457,6 +442,96 @@ fail1:
return (rc);
}
+static void
+lowest_set_bit(
+ __in uint32_t input_mask,
+ __out uint32_t *lowest_bit_mask,
+ __out uint32_t *lowest_bit_num
+)
+{
+ uint32_t x;
+ uint32_t set_bit, bit_index;
+
+ x = (input_mask ^ (input_mask - 1));
+ set_bit = (x + 1) >> 1;
+ if (!set_bit)
+ set_bit = (1U << 31U);
+
+ bit_index = 0;
+ if (set_bit & 0xFFFF0000)
+ bit_index += 16;
+ if (set_bit & 0xFF00FF00)
+ bit_index += 8;
+ if (set_bit & 0xF0F0F0F0)
+ bit_index += 4;
+ if (set_bit & 0xCCCCCCCC)
+ bit_index += 2;
+ if (set_bit & 0xAAAAAAAA)
+ bit_index += 1;
+
+ *lowest_bit_mask = set_bit;
+ *lowest_bit_num = bit_index;
+}
+
+ __checkReturn efx_rc_t
+mcdi_mon_limits_update(
+ __in efx_nic_t *enp,
+ __inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values)
+{
+ efx_rc_t rc;
+ uint32_t page;
+ uint32_t page_mask;
+ uint32_t limit_index;
+ efx_mon_stat_limits_t limits[sizeof (page_mask) * 8];
+ efx_mon_stat_t stat;
+
+ page = 0;
+ page--;
+ do {
+ page++;
+
+ rc = efx_mcdi_sensor_info_page(enp, page, &page_mask, limits);
+ if (rc != 0)
+ goto fail1;
+
+ limit_index = 0;
+ while (page_mask) {
+ uint32_t set_bit;
+ uint32_t page_index;
+ uint32_t mcdi_index;
+
+ if (page_mask == (1U << MC_CMD_SENSOR_PAGE0_NEXT))
+ break;
+
+ lowest_set_bit(page_mask, &set_bit, &page_index);
+ page_mask = page_mask & ~set_bit;
+
+ mcdi_index =
+ page_index + (sizeof (page_mask) * 8 * page);
+
+ /*
+ * This can fail if MCDI reports newer stats than the
+ * drivers understand, or the bit is the next page bit.
+ *
+ * Driver needs to be tolerant of this.
+ */
+ if (!efx_mon_mcdi_to_efx_stat(mcdi_index, &stat))
+ continue;
+
+ values[stat] = limits[limit_index];
+ limit_index++;
+ }
+
+ } while (page_mask & (1U << MC_CMD_SENSOR_PAGE0_NEXT));
+
+ return (rc);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
__checkReturn efx_rc_t
mcdi_mon_cfg_build(
__in efx_nic_t *enp)