common/sfc_efx/base: support adding deliver action to set
authorIvan Malov <ivan.malov@oktetlabs.ru>
Tue, 20 Oct 2020 09:13:00 +0000 (10:13 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 3 Nov 2020 22:24:25 +0000 (23:24 +0100)
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>
drivers/common/sfc_efx/base/efx.h
drivers/common/sfc_efx/base/efx_impl.h
drivers/common/sfc_efx/base/efx_mae.c
drivers/common/sfc_efx/version.map

index 8d88834..6f63a6e 100644 (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(
index 44e6467..50f2b74 100644 (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 */
index 01b2e31..26e857c 100644 (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,
index 86ed437..d2a5d58 100644 (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;