common/sfc_efx/base: support adding deliver action to set

Introduce a mechanism for adding actions to an action set and
add support for DELIVER action.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
This commit is contained in:
Ivan Malov 2020-10-20 10:13:00 +01:00 committed by Ferruh Yigit
parent 0b90a1377d
commit 80019097c9
4 changed files with 163 additions and 1 deletions

View File

@ -4094,11 +4094,14 @@ typedef struct efx_mport_sel_s {
uint32_t sel;
} efx_mport_sel_t;
#define EFX_MPORT_NULL (0U)
/*
* Get MPORT selector of a physical port.
*
* The resulting MPORT selector is opaque to the caller and can be
* passed as an argument to efx_mae_match_spec_mport_set().
* passed as an argument to efx_mae_match_spec_mport_set()
* and efx_mae_action_set_populate_deliver().
*/
LIBEFX_API
extern __checkReturn efx_rc_t
@ -4163,6 +4166,12 @@ efx_mae_action_set_spec_fini(
__in efx_nic_t *enp,
__in efx_mae_actions_t *spec);
LIBEFX_API
extern __checkReturn efx_rc_t
efx_mae_action_set_populate_deliver(
__in efx_mae_actions_t *spec,
__in const efx_mport_sel_t *mportp);
LIBEFX_API
extern __checkReturn boolean_t
efx_mae_action_set_specs_equal(

View File

@ -1699,7 +1699,18 @@ struct efx_mae_match_spec_s {
} emms_mask_value_pairs;
};
typedef enum efx_mae_action_e {
/* DELIVER is always the last action. */
EFX_MAE_ACTION_DELIVER,
EFX_MAE_NACTIONS
} efx_mae_action_t;
struct efx_mae_actions_s {
/* Bitmap of actions in spec, indexed by action type */
uint32_t ema_actions;
efx_mport_sel_t ema_deliver_mport;
};
#endif /* EFSYS_OPT_MAE */

View File

@ -641,6 +641,147 @@ efx_mae_action_set_spec_fini(
EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
}
static __checkReturn efx_rc_t
efx_mae_action_set_add_deliver(
__in efx_mae_actions_t *spec,
__in size_t arg_size,
__in_bcount(arg_size) const uint8_t *arg)
{
efx_rc_t rc;
if (arg_size != sizeof (spec->ema_deliver_mport)) {
rc = EINVAL;
goto fail1;
}
if (arg == NULL) {
rc = EINVAL;
goto fail2;
}
memcpy(&spec->ema_deliver_mport, arg, arg_size);
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
typedef struct efx_mae_action_desc_s {
/* Action specific handler */
efx_rc_t (*emad_add)(efx_mae_actions_t *,
size_t, const uint8_t *);
} efx_mae_action_desc_t;
static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
[EFX_MAE_ACTION_DELIVER] = {
.emad_add = efx_mae_action_set_add_deliver
}
};
static const uint32_t efx_mae_action_ordered_map =
(1U << EFX_MAE_ACTION_DELIVER);
static const uint32_t efx_mae_action_repeat_map = 0;
/*
* Add an action to an action set.
*
* This has to be invoked in the desired action order.
* An out-of-order action request will be turned down.
*/
static __checkReturn efx_rc_t
efx_mae_action_set_spec_populate(
__in efx_mae_actions_t *spec,
__in efx_mae_action_t type,
__in size_t arg_size,
__in_bcount(arg_size) const uint8_t *arg)
{
uint32_t action_mask;
efx_rc_t rc;
EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
(sizeof (efx_mae_action_ordered_map) * 8));
EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
(sizeof (efx_mae_action_repeat_map) * 8));
EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
rc = EINVAL;
goto fail1;
}
action_mask = (1U << type);
if ((spec->ema_actions & action_mask) != 0) {
/* The action set already contains this action. */
if ((efx_mae_action_repeat_map & action_mask) == 0) {
/* Cannot add another non-repeatable action. */
rc = ENOTSUP;
goto fail2;
}
}
if ((efx_mae_action_ordered_map & action_mask) != 0) {
uint32_t later_actions_mask =
efx_mae_action_ordered_map &
~(action_mask | (action_mask - 1));
if ((spec->ema_actions & later_actions_mask) != 0) {
/* Cannot add an action after later ordered actions. */
rc = ENOTSUP;
goto fail3;
}
}
if (efx_mae_actions[type].emad_add != NULL) {
rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
if (rc != 0)
goto fail4;
}
spec->ema_actions |= action_mask;
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_action_set_populate_deliver(
__in efx_mae_actions_t *spec,
__in const efx_mport_sel_t *mportp)
{
const uint8_t *arg;
efx_rc_t rc;
if (mportp == NULL) {
rc = EINVAL;
goto fail1;
}
arg = (const uint8_t *)&mportp->sel;
return (efx_mae_action_set_spec_populate(spec,
EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
__checkReturn boolean_t
efx_mae_action_set_specs_equal(
__in const efx_mae_actions_t *left,

View File

@ -85,6 +85,7 @@ INTERNAL {
efx_mac_stats_upload;
efx_mac_up;
efx_mae_action_set_populate_deliver;
efx_mae_action_set_spec_fini;
efx_mae_action_set_spec_init;
efx_mae_action_set_specs_equal;