sfc: support offloading TC VLAN push/pop actions to the MAE
authorEdward Cree <ecree.xilinx@gmail.com>
Thu, 9 Mar 2023 11:59:04 +0000 (11:59 +0000)
committerJakub Kicinski <kuba@kernel.org>
Sat, 11 Mar 2023 05:28:59 +0000 (21:28 -0800)
EF100 can pop and/or push up to two VLAN tags.

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Link: https://lore.kernel.org/r/20230309115904.56442-1-edward.cree@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/sfc/mae.c
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/sfc/tc.h

index 2d32abe..c53d354 100644 (file)
@@ -682,6 +682,10 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
        size_t outlen;
        int rc;
 
+       MCDI_POPULATE_DWORD_2(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+                             MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push,
+                             MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop);
+
        MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
                       MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
        MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
@@ -694,6 +698,18 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
                               MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
        MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID,
                       MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL);
+       if (act->vlan_push) {
+               MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
+                                act->vlan_tci[0]);
+               MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
+                                act->vlan_proto[0]);
+       }
+       if (act->vlan_push >= 2) {
+               MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
+                                act->vlan_tci[1]);
+               MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
+                                act->vlan_proto[1]);
+       }
        MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
                       MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
        if (act->deliver)
index b139b76..454e9d5 100644 (file)
@@ -233,6 +233,11 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
        ((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2),  \
        le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field)))
 /* Write a 16-bit field defined in the protocol as being big-endian. */
+#define MCDI_SET_WORD_BE(_buf, _field, _value) do {                    \
+       BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2);                   \
+       BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1);                   \
+       *(__force __be16 *)MCDI_PTR(_buf, _field) = (_value);           \
+       } while (0)
 #define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do {             \
        BUILD_BUG_ON(_field ## _LEN != 2);                              \
        BUILD_BUG_ON(_field ## _OFST & 1);                              \
index deeaab9..2b07bb2 100644 (file)
@@ -286,6 +286,8 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
 
 /* For details of action order constraints refer to SF-123102-TC-1ยง12.6.1 */
 enum efx_tc_action_order {
+       EFX_TC_AO_VLAN_POP,
+       EFX_TC_AO_VLAN_PUSH,
        EFX_TC_AO_COUNT,
        EFX_TC_AO_DELIVER
 };
@@ -294,6 +296,20 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
                                          enum efx_tc_action_order new)
 {
        switch (new) {
+       case EFX_TC_AO_VLAN_POP:
+               if (act->vlan_pop >= 2)
+                       return false;
+               /* If we've already pushed a VLAN, we can't then pop it;
+                * the hardware would instead try to pop an existing VLAN
+                * before pushing the new one.
+                */
+               if (act->vlan_push)
+                       return false;
+               fallthrough;
+       case EFX_TC_AO_VLAN_PUSH:
+               if (act->vlan_push >= 2)
+                       return false;
+               fallthrough;
        case EFX_TC_AO_COUNT:
                if (act->count)
                        return false;
@@ -393,6 +409,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
 
        flow_action_for_each(i, fa, &fr->action) {
                struct efx_tc_action_set save;
+               u16 tci;
 
                if (!act) {
                        /* more actions after a non-pipe action */
@@ -494,6 +511,31 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
                        }
                        *act = save;
                        break;
+               case FLOW_ACTION_VLAN_POP:
+                       if (act->vlan_push) {
+                               act->vlan_push--;
+                       } else if (efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_POP)) {
+                               act->vlan_pop++;
+                       } else {
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "More than two VLAN pops, or action order violated");
+                               rc = -EINVAL;
+                               goto release;
+                       }
+                       break;
+               case FLOW_ACTION_VLAN_PUSH:
+                       if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_PUSH)) {
+                               rc = -EINVAL;
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "More than two VLAN pushes, or action order violated");
+                               goto release;
+                       }
+                       tci = fa->vlan.vid & VLAN_VID_MASK;
+                       tci |= fa->vlan.prio << VLAN_PRIO_SHIFT;
+                       act->vlan_tci[act->vlan_push] = cpu_to_be16(tci);
+                       act->vlan_proto[act->vlan_push] = fa->vlan.proto;
+                       act->vlan_push++;
+                       break;
                default:
                        NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u",
                                               fa->id);
index 418ce8c..542853f 100644 (file)
 #define IS_ALL_ONES(v) (!(typeof (v))~(v))
 
 struct efx_tc_action_set {
+       u16 vlan_push:2;
+       u16 vlan_pop:2;
        u16 deliver:1;
+       __be16 vlan_tci[2]; /* TCIs for vlan_push */
+       __be16 vlan_proto[2]; /* Ethertypes for vlan_push */
        struct efx_tc_counter_index *count;
        u32 dest_mport;
        u32 fw_id; /* index of this entry in firmware actions table */