+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);
+}
+