Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfc: support offloading TC VLAN push/pop actions to the MAE

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>

authored by

Edward Cree and committed by
Jakub Kicinski
05ccd8d8 494f642f

+67
+16
drivers/net/ethernet/sfc/mae.c
··· 682 682 size_t outlen; 683 683 int rc; 684 684 685 + MCDI_POPULATE_DWORD_2(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, 686 + MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push, 687 + MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop); 688 + 685 689 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, 686 690 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 687 691 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, ··· 698 694 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL); 699 695 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, 700 696 MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL); 697 + if (act->vlan_push) { 698 + MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE, 699 + act->vlan_tci[0]); 700 + MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE, 701 + act->vlan_proto[0]); 702 + } 703 + if (act->vlan_push >= 2) { 704 + MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE, 705 + act->vlan_tci[1]); 706 + MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, 707 + act->vlan_proto[1]); 708 + } 701 709 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, 702 710 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); 703 711 if (act->deliver)
+5
drivers/net/ethernet/sfc/mcdi.h
··· 233 233 ((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2), \ 234 234 le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field))) 235 235 /* Write a 16-bit field defined in the protocol as being big-endian. */ 236 + #define MCDI_SET_WORD_BE(_buf, _field, _value) do { \ 237 + BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2); \ 238 + BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \ 239 + *(__force __be16 *)MCDI_PTR(_buf, _field) = (_value); \ 240 + } while (0) 236 241 #define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do { \ 237 242 BUILD_BUG_ON(_field ## _LEN != 2); \ 238 243 BUILD_BUG_ON(_field ## _OFST & 1); \
+42
drivers/net/ethernet/sfc/tc.c
··· 286 286 287 287 /* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */ 288 288 enum efx_tc_action_order { 289 + EFX_TC_AO_VLAN_POP, 290 + EFX_TC_AO_VLAN_PUSH, 289 291 EFX_TC_AO_COUNT, 290 292 EFX_TC_AO_DELIVER 291 293 }; ··· 296 294 enum efx_tc_action_order new) 297 295 { 298 296 switch (new) { 297 + case EFX_TC_AO_VLAN_POP: 298 + if (act->vlan_pop >= 2) 299 + return false; 300 + /* If we've already pushed a VLAN, we can't then pop it; 301 + * the hardware would instead try to pop an existing VLAN 302 + * before pushing the new one. 303 + */ 304 + if (act->vlan_push) 305 + return false; 306 + fallthrough; 307 + case EFX_TC_AO_VLAN_PUSH: 308 + if (act->vlan_push >= 2) 309 + return false; 310 + fallthrough; 299 311 case EFX_TC_AO_COUNT: 300 312 if (act->count) 301 313 return false; ··· 409 393 410 394 flow_action_for_each(i, fa, &fr->action) { 411 395 struct efx_tc_action_set save; 396 + u16 tci; 412 397 413 398 if (!act) { 414 399 /* more actions after a non-pipe action */ ··· 510 493 goto release; 511 494 } 512 495 *act = save; 496 + break; 497 + case FLOW_ACTION_VLAN_POP: 498 + if (act->vlan_push) { 499 + act->vlan_push--; 500 + } else if (efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_POP)) { 501 + act->vlan_pop++; 502 + } else { 503 + NL_SET_ERR_MSG_MOD(extack, 504 + "More than two VLAN pops, or action order violated"); 505 + rc = -EINVAL; 506 + goto release; 507 + } 508 + break; 509 + case FLOW_ACTION_VLAN_PUSH: 510 + if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_VLAN_PUSH)) { 511 + rc = -EINVAL; 512 + NL_SET_ERR_MSG_MOD(extack, 513 + "More than two VLAN pushes, or action order violated"); 514 + goto release; 515 + } 516 + tci = fa->vlan.vid & VLAN_VID_MASK; 517 + tci |= fa->vlan.prio << VLAN_PRIO_SHIFT; 518 + act->vlan_tci[act->vlan_push] = cpu_to_be16(tci); 519 + act->vlan_proto[act->vlan_push] = fa->vlan.proto; 520 + act->vlan_push++; 513 521 break; 514 522 default: 515 523 NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u",
+4
drivers/net/ethernet/sfc/tc.h
··· 19 19 #define IS_ALL_ONES(v) (!(typeof (v))~(v)) 20 20 21 21 struct efx_tc_action_set { 22 + u16 vlan_push:2; 23 + u16 vlan_pop:2; 22 24 u16 deliver:1; 25 + __be16 vlan_tci[2]; /* TCIs for vlan_push */ 26 + __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ 23 27 struct efx_tc_counter_index *count; 24 28 u32 dest_mport; 25 29 u32 fw_id; /* index of this entry in firmware actions table */