diff --git a/drivers/net/sfc/efx/base/ef10_ev.c b/drivers/net/sfc/efx/base/ef10_ev.c
index f58ccc6..e93b458 100644
--- a/drivers/net/sfc/efx/base/ef10_ev.c
+++ b/drivers/net/sfc/efx/base/ef10_ev.c
@@ -30,6 +30,9 @@
 
 #include "efx.h"
 #include "efx_impl.h"
+#if EFSYS_OPT_MON_STATS
+#include "mcdi_mon.h"
+#endif
 
 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
 
@@ -1085,6 +1088,23 @@ ef10_ev_mcdi(
 	}
 
 	case MCDI_EVENT_CODE_SENSOREVT: {
+#if EFSYS_OPT_MON_STATS
+		efx_mon_stat_t id;
+		efx_mon_stat_value_t value;
+		efx_rc_t rc;
+
+		/* Decode monitor stat for MCDI sensor (if supported) */
+		if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0) {
+			/* Report monitor stat change */
+			should_abort = eecp->eec_monitor(arg, id, value);
+		} else if (rc == ENOTSUP) {
+			should_abort = eecp->eec_exception(arg,
+				EFX_EXCEPTION_UNKNOWN_SENSOREVT,
+				MCDI_EV_FIELD(eqp, DATA));
+		} else {
+			EFSYS_ASSERT(rc == ENODEV);	/* Wrong port */
+		}
+#endif
 		break;
 	}
 
diff --git a/drivers/net/sfc/efx/base/ef10_nic.c b/drivers/net/sfc/efx/base/ef10_nic.c
index fec6a69..32706f4 100644
--- a/drivers/net/sfc/efx/base/ef10_nic.c
+++ b/drivers/net/sfc/efx/base/ef10_nic.c
@@ -1382,10 +1382,22 @@ ef10_nic_probe(
 		goto fail6;
 #endif
 
+#if EFSYS_OPT_MON_STATS
+	if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
+		/* Unprivileged functions do not have access to sensors */
+		if (rc != EACCES)
+			goto fail7;
+	}
+#endif
+
 	encp->enc_features = enp->en_features;
 
 	return (0);
 
+#if EFSYS_OPT_MON_STATS
+fail7:
+	EFSYS_PROBE(fail7);
+#endif
 #if EFSYS_OPT_LOOPBACK
 fail6:
 	EFSYS_PROBE(fail6);
@@ -1781,6 +1793,9 @@ ef10_nic_fini(
 ef10_nic_unprobe(
 	__in		efx_nic_t *enp)
 {
+#if EFSYS_OPT_MON_STATS
+	mcdi_mon_cfg_free(enp);
+#endif /* EFSYS_OPT_MON_STATS */
 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
 }
 
diff --git a/drivers/net/sfc/efx/base/efx.h b/drivers/net/sfc/efx/base/efx.h
index 70569e7..4fc0207 100644
--- a/drivers/net/sfc/efx/base/efx.h
+++ b/drivers/net/sfc/efx/base/efx.h
@@ -615,6 +615,125 @@ extern	__checkReturn	efx_rc_t
 efx_mon_init(
 	__in		efx_nic_t *enp);
 
+#if EFSYS_OPT_MON_STATS
+
+#define	EFX_MON_STATS_PAGE_SIZE 0x100
+#define	EFX_MON_MASK_ELEMENT_SIZE 32
+
+/* START MKCONFIG GENERATED MonitorHeaderStatsBlock 5d4ee5185e419abe */
+typedef enum efx_mon_stat_e {
+	EFX_MON_STAT_2_5V,
+	EFX_MON_STAT_VCCP1,
+	EFX_MON_STAT_VCC,
+	EFX_MON_STAT_5V,
+	EFX_MON_STAT_12V,
+	EFX_MON_STAT_VCCP2,
+	EFX_MON_STAT_EXT_TEMP,
+	EFX_MON_STAT_INT_TEMP,
+	EFX_MON_STAT_AIN1,
+	EFX_MON_STAT_AIN2,
+	EFX_MON_STAT_INT_COOLING,
+	EFX_MON_STAT_EXT_COOLING,
+	EFX_MON_STAT_1V,
+	EFX_MON_STAT_1_2V,
+	EFX_MON_STAT_1_8V,
+	EFX_MON_STAT_3_3V,
+	EFX_MON_STAT_1_2VA,
+	EFX_MON_STAT_VREF,
+	EFX_MON_STAT_VAOE,
+	EFX_MON_STAT_AOE_TEMP,
+	EFX_MON_STAT_PSU_AOE_TEMP,
+	EFX_MON_STAT_PSU_TEMP,
+	EFX_MON_STAT_FAN0,
+	EFX_MON_STAT_FAN1,
+	EFX_MON_STAT_FAN2,
+	EFX_MON_STAT_FAN3,
+	EFX_MON_STAT_FAN4,
+	EFX_MON_STAT_VAOE_IN,
+	EFX_MON_STAT_IAOE,
+	EFX_MON_STAT_IAOE_IN,
+	EFX_MON_STAT_NIC_POWER,
+	EFX_MON_STAT_0_9V,
+	EFX_MON_STAT_I0_9V,
+	EFX_MON_STAT_I1_2V,
+	EFX_MON_STAT_0_9V_ADC,
+	EFX_MON_STAT_INT_TEMP2,
+	EFX_MON_STAT_VREG_TEMP,
+	EFX_MON_STAT_VREG_0_9V_TEMP,
+	EFX_MON_STAT_VREG_1_2V_TEMP,
+	EFX_MON_STAT_INT_VPTAT,
+	EFX_MON_STAT_INT_ADC_TEMP,
+	EFX_MON_STAT_EXT_VPTAT,
+	EFX_MON_STAT_EXT_ADC_TEMP,
+	EFX_MON_STAT_AMBIENT_TEMP,
+	EFX_MON_STAT_AIRFLOW,
+	EFX_MON_STAT_VDD08D_VSS08D_CSR,
+	EFX_MON_STAT_VDD08D_VSS08D_CSR_EXTADC,
+	EFX_MON_STAT_HOTPOINT_TEMP,
+	EFX_MON_STAT_PHY_POWER_SWITCH_PORT0,
+	EFX_MON_STAT_PHY_POWER_SWITCH_PORT1,
+	EFX_MON_STAT_MUM_VCC,
+	EFX_MON_STAT_0V9_A,
+	EFX_MON_STAT_I0V9_A,
+	EFX_MON_STAT_0V9_A_TEMP,
+	EFX_MON_STAT_0V9_B,
+	EFX_MON_STAT_I0V9_B,
+	EFX_MON_STAT_0V9_B_TEMP,
+	EFX_MON_STAT_CCOM_AVREG_1V2_SUPPLY,
+	EFX_MON_STAT_CCOM_AVREG_1V2_SUPPLY_EXT_ADC,
+	EFX_MON_STAT_CCOM_AVREG_1V8_SUPPLY,
+	EFX_MON_STAT_CCOM_AVREG_1V8_SUPPLY_EXT_ADC,
+	EFX_MON_STAT_CONTROLLER_MASTER_VPTAT,
+	EFX_MON_STAT_CONTROLLER_MASTER_INTERNAL_TEMP,
+	EFX_MON_STAT_CONTROLLER_MASTER_VPTAT_EXT_ADC,
+	EFX_MON_STAT_CONTROLLER_MASTER_INTERNAL_TEMP_EXT_ADC,
+	EFX_MON_STAT_CONTROLLER_SLAVE_VPTAT,
+	EFX_MON_STAT_CONTROLLER_SLAVE_INTERNAL_TEMP,
+	EFX_MON_STAT_CONTROLLER_SLAVE_VPTAT_EXT_ADC,
+	EFX_MON_STAT_CONTROLLER_SLAVE_INTERNAL_TEMP_EXT_ADC,
+	EFX_MON_STAT_SODIMM_VOUT,
+	EFX_MON_STAT_SODIMM_0_TEMP,
+	EFX_MON_STAT_SODIMM_1_TEMP,
+	EFX_MON_STAT_PHY0_VCC,
+	EFX_MON_STAT_PHY1_VCC,
+	EFX_MON_STAT_CONTROLLER_TDIODE_TEMP,
+	EFX_MON_STAT_BOARD_FRONT_TEMP,
+	EFX_MON_STAT_BOARD_BACK_TEMP,
+	EFX_MON_NSTATS
+} efx_mon_stat_t;
+
+/* END MKCONFIG GENERATED MonitorHeaderStatsBlock */
+
+typedef enum efx_mon_stat_state_e {
+	EFX_MON_STAT_STATE_OK = 0,
+	EFX_MON_STAT_STATE_WARNING = 1,
+	EFX_MON_STAT_STATE_FATAL = 2,
+	EFX_MON_STAT_STATE_BROKEN = 3,
+	EFX_MON_STAT_STATE_NO_READING = 4,
+} efx_mon_stat_state_t;
+
+typedef struct efx_mon_stat_value_s {
+	uint16_t	emsv_value;
+	uint16_t	emsv_state;
+} efx_mon_stat_value_t;
+
+#if EFSYS_OPT_NAMES
+
+extern					const char *
+efx_mon_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_mon_stat_t id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn			efx_rc_t
+efx_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
 extern		void
 efx_mon_fini(
 	__in	efx_nic_t *enp);
@@ -973,6 +1092,10 @@ typedef struct efx_nic_cfg_s {
 #endif
 	char			enc_phy_revision[21];
 	efx_mon_type_t		enc_mon_type;
+#if EFSYS_OPT_MON_STATS
+	uint32_t		enc_mon_stat_dma_buf_size;
+	uint32_t		enc_mon_stat_mask[(EFX_MON_NSTATS + 31) / 32];
+#endif
 	unsigned int		enc_features;
 	uint8_t			enc_mac_addr[6];
 	uint8_t			enc_port;	/* PHY port number */
@@ -1009,6 +1132,10 @@ typedef struct efx_nic_cfg_s {
 #if EFSYS_OPT_PHY_STATS
 	uint32_t		enc_mcdi_phy_stat_mask;
 #endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_MON_STATS
+	uint32_t		*enc_mcdi_sensor_maskp;
+	uint32_t		enc_mcdi_sensor_mask_size;
+#endif	/* EFSYS_OPT_MON_STATS */
 #endif	/* EFSYS_OPT_MCDI */
 #if EFSYS_OPT_BIST
 	uint32_t		enc_bist_mask;
@@ -1358,6 +1485,16 @@ typedef __checkReturn	boolean_t
 	__in_opt	void *arg,
 	__in		efx_link_mode_t	link_mode);
 
+#if EFSYS_OPT_MON_STATS
+
+typedef __checkReturn	boolean_t
+(*efx_monitor_ev_t)(
+	__in_opt	void *arg,
+	__in		efx_mon_stat_t id,
+	__in		efx_mon_stat_value_t value);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
 #if EFSYS_OPT_MAC_STATS
 
 typedef __checkReturn	boolean_t
@@ -1381,6 +1518,9 @@ typedef struct efx_ev_callbacks_s {
 	efx_wake_up_ev_t		eec_wake_up;
 	efx_timer_ev_t			eec_timer;
 	efx_link_change_ev_t		eec_link_change;
+#if EFSYS_OPT_MON_STATS
+	efx_monitor_ev_t		eec_monitor;
+#endif	/* EFSYS_OPT_MON_STATS */
 #if EFSYS_OPT_MAC_STATS
 	efx_mac_stats_ev_t		eec_mac_stats;
 #endif	/* EFSYS_OPT_MAC_STATS */
diff --git a/drivers/net/sfc/efx/base/efx_check.h b/drivers/net/sfc/efx/base/efx_check.h
index 22cf892..3e4e9ba 100644
--- a/drivers/net/sfc/efx/base/efx_check.h
+++ b/drivers/net/sfc/efx/base/efx_check.h
@@ -159,6 +159,13 @@
 #  error "MON_HUNTINGTON is obsolete (replaced by MON_MCDI)."
 #endif
 
+#if EFSYS_OPT_MON_STATS
+/* Support monitor statistics (voltage/temperature) */
+# if !(EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)
+#  error "MON_STATS requires SIENA or HUNTINGTON or MEDFORD"
+# endif
+#endif /* EFSYS_OPT_MON_STATS */
+
 #if EFSYS_OPT_NAMES
 /* Support printable names for statistics */
 # if !(EFSYS_OPT_LOOPBACK || EFSYS_OPT_MAC_STATS || EFSYS_OPT_MCDI || \
diff --git a/drivers/net/sfc/efx/base/efx_ev.c b/drivers/net/sfc/efx/base/efx_ev.c
index 9f6a309..ac3ebe3 100644
--- a/drivers/net/sfc/efx/base/efx_ev.c
+++ b/drivers/net/sfc/efx/base/efx_ev.c
@@ -1100,6 +1100,9 @@ siena_ev_mcdi(
 
 	EFSYS_ASSERT(eecp->eec_link_change != NULL);
 	EFSYS_ASSERT(eecp->eec_exception != NULL);
+#if EFSYS_OPT_MON_STATS
+	EFSYS_ASSERT(eecp->eec_monitor != NULL);
+#endif
 
 	EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE);
 
@@ -1124,7 +1127,22 @@ siena_ev_mcdi(
 		break;
 	}
 	case MCDI_EVENT_CODE_SENSOREVT: {
+#if EFSYS_OPT_MON_STATS
+		efx_mon_stat_t id;
+		efx_mon_stat_value_t value;
+		efx_rc_t rc;
+
+		if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0)
+			should_abort = eecp->eec_monitor(arg, id, value);
+		else if (rc == ENOTSUP) {
+			should_abort = eecp->eec_exception(arg,
+				EFX_EXCEPTION_UNKNOWN_SENSOREVT,
+				MCDI_EV_FIELD(eqp, DATA));
+		} else
+			EFSYS_ASSERT(rc == ENODEV);	/* Wrong port */
+#else
 		should_abort = B_FALSE;
+#endif
 		break;
 	}
 	case MCDI_EVENT_CODE_SCHEDERR:
diff --git a/drivers/net/sfc/efx/base/efx_impl.h b/drivers/net/sfc/efx/base/efx_impl.h
index 12a8a4f..c9d2d11 100644
--- a/drivers/net/sfc/efx/base/efx_impl.h
+++ b/drivers/net/sfc/efx/base/efx_impl.h
@@ -291,6 +291,10 @@ typedef struct efx_port_s {
 } efx_port_t;
 
 typedef struct efx_mon_ops_s {
+#if EFSYS_OPT_MON_STATS
+	efx_rc_t	(*emo_stats_update)(efx_nic_t *, efsys_mem_t *,
+					    efx_mon_stat_value_t *);
+#endif	/* EFSYS_OPT_MON_STATS */
 } efx_mon_ops_t;
 
 typedef struct efx_mon_s {
diff --git a/drivers/net/sfc/efx/base/efx_mon.c b/drivers/net/sfc/efx/base/efx_mon.c
index d3ed40d..68314cf 100644
--- a/drivers/net/sfc/efx/base/efx_mon.c
+++ b/drivers/net/sfc/efx/base/efx_mon.c
@@ -100,6 +100,124 @@ efx_mon_init(
 	return (rc);
 }
 
+#if EFSYS_OPT_MON_STATS
+
+#if EFSYS_OPT_NAMES
+
+/* START MKCONFIG GENERATED MonitorStatNamesBlock 31f437eafb0b0437 */
+static const char * const __mon_stat_name[] = {
+	"value_2_5v",
+	"value_vccp1",
+	"value_vcc",
+	"value_5v",
+	"value_12v",
+	"value_vccp2",
+	"value_ext_temp",
+	"value_int_temp",
+	"value_ain1",
+	"value_ain2",
+	"controller_cooling",
+	"ext_cooling",
+	"1v",
+	"1_2v",
+	"1_8v",
+	"3_3v",
+	"1_2va",
+	"vref",
+	"vaoe",
+	"aoe_temperature",
+	"psu_aoe_temperature",
+	"psu_temperature",
+	"fan0",
+	"fan1",
+	"fan2",
+	"fan3",
+	"fan4",
+	"vaoe_in",
+	"iaoe",
+	"iaoe_in",
+	"nic_power",
+	"0_9v",
+	"i0_9v",
+	"i1_2v",
+	"0_9v_adc",
+	"controller_temperature2",
+	"vreg_temperature",
+	"vreg_0_9v_temperature",
+	"vreg_1_2v_temperature",
+	"int_vptat",
+	"controller_internal_adc_temperature",
+	"ext_vptat",
+	"controller_external_adc_temperature",
+	"ambient_temperature",
+	"airflow",
+	"vdd08d_vss08d_csr",
+	"vdd08d_vss08d_csr_extadc",
+	"hotpoint_temperature",
+	"phy_power_switch_port0",
+	"phy_power_switch_port1",
+	"mum_vcc",
+	"0v9_a",
+	"i0v9_a",
+	"0v9_a_temp",
+	"0v9_b",
+	"i0v9_b",
+	"0v9_b_temp",
+	"ccom_avreg_1v2_supply",
+	"ccom_avreg_1v2_supply_ext_adc",
+	"ccom_avreg_1v8_supply",
+	"ccom_avreg_1v8_supply_ext_adc",
+	"controller_master_vptat",
+	"controller_master_internal_temp",
+	"controller_master_vptat_ext_adc",
+	"controller_master_internal_temp_ext_adc",
+	"controller_slave_vptat",
+	"controller_slave_internal_temp",
+	"controller_slave_vptat_ext_adc",
+	"controller_slave_internal_temp_ext_adc",
+	"sodimm_vout",
+	"sodimm_0_temp",
+	"sodimm_1_temp",
+	"phy0_vcc",
+	"phy1_vcc",
+	"controller_tdiode_temp",
+	"board_front_temp",
+	"board_back_temp",
+};
+
+/* END MKCONFIG GENERATED MonitorStatNamesBlock */
+
+extern					const char *
+efx_mon_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_mon_stat_t id)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	EFSYS_ASSERT3U(id, <, EFX_MON_NSTATS);
+	return (__mon_stat_name[id]);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn			efx_rc_t
+efx_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	efx_mon_t *emp = &(enp->en_mon);
+	const efx_mon_ops_t *emop = emp->em_emop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MON);
+
+	return (emop->emo_stats_update(enp, esmp, values));
+}
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
 		void
 efx_mon_fini(
 	__in	efx_nic_t *enp)
diff --git a/drivers/net/sfc/efx/base/siena_nic.c b/drivers/net/sfc/efx/base/siena_nic.c
index d28d1d2..5d0f6e8 100644
--- a/drivers/net/sfc/efx/base/siena_nic.c
+++ b/drivers/net/sfc/efx/base/siena_nic.c
@@ -221,10 +221,19 @@ siena_nic_probe(
 		goto fail11;
 #endif
 
+#if EFSYS_OPT_MON_STATS
+	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
+		goto fail12;
+#endif
+
 	encp->enc_features = enp->en_features;
 
 	return (0);
 
+#if EFSYS_OPT_MON_STATS
+fail12:
+	EFSYS_PROBE(fail12);
+#endif
 #if EFSYS_OPT_LOOPBACK
 fail11:
 	EFSYS_PROBE(fail11);
@@ -376,6 +385,9 @@ siena_nic_fini(
 siena_nic_unprobe(
 	__in		efx_nic_t *enp)
 {
+#if EFSYS_OPT_MON_STATS
+	mcdi_mon_cfg_free(enp);
+#endif /* EFSYS_OPT_MON_STATS */
 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
 }
 
