net/sfc/base: add API to retrieve sensor limits
Signed-off-by: Martin Harvey <mharvey@solarflare.com> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
This commit is contained in:
parent
252faf84f4
commit
dded2ffdf9
@ -774,6 +774,13 @@ typedef struct efx_mon_stat_value_s {
|
||||
efx_mon_stat_unit_t emsv_unit;
|
||||
} efx_mon_stat_value_t;
|
||||
|
||||
typedef struct efx_mon_limit_value_s {
|
||||
uint16_t emlv_warning_min;
|
||||
uint16_t emlv_warning_max;
|
||||
uint16_t emlv_fatal_min;
|
||||
uint16_t emlv_fatal_max;
|
||||
} efx_mon_stat_limits_t;
|
||||
|
||||
typedef enum efx_mon_stat_portmask_e {
|
||||
EFX_MON_STAT_PORTMAP_NONE = 0,
|
||||
EFX_MON_STAT_PORTMAP_PORT0 = 1,
|
||||
@ -819,6 +826,11 @@ efx_mon_stats_update(
|
||||
__in efsys_mem_t *esmp,
|
||||
__inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
efx_mon_limits_update(
|
||||
__in efx_nic_t *enp,
|
||||
__inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values);
|
||||
|
||||
#endif /* EFSYS_OPT_MON_STATS */
|
||||
|
||||
extern void
|
||||
|
@ -317,6 +317,8 @@ 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 *);
|
||||
efx_rc_t (*emo_limits_update)(efx_nic_t *,
|
||||
efx_mon_stat_limits_t *);
|
||||
#endif /* EFSYS_OPT_MON_STATS */
|
||||
} efx_mon_ops_t;
|
||||
|
||||
|
@ -38,7 +38,8 @@ efx_mon_name(
|
||||
#if EFSYS_OPT_MON_MCDI
|
||||
static const efx_mon_ops_t __efx_mon_mcdi_ops = {
|
||||
#if EFSYS_OPT_MON_STATS
|
||||
mcdi_mon_stats_update /* emo_stats_update */
|
||||
mcdi_mon_stats_update, /* emo_stats_update */
|
||||
mcdi_mon_limits_update, /* emo_limits_update */
|
||||
#endif /* EFSYS_OPT_MON_STATS */
|
||||
};
|
||||
#endif
|
||||
@ -815,6 +816,20 @@ efx_mon_stats_update(
|
||||
return (emop->emo_stats_update(enp, esmp, values));
|
||||
}
|
||||
|
||||
__checkReturn efx_rc_t
|
||||
efx_mon_limits_update(
|
||||
__in efx_nic_t *enp,
|
||||
__inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_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_limits_update(enp, values));
|
||||
}
|
||||
|
||||
#endif /* EFSYS_OPT_MON_STATS */
|
||||
|
||||
void
|
||||
|
@ -334,6 +334,87 @@ efx_mcdi_sensor_info(
|
||||
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;
|
||||
uint8_t payload[MAX(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));
|
||||
|
||||
(void) memset(payload, 0, sizeof (payload));
|
||||
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,
|
||||
@ -356,6 +437,96 @@ mcdi_mon_stats_update(
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -39,6 +39,11 @@ mcdi_mon_stats_update(
|
||||
__in efsys_mem_t *esmp,
|
||||
__inout_ecount(EFX_MON_NSTATS) efx_mon_stat_value_t *values);
|
||||
|
||||
extern __checkReturn efx_rc_t
|
||||
mcdi_mon_limits_update(
|
||||
__in efx_nic_t *enp,
|
||||
__inout_ecount(EFX_MON_NSTATS) efx_mon_stat_limits_t *values);
|
||||
|
||||
#endif /* EFSYS_OPT_MON_STATS */
|
||||
|
||||
#endif /* EFSYS_OPT_MON_MCDI */
|
||||
|
Loading…
Reference in New Issue
Block a user