From bbc42f34116c4baf04ead3e29e8d249311f31991 Mon Sep 17 00:00:00 2001 From: Igor Romanov Date: Fri, 2 Jul 2021 11:39:41 +0300 Subject: [PATCH] common/sfc_efx/base: add counter creation MCDI wrappers User will be able to create and free MAE counters. Support for associating counters with action set will be added in upcoming patches. Signed-off-by: Igor Romanov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton Reviewed-by: Ivan Malov --- drivers/common/sfc_efx/base/efx.h | 37 ++++++ drivers/common/sfc_efx/base/efx_impl.h | 1 + drivers/common/sfc_efx/base/efx_mae.c | 158 +++++++++++++++++++++++++ drivers/common/sfc_efx/base/efx_mcdi.h | 7 ++ drivers/common/sfc_efx/version.map | 2 + 5 files changed, 205 insertions(+) diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h index 9bbd7cae55..d0f8bc10b3 100644 --- a/drivers/common/sfc_efx/base/efx.h +++ b/drivers/common/sfc_efx/base/efx.h @@ -4406,6 +4406,10 @@ efx_mae_action_set_fill_in_eh_id( __in efx_mae_actions_t *spec, __in const efx_mae_eh_id_t *eh_idp); +typedef struct efx_counter_s { + uint32_t id; +} efx_counter_t; + /* Action set ID */ typedef struct efx_mae_aset_id_s { uint32_t id; @@ -4418,6 +4422,39 @@ efx_mae_action_set_alloc( __in const efx_mae_actions_t *spec, __out efx_mae_aset_id_t *aset_idp); +/* + * Generation count has two purposes: + * + * 1) Distinguish between counter packets that belong to freed counter + * and the packets that belong to reallocated counter (with the same ID); + * 2) Make sure that all packets are received for a counter that was freed; + * + * API users should provide generation count out parameter in allocation + * function if counters can be reallocated and consistent counter values are + * required. + * + * API users that need consistent final counter values after counter + * deallocation or counter stream stop should provide the parameter in + * functions that free the counters and stop the counter stream. + */ +LIBEFX_API +extern __checkReturn efx_rc_t +efx_mae_counters_alloc( + __in efx_nic_t *enp, + __in uint32_t n_counters, + __out uint32_t *n_allocatedp, + __out_ecount(n_counters) efx_counter_t *countersp, + __out_opt uint32_t *gen_countp); + +LIBEFX_API +extern __checkReturn efx_rc_t +efx_mae_counters_free( + __in efx_nic_t *enp, + __in uint32_t n_counters, + __out uint32_t *n_freedp, + __in_ecount(n_counters) const efx_counter_t *countersp, + __out_opt uint32_t *gen_countp); + LIBEFX_API extern __checkReturn efx_rc_t efx_mae_action_set_free( diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h index f891e2616e..9dbf6d450c 100644 --- a/drivers/common/sfc_efx/base/efx_impl.h +++ b/drivers/common/sfc_efx/base/efx_impl.h @@ -821,6 +821,7 @@ typedef struct efx_mae_s { /** Outer rule match field capabilities. */ efx_mae_field_cap_t *em_outer_rule_field_caps; size_t em_outer_rule_field_caps_size; + uint32_t em_max_ncounters; } efx_mae_t; #endif /* EFSYS_OPT_MAE */ diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c index 5697488040..8f9f9f417d 100644 --- a/drivers/common/sfc_efx/base/efx_mae.c +++ b/drivers/common/sfc_efx/base/efx_mae.c @@ -67,6 +67,9 @@ efx_mae_get_capabilities( maep->em_max_nfields = MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT); + maep->em_max_ncounters = + MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS); + return (0); fail2: @@ -2385,6 +2388,161 @@ efx_mae_action_set_alloc( return (0); +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + __checkReturn efx_rc_t +efx_mae_counters_alloc( + __in efx_nic_t *enp, + __in uint32_t n_counters, + __out uint32_t *n_allocatedp, + __out_ecount(n_counters) efx_counter_t *countersp, + __out_opt uint32_t *gen_countp) +{ + EFX_MCDI_DECLARE_BUF(payload, + MC_CMD_MAE_COUNTER_ALLOC_IN_LEN, + MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2); + efx_mae_t *maep = enp->en_maep; + uint32_t n_allocated; + efx_mcdi_req_t req; + unsigned int i; + efx_rc_t rc; + + if (n_counters > maep->em_max_ncounters || + n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM || + n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) { + rc = EINVAL; + goto fail1; + } + + req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters); + + MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT, + n_counters); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail2; + } + + if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) { + rc = EMSGSIZE; + goto fail3; + } + + n_allocated = MCDI_OUT_DWORD(req, + MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT); + if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) { + rc = EFAULT; + goto fail4; + } + + for (i = 0; i < n_allocated; i++) { + countersp[i].id = MCDI_OUT_INDEXED_DWORD(req, + MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i); + } + + if (gen_countp != NULL) { + *gen_countp = MCDI_OUT_DWORD(req, + MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT); + } + + *n_allocatedp = n_allocated; + + return (0); + +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_mae_counters_free( + __in efx_nic_t *enp, + __in uint32_t n_counters, + __out uint32_t *n_freedp, + __in_ecount(n_counters) const efx_counter_t *countersp, + __out_opt uint32_t *gen_countp) +{ + EFX_MCDI_DECLARE_BUF(payload, + MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2, + MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2); + efx_mae_t *maep = enp->en_maep; + efx_mcdi_req_t req; + uint32_t n_freed; + unsigned int i; + efx_rc_t rc; + + if (n_counters > maep->em_max_ncounters || + n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM || + n_counters > + MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) { + rc = EINVAL; + goto fail1; + } + + req.emr_cmd = MC_CMD_MAE_COUNTER_FREE; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters); + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters); + + for (i = 0; i < n_counters; i++) { + MCDI_IN_SET_INDEXED_DWORD(req, + MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id); + } + MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT, + n_counters); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail2; + } + + if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) { + rc = EMSGSIZE; + goto fail3; + } + + n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT); + + if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) { + rc = EFAULT; + goto fail4; + } + + if (gen_countp != NULL) { + *gen_countp = MCDI_OUT_DWORD(req, + MAE_COUNTER_FREE_OUT_GENERATION_COUNT); + } + + *n_freedp = n_freed; + + return (0); + fail4: EFSYS_PROBE(fail4); fail3: diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h index 70a97ea337..90b70de97b 100644 --- a/drivers/common/sfc_efx/base/efx_mcdi.h +++ b/drivers/common/sfc_efx/base/efx_mcdi.h @@ -311,6 +311,10 @@ efx_mcdi_phy_module_get_info( EFX_SET_DWORD_FIELD(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ MC_CMD_ ## _field, _value) +#define MCDI_IN_SET_INDEXED_DWORD(_emr, _ofst, _idx, _value) \ + EFX_POPULATE_DWORD_1(*(MCDI_IN2(_emr, efx_dword_t, _ofst) + \ + (_idx)), EFX_DWORD_0, _value) \ + #define MCDI_IN_POPULATE_DWORD_1(_emr, _ofst, _field1, _value1) \ EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst), \ MC_CMD_ ## _field1, _value1) @@ -451,6 +455,9 @@ efx_mcdi_phy_module_get_info( EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst), \ MC_CMD_ ## _field) +#define MCDI_OUT_INDEXED_DWORD(_emr, _ofst, _idx) \ + MCDI_OUT_INDEXED_DWORD_FIELD(_emr, _ofst, _idx, EFX_DWORD_0) + #define MCDI_OUT_INDEXED_DWORD_FIELD(_emr, _ofst, _idx, _field) \ EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) + \ (_idx)), _field) diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map index ae85ed18c6..30b243a1e7 100644 --- a/drivers/common/sfc_efx/version.map +++ b/drivers/common/sfc_efx/version.map @@ -102,6 +102,8 @@ INTERNAL { efx_mae_action_set_spec_fini; efx_mae_action_set_spec_init; efx_mae_action_set_specs_equal; + efx_mae_counters_alloc; + efx_mae_counters_free; efx_mae_encap_header_alloc; efx_mae_encap_header_free; efx_mae_fini; -- 2.20.1