Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
100GbE Intel Wired LAN Driver Updates 2022-02-09

This series contains updates to ice driver only.

Brett adds support for QinQ. This begins with code refactoring and
re-organization of VLAN configuration functions to allow for
introduction of VSI VLAN ops to enable setting and calling of
respective operations based on device support of single or double
VLANs. Implementations are added for outer VLAN support.

To support QinQ, the device must be set to double VLAN mode (DVM).
In order for this to occur, the DDP package and NVM must also support
DVM. Functions to determine compatibility and properly configure the
device are added as well as setting the proper bits to advertise and
utilize the proper offloads. Support for VIRTCHNL_VF_OFFLOAD_VLAN_V2
is also included to allow for VF to negotiate and utilize this
functionality.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2022-02-10 11:00:13 +00:00
commit adc27288f2
41 changed files with 4150 additions and 689 deletions

View file

@ -18,8 +18,12 @@ ice-y := ice_main.o \
ice_txrx_lib.o \
ice_txrx.o \
ice_fltr.o \
ice_pf_vsi_vlan_ops.o \
ice_vsi_vlan_ops.o \
ice_vsi_vlan_lib.o \
ice_fdir.o \
ice_ethtool_fdir.o \
ice_vlan_mode.o \
ice_flex_pipe.o \
ice_flow.o \
ice_idc.o \
@ -29,8 +33,12 @@ ice-y := ice_main.o \
ice_ethtool.o \
ice_repr.o \
ice_tc_lib.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_allowlist.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice_virtchnl_fdir.o
ice-$(CONFIG_PCI_IOV) += \
ice_virtchnl_allowlist.o \
ice_virtchnl_fdir.o \
ice_sriov.o \
ice_vf_vsi_vlan_ops.o \
ice_virtchnl_pf.o
ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o

View file

@ -72,6 +72,7 @@
#include "ice_repr.h"
#include "ice_eswitch.h"
#include "ice_lag.h"
#include "ice_vsi_vlan_ops.h"
#define ICE_BAR0 0
#define ICE_REQ_DESC_MULTIPLE 32
@ -368,6 +369,8 @@ struct ice_vsi {
u8 irqs_ready:1;
u8 current_isup:1; /* Sync 'link up' logging */
u8 stat_offsets_loaded:1;
struct ice_vsi_vlan_ops inner_vlan_ops;
struct ice_vsi_vlan_ops outer_vlan_ops;
u16 num_vlan;
/* queue information */
@ -482,6 +485,7 @@ enum ice_pf_flags {
ICE_FLAG_LEGACY_RX,
ICE_FLAG_VF_TRUE_PROMISC_ENA,
ICE_FLAG_MDD_AUTO_RESET_VF,
ICE_FLAG_VF_VLAN_PRUNING,
ICE_FLAG_LINK_LENIENT_MODE_ENA,
ICE_PF_FLAGS_NBITS /* must be last */
};

View file

@ -226,6 +226,15 @@ struct ice_aqc_get_sw_cfg_resp_elem {
#define ICE_AQC_GET_SW_CONF_RESP_IS_VF BIT(15)
};
/* Set Port parameters, (direct, 0x0203) */
struct ice_aqc_set_port_params {
__le16 cmd_flags;
#define ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA BIT(2)
__le16 bad_frame_vsi;
__le16 swid;
u8 reserved[10];
};
/* These resource type defines are used for all switch resource
* commands where a resource type is required, such as:
* Get Resource Allocation command (indirect 0x0204)
@ -283,6 +292,40 @@ struct ice_aqc_alloc_free_res_elem {
struct ice_aqc_res_elem elem[];
};
/* Request buffer for Set VLAN Mode AQ command (indirect 0x020C) */
struct ice_aqc_set_vlan_mode {
u8 reserved;
u8 l2tag_prio_tagging;
#define ICE_AQ_VLAN_PRIO_TAG_S 0
#define ICE_AQ_VLAN_PRIO_TAG_M (0x7 << ICE_AQ_VLAN_PRIO_TAG_S)
#define ICE_AQ_VLAN_PRIO_TAG_NOT_SUPPORTED 0x0
#define ICE_AQ_VLAN_PRIO_TAG_STAG 0x1
#define ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG 0x2
#define ICE_AQ_VLAN_PRIO_TAG_OUTER_VLAN 0x3
#define ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG 0x4
#define ICE_AQ_VLAN_PRIO_TAG_MAX 0x4
#define ICE_AQ_VLAN_PRIO_TAG_ERROR 0x7
u8 l2tag_reserved[64];
u8 rdma_packet;
#define ICE_AQ_VLAN_RDMA_TAG_S 0
#define ICE_AQ_VLAN_RDMA_TAG_M (0x3F << ICE_AQ_VLAN_RDMA_TAG_S)
#define ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING 0x10
#define ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING 0x1A
u8 rdma_reserved[2];
u8 mng_vlan_prot_id;
#define ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER 0x10
#define ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER 0x11
u8 prot_id_reserved[30];
};
/* Response buffer for Get VLAN Mode AQ command (indirect 0x020D) */
struct ice_aqc_get_vlan_mode {
u8 vlan_mode;
#define ICE_AQ_VLAN_MODE_DVM_ENA BIT(0)
u8 l2tag_prio_tagging;
u8 reserved[98];
};
/* Add VSI (indirect 0x0210)
* Update VSI (indirect 0x0211)
* Get VSI (indirect 0x0212)
@ -343,108 +386,113 @@ struct ice_aqc_vsi_props {
#define ICE_AQ_VSI_SW_FLAG_SRC_PRUNE BIT(7)
u8 sw_flags2;
#define ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_S 0
#define ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M \
(0xF << ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_S)
#define ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M (0xF << ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_S)
#define ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA BIT(0)
#define ICE_AQ_VSI_SW_FLAG_LAN_ENA BIT(4)
u8 veb_stat_id;
#define ICE_AQ_VSI_SW_VEB_STAT_ID_S 0
#define ICE_AQ_VSI_SW_VEB_STAT_ID_M (0x1F << ICE_AQ_VSI_SW_VEB_STAT_ID_S)
#define ICE_AQ_VSI_SW_VEB_STAT_ID_M (0x1F << ICE_AQ_VSI_SW_VEB_STAT_ID_S)
#define ICE_AQ_VSI_SW_VEB_STAT_ID_VALID BIT(5)
/* security section */
u8 sec_flags;
#define ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD BIT(0)
#define ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF BIT(2)
#define ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S 4
#define ICE_AQ_VSI_SEC_TX_PRUNE_ENA_M (0xF << ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S)
#define ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S 4
#define ICE_AQ_VSI_SEC_TX_PRUNE_ENA_M (0xF << ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S)
#define ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA BIT(0)
u8 sec_reserved;
/* VLAN section */
__le16 pvid; /* VLANS include priority bits */
u8 pvlan_reserved[2];
u8 vlan_flags;
#define ICE_AQ_VSI_VLAN_MODE_S 0
#define ICE_AQ_VSI_VLAN_MODE_M (0x3 << ICE_AQ_VSI_VLAN_MODE_S)
#define ICE_AQ_VSI_VLAN_MODE_UNTAGGED 0x1
#define ICE_AQ_VSI_VLAN_MODE_TAGGED 0x2
#define ICE_AQ_VSI_VLAN_MODE_ALL 0x3
#define ICE_AQ_VSI_PVLAN_INSERT_PVID BIT(2)
#define ICE_AQ_VSI_VLAN_EMOD_S 3
#define ICE_AQ_VSI_VLAN_EMOD_M (0x3 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR_BOTH (0x0 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR_UP (0x1 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_STR (0x2 << ICE_AQ_VSI_VLAN_EMOD_S)
#define ICE_AQ_VSI_VLAN_EMOD_NOTHING (0x3 << ICE_AQ_VSI_VLAN_EMOD_S)
u8 pvlan_reserved2[3];
__le16 port_based_inner_vlan; /* VLANS include priority bits */
u8 inner_vlan_reserved[2];
u8 inner_vlan_flags;
#define ICE_AQ_VSI_INNER_VLAN_TX_MODE_S 0
#define ICE_AQ_VSI_INNER_VLAN_TX_MODE_M (0x3 << ICE_AQ_VSI_INNER_VLAN_TX_MODE_S)
#define ICE_AQ_VSI_INNER_VLAN_TX_MODE_ACCEPTUNTAGGED 0x1
#define ICE_AQ_VSI_INNER_VLAN_TX_MODE_ACCEPTTAGGED 0x2
#define ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL 0x3
#define ICE_AQ_VSI_INNER_VLAN_INSERT_PVID BIT(2)
#define ICE_AQ_VSI_INNER_VLAN_EMODE_S 3
#define ICE_AQ_VSI_INNER_VLAN_EMODE_M (0x3 << ICE_AQ_VSI_INNER_VLAN_EMODE_S)
#define ICE_AQ_VSI_INNER_VLAN_EMODE_STR_BOTH (0x0 << ICE_AQ_VSI_INNER_VLAN_EMODE_S)
#define ICE_AQ_VSI_INNER_VLAN_EMODE_STR_UP (0x1 << ICE_AQ_VSI_INNER_VLAN_EMODE_S)
#define ICE_AQ_VSI_INNER_VLAN_EMODE_STR (0x2 << ICE_AQ_VSI_INNER_VLAN_EMODE_S)
#define ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING (0x3 << ICE_AQ_VSI_INNER_VLAN_EMODE_S)
u8 inner_vlan_reserved2[3];
/* ingress egress up sections */
__le32 ingress_table; /* bitmap, 3 bits per up */
#define ICE_AQ_VSI_UP_TABLE_UP0_S 0
#define ICE_AQ_VSI_UP_TABLE_UP0_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP0_S)
#define ICE_AQ_VSI_UP_TABLE_UP1_S 3
#define ICE_AQ_VSI_UP_TABLE_UP1_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP1_S)
#define ICE_AQ_VSI_UP_TABLE_UP2_S 6
#define ICE_AQ_VSI_UP_TABLE_UP2_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP2_S)
#define ICE_AQ_VSI_UP_TABLE_UP3_S 9
#define ICE_AQ_VSI_UP_TABLE_UP3_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP3_S)
#define ICE_AQ_VSI_UP_TABLE_UP4_S 12
#define ICE_AQ_VSI_UP_TABLE_UP4_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP4_S)
#define ICE_AQ_VSI_UP_TABLE_UP5_S 15
#define ICE_AQ_VSI_UP_TABLE_UP5_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP5_S)
#define ICE_AQ_VSI_UP_TABLE_UP6_S 18
#define ICE_AQ_VSI_UP_TABLE_UP6_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP6_S)
#define ICE_AQ_VSI_UP_TABLE_UP7_S 21
#define ICE_AQ_VSI_UP_TABLE_UP7_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP7_S)
#define ICE_AQ_VSI_UP_TABLE_UP0_S 0
#define ICE_AQ_VSI_UP_TABLE_UP0_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP0_S)
#define ICE_AQ_VSI_UP_TABLE_UP1_S 3
#define ICE_AQ_VSI_UP_TABLE_UP1_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP1_S)
#define ICE_AQ_VSI_UP_TABLE_UP2_S 6
#define ICE_AQ_VSI_UP_TABLE_UP2_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP2_S)
#define ICE_AQ_VSI_UP_TABLE_UP3_S 9
#define ICE_AQ_VSI_UP_TABLE_UP3_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP3_S)
#define ICE_AQ_VSI_UP_TABLE_UP4_S 12
#define ICE_AQ_VSI_UP_TABLE_UP4_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP4_S)
#define ICE_AQ_VSI_UP_TABLE_UP5_S 15
#define ICE_AQ_VSI_UP_TABLE_UP5_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP5_S)
#define ICE_AQ_VSI_UP_TABLE_UP6_S 18
#define ICE_AQ_VSI_UP_TABLE_UP6_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP6_S)
#define ICE_AQ_VSI_UP_TABLE_UP7_S 21
#define ICE_AQ_VSI_UP_TABLE_UP7_M (0x7 << ICE_AQ_VSI_UP_TABLE_UP7_S)
__le32 egress_table; /* same defines as for ingress table */
/* outer tags section */
__le16 outer_tag;
u8 outer_tag_flags;
#define ICE_AQ_VSI_OUTER_TAG_MODE_S 0
#define ICE_AQ_VSI_OUTER_TAG_MODE_M (0x3 << ICE_AQ_VSI_OUTER_TAG_MODE_S)
#define ICE_AQ_VSI_OUTER_TAG_NOTHING 0x0
#define ICE_AQ_VSI_OUTER_TAG_REMOVE 0x1
#define ICE_AQ_VSI_OUTER_TAG_COPY 0x2
#define ICE_AQ_VSI_OUTER_TAG_TYPE_S 2
#define ICE_AQ_VSI_OUTER_TAG_TYPE_M (0x3 << ICE_AQ_VSI_OUTER_TAG_TYPE_S)
#define ICE_AQ_VSI_OUTER_TAG_NONE 0x0
#define ICE_AQ_VSI_OUTER_TAG_STAG 0x1
#define ICE_AQ_VSI_OUTER_TAG_VLAN_8100 0x2
#define ICE_AQ_VSI_OUTER_TAG_VLAN_9100 0x3
#define ICE_AQ_VSI_OUTER_TAG_INSERT BIT(4)
#define ICE_AQ_VSI_OUTER_TAG_ACCEPT_HOST BIT(6)
u8 outer_tag_reserved;
__le16 port_based_outer_vlan;
u8 outer_vlan_flags;
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_S 0
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_M (0x3 << ICE_AQ_VSI_OUTER_VLAN_EMODE_S)
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_SHOW_BOTH 0x0
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_SHOW_UP 0x1
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_SHOW 0x2
#define ICE_AQ_VSI_OUTER_VLAN_EMODE_NOTHING 0x3
#define ICE_AQ_VSI_OUTER_TAG_TYPE_S 2
#define ICE_AQ_VSI_OUTER_TAG_TYPE_M (0x3 << ICE_AQ_VSI_OUTER_TAG_TYPE_S)
#define ICE_AQ_VSI_OUTER_TAG_NONE 0x0
#define ICE_AQ_VSI_OUTER_TAG_STAG 0x1
#define ICE_AQ_VSI_OUTER_TAG_VLAN_8100 0x2
#define ICE_AQ_VSI_OUTER_TAG_VLAN_9100 0x3
#define ICE_AQ_VSI_OUTER_VLAN_PORT_BASED_INSERT BIT(4)
#define ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S 5
#define ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M (0x3 << ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S)
#define ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ACCEPTUNTAGGED 0x1
#define ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ACCEPTTAGGED 0x2
#define ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL 0x3
#define ICE_AQ_VSI_OUTER_VLAN_BLOCK_TX_DESC BIT(7)
u8 outer_vlan_reserved;
/* queue mapping section */
__le16 mapping_flags;
#define ICE_AQ_VSI_Q_MAP_CONTIG 0x0
#define ICE_AQ_VSI_Q_MAP_NONCONTIG BIT(0)
#define ICE_AQ_VSI_Q_MAP_CONTIG 0x0
#define ICE_AQ_VSI_Q_MAP_NONCONTIG BIT(0)
__le16 q_mapping[16];
#define ICE_AQ_VSI_Q_S 0
#define ICE_AQ_VSI_Q_M (0x7FF << ICE_AQ_VSI_Q_S)
#define ICE_AQ_VSI_Q_S 0
#define ICE_AQ_VSI_Q_M (0x7FF << ICE_AQ_VSI_Q_S)
__le16 tc_mapping[8];
#define ICE_AQ_VSI_TC_Q_OFFSET_S 0
#define ICE_AQ_VSI_TC_Q_OFFSET_M (0x7FF << ICE_AQ_VSI_TC_Q_OFFSET_S)
#define ICE_AQ_VSI_TC_Q_NUM_S 11
#define ICE_AQ_VSI_TC_Q_NUM_M (0xF << ICE_AQ_VSI_TC_Q_NUM_S)
#define ICE_AQ_VSI_TC_Q_OFFSET_S 0
#define ICE_AQ_VSI_TC_Q_OFFSET_M (0x7FF << ICE_AQ_VSI_TC_Q_OFFSET_S)
#define ICE_AQ_VSI_TC_Q_NUM_S 11
#define ICE_AQ_VSI_TC_Q_NUM_M (0xF << ICE_AQ_VSI_TC_Q_NUM_S)
/* queueing option section */
u8 q_opt_rss;
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_S 0
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_M (0x3 << ICE_AQ_VSI_Q_OPT_RSS_LUT_S)
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI 0x0
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_PF 0x2
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_GBL 0x3
#define ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_S 2
#define ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M (0xF << ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_S)
#define ICE_AQ_VSI_Q_OPT_RSS_HASH_S 6
#define ICE_AQ_VSI_Q_OPT_RSS_HASH_M (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_TPLZ (0x0 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_SYM_TPLZ (0x1 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_XOR (0x2 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_JHASH (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_S 0
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_M (0x3 << ICE_AQ_VSI_Q_OPT_RSS_LUT_S)
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI 0x0
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_PF 0x2
#define ICE_AQ_VSI_Q_OPT_RSS_LUT_GBL 0x3
#define ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_S 2
#define ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M (0xF << ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_S)
#define ICE_AQ_VSI_Q_OPT_RSS_HASH_S 6
#define ICE_AQ_VSI_Q_OPT_RSS_HASH_M (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_TPLZ (0x0 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_SYM_TPLZ (0x1 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_XOR (0x2 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
#define ICE_AQ_VSI_Q_OPT_RSS_JHASH (0x3 << ICE_AQ_VSI_Q_OPT_RSS_HASH_S)
u8 q_opt_tc;
#define ICE_AQ_VSI_Q_OPT_TC_OVR_S 0
#define ICE_AQ_VSI_Q_OPT_TC_OVR_M (0x1F << ICE_AQ_VSI_Q_OPT_TC_OVR_S)
#define ICE_AQ_VSI_Q_OPT_PROF_TC_OVR BIT(7)
#define ICE_AQ_VSI_Q_OPT_TC_OVR_S 0
#define ICE_AQ_VSI_Q_OPT_TC_OVR_M (0x1F << ICE_AQ_VSI_Q_OPT_TC_OVR_S)
#define ICE_AQ_VSI_Q_OPT_PROF_TC_OVR BIT(7)
u8 q_opt_flags;
#define ICE_AQ_VSI_Q_OPT_PE_FLTR_EN BIT(0)
#define ICE_AQ_VSI_Q_OPT_PE_FLTR_EN BIT(0)
u8 q_opt_reserved[3];
/* outer up section */
__le32 outer_up_table; /* same structure and defines as ingress tbl */
@ -452,27 +500,27 @@ struct ice_aqc_vsi_props {
__le16 sect_10_reserved;
/* flow director section */
__le16 fd_options;
#define ICE_AQ_VSI_FD_ENABLE BIT(0)
#define ICE_AQ_VSI_FD_TX_AUTO_ENABLE BIT(1)
#define ICE_AQ_VSI_FD_PROG_ENABLE BIT(3)
#define ICE_AQ_VSI_FD_ENABLE BIT(0)
#define ICE_AQ_VSI_FD_TX_AUTO_ENABLE BIT(1)
#define ICE_AQ_VSI_FD_PROG_ENABLE BIT(3)
__le16 max_fd_fltr_dedicated;
__le16 max_fd_fltr_shared;
__le16 fd_def_q;
#define ICE_AQ_VSI_FD_DEF_Q_S 0
#define ICE_AQ_VSI_FD_DEF_Q_M (0x7FF << ICE_AQ_VSI_FD_DEF_Q_S)
#define ICE_AQ_VSI_FD_DEF_GRP_S 12
#define ICE_AQ_VSI_FD_DEF_GRP_M (0x7 << ICE_AQ_VSI_FD_DEF_GRP_S)
#define ICE_AQ_VSI_FD_DEF_Q_S 0
#define ICE_AQ_VSI_FD_DEF_Q_M (0x7FF << ICE_AQ_VSI_FD_DEF_Q_S)
#define ICE_AQ_VSI_FD_DEF_GRP_S 12
#define ICE_AQ_VSI_FD_DEF_GRP_M (0x7 << ICE_AQ_VSI_FD_DEF_GRP_S)
__le16 fd_report_opt;
#define ICE_AQ_VSI_FD_REPORT_Q_S 0
#define ICE_AQ_VSI_FD_REPORT_Q_M (0x7FF << ICE_AQ_VSI_FD_REPORT_Q_S)
#define ICE_AQ_VSI_FD_DEF_PRIORITY_S 12
#define ICE_AQ_VSI_FD_DEF_PRIORITY_M (0x7 << ICE_AQ_VSI_FD_DEF_PRIORITY_S)
#define ICE_AQ_VSI_FD_DEF_DROP BIT(15)
#define ICE_AQ_VSI_FD_REPORT_Q_S 0
#define ICE_AQ_VSI_FD_REPORT_Q_M (0x7FF << ICE_AQ_VSI_FD_REPORT_Q_S)
#define ICE_AQ_VSI_FD_DEF_PRIORITY_S 12
#define ICE_AQ_VSI_FD_DEF_PRIORITY_M (0x7 << ICE_AQ_VSI_FD_DEF_PRIORITY_S)
#define ICE_AQ_VSI_FD_DEF_DROP BIT(15)
/* PASID section */
__le32 pasid_id;
#define ICE_AQ_VSI_PASID_ID_S 0
#define ICE_AQ_VSI_PASID_ID_M (0xFFFFF << ICE_AQ_VSI_PASID_ID_S)
#define ICE_AQ_VSI_PASID_ID_VALID BIT(31)
#define ICE_AQ_VSI_PASID_ID_S 0
#define ICE_AQ_VSI_PASID_ID_M (0xFFFFF << ICE_AQ_VSI_PASID_ID_S)
#define ICE_AQ_VSI_PASID_ID_VALID BIT(31)
u8 reserved[24];
};
@ -489,9 +537,13 @@ struct ice_aqc_add_get_recipe {
struct ice_aqc_recipe_content {
u8 rid;
#define ICE_AQ_RECIPE_ID_S 0
#define ICE_AQ_RECIPE_ID_M (0x3F << ICE_AQ_RECIPE_ID_S)
#define ICE_AQ_RECIPE_ID_IS_ROOT BIT(7)
#define ICE_AQ_SW_ID_LKUP_IDX 0
u8 lkup_indx[5];
#define ICE_AQ_RECIPE_LKUP_DATA_S 0
#define ICE_AQ_RECIPE_LKUP_DATA_M (0x3F << ICE_AQ_RECIPE_LKUP_DATA_S)
#define ICE_AQ_RECIPE_LKUP_IGNORE BIT(7)
#define ICE_AQ_SW_ID_LKUP_MASK 0x00FF
__le16 mask[5];
@ -502,15 +554,25 @@ struct ice_aqc_recipe_content {
u8 rsvd0[3];
u8 act_ctrl_join_priority;
u8 act_ctrl_fwd_priority;
#define ICE_AQ_RECIPE_FWD_PRIORITY_S 0
#define ICE_AQ_RECIPE_FWD_PRIORITY_M (0xF << ICE_AQ_RECIPE_FWD_PRIORITY_S)
u8 act_ctrl;
#define ICE_AQ_RECIPE_ACT_NEED_PASS_L2 BIT(0)
#define ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2 BIT(1)
#define ICE_AQ_RECIPE_ACT_INV_ACT BIT(2)
#define ICE_AQ_RECIPE_ACT_PRUNE_INDX_S 4
#define ICE_AQ_RECIPE_ACT_PRUNE_INDX_M (0x3 << ICE_AQ_RECIPE_ACT_PRUNE_INDX_S)
u8 rsvd1;
__le32 dflt_act;
#define ICE_AQ_RECIPE_DFLT_ACT_S 0
#define ICE_AQ_RECIPE_DFLT_ACT_M (0x7FFFF << ICE_AQ_RECIPE_DFLT_ACT_S)
#define ICE_AQ_RECIPE_DFLT_ACT_VALID BIT(31)
};
struct ice_aqc_recipe_data_elem {
u8 recipe_indx;
u8 resp_bits;
#define ICE_AQ_RECIPE_WAS_UPDATED BIT(0)
u8 rsvd0[2];
u8 recipe_bitmap[8];
u8 rsvd1[4];
@ -1883,7 +1945,7 @@ struct ice_aqc_get_clear_fw_log {
};
/* Download Package (indirect 0x0C40) */
/* Also used for Update Package (indirect 0x0C42) */
/* Also used for Update Package (indirect 0x0C41 and 0x0C42) */
struct ice_aqc_download_pkg {
u8 flags;
#define ICE_AQC_DOWNLOAD_PKG_LAST_BUF 0x01
@ -2009,6 +2071,7 @@ struct ice_aq_desc {
struct ice_aqc_sff_eeprom read_write_sff_param;
struct ice_aqc_set_port_id_led set_port_id_led;
struct ice_aqc_get_sw_cfg get_sw_conf;
struct ice_aqc_set_port_params set_port_params;
struct ice_aqc_sw_rules sw_rules;
struct ice_aqc_add_get_recipe add_get_recipe;
struct ice_aqc_recipe_to_profile recipe_to_profile;
@ -2110,10 +2173,13 @@ enum ice_adminq_opc {
/* internal switch commands */
ice_aqc_opc_get_sw_cfg = 0x0200,
ice_aqc_opc_set_port_params = 0x0203,
/* Alloc/Free/Get Resources */
ice_aqc_opc_alloc_res = 0x0208,
ice_aqc_opc_free_res = 0x0209,
ice_aqc_opc_set_vlan_mode_parameters = 0x020C,
ice_aqc_opc_get_vlan_mode_parameters = 0x020D,
/* VSI commands */
ice_aqc_opc_add_vsi = 0x0210,
@ -2204,6 +2270,7 @@ enum ice_adminq_opc {
/* package commands */
ice_aqc_opc_download_pkg = 0x0C40,
ice_aqc_opc_upload_section = 0x0C41,
ice_aqc_opc_update_pkg = 0x0C42,
ice_aqc_opc_get_pkg_info_list = 0x0C43,

View file

@ -5,6 +5,7 @@
#include "ice_base.h"
#include "ice_lib.h"
#include "ice_dcb_lib.h"
#include "ice_virtchnl_pf.h"
static bool ice_alloc_rx_buf_zc(struct ice_rx_ring *rx_ring)
{
@ -418,8 +419,22 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
*/
rlan_ctx.crcstrip = 1;
/* L2TSEL flag defines the reported L2 Tags in the receive descriptor */
rlan_ctx.l2tsel = 1;
/* L2TSEL flag defines the reported L2 Tags in the receive descriptor
* and it needs to remain 1 for non-DVM capable configurations to not
* break backward compatibility for VF drivers. Setting this field to 0
* will cause the single/outer VLAN tag to be stripped to the L2TAG2_2ND
* field in the Rx descriptor. Setting it to 1 allows the VLAN tag to
* be stripped in L2TAG1 of the Rx descriptor, which is where VFs will
* check for the tag
*/
if (ice_is_dvm_ena(hw))
if (vsi->type == ICE_VSI_VF &&
ice_vf_is_port_vlan_ena(&vsi->back->vf[vsi->vf_id]))
rlan_ctx.l2tsel = 1;
else
rlan_ctx.l2tsel = 0;
else
rlan_ctx.l2tsel = 1;
rlan_ctx.dtype = ICE_RX_DTYPE_NO_SPLIT;
rlan_ctx.hsplit_0 = ICE_RLAN_RX_HSPLIT_0_NO_SPLIT;

View file

@ -1518,16 +1518,27 @@ ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf,
/* When a package download is in process (i.e. when the firmware's
* Global Configuration Lock resource is held), only the Download
* Package, Get Version, Get Package Info List and Release Resource
* (with resource ID set to Global Config Lock) AdminQ commands are
* allowed; all others must block until the package download completes
* and the Global Config Lock is released. See also
* ice_acquire_global_cfg_lock().
* Package, Get Version, Get Package Info List, Upload Section,
* Update Package, Set Port Parameters, Get/Set VLAN Mode Parameters,
* Add Recipe, Set Recipes to Profile Association, Get Recipe, and Get
* Recipes to Profile Association, and Release Resource (with resource
* ID set to Global Config Lock) AdminQ commands are allowed; all others
* must block until the package download completes and the Global Config
* Lock is released. See also ice_acquire_global_cfg_lock().
*/
switch (le16_to_cpu(desc->opcode)) {
case ice_aqc_opc_download_pkg:
case ice_aqc_opc_get_pkg_info_list:
case ice_aqc_opc_get_ver:
case ice_aqc_opc_upload_section:
case ice_aqc_opc_update_pkg:
case ice_aqc_opc_set_port_params:
case ice_aqc_opc_get_vlan_mode_parameters:
case ice_aqc_opc_set_vlan_mode_parameters:
case ice_aqc_opc_add_recipe:
case ice_aqc_opc_recipe_to_profile:
case ice_aqc_opc_get_recipe:
case ice_aqc_opc_get_recipe_to_profile:
break;
case ice_aqc_opc_release_res:
if (le16_to_cpu(cmd->res_id) == ICE_AQC_RES_ID_GLBL_LOCK)
@ -2736,6 +2747,34 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
ice_aq_clear_pxe_mode(hw);
}
/**
* ice_aq_set_port_params - set physical port parameters.
* @pi: pointer to the port info struct
* @double_vlan: if set double VLAN is enabled
* @cd: pointer to command details structure or NULL
*
* Set Physical port parameters (0x0203)
*/
int
ice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
struct ice_sq_cd *cd)
{
struct ice_aqc_set_port_params *cmd;
struct ice_hw *hw = pi->hw;
struct ice_aq_desc desc;
u16 cmd_flags = 0;
cmd = &desc.params.set_port_params;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
if (double_vlan)
cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
cmd->cmd_flags = cpu_to_le16(cmd_flags);
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
/**
* ice_get_link_speed_based_on_phy_type - returns link speed
* @phy_type_low: lower part of phy_type

View file

@ -85,6 +85,9 @@ int
ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
struct ice_sq_cd *cd);
int
ice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
struct ice_sq_cd *cd);
int
ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
struct ice_aqc_get_phy_caps_data *caps,
struct ice_sq_cd *cd);

View file

@ -916,7 +916,8 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring,
return;
/* Insert 802.1p priority into VLAN header */
if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN) ||
if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN ||
first->tx_flags & ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN) ||
skb->priority != TC_PRIO_CONTROL) {
first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
/* Mask the lower 3 bits to set the 802.1p priority */
@ -925,7 +926,10 @@ ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring,
/* if this is not already set it means a VLAN 0 + priority needs
* to be offloaded
*/
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
if (tx_ring->flags & ICE_TX_FLAGS_RING_VLAN_L2TAG2)
first->tx_flags |= ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN;
else
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
}
}

View file

@ -115,9 +115,12 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
struct ice_vsi *uplink_vsi = pf->switchdev.uplink_vsi;
struct net_device *uplink_netdev = uplink_vsi->netdev;
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
struct ice_vsi_vlan_ops *vlan_ops;
bool rule_added = false;
ice_vsi_manage_vlan_stripping(ctrl_vsi, false);
vlan_ops = ice_get_compat_vsi_vlan_ops(ctrl_vsi);
if (vlan_ops->dis_stripping(ctrl_vsi))
return -ENODEV;
ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);
@ -126,7 +129,7 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
__dev_mc_unsync(uplink_netdev, NULL);
netif_addr_unlock_bh(uplink_netdev);
if (ice_vsi_add_vlan(uplink_vsi, 0, ICE_FWD_TO_VSI))
if (ice_vsi_add_vlan_zero(uplink_vsi))
goto err_def_rx;
if (!ice_is_dflt_vsi_in_use(uplink_vsi->vsw)) {
@ -230,7 +233,7 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
goto err;
}
if (ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI)) {
if (ice_vsi_add_vlan_zero(vsi)) {
ice_fltr_add_mac_and_broadcast(vsi,
vf->hw_lan_addr.addr,
ICE_FWD_TO_VSI);

View file

@ -164,6 +164,7 @@ static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
ICE_PRIV_FLAG("vf-true-promisc-support",
ICE_FLAG_VF_TRUE_PROMISC_ENA),
ICE_PRIV_FLAG("mdd-auto-reset-vf", ICE_FLAG_MDD_AUTO_RESET_VF),
ICE_PRIV_FLAG("vf-vlan-pruning", ICE_FLAG_VF_VLAN_PRUNING),
ICE_PRIV_FLAG("legacy-rx", ICE_FLAG_LEGACY_RX),
};
@ -1295,6 +1296,14 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
ret = -EAGAIN;
}
if (test_bit(ICE_FLAG_VF_VLAN_PRUNING, change_flags) &&
pf->num_alloc_vfs) {
dev_err(dev, "vf-vlan-pruning: VLAN pruning cannot be changed while VFs are active.\n");
/* toggle bit back to previous state */
change_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags);
ret = -EOPNOTSUPP;
}
ethtool_exit:
clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
return ret;

View file

@ -5,9 +5,17 @@
#include "ice_flex_pipe.h"
#include "ice_flow.h"
/* For supporting double VLAN mode, it is necessary to enable or disable certain
* boost tcam entries. The metadata labels names that match the following
* prefixes will be saved to allow enabling double VLAN mode.
*/
#define ICE_DVM_PRE "BOOST_MAC_VLAN_DVM" /* enable these entries */
#define ICE_SVM_PRE "BOOST_MAC_VLAN_SVM" /* disable these entries */
/* To support tunneling entries by PF, the package will append the PF number to
* the label; for example TNL_VXLAN_PF0, TNL_VXLAN_PF1, TNL_VXLAN_PF2, etc.
*/
#define ICE_TNL_PRE "TNL_"
static const struct ice_tunnel_type_scan tnls[] = {
{ TNL_VXLAN, "TNL_VXLAN_PF" },
{ TNL_GENEVE, "TNL_GENEVE_PF" },
@ -522,6 +530,55 @@ ice_enum_labels(struct ice_seg *ice_seg, u32 type, struct ice_pkg_enum *state,
return label->name;
}
/**
* ice_add_tunnel_hint
* @hw: pointer to the HW structure
* @label_name: label text
* @val: value of the tunnel port boost entry
*/
static void ice_add_tunnel_hint(struct ice_hw *hw, char *label_name, u16 val)
{
if (hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
u16 i;
for (i = 0; tnls[i].type != TNL_LAST; i++) {
size_t len = strlen(tnls[i].label_prefix);
/* Look for matching label start, before continuing */
if (strncmp(label_name, tnls[i].label_prefix, len))
continue;
/* Make sure this label matches our PF. Note that the PF
* character ('0' - '7') will be located where our
* prefix string's null terminator is located.
*/
if ((label_name[len] - '0') == hw->pf_id) {
hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
hw->tnl.tbl[hw->tnl.count].valid = false;
hw->tnl.tbl[hw->tnl.count].boost_addr = val;
hw->tnl.tbl[hw->tnl.count].port = 0;
hw->tnl.count++;
break;
}
}
}
}
/**
* ice_add_dvm_hint
* @hw: pointer to the HW structure
* @val: value of the boost entry
* @enable: true if entry needs to be enabled, or false if needs to be disabled
*/
static void ice_add_dvm_hint(struct ice_hw *hw, u16 val, bool enable)
{
if (hw->dvm_upd.count < ICE_DVM_MAX_ENTRIES) {
hw->dvm_upd.tbl[hw->dvm_upd.count].boost_addr = val;
hw->dvm_upd.tbl[hw->dvm_upd.count].enable = enable;
hw->dvm_upd.count++;
}
}
/**
* ice_init_pkg_hints
* @hw: pointer to the HW structure
@ -548,32 +605,23 @@ static void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
label_name = ice_enum_labels(ice_seg, ICE_SID_LBL_RXPARSER_TMEM, &state,
&val);
while (label_name && hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
for (i = 0; tnls[i].type != TNL_LAST; i++) {
size_t len = strlen(tnls[i].label_prefix);
while (label_name) {
if (!strncmp(label_name, ICE_TNL_PRE, strlen(ICE_TNL_PRE)))
/* check for a tunnel entry */
ice_add_tunnel_hint(hw, label_name, val);
/* Look for matching label start, before continuing */
if (strncmp(label_name, tnls[i].label_prefix, len))
continue;
/* check for a dvm mode entry */
else if (!strncmp(label_name, ICE_DVM_PRE, strlen(ICE_DVM_PRE)))
ice_add_dvm_hint(hw, val, true);
/* Make sure this label matches our PF. Note that the PF
* character ('0' - '7') will be located where our
* prefix string's null terminator is located.
*/
if ((label_name[len] - '0') == hw->pf_id) {
hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
hw->tnl.tbl[hw->tnl.count].valid = false;
hw->tnl.tbl[hw->tnl.count].boost_addr = val;
hw->tnl.tbl[hw->tnl.count].port = 0;
hw->tnl.count++;
break;
}
}
/* check for a svm mode entry */
else if (!strncmp(label_name, ICE_SVM_PRE, strlen(ICE_SVM_PRE)))
ice_add_dvm_hint(hw, val, false);
label_name = ice_enum_labels(NULL, 0, &state, &val);
}
/* Cache the appropriate boost TCAM entry pointers */
/* Cache the appropriate boost TCAM entry pointers for tunnels */
for (i = 0; i < hw->tnl.count; i++) {
ice_find_boost_entry(ice_seg, hw->tnl.tbl[i].boost_addr,
&hw->tnl.tbl[i].boost_entry);
@ -583,6 +631,11 @@ static void ice_init_pkg_hints(struct ice_hw *hw, struct ice_seg *ice_seg)
hw->tnl.valid_count[hw->tnl.tbl[i].type]++;
}
}
/* Cache the appropriate boost TCAM entry pointers for DVM and SVM */
for (i = 0; i < hw->dvm_upd.count; i++)
ice_find_boost_entry(ice_seg, hw->dvm_upd.tbl[i].boost_addr,
&hw->dvm_upd.tbl[i].boost_entry);
}
/* Key creation */
@ -873,6 +926,27 @@ ice_aq_download_pkg(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
return status;
}
/**
* ice_aq_upload_section
* @hw: pointer to the hardware structure
* @pkg_buf: the package buffer which will receive the section
* @buf_size: the size of the package buffer
* @cd: pointer to command details structure or NULL
*
* Upload Section (0x0C41)
*/
int
ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
u16 buf_size, struct ice_sq_cd *cd)
{
struct ice_aq_desc desc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_upload_section);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
return ice_aq_send_cmd(hw, &desc, pkg_buf, buf_size, cd);
}
/**
* ice_aq_update_pkg
* @hw: pointer to the hardware structure
@ -957,25 +1031,21 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
}
/**
* ice_update_pkg
* ice_update_pkg_no_lock
* @hw: pointer to the hardware structure
* @bufs: pointer to an array of buffers
* @count: the number of buffers in the array
*
* Obtains change lock and updates package.
*/
static int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
static int
ice_update_pkg_no_lock(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
{
u32 offset, info, i;
int status;
status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
if (status)
return status;
int status = 0;
u32 i;
for (i = 0; i < count; i++) {
struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i);
bool last = ((i + 1) == count);
u32 offset, info;
status = ice_aq_update_pkg(hw, bh, le16_to_cpu(bh->data_end),
last, &offset, &info, NULL);
@ -987,6 +1057,27 @@ static int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
}
}
return status;
}
/**
* ice_update_pkg
* @hw: pointer to the hardware structure
* @bufs: pointer to an array of buffers
* @count: the number of buffers in the array
*
* Obtains change lock and updates package.
*/
static int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
{
int status;
status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
if (status)
return status;
status = ice_update_pkg_no_lock(hw, bufs, count);
ice_release_change_lock(hw);
return status;
@ -1080,6 +1171,13 @@ ice_dwnld_cfg_bufs(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
break;
}
if (!status) {
status = ice_set_vlan_mode(hw);
if (status)
ice_debug(hw, ICE_DBG_PKG, "Failed to set VLAN mode: err %d\n",
status);
}
ice_release_global_cfg_lock(hw);
return state;
@ -1117,6 +1215,7 @@ static enum ice_ddp_state
ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
{
struct ice_buf_table *ice_buf_tbl;
int status;
ice_debug(hw, ICE_DBG_PKG, "Segment format version: %d.%d.%d.%d\n",
ice_seg->hdr.seg_format_ver.major,
@ -1133,8 +1232,12 @@ ice_download_pkg(struct ice_hw *hw, struct ice_seg *ice_seg)
ice_debug(hw, ICE_DBG_PKG, "Seg buf count: %d\n",
le32_to_cpu(ice_buf_tbl->buf_count));
return ice_dwnld_cfg_bufs(hw, ice_buf_tbl->buf_array,
le32_to_cpu(ice_buf_tbl->buf_count));
status = ice_dwnld_cfg_bufs(hw, ice_buf_tbl->buf_array,
le32_to_cpu(ice_buf_tbl->buf_count));
ice_post_pkg_dwnld_vlan_mode_cfg(hw);
return status;
}
/**
@ -1897,7 +2000,7 @@ void ice_init_prof_result_bm(struct ice_hw *hw)
*
* Frees a package buffer
*/
static void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld)
void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld)
{
devm_kfree(ice_hw_to_dev(hw), bld);
}
@ -1996,6 +2099,43 @@ ice_pkg_buf_alloc_section(struct ice_buf_build *bld, u32 type, u16 size)
return NULL;
}
/**
* ice_pkg_buf_alloc_single_section
* @hw: pointer to the HW structure
* @type: the section type value
* @size: the size of the section to reserve (in bytes)
* @section: returns pointer to the section
*
* Allocates a package buffer with a single section.
* Note: all package contents must be in Little Endian form.
*/
struct ice_buf_build *
ice_pkg_buf_alloc_single_section(struct ice_hw *hw, u32 type, u16 size,
void **section)
{
struct ice_buf_build *buf;
if (!section)
return NULL;
buf = ice_pkg_buf_alloc(hw);
if (!buf)
return NULL;
if (ice_pkg_buf_reserve_section(buf, 1))
goto ice_pkg_buf_alloc_single_section_err;
*section = ice_pkg_buf_alloc_section(buf, type, size);
if (!*section)
goto ice_pkg_buf_alloc_single_section_err;
return buf;
ice_pkg_buf_alloc_single_section_err:
ice_pkg_buf_free(hw, buf);
return NULL;
}
/**
* ice_pkg_buf_get_active_sections
* @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
@ -2023,7 +2163,7 @@ static u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld)
*
* Return a pointer to the buffer's header
*/
static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
{
if (!bld)
return NULL;
@ -2059,6 +2199,89 @@ ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port,
return res;
}
/**
* ice_upd_dvm_boost_entry
* @hw: pointer to the HW structure
* @entry: pointer to double vlan boost entry info
*/
static int
ice_upd_dvm_boost_entry(struct ice_hw *hw, struct ice_dvm_entry *entry)
{
struct ice_boost_tcam_section *sect_rx, *sect_tx;
int status = -ENOSPC;
struct ice_buf_build *bld;
u8 val, dc, nm;
bld = ice_pkg_buf_alloc(hw);
if (!bld)
return -ENOMEM;
/* allocate 2 sections, one for Rx parser, one for Tx parser */
if (ice_pkg_buf_reserve_section(bld, 2))
goto ice_upd_dvm_boost_entry_err;
sect_rx = ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
struct_size(sect_rx, tcam, 1));
if (!sect_rx)
goto ice_upd_dvm_boost_entry_err;
sect_rx->count = cpu_to_le16(1);
sect_tx = ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
struct_size(sect_tx, tcam, 1));
if (!sect_tx)
goto ice_upd_dvm_boost_entry_err;
sect_tx->count = cpu_to_le16(1);
/* copy original boost entry to update package buffer */
memcpy(sect_rx->tcam, entry->boost_entry, sizeof(*sect_rx->tcam));
/* re-write the don't care and never match bits accordingly */
if (entry->enable) {
/* all bits are don't care */
val = 0x00;
dc = 0xFF;
nm = 0x00;
} else {
/* disable, one never match bit, the rest are don't care */
val = 0x00;
dc = 0xF7;
nm = 0x08;
}
ice_set_key((u8 *)&sect_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key),
&val, NULL, &dc, &nm, 0, sizeof(u8));
/* exact copy of entry to Tx section entry */
memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam));
status = ice_update_pkg_no_lock(hw, ice_pkg_buf(bld), 1);
ice_upd_dvm_boost_entry_err:
ice_pkg_buf_free(hw, bld);
return status;
}
/**
* ice_set_dvm_boost_entries
* @hw: pointer to the HW structure
*
* Enable double vlan by updating the appropriate boost tcam entries.
*/
int ice_set_dvm_boost_entries(struct ice_hw *hw)
{
int status;
u16 i;
for (i = 0; i < hw->dvm_upd.count; i++) {
status = ice_upd_dvm_boost_entry(hw, &hw->dvm_upd.tbl[i]);
if (status)
return status;
}
return 0;
}
/**
* ice_tunnel_idx_to_entry - convert linear index to the sparse one
* @hw: pointer to the HW structure

View file

@ -89,6 +89,12 @@ ice_init_prof_result_bm(struct ice_hw *hw);
int
ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
unsigned long *bm, struct list_head *fv_list);
int
ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count);
u16 ice_pkg_buf_get_free_space(struct ice_buf_build *bld);
int
ice_aq_upload_section(struct ice_hw *hw, struct ice_buf_hdr *pkg_buf,
u16 buf_size, struct ice_sq_cd *cd);
bool
ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port,
enum ice_tunnel_type type);
@ -96,6 +102,7 @@ int ice_udp_tunnel_set_port(struct net_device *netdev, unsigned int table,
unsigned int idx, struct udp_tunnel_info *ti);
int ice_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table,
unsigned int idx, struct udp_tunnel_info *ti);
int ice_set_dvm_boost_entries(struct ice_hw *hw);
/* Rx parser PTYPE functions */
bool ice_hw_ptype_ena(struct ice_hw *hw, u16 ptype);
@ -119,4 +126,10 @@ void ice_fill_blk_tbls(struct ice_hw *hw);
void ice_clear_hw_tbls(struct ice_hw *hw);
void ice_free_hw_tbls(struct ice_hw *hw);
int ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id);
struct ice_buf_build *
ice_pkg_buf_alloc_single_section(struct ice_hw *hw, u32 type, u16 size,
void **section);
struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld);
void ice_pkg_buf_free(struct ice_hw *hw, struct ice_buf_build *bld);
#endif /* _ICE_FLEX_PIPE_H_ */

View file

@ -162,6 +162,7 @@ struct ice_meta_sect {
#define ICE_SID_RXPARSER_MARKER_PTYPE 55
#define ICE_SID_RXPARSER_BOOST_TCAM 56
#define ICE_SID_RXPARSER_METADATA_INIT 58
#define ICE_SID_TXPARSER_BOOST_TCAM 66
#define ICE_SID_XLT0_PE 80
@ -442,6 +443,19 @@ struct ice_tunnel_table {
u16 valid_count[__TNL_TYPE_CNT];
};
struct ice_dvm_entry {
u16 boost_addr;
u16 enable;
struct ice_boost_tcam_entry *boost_entry;
};
#define ICE_DVM_MAX_ENTRIES 48
struct ice_dvm_table {
struct ice_dvm_entry tbl[ICE_DVM_MAX_ENTRIES];
u16 count;
};
struct ice_pkg_es {
__le16 count;
__le16 offset;
@ -662,4 +676,30 @@ enum ice_prof_type {
ICE_PROF_TUN_ALL = 0x6,
ICE_PROF_ALL = 0xFF,
};
/* Number of bits/bytes contained in meta init entry. Note, this should be a
* multiple of 32 bits.
*/
#define ICE_META_INIT_BITS 192
#define ICE_META_INIT_DW_CNT (ICE_META_INIT_BITS / (sizeof(__le32) * \
BITS_PER_BYTE))
/* The meta init Flag field starts at this bit */
#define ICE_META_FLAGS_ST 123
/* The entry and bit to check for Double VLAN Mode (DVM) support */
#define ICE_META_VLAN_MODE_ENTRY 0
#define ICE_META_FLAG_VLAN_MODE 60
#define ICE_META_VLAN_MODE_BIT (ICE_META_FLAGS_ST + \
ICE_META_FLAG_VLAN_MODE)
struct ice_meta_init_entry {
__le32 bm[ICE_META_INIT_DW_CNT];
};
struct ice_meta_init_section {
__le16 count;
__le16 offset;
struct ice_meta_init_entry entry;
};
#endif /* _ICE_FLEX_TYPE_H_ */

View file

@ -203,21 +203,22 @@ ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list,
* ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list
* @vsi: pointer to VSI struct
* @list: list to add filter info to
* @vlan_id: VLAN ID to add
* @action: filter action
* @vlan: VLAN filter details
*/
static int
ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list,
u16 vlan_id, enum ice_sw_fwd_act_type action)
struct ice_vlan *vlan)
{
struct ice_fltr_info info = { 0 };
info.flag = ICE_FLTR_TX;
info.src_id = ICE_SRC_ID_VSI;
info.lkup_type = ICE_SW_LKUP_VLAN;
info.fltr_act = action;
info.fltr_act = ICE_FWD_TO_VSI;
info.vsi_handle = vsi->idx;
info.l_data.vlan.vlan_id = vlan_id;
info.l_data.vlan.vlan_id = vlan->vid;
info.l_data.vlan.tpid = vlan->tpid;
info.l_data.vlan.tpid_valid = true;
return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
list);
@ -310,19 +311,17 @@ ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
/**
* ice_fltr_prepare_vlan - add or remove VLAN filter
* @vsi: pointer to VSI struct
* @vlan_id: VLAN ID to add
* @action: action to be performed on filter match
* @vlan: VLAN filter details
* @vlan_action: pointer to add or remove VLAN function
*/
static int
ice_fltr_prepare_vlan(struct ice_vsi *vsi, u16 vlan_id,
enum ice_sw_fwd_act_type action,
ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan,
int (*vlan_action)(struct ice_vsi *, struct list_head *))
{
LIST_HEAD(tmp_list);
int result;
if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan_id, action))
if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan))
return -ENOMEM;
result = vlan_action(vsi, &tmp_list);
@ -395,27 +394,21 @@ int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,
/**
* ice_fltr_add_vlan - add single VLAN filter
* @vsi: pointer to VSI struct
* @vlan_id: VLAN ID to add
* @action: action to be performed on filter match
* @vlan: VLAN filter details
*/
int ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vlan_id,
enum ice_sw_fwd_act_type action)
int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
return ice_fltr_prepare_vlan(vsi, vlan_id, action,
ice_fltr_add_vlan_list);
return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list);
}
/**
* ice_fltr_remove_vlan - remove VLAN filter
* @vsi: pointer to VSI struct
* @vlan_id: filter VLAN to remove
* @action: action to remove
* @vlan: VLAN filter details
*/
int ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vlan_id,
enum ice_sw_fwd_act_type action)
int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
return ice_fltr_prepare_vlan(vsi, vlan_id, action,
ice_fltr_remove_vlan_list);
return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list);
}
/**

View file

@ -4,6 +4,8 @@
#ifndef _ICE_FLTR_H_
#define _ICE_FLTR_H_
#include "ice_vlan.h"
void ice_fltr_free_list(struct device *dev, struct list_head *h);
int
ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
@ -32,12 +34,8 @@ ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,
enum ice_sw_fwd_act_type action);
int ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list);
int
ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vid,
enum ice_sw_fwd_act_type action);
int
ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vid,
enum ice_sw_fwd_act_type action);
int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
int
ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,

View file

@ -424,6 +424,8 @@ enum ice_rx_flex_desc_status_error_0_bits {
enum ice_rx_flex_desc_status_error_1_bits {
/* Note: These are predefined bit offsets */
ICE_RX_FLEX_DESC_STATUS1_NAT_S = 4,
/* [10:5] reserved */
ICE_RX_FLEX_DESC_STATUS1_L2TAG2P_S = 11,
ICE_RX_FLEX_DESC_STATUS1_LAST /* this entry must be last!!! */
};

View file

@ -8,6 +8,7 @@
#include "ice_fltr.h"
#include "ice_dcb_lib.h"
#include "ice_devlink.h"
#include "ice_vsi_vlan_ops.h"
/**
* ice_vsi_type_str - maps VSI type enum to string equivalents
@ -838,11 +839,12 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
/**
* ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
* @hw: HW structure used to determine the VLAN mode of the device
* @ctxt: the VSI context being set
*
* This initializes a default VSI context for all sections except the Queues.
*/
static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
static void ice_set_dflt_vsi_ctx(struct ice_hw *hw, struct ice_vsi_ctx *ctxt)
{
u32 table = 0;
@ -853,13 +855,27 @@ static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
/* Traffic from VSI can be sent to LAN */
ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
* behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
* packets untagged/tagged.
/* allow all untagged/tagged packets by default on Tx */
ctxt->info.inner_vlan_flags = ((ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL &
ICE_AQ_VSI_INNER_VLAN_TX_MODE_M) >>
ICE_AQ_VSI_INNER_VLAN_TX_MODE_S);
/* SVM - by default bits 3 and 4 in inner_vlan_flags are 0's which
* results in legacy behavior (show VLAN, DEI, and UP) in descriptor.
*
* DVM - leave inner VLAN in packet by default
*/
ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
ICE_AQ_VSI_VLAN_MODE_M) >>
ICE_AQ_VSI_VLAN_MODE_S);
if (ice_is_dvm_ena(hw)) {
ctxt->info.inner_vlan_flags |=
ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING;
ctxt->info.outer_vlan_flags =
(ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL <<
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) &
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M;
ctxt->info.outer_vlan_flags |=
(ICE_AQ_VSI_OUTER_TAG_VLAN_8100 <<
ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
ICE_AQ_VSI_OUTER_TAG_TYPE_M;
}
/* Have 1:1 UP mapping for both ingress/egress tables */
table |= ICE_UP_TABLE_TRANSLATE(0, 0);
table |= ICE_UP_TABLE_TRANSLATE(1, 1);
@ -1136,7 +1152,7 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
}
ice_set_dflt_vsi_ctx(ctxt);
ice_set_dflt_vsi_ctx(hw, ctxt);
if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
ice_set_fd_vsi_ctx(ctxt, vsi);
/* if the switch is in VEB mode, allow VSI loopback */
@ -1168,25 +1184,6 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
}
/* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off
* respectively
*/
if (vsi->type == ICE_VSI_VF) {
ctxt->info.valid_sections |=
cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
if (pf->vf[vsi->vf_id].spoofchk) {
ctxt->info.sec_flags |=
ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
} else {
ctxt->info.sec_flags &=
~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S));
}
}
/* Allow control frames out of main VSI */
if (vsi->type == ICE_VSI_PF) {
ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
@ -1431,6 +1428,7 @@ static void ice_vsi_clear_rings(struct ice_vsi *vsi)
*/
static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
{
bool dvm_ena = ice_is_dvm_ena(&vsi->back->hw);
struct ice_pf *pf = vsi->back;
struct device *dev;
u16 i;
@ -1452,6 +1450,10 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
ring->tx_tstamps = &pf->ptp.port.tx;
ring->dev = dev;
ring->count = vsi->num_tx_desc;
if (dvm_ena)
ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG2;
else
ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG1;
WRITE_ONCE(vsi->tx_rings[i], ring);
}
@ -1756,62 +1758,6 @@ void ice_update_eth_stats(struct ice_vsi *vsi)
vsi->stat_offsets_loaded = true;
}
/**
* ice_vsi_add_vlan - Add VSI membership for given VLAN
* @vsi: the VSI being configured
* @vid: VLAN ID to be added
* @action: filter action to be performed on match
*/
int
ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action)
{
struct ice_pf *pf = vsi->back;
struct device *dev;
int err = 0;
dev = ice_pf_to_dev(pf);
if (!ice_fltr_add_vlan(vsi, vid, action)) {
vsi->num_vlan++;
} else {
err = -ENODEV;
dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid,
vsi->vsi_num);
}
return err;
}
/**
* ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
* @vsi: the VSI being configured
* @vid: VLAN ID to be removed
*
* Returns 0 on success and negative on failure
*/
int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
{
struct ice_pf *pf = vsi->back;
struct device *dev;
int err;
dev = ice_pf_to_dev(pf);
err = ice_fltr_remove_vlan(vsi, vid, ICE_FWD_TO_VSI);
if (!err) {
vsi->num_vlan--;
} else if (err == -ENOENT) {
dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, error: %d\n",
vid, vsi->vsi_num, err);
err = 0;
} else {
dev_err(dev, "Error removing VLAN %d on vsi %i error: %d\n",
vid, vsi->vsi_num, err);
}
return err;
}
/**
* ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
* @vsi: VSI
@ -2139,95 +2085,6 @@ void ice_vsi_cfg_msix(struct ice_vsi *vsi)
}
}
/**
* ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
* @vsi: the VSI being changed
*/
int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int ret;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
/* Here we are configuring the VSI to let the driver add VLAN tags by
* setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
* insertion happens in the Tx hot path, in ice_tx_map.
*/
ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
/* Preserve existing VLAN strip setting */
ctxt->info.vlan_flags |= (vsi->info.vlan_flags &
ICE_AQ_VSI_VLAN_EMOD_M);
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (ret) {
dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %d aq_err %s\n",
ret, ice_aq_str(hw->adminq.sq_last_status));
goto out;
}
vsi->info.vlan_flags = ctxt->info.vlan_flags;
out:
kfree(ctxt);
return ret;
}
/**
* ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
* @vsi: the VSI being changed
* @ena: boolean value indicating if this is a enable or disable request
*/
int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int ret;
/* do not allow modifying VLAN stripping when a port VLAN is configured
* on this VSI
*/
if (vsi->info.pvid)
return 0;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
/* Here we are configuring what the VSI should do with the VLAN tag in
* the Rx packet. We can either leave the tag in the packet or put it in
* the Rx descriptor.
*/
if (ena)
/* Strip VLAN tag from Rx packet and put it in the desc */
ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
else
/* Disable stripping. Leave tag in packet */
ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
/* Allow all packets untagged/tagged */
ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (ret) {
dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %d aq_err %s\n",
ena, ret, ice_aq_str(hw->adminq.sq_last_status));
goto out;
}
vsi->info.vlan_flags = ctxt->info.vlan_flags;
out:
kfree(ctxt);
return ret;
}
/**
* ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
* @vsi: the VSI whose rings are to be enabled
@ -2321,61 +2178,6 @@ bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA);
}
/**
* ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
* @vsi: VSI to enable or disable VLAN pruning on
* @ena: set to true to enable VLAN pruning and false to disable it
*
* returns 0 if VSI is updated, negative otherwise
*/
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
{
struct ice_vsi_ctx *ctxt;
struct ice_pf *pf;
int status;
if (!vsi)
return -EINVAL;
/* Don't enable VLAN pruning if the netdev is currently in promiscuous
* mode. VLAN pruning will be enabled when the interface exits
* promiscuous mode if any VLAN filters are active.
*/
if (vsi->netdev && vsi->netdev->flags & IFF_PROMISC && ena)
return 0;
pf = vsi->back;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info = vsi->info;
if (ena)
ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
else
ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
if (status) {
netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %s\n",
ena ? "En" : "Dis", vsi->idx, vsi->vsi_num,
status, ice_aq_str(pf->hw.adminq.sq_last_status));
goto err_out;
}
vsi->info.sw_flags2 = ctxt->info.sw_flags2;
kfree(ctxt);
return 0;
err_out:
kfree(ctxt);
return -EIO;
}
static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
{
if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
@ -2655,6 +2457,8 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
if (ret)
goto unroll_get_qs;
ice_vsi_init_vlan_ops(vsi);
switch (vsi->type) {
case ICE_VSI_CTRL:
case ICE_VSI_SWITCHDEV_CTRL:
@ -2675,17 +2479,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
if (ret)
goto unroll_vector_base;
/* Always add VLAN ID 0 switch rule by default. This is needed
* in order to allow all untagged and 0 tagged priority traffic
* if Rx VLAN pruning is enabled. Also there are cases where we
* don't get the call to add VLAN 0 via ice_vlan_rx_add_vid()
* so this handles those cases (i.e. adding the PF to a bridge
* without the 8021q module loaded).
*/
ret = ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI);
if (ret)
goto unroll_clear_rings;
ice_vsi_map_rings_to_vectors(vsi);
/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
@ -3318,6 +3111,8 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
if (vtype == ICE_VSI_VF)
vf = &pf->vf[vsi->vf_id];
ice_vsi_init_vlan_ops(vsi);
coalesce = kcalloc(vsi->num_q_vectors,
sizeof(struct ice_coalesce_stored), GFP_KERNEL);
if (!coalesce)
@ -4130,6 +3925,115 @@ int ice_set_link(struct ice_vsi *vsi, bool ena)
return 0;
}
/**
* ice_vsi_add_vlan_zero - add VLAN 0 filter(s) for this VSI
* @vsi: VSI used to add VLAN filters
*
* In Single VLAN Mode (SVM), single VLAN filters via ICE_SW_LKUP_VLAN are based
* on the inner VLAN ID, so the VLAN TPID (i.e. 0x8100 or 0x888a8) doesn't
* matter. In Double VLAN Mode (DVM), outer/single VLAN filters via
* ICE_SW_LKUP_VLAN are based on the outer/single VLAN ID + VLAN TPID.
*
* For both modes add a VLAN 0 + no VLAN TPID filter to handle untagged traffic
* when VLAN pruning is enabled. Also, this handles VLAN 0 priority tagged
* traffic in SVM, since the VLAN TPID isn't part of filtering.
*
* If DVM is enabled then an explicit VLAN 0 + VLAN TPID filter needs to be
* added to allow VLAN 0 priority tagged traffic in DVM, since the VLAN TPID is
* part of filtering.
*/
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
struct ice_vlan vlan;
int err;
vlan = ICE_VLAN(0, 0, 0);
err = vlan_ops->add_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;
/* in SVM both VLAN 0 filters are identical */
if (!ice_is_dvm_ena(&vsi->back->hw))
return 0;
vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
err = vlan_ops->add_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;
return 0;
}
/**
* ice_vsi_del_vlan_zero - delete VLAN 0 filter(s) for this VSI
* @vsi: VSI used to add VLAN filters
*
* Delete the VLAN 0 filters in the same manner that they were added in
* ice_vsi_add_vlan_zero.
*/
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
struct ice_vlan vlan;
int err;
vlan = ICE_VLAN(0, 0, 0);
err = vlan_ops->del_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;
/* in SVM both VLAN 0 filters are identical */
if (!ice_is_dvm_ena(&vsi->back->hw))
return 0;
vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
err = vlan_ops->del_vlan(vsi, &vlan);
if (err && err != -EEXIST)
return err;
return 0;
}
/**
* ice_vsi_num_zero_vlans - get number of VLAN 0 filters based on VLAN mode
* @vsi: VSI used to get the VLAN mode
*
* If DVM is enabled then 2 VLAN 0 filters are added, else if SVM is enabled
* then 1 VLAN 0 filter is added. See ice_vsi_add_vlan_zero for more details.
*/
static u16 ice_vsi_num_zero_vlans(struct ice_vsi *vsi)
{
#define ICE_DVM_NUM_ZERO_VLAN_FLTRS 2
#define ICE_SVM_NUM_ZERO_VLAN_FLTRS 1
/* no VLAN 0 filter is created when a port VLAN is active */
if (vsi->type == ICE_VSI_VF &&
ice_vf_is_port_vlan_ena(&vsi->back->vf[vsi->vf_id]))
return 0;
if (ice_is_dvm_ena(&vsi->back->hw))
return ICE_DVM_NUM_ZERO_VLAN_FLTRS;
else
return ICE_SVM_NUM_ZERO_VLAN_FLTRS;
}
/**
* ice_vsi_has_non_zero_vlans - check if VSI has any non-zero VLANs
* @vsi: VSI used to determine if any non-zero VLANs have been added
*/
bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi)
{
return (vsi->num_vlan > ice_vsi_num_zero_vlans(vsi));
}
/**
* ice_vsi_num_non_zero_vlans - get the number of non-zero VLANs for this VSI
* @vsi: VSI used to get the number of non-zero VLANs added
*/
u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi)
{
return (vsi->num_vlan - ice_vsi_num_zero_vlans(vsi));
}
/**
* ice_is_feature_supported
* @pf: pointer to the struct ice_pf instance

View file

@ -5,6 +5,7 @@
#define _ICE_LIB_H_
#include "ice.h"
#include "ice_vlan.h"
const char *ice_vsi_type_str(enum ice_vsi_type vsi_type);
@ -22,15 +23,6 @@ int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi);
void ice_vsi_cfg_msix(struct ice_vsi *vsi);
int
ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action);
int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid);
int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi);
int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena);
int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi);
int ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi);
@ -45,8 +37,6 @@ int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi);
bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi);
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena);
void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);
int ice_set_link(struct ice_vsi *vsi, bool ena);
@ -132,7 +122,10 @@ void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx);
void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx);
void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx);
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi);
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi);
bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi);
u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi);
bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f);
void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f);
void ice_init_feature_support(struct ice_pf *pf);

View file

@ -21,6 +21,7 @@
#include "ice_trace.h"
#include "ice_eswitch.h"
#include "ice_tc_lib.h"
#include "ice_vsi_vlan_ops.h"
#define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver"
static const char ice_driver_string[] = DRV_SUMMARY;
@ -244,7 +245,7 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m)
if (vsi->type != ICE_VSI_PF)
return 0;
if (vsi->num_vlan > 1)
if (ice_vsi_has_non_zero_vlans(vsi))
status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m);
else
status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0);
@ -264,7 +265,7 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
if (vsi->type != ICE_VSI_PF)
return 0;
if (vsi->num_vlan > 1)
if (ice_vsi_has_non_zero_vlans(vsi))
status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m);
else
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0);
@ -279,6 +280,7 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
*/
static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
struct device *dev = ice_pf_to_dev(vsi->back);
struct net_device *netdev = vsi->netdev;
bool promisc_forced_on = false;
@ -352,7 +354,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
/* check for changes in promiscuous modes */
if (changed_flags & IFF_ALLMULTI) {
if (vsi->current_netdev_flags & IFF_ALLMULTI) {
if (vsi->num_vlan > 1)
if (ice_vsi_has_non_zero_vlans(vsi))
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_MCAST_PROMISC_BITS;
@ -366,7 +368,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
}
} else {
/* !(vsi->current_netdev_flags & IFF_ALLMULTI) */
if (vsi->num_vlan > 1)
if (ice_vsi_has_non_zero_vlans(vsi))
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_MCAST_PROMISC_BITS;
@ -396,7 +398,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
goto out_promisc;
}
err = 0;
ice_cfg_vlan_pruning(vsi, false);
vlan_ops->dis_rx_filtering(vsi);
}
} else {
/* Clear Rx filter to remove traffic from wire */
@ -409,8 +411,9 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
IFF_PROMISC;
goto out_promisc;
}
if (vsi->num_vlan > 1)
ice_cfg_vlan_pruning(vsi, true);
if (vsi->current_netdev_flags &
NETIF_F_HW_VLAN_CTAG_FILTER)
vlan_ops->ena_rx_filtering(vsi);
}
}
}
@ -3230,6 +3233,7 @@ static void ice_set_ops(struct net_device *netdev)
static void ice_set_netdev_features(struct net_device *netdev)
{
struct ice_pf *pf = ice_netdev_to_pf(netdev);
bool is_dvm_ena = ice_is_dvm_ena(&pf->hw);
netdev_features_t csumo_features;
netdev_features_t vlano_features;
netdev_features_t dflt_features;
@ -3256,6 +3260,10 @@ static void ice_set_netdev_features(struct net_device *netdev)
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX;
/* Enable CTAG/STAG filtering by default in Double VLAN Mode (DVM) */
if (is_dvm_ena)
vlano_features |= NETIF_F_HW_VLAN_STAG_FILTER;
tso_features = NETIF_F_TSO |
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
@ -3287,6 +3295,15 @@ static void ice_set_netdev_features(struct net_device *netdev)
tso_features;
netdev->vlan_features |= dflt_features | csumo_features |
tso_features;
/* advertise support but don't enable by default since only one type of
* VLAN offload can be enabled at a time (i.e. CTAG or STAG). When one
* type turns on the other has to be turned off. This is enforced by the
* ice_fix_features() ndo callback.
*/
if (is_dvm_ena)
netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX |
NETIF_F_HW_VLAN_STAG_TX;
}
/**
@ -3402,34 +3419,31 @@ ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
/**
* ice_vlan_rx_add_vid - Add a VLAN ID filter to HW offload
* @netdev: network interface to be adjusted
* @proto: unused protocol
* @proto: VLAN TPID
* @vid: VLAN ID to be added
*
* net_device_ops implementation for adding VLAN IDs
*/
static int
ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
u16 vid)
ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_vsi *vsi = np->vsi;
struct ice_vlan vlan;
int ret;
/* VLAN 0 is added by default during load/reset */
if (!vid)
return 0;
/* Enable VLAN pruning when a VLAN other than 0 is added */
if (!ice_vsi_is_vlan_pruning_ena(vsi)) {
ret = ice_cfg_vlan_pruning(vsi, true);
if (ret)
return ret;
}
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
/* Add a switch rule for this VLAN ID so its corresponding VLAN tagged
* packets aren't pruned by the device's internal switch on Rx
*/
ret = ice_vsi_add_vlan(vsi, vid, ICE_FWD_TO_VSI);
vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
ret = vlan_ops->add_vlan(vsi, &vlan);
if (!ret)
set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
@ -3439,36 +3453,36 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
/**
* ice_vlan_rx_kill_vid - Remove a VLAN ID filter from HW offload
* @netdev: network interface to be adjusted
* @proto: unused protocol
* @proto: VLAN TPID
* @vid: VLAN ID to be removed
*
* net_device_ops implementation for removing VLAN IDs
*/
static int
ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
u16 vid)
ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_vsi *vsi = np->vsi;
struct ice_vlan vlan;
int ret;
/* don't allow removal of VLAN 0 */
if (!vid)
return 0;
/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
/* Make sure VLAN delete is successful before updating VLAN
* information
*/
ret = ice_vsi_kill_vlan(vsi, vid);
vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
ret = vlan_ops->del_vlan(vsi, &vlan);
if (ret)
return ret;
/* Disable pruning when VLAN 0 is the only VLAN rule */
if (vsi->num_vlan == 1 && ice_vsi_is_vlan_pruning_ena(vsi))
ret = ice_cfg_vlan_pruning(vsi, false);
set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
return ret;
return 0;
}
/**
@ -3537,12 +3551,17 @@ static int ice_tc_indir_block_register(struct ice_vsi *vsi)
static int ice_setup_pf_sw(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
bool dvm = ice_is_dvm_ena(&pf->hw);
struct ice_vsi *vsi;
int status;
if (ice_is_reset_in_progress(pf->state))
return -EBUSY;
status = ice_aq_set_port_params(pf->hw.port_info, dvm, NULL);
if (status)
return -EIO;
vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
if (!vsi)
return -ENOMEM;
@ -4064,8 +4083,8 @@ static void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf)
ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
/* allow all VLANs on Tx and don't strip on Rx */
ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL |
ICE_AQ_VSI_VLAN_EMOD_NOTHING;
ctxt->info.inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL |
ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING;
status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (status) {
@ -4074,7 +4093,7 @@ static void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf)
} else {
vsi->info.sec_flags = ctxt->info.sec_flags;
vsi->info.sw_flags2 = ctxt->info.sw_flags2;
vsi->info.vlan_flags = ctxt->info.vlan_flags;
vsi->info.inner_vlan_flags = ctxt->info.inner_vlan_flags;
}
kfree(ctxt);
@ -5568,6 +5587,194 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
return err;
}
#define NETIF_VLAN_OFFLOAD_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_HW_VLAN_STAG_RX | \
NETIF_F_HW_VLAN_STAG_TX)
#define NETIF_VLAN_FILTERING_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \
NETIF_F_HW_VLAN_STAG_FILTER)
/**
* ice_fix_features - fix the netdev features flags based on device limitations
* @netdev: ptr to the netdev that flags are being fixed on
* @features: features that need to be checked and possibly fixed
*
* Make sure any fixups are made to features in this callback. This enables the
* driver to not have to check unsupported configurations throughout the driver
* because that's the responsiblity of this callback.
*
* Single VLAN Mode (SVM) Supported Features:
* NETIF_F_HW_VLAN_CTAG_FILTER
* NETIF_F_HW_VLAN_CTAG_RX
* NETIF_F_HW_VLAN_CTAG_TX
*
* Double VLAN Mode (DVM) Supported Features:
* NETIF_F_HW_VLAN_CTAG_FILTER
* NETIF_F_HW_VLAN_CTAG_RX
* NETIF_F_HW_VLAN_CTAG_TX
*
* NETIF_F_HW_VLAN_STAG_FILTER
* NETIF_HW_VLAN_STAG_RX
* NETIF_HW_VLAN_STAG_TX
*
* Features that need fixing:
* Cannot simultaneously enable CTAG and STAG stripping and/or insertion.
* These are mutually exlusive as the VSI context cannot support multiple
* VLAN ethertypes simultaneously for stripping and/or insertion. If this
* is not done, then default to clearing the requested STAG offload
* settings.
*
* All supported filtering has to be enabled or disabled together. For
* example, in DVM, CTAG and STAG filtering have to be enabled and disabled
* together. If this is not done, then default to VLAN filtering disabled.
* These are mutually exclusive as there is currently no way to
* enable/disable VLAN filtering based on VLAN ethertype when using VLAN
* prune rules.
*/
static netdev_features_t
ice_fix_features(struct net_device *netdev, netdev_features_t features)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
netdev_features_t supported_vlan_filtering;
netdev_features_t requested_vlan_filtering;
struct ice_vsi *vsi = np->vsi;
requested_vlan_filtering = features & NETIF_VLAN_FILTERING_FEATURES;
/* make sure supported_vlan_filtering works for both SVM and DVM */
supported_vlan_filtering = NETIF_F_HW_VLAN_CTAG_FILTER;
if (ice_is_dvm_ena(&vsi->back->hw))
supported_vlan_filtering |= NETIF_F_HW_VLAN_STAG_FILTER;
if (requested_vlan_filtering &&
requested_vlan_filtering != supported_vlan_filtering) {
if (requested_vlan_filtering & NETIF_F_HW_VLAN_CTAG_FILTER) {
netdev_warn(netdev, "cannot support requested VLAN filtering settings, enabling all supported VLAN filtering settings\n");
features |= supported_vlan_filtering;
} else {
netdev_warn(netdev, "cannot support requested VLAN filtering settings, clearing all supported VLAN filtering settings\n");
features &= ~supported_vlan_filtering;
}
}
if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX)) &&
(features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))) {
netdev_warn(netdev, "cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings\n");
features &= ~(NETIF_F_HW_VLAN_STAG_RX |
NETIF_F_HW_VLAN_STAG_TX);
}
return features;
}
/**
* ice_set_vlan_offload_features - set VLAN offload features for the PF VSI
* @vsi: PF's VSI
* @features: features used to determine VLAN offload settings
*
* First, determine the vlan_ethertype based on the VLAN offload bits in
* features. Then determine if stripping and insertion should be enabled or
* disabled. Finally enable or disable VLAN stripping and insertion.
*/
static int
ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features)
{
bool enable_stripping = true, enable_insertion = true;
struct ice_vsi_vlan_ops *vlan_ops;
int strip_err = 0, insert_err = 0;
u16 vlan_ethertype = 0;
vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
if (features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX))
vlan_ethertype = ETH_P_8021AD;
else if (features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX))
vlan_ethertype = ETH_P_8021Q;
if (!(features & (NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_CTAG_RX)))
enable_stripping = false;
if (!(features & (NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX)))
enable_insertion = false;
if (enable_stripping)
strip_err = vlan_ops->ena_stripping(vsi, vlan_ethertype);
else
strip_err = vlan_ops->dis_stripping(vsi);
if (enable_insertion)
insert_err = vlan_ops->ena_insertion(vsi, vlan_ethertype);
else
insert_err = vlan_ops->dis_insertion(vsi);
if (strip_err || insert_err)
return -EIO;
return 0;
}
/**
* ice_set_vlan_filtering_features - set VLAN filtering features for the PF VSI
* @vsi: PF's VSI
* @features: features used to determine VLAN filtering settings
*
* Enable or disable Rx VLAN filtering based on the VLAN filtering bits in the
* features.
*/
static int
ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
{
struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
int err = 0;
/* support Single VLAN Mode (SVM) and Double VLAN Mode (DVM) by checking
* if either bit is set
*/
if (features &
(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER))
err = vlan_ops->ena_rx_filtering(vsi);
else
err = vlan_ops->dis_rx_filtering(vsi);
return err;
}
/**
* ice_set_vlan_features - set VLAN settings based on suggested feature set
* @netdev: ptr to the netdev being adjusted
* @features: the feature set that the stack is suggesting
*
* Only update VLAN settings if the requested_vlan_features are different than
* the current_vlan_features.
*/
static int
ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
{
netdev_features_t current_vlan_features, requested_vlan_features;
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
int err;
current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
if (current_vlan_features ^ requested_vlan_features) {
err = ice_set_vlan_offload_features(vsi, features);
if (err)
return err;
}
current_vlan_features = netdev->features &
NETIF_VLAN_FILTERING_FEATURES;
requested_vlan_features = features & NETIF_VLAN_FILTERING_FEATURES;
if (current_vlan_features ^ requested_vlan_features) {
err = ice_set_vlan_filtering_features(vsi, features);
if (err)
return err;
}
return 0;
}
/**
* ice_set_features - set the netdev feature flags
* @netdev: ptr to the netdev being adjusted
@ -5602,26 +5809,9 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
netdev->features & NETIF_F_RXHASH)
ice_vsi_manage_rss_lut(vsi, false);
if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
ret = ice_vsi_manage_vlan_stripping(vsi, true);
else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) &&
(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
ret = ice_vsi_manage_vlan_stripping(vsi, false);
if ((features & NETIF_F_HW_VLAN_CTAG_TX) &&
!(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
ret = ice_vsi_manage_vlan_insertion(vsi);
else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) &&
(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
ret = ice_vsi_manage_vlan_insertion(vsi);
if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
!(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
ret = ice_cfg_vlan_pruning(vsi, true);
else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
ret = ice_cfg_vlan_pruning(vsi, false);
ret = ice_set_vlan_features(netdev, features);
if (ret)
return ret;
if ((features & NETIF_F_NTUPLE) &&
!(netdev->features & NETIF_F_NTUPLE)) {
@ -5645,23 +5835,26 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
else
clear_bit(ICE_FLAG_CLS_FLOWER, pf->flags);
return ret;
return 0;
}
/**
* ice_vsi_vlan_setup - Setup VLAN offload properties on a VSI
* ice_vsi_vlan_setup - Setup VLAN offload properties on a PF VSI
* @vsi: VSI to setup VLAN properties for
*/
static int ice_vsi_vlan_setup(struct ice_vsi *vsi)
{
int ret = 0;
int err;
if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
ret = ice_vsi_manage_vlan_stripping(vsi, true);
if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
ret = ice_vsi_manage_vlan_insertion(vsi);
err = ice_set_vlan_offload_features(vsi, vsi->netdev->features);
if (err)
return err;
return ret;
err = ice_set_vlan_filtering_features(vsi, vsi->netdev->features);
if (err)
return err;
return ice_vsi_add_vlan_zero(vsi);
}
/**
@ -6262,11 +6455,12 @@ static void ice_napi_disable_all(struct ice_vsi *vsi)
*/
int ice_down(struct ice_vsi *vsi)
{
int i, tx_err, rx_err, link_err = 0;
int i, tx_err, rx_err, link_err = 0, vlan_err = 0;
WARN_ON(!test_bit(ICE_VSI_DOWN, vsi->state));
if (vsi->netdev && vsi->type == ICE_VSI_PF) {
vlan_err = ice_vsi_del_vlan_zero(vsi);
if (!ice_is_e810(&vsi->back->hw))
ice_ptp_link_change(vsi->back, vsi->back->hw.pf_id, false);
netif_carrier_off(vsi->netdev);
@ -6308,7 +6502,7 @@ int ice_down(struct ice_vsi *vsi)
ice_for_each_rxq(vsi, i)
ice_clean_rx_ring(vsi->rx_rings[i]);
if (tx_err || rx_err || link_err) {
if (tx_err || rx_err || link_err || vlan_err) {
netdev_err(vsi->netdev, "Failed to close VSI 0x%04X on switch 0x%04X\n",
vsi->vsi_num, vsi->vsw->sw_id);
return -EIO;
@ -6618,6 +6812,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
bool dvm;
int err;
if (test_bit(ICE_DOWN, pf->state))
@ -6681,6 +6876,12 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
goto err_init_ctrlq;
}
dvm = ice_is_dvm_ena(hw);
err = ice_aq_set_port_params(pf->hw.port_info, dvm, NULL);
if (err)
goto err_init_ctrlq;
err = ice_sched_init_port(hw->port_info);
if (err)
goto err_sched_init_port;
@ -8580,6 +8781,7 @@ static const struct net_device_ops ice_netdev_ops = {
.ndo_start_xmit = ice_start_xmit,
.ndo_select_queue = ice_select_queue,
.ndo_features_check = ice_features_check,
.ndo_fix_features = ice_fix_features,
.ndo_set_rx_mode = ice_set_rx_mode,
.ndo_set_mac_address = ice_set_mac_address,
.ndo_validate_addr = eth_validate_addr,

View file

@ -9,6 +9,7 @@
#ifndef CONFIG_64BIT
#include <linux/io-64-nonatomic-lo-hi.h>
#endif
#include <net/udp_tunnel.h>
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#define rd32(a, reg) readl((a)->hw_addr + (reg))

View file

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2021, Intel Corporation. */
#include "ice_vsi_vlan_ops.h"
#include "ice_vsi_vlan_lib.h"
#include "ice_vlan_mode.h"
#include "ice.h"
#include "ice_pf_vsi_vlan_ops.h"
void ice_pf_vsi_init_vlan_ops(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops;
if (ice_is_dvm_ena(&vsi->back->hw)) {
vlan_ops = &vsi->outer_vlan_ops;
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_outer_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_outer_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion;
vlan_ops->ena_rx_filtering = ice_vsi_ena_rx_vlan_filtering;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
} else {
vlan_ops = &vsi->inner_vlan_ops;
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
vlan_ops->ena_rx_filtering = ice_vsi_ena_rx_vlan_filtering;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
}
}

View file

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_PF_VSI_VLAN_OPS_H_
#define _ICE_PF_VSI_VLAN_OPS_H_
#include "ice_vsi_vlan_ops.h"
struct ice_vsi;
void ice_pf_vsi_init_vlan_ops(struct ice_vsi *vsi);
#endif /* _ICE_PF_VSI_VLAN_OPS_H_ */

View file

@ -1096,6 +1096,64 @@ ice_aq_get_recipe(struct ice_hw *hw,
return status;
}
/**
* ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
* @hw: pointer to the HW struct
* @params: parameters used to update the default recipe
*
* This function only supports updating default recipes and it only supports
* updating a single recipe based on the lkup_idx at a time.
*
* This is done as a read-modify-write operation. First, get the current recipe
* contents based on the recipe's ID. Then modify the field vector index and
* mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
* the pre-existing recipe with the modifications.
*/
int
ice_update_recipe_lkup_idx(struct ice_hw *hw,
struct ice_update_recipe_lkup_idx_params *params)
{
struct ice_aqc_recipe_data_elem *rcp_list;
u16 num_recps = ICE_MAX_NUM_RECIPES;
int status;
rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
if (!rcp_list)
return -ENOMEM;
/* read current recipe list from firmware */
rcp_list->recipe_indx = params->rid;
status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
if (status) {
ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
params->rid, status);
goto error_out;
}
/* only modify existing recipe's lkup_idx and mask if valid, while
* leaving all other fields the same, then update the recipe firmware
*/
rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
if (params->mask_valid)
rcp_list->content.mask[params->lkup_idx] =
cpu_to_le16(params->mask);
if (params->ignore_valid)
rcp_list->content.lkup_indx[params->lkup_idx] |=
ICE_AQ_RECIPE_LKUP_IGNORE;
status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
if (status)
ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n",
params->rid, params->lkup_idx, params->fv_idx,
params->mask, params->mask_valid ? "true" : "false",
status);
error_out:
kfree(rcp_list);
return status;
}
/**
* ice_aq_map_recipe_to_profile - Map recipe to packet profile
* @hw: pointer to the HW struct
@ -1539,6 +1597,7 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
{
u16 vlan_id = ICE_MAX_VLAN_ID + 1;
u16 vlan_tpid = ETH_P_8021Q;
void *daddr = NULL;
u16 eth_hdr_sz;
u8 *eth_hdr;
@ -1611,6 +1670,8 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
break;
case ICE_SW_LKUP_VLAN:
vlan_id = f_info->l_data.vlan.vlan_id;
if (f_info->l_data.vlan.tpid_valid)
vlan_tpid = f_info->l_data.vlan.tpid;
if (f_info->fltr_act == ICE_FWD_TO_VSI ||
f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
act |= ICE_SINGLE_ACT_PRUNE;
@ -1653,6 +1714,8 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
if (!(vlan_id > ICE_MAX_VLAN_ID)) {
off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
*off = cpu_to_be16(vlan_id);
off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
*off = cpu_to_be16(vlan_tpid);
}
/* Create the switch rule with the final dummy Ethernet header */
@ -3867,6 +3930,23 @@ ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
return ICE_MAX_NUM_RECIPES;
}
/**
* ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
*
* As protocol id for outer vlan is different in dvm and svm, if dvm is
* supported protocol array record for outer vlan has to be modified to
* reflect the value proper for DVM.
*/
void ice_change_proto_id_to_dvm(void)
{
u8 i;
for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
}
/**
* ice_prot_type_to_id - get protocol ID from protocol type
* @type: protocol type

View file

@ -33,15 +33,6 @@ struct ice_vsi_ctx {
struct ice_q_ctx *rdma_q_ctx[ICE_MAX_TRAFFIC_CLASS];
};
enum ice_sw_fwd_act_type {
ICE_FWD_TO_VSI = 0,
ICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */
ICE_FWD_TO_Q,
ICE_FWD_TO_QGRP,
ICE_DROP_PACKET,
ICE_INVAL_ACT
};
/* Switch recipe ID enum values are specific to hardware */
enum ice_sw_lkup_type {
ICE_SW_LKUP_ETHERTYPE = 0,
@ -86,6 +77,8 @@ struct ice_fltr_info {
} mac_vlan;
struct {
u16 vlan_id;
u16 tpid;
u8 tpid_valid;
} vlan;
/* Set lkup_type as ICE_SW_LKUP_ETHERTYPE
* if just using ethertype as filter. Set lkup_type as
@ -125,6 +118,15 @@ struct ice_fltr_info {
u8 lan_en; /* Indicate if packet can be forwarded to the uplink */
};
struct ice_update_recipe_lkup_idx_params {
u16 rid;
u16 fv_idx;
bool ignore_valid;
u16 mask;
bool mask_valid;
u8 lkup_idx;
};
struct ice_adv_lkup_elem {
enum ice_protocol_type type;
union ice_prot_hdr h_u; /* Header values */
@ -367,4 +369,8 @@ void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw);
int
ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd);
int
ice_update_recipe_lkup_idx(struct ice_hw *hw,
struct ice_update_recipe_lkup_idx_params *params);
void ice_change_proto_id_to_dvm(void);
#endif /* _ICE_SWITCH_H_ */

View file

@ -1089,7 +1089,7 @@ ice_is_non_eop(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc)
{
/* if we are the last buffer then there is nothing else to do */
#define ICE_RXD_EOF BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S)
if (likely(ice_test_staterr(rx_desc, ICE_RXD_EOF)))
if (likely(ice_test_staterr(rx_desc->wb.status_error0, ICE_RXD_EOF)))
return false;
rx_ring->rx_stats.non_eop_descs++;
@ -1151,7 +1151,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
* hardware wrote DD then it will be non-zero
*/
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S);
if (!ice_test_staterr(rx_desc, stat_err_bits))
if (!ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits))
break;
/* This memory barrier is needed to keep us from reading
@ -1237,14 +1237,13 @@ construct_skb:
continue;
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S);
if (unlikely(ice_test_staterr(rx_desc, stat_err_bits))) {
if (unlikely(ice_test_staterr(rx_desc->wb.status_error0,
stat_err_bits))) {
dev_kfree_skb_any(skb);
continue;
}
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S);
if (ice_test_staterr(rx_desc, stat_err_bits))
vlan_tag = le16_to_cpu(rx_desc->wb.l2tag1);
vlan_tag = ice_get_vlan_tag_from_rx_desc(rx_desc);
/* pad the skb if needed, to make a valid ethernet frame */
if (eth_skb_pad(skb)) {
@ -1926,12 +1925,16 @@ ice_tx_prepare_vlan_flags(struct ice_tx_ring *tx_ring, struct ice_tx_buf *first)
if (!skb_vlan_tag_present(skb) && eth_type_vlan(skb->protocol))
return;
/* currently, we always assume 802.1Q for VLAN insertion as VLAN
* insertion for 802.1AD is not supported
/* the VLAN ethertype/tpid is determined by VSI configuration and netdev
* feature flags, which the driver only allows either 802.1Q or 802.1ad
* VLAN offloads exclusively so we only care about the VLAN ID here
*/
if (skb_vlan_tag_present(skb)) {
first->tx_flags |= skb_vlan_tag_get(skb) << ICE_TX_FLAGS_VLAN_S;
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
if (tx_ring->flags & ICE_TX_FLAGS_RING_VLAN_L2TAG2)
first->tx_flags |= ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN;
else
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
}
ice_tx_prepare_vlan_flags_dcb(tx_ring, first);
@ -2304,6 +2307,13 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
/* prepare the VLAN tagging flags for Tx */
ice_tx_prepare_vlan_flags(tx_ring, first);
if (first->tx_flags & ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN) {
offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
(ICE_TX_CTX_DESC_IL2TAG2 <<
ICE_TXD_CTX_QW1_CMD_S));
offload.cd_l2tag2 = (first->tx_flags & ICE_TX_FLAGS_VLAN_M) >>
ICE_TX_FLAGS_VLAN_S;
}
/* set up TSO offload */
tso = ice_tso(first, &offload);

View file

@ -123,6 +123,7 @@ static inline int ice_skb_pad(void)
#define ICE_TX_FLAGS_IPV4 BIT(5)
#define ICE_TX_FLAGS_IPV6 BIT(6)
#define ICE_TX_FLAGS_TUNNEL BIT(7)
#define ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN BIT(8)
#define ICE_TX_FLAGS_VLAN_M 0xffff0000
#define ICE_TX_FLAGS_VLAN_PR_M 0xe0000000
#define ICE_TX_FLAGS_VLAN_PR_S 29
@ -335,6 +336,8 @@ struct ice_tx_ring {
/* CL4 - 4th cacheline starts here */
u16 xdp_tx_active;
#define ICE_TX_FLAGS_RING_XDP BIT(0)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG1 BIT(1)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)
u8 flags;
u8 dcb_tc; /* Traffic class of ring */
u8 ptp_tx;

View file

@ -209,9 +209,14 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
void
ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag)
{
if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
(vlan_tag & VLAN_VID_MASK))
netdev_features_t features = rx_ring->netdev->features;
bool non_zero_vlan = !!(vlan_tag & VLAN_VID_MASK);
if ((features & NETIF_F_HW_VLAN_CTAG_RX) && non_zero_vlan)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
else if ((features & NETIF_F_HW_VLAN_STAG_RX) && non_zero_vlan)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan_tag);
napi_gro_receive(&rx_ring->q_vector->napi, skb);
}

View file

@ -7,7 +7,7 @@
/**
* ice_test_staterr - tests bits in Rx descriptor status and error fields
* @rx_desc: pointer to receive descriptor (in le64 format)
* @status_err_n: Rx descriptor status_error0 or status_error1 bits
* @stat_err_bits: value to mask
*
* This function does some fast chicanery in order to return the
@ -16,9 +16,9 @@
* at offset zero.
*/
static inline bool
ice_test_staterr(union ice_32b_rx_flex_desc *rx_desc, const u16 stat_err_bits)
ice_test_staterr(__le16 status_err_n, const u16 stat_err_bits)
{
return !!(rx_desc->wb.status_error0 & cpu_to_le16(stat_err_bits));
return !!(status_err_n & cpu_to_le16(stat_err_bits));
}
static inline __le64
@ -31,6 +31,30 @@ ice_build_ctob(u64 td_cmd, u64 td_offset, unsigned int size, u64 td_tag)
(td_tag << ICE_TXD_QW1_L2TAG1_S));
}
/**
* ice_get_vlan_tag_from_rx_desc - get VLAN from Rx flex descriptor
* @rx_desc: Rx 32b flex descriptor with RXDID=2
*
* The OS and current PF implementation only support stripping a single VLAN tag
* at a time, so there should only ever be 0 or 1 tags in the l2tag* fields. If
* one is found return the tag, else return 0 to mean no VLAN tag was found.
*/
static inline u16
ice_get_vlan_tag_from_rx_desc(union ice_32b_rx_flex_desc *rx_desc)
{
u16 stat_err_bits;
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S);
if (ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits))
return le16_to_cpu(rx_desc->wb.l2tag1);
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS1_L2TAG2P_S);
if (ice_test_staterr(rx_desc->wb.status_error1, stat_err_bits))
return le16_to_cpu(rx_desc->wb.l2tag2_2nd);
return 0;
}
/**
* ice_xdp_ring_update_tail - Updates the XDP Tx ring tail register
* @xdp_ring: XDP Tx ring

View file

@ -15,6 +15,7 @@
#include "ice_flex_type.h"
#include "ice_protocol_type.h"
#include "ice_sbq_cmd.h"
#include "ice_vlan_mode.h"
static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc)
{
@ -54,6 +55,11 @@ static inline u32 ice_round_to_num(u32 N, u32 R)
#define ICE_DBG_AQ_DESC BIT_ULL(25)
#define ICE_DBG_AQ_DESC_BUF BIT_ULL(26)
#define ICE_DBG_AQ_CMD BIT_ULL(27)
#define ICE_DBG_AQ (ICE_DBG_AQ_MSG | \
ICE_DBG_AQ_DESC | \
ICE_DBG_AQ_DESC_BUF | \
ICE_DBG_AQ_CMD)
#define ICE_DBG_USER BIT_ULL(31)
enum ice_aq_res_ids {
@ -920,6 +926,9 @@ struct ice_hw {
struct udp_tunnel_nic_shared udp_tunnel_shared;
struct udp_tunnel_nic_info udp_tunnel_nic;
/* dvm boost update information */
struct ice_dvm_table dvm_upd;
/* HW block tables */
struct ice_blk_info blk[ICE_BLK_COUNT];
struct mutex fl_profs_locks[ICE_BLK_COUNT]; /* lock fltr profiles */
@ -943,6 +952,7 @@ struct ice_hw {
struct list_head rss_list_head;
struct ice_mbx_snapshot mbx_snapshot;
DECLARE_BITMAP(hw_ptype, ICE_FLOW_PTYPE_MAX);
u8 dvm_ena;
u16 io_expander_handle;
};
@ -1008,6 +1018,15 @@ struct ice_hw_port_stats {
u64 fd_sb_match;
};
enum ice_sw_fwd_act_type {
ICE_FWD_TO_VSI = 0,
ICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */
ICE_FWD_TO_Q,
ICE_FWD_TO_QGRP,
ICE_DROP_PACKET,
ICE_INVAL_ACT
};
struct ice_aq_get_set_rss_lut_params {
u16 vsi_handle; /* software VSI handle */
u16 lut_size; /* size of the LUT buffer */

View file

@ -0,0 +1,202 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2021, Intel Corporation. */
#include "ice_vsi_vlan_ops.h"
#include "ice_vsi_vlan_lib.h"
#include "ice_vlan_mode.h"
#include "ice.h"
#include "ice_vf_vsi_vlan_ops.h"
#include "ice_virtchnl_pf.h"
static int
noop_vlan_arg(struct ice_vsi __always_unused *vsi,
struct ice_vlan __always_unused *vlan)
{
return 0;
}
static int
noop_vlan(struct ice_vsi __always_unused *vsi)
{
return 0;
}
/**
* ice_vf_vsi_init_vlan_ops - Initialize default VSI VLAN ops for VF VSI
* @vsi: VF's VSI being configured
*
* If Double VLAN Mode (DVM) is enabled, assume that the VF supports the new
* VIRTCHNL_VF_VLAN_OFFLOAD_V2 capability and set up the VLAN ops accordingly.
* If SVM is enabled maintain the same level of VLAN support previous to
* VIRTCHNL_VF_VLAN_OFFLOAD_V2.
*/
void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi)
{
struct ice_vsi_vlan_ops *vlan_ops;
struct ice_pf *pf = vsi->back;
struct ice_vf *vf;
vf = &pf->vf[vsi->vf_id];
if (ice_is_dvm_ena(&pf->hw)) {
vlan_ops = &vsi->outer_vlan_ops;
/* outer VLAN ops regardless of port VLAN config */
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering;
vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering;
if (ice_vf_is_port_vlan_ena(vf)) {
/* setup outer VLAN ops */
vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan;
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
/* setup inner VLAN ops */
vlan_ops = &vsi->inner_vlan_ops;
vlan_ops->add_vlan = noop_vlan_arg;
vlan_ops->del_vlan = noop_vlan_arg;
vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
} else {
if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags))
vlan_ops->ena_rx_filtering = noop_vlan;
else
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_outer_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_outer_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion;
/* setup inner VLAN ops */
vlan_ops = &vsi->inner_vlan_ops;
vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
}
} else {
vlan_ops = &vsi->inner_vlan_ops;
/* inner VLAN ops regardless of port VLAN config */
vlan_ops->add_vlan = ice_vsi_add_vlan;
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
vlan_ops->ena_tx_filtering = ice_vsi_ena_tx_vlan_filtering;
vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering;
if (ice_vf_is_port_vlan_ena(vf)) {
vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan;
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
} else {
if (!test_bit(ICE_FLAG_VF_VLAN_PRUNING, pf->flags))
vlan_ops->ena_rx_filtering = noop_vlan;
else
vlan_ops->ena_rx_filtering =
ice_vsi_ena_rx_vlan_filtering;
vlan_ops->del_vlan = ice_vsi_del_vlan;
vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;
vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
}
}
}
/**
* ice_vf_vsi_cfg_dvm_legacy_vlan_mode - Config VLAN mode for old VFs in DVM
* @vsi: VF's VSI being configured
*
* This should only be called when Double VLAN Mode (DVM) is enabled, there
* is not a port VLAN enabled on this VF, and the VF negotiates
* VIRTCHNL_VF_OFFLOAD_VLAN.
*
* This function sets up the VF VSI's inner and outer ice_vsi_vlan_ops and also
* initializes software only VLAN mode (i.e. allow all VLANs). Also, use no-op
* implementations for any functions that may be called during the lifetime of
* the VF so these methods do nothing and succeed.
*/
void ice_vf_vsi_cfg_dvm_legacy_vlan_mode(struct ice_vsi *vsi)
{
struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
struct device *dev = ice_pf_to_dev(vf->pf);
struct ice_vsi_vlan_ops *vlan_ops;
if (!ice_is_dvm_ena(&vsi->back->hw) || ice_vf_is_port_vlan_ena(vf))
return;
vlan_ops = &vsi->outer_vlan_ops;
/* Rx VLAN filtering always disabled to allow software offloaded VLANs
* for VFs that only support VIRTCHNL_VF_OFFLOAD_VLAN and don't have a
* port VLAN configured
*/
vlan_ops->dis_rx_filtering = ice_vsi_dis_rx_vlan_filtering;
/* Don't fail when attempting to enable Rx VLAN filtering */
vlan_ops->ena_rx_filtering = noop_vlan;
/* Tx VLAN filtering always disabled to allow software offloaded VLANs
* for VFs that only support VIRTCHNL_VF_OFFLOAD_VLAN and don't have a
* port VLAN configured
*/
vlan_ops->dis_tx_filtering = ice_vsi_dis_tx_vlan_filtering;
/* Don't fail when attempting to enable Tx VLAN filtering */
vlan_ops->ena_tx_filtering = noop_vlan;
if (vlan_ops->dis_rx_filtering(vsi))
dev_dbg(dev, "Failed to disable Rx VLAN filtering for old VF without VIRTCHNL_VF_OFFLOAD_VLAN_V2 support\n");
if (vlan_ops->dis_tx_filtering(vsi))
dev_dbg(dev, "Failed to disable Tx VLAN filtering for old VF without VIRTHCNL_VF_OFFLOAD_VLAN_V2 support\n");
/* All outer VLAN offloads must be disabled */
vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping;
vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion;
if (vlan_ops->dis_stripping(vsi))
dev_dbg(dev, "Failed to disable outer VLAN stripping for old VF without VIRTCHNL_VF_OFFLOAD_VLAN_V2 support\n");
if (vlan_ops->dis_insertion(vsi))
dev_dbg(dev, "Failed to disable outer VLAN insertion for old VF without VIRTCHNL_VF_OFFLOAD_VLAN_V2 support\n");
/* All inner VLAN offloads must be disabled */
vlan_ops = &vsi->inner_vlan_ops;
vlan_ops->dis_stripping = ice_vsi_dis_outer_stripping;
vlan_ops->dis_insertion = ice_vsi_dis_outer_insertion;
if (vlan_ops->dis_stripping(vsi))
dev_dbg(dev, "Failed to disable inner VLAN stripping for old VF without VIRTCHNL_VF_OFFLOAD_VLAN_V2 support\n");
if (vlan_ops->dis_insertion(vsi))
dev_dbg(dev, "Failed to disable inner VLAN insertion for old VF without VIRTCHNL_VF_OFFLOAD_VLAN_V2 support\n");
}
/**
* ice_vf_vsi_cfg_svm_legacy_vlan_mode - Config VLAN mode for old VFs in SVM
* @vsi: VF's VSI being configured
*
* This should only be called when Single VLAN Mode (SVM) is enabled, there is
* not a port VLAN enabled on this VF, and the VF negotiates
* VIRTCHNL_VF_OFFLOAD_VLAN.
*
* All of the normal SVM VLAN ops are identical for this case. However, by
* default Rx VLAN filtering should be turned off by default in this case.
*/
void ice_vf_vsi_cfg_svm_legacy_vlan_mode(struct ice_vsi *vsi)
{
struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
if (ice_is_dvm_ena(&vsi->back->hw) || ice_vf_is_port_vlan_ena(vf))
return;
if (vsi->inner_vlan_ops.dis_rx_filtering(vsi))
dev_dbg(ice_pf_to_dev(vf->pf), "Failed to disable Rx VLAN filtering for old VF with VIRTCHNL_VF_OFFLOAD_VLAN support\n");
}

View file

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_VF_VSI_VLAN_OPS_H_
#define _ICE_VF_VSI_VLAN_OPS_H_
#include "ice_vsi_vlan_ops.h"
struct ice_vsi;
void ice_vf_vsi_cfg_dvm_legacy_vlan_mode(struct ice_vsi *vsi);
void ice_vf_vsi_cfg_svm_legacy_vlan_mode(struct ice_vsi *vsi);
#ifdef CONFIG_PCI_IOV
void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi);
#else
static inline void ice_vf_vsi_init_vlan_ops(struct ice_vsi *vsi) { }
#endif /* CONFIG_PCI_IOV */
#endif /* _ICE_PF_VSI_VLAN_OPS_H_ */

View file

@ -55,6 +55,15 @@ static const u32 vlan_allowlist_opcodes[] = {
VIRTCHNL_OP_ENABLE_VLAN_STRIPPING, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
};
/* VIRTCHNL_VF_OFFLOAD_VLAN_V2 */
static const u32 vlan_v2_allowlist_opcodes[] = {
VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS, VIRTCHNL_OP_ADD_VLAN_V2,
VIRTCHNL_OP_DEL_VLAN_V2, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2,
VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2,
VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2,
VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2,
};
/* VIRTCHNL_VF_OFFLOAD_RSS_PF */
static const u32 rss_pf_allowlist_opcodes[] = {
VIRTCHNL_OP_CONFIG_RSS_KEY, VIRTCHNL_OP_CONFIG_RSS_LUT,
@ -89,6 +98,7 @@ static const struct allowlist_opcode_info allowlist_opcodes[] = {
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_RSS_PF, rss_pf_allowlist_opcodes),
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF, adv_rss_pf_allowlist_opcodes),
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_FDIR_PF, fdir_pf_allowlist_opcodes),
ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_VLAN_V2, vlan_v2_allowlist_opcodes),
};
/**

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
#define _ICE_VIRTCHNL_PF_H_
#include "ice.h"
#include "ice_virtchnl_fdir.h"
#include "ice_vsi_vlan_ops.h"
/* Restrict number of MAC Addr and VLAN that non-trusted VF can programmed */
#define ICE_MAX_VLAN_PER_VF 8
@ -94,6 +95,13 @@ struct ice_vc_vf_ops {
int (*handle_rss_cfg_msg)(struct ice_vf *vf, u8 *msg, bool add);
int (*add_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
int (*del_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
int (*get_offload_vlan_v2_caps)(struct ice_vf *vf);
int (*add_vlan_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*remove_vlan_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*ena_vlan_stripping_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*dis_vlan_stripping_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*ena_vlan_insertion_v2_msg)(struct ice_vf *vf, u8 *msg);
int (*dis_vlan_insertion_v2_msg)(struct ice_vf *vf, u8 *msg);
};
/* VF information structure */
@ -119,7 +127,8 @@ struct ice_vf {
struct ice_time_mac legacy_last_added_umac;
DECLARE_BITMAP(txq_ena, ICE_MAX_RSS_QS_PER_VF);
DECLARE_BITMAP(rxq_ena, ICE_MAX_RSS_QS_PER_VF);
u16 port_vlan_info; /* Port VLAN ID and QoS */
struct ice_vlan port_vlan_info; /* Port VLAN ID, QoS, and TPID */
struct virtchnl_vlan_caps vlan_v2_caps;
u8 pf_set_mac:1; /* VF MAC address set by VMM admin */
u8 trusted:1;
u8 spoofchk:1;
@ -210,6 +219,7 @@ int
ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
enum virtchnl_status_code v_retval, u8 *msg, u16 msglen);
bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id);
bool ice_vf_is_port_vlan_ena(struct ice_vf *vf);
#else /* CONFIG_PCI_IOV */
static inline void ice_process_vflr_event(struct ice_pf *pf) { }
static inline void ice_free_vfs(struct ice_pf *pf) { }
@ -342,5 +352,10 @@ static inline bool ice_is_any_vf_in_promisc(struct ice_pf __always_unused *pf)
{
return false;
}
static inline bool ice_vf_is_port_vlan_ena(struct ice_vf __always_unused *vf)
{
return false;
}
#endif /* CONFIG_PCI_IOV */
#endif /* _ICE_VIRTCHNL_PF_H_ */

View file

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_VLAN_H_
#define _ICE_VLAN_H_
#include <linux/types.h>
#include "ice_type.h"
struct ice_vlan {
u16 tpid;
u16 vid;
u8 prio;
};
#define ICE_VLAN(tpid, vid, prio) ((struct ice_vlan){ tpid, vid, prio })
#endif /* _ICE_VLAN_H_ */

View file

@ -0,0 +1,439 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2021, Intel Corporation. */
#include "ice_common.h"
/**
* ice_pkg_get_supported_vlan_mode - determine if DDP supports Double VLAN mode
* @hw: pointer to the HW struct
* @dvm: output variable to determine if DDP supports DVM(true) or SVM(false)
*/
static int
ice_pkg_get_supported_vlan_mode(struct ice_hw *hw, bool *dvm)
{
u16 meta_init_size = sizeof(struct ice_meta_init_section);
struct ice_meta_init_section *sect;
struct ice_buf_build *bld;
int status;
/* if anything fails, we assume there is no DVM support */
*dvm = false;
bld = ice_pkg_buf_alloc_single_section(hw,
ICE_SID_RXPARSER_METADATA_INIT,
meta_init_size, (void **)&sect);
if (!bld)
return -ENOMEM;
/* only need to read a single section */
sect->count = cpu_to_le16(1);
sect->offset = cpu_to_le16(ICE_META_VLAN_MODE_ENTRY);
status = ice_aq_upload_section(hw,
(struct ice_buf_hdr *)ice_pkg_buf(bld),
ICE_PKG_BUF_SIZE, NULL);
if (!status) {
DECLARE_BITMAP(entry, ICE_META_INIT_BITS);
u32 arr[ICE_META_INIT_DW_CNT];
u16 i;
/* convert to host bitmap format */
for (i = 0; i < ICE_META_INIT_DW_CNT; i++)
arr[i] = le32_to_cpu(sect->entry.bm[i]);
bitmap_from_arr32(entry, arr, (u16)ICE_META_INIT_BITS);
/* check if DVM is supported */
*dvm = test_bit(ICE_META_VLAN_MODE_BIT, entry);
}
ice_pkg_buf_free(hw, bld);
return status;
}
/**
* ice_aq_get_vlan_mode - get the VLAN mode of the device
* @hw: pointer to the HW structure
* @get_params: structure FW fills in based on the current VLAN mode config
*
* Get VLAN Mode Parameters (0x020D)
*/
static int
ice_aq_get_vlan_mode(struct ice_hw *hw,
struct ice_aqc_get_vlan_mode *get_params)
{
struct ice_aq_desc desc;
if (!get_params)
return -EINVAL;
ice_fill_dflt_direct_cmd_desc(&desc,
ice_aqc_opc_get_vlan_mode_parameters);
return ice_aq_send_cmd(hw, &desc, get_params, sizeof(*get_params),
NULL);
}
/**
* ice_aq_is_dvm_ena - query FW to check if double VLAN mode is enabled
* @hw: pointer to the HW structure
*
* Returns true if the hardware/firmware is configured in double VLAN mode,
* else return false signaling that the hardware/firmware is configured in
* single VLAN mode.
*
* Also, return false if this call fails for any reason (i.e. firmware doesn't
* support this AQ call).
*/
static bool ice_aq_is_dvm_ena(struct ice_hw *hw)
{
struct ice_aqc_get_vlan_mode get_params = { 0 };
int status;
status = ice_aq_get_vlan_mode(hw, &get_params);
if (status) {
ice_debug(hw, ICE_DBG_AQ, "Failed to get VLAN mode, status %d\n",
status);
return false;
}
return (get_params.vlan_mode & ICE_AQ_VLAN_MODE_DVM_ENA);
}
/**
* ice_is_dvm_ena - check if double VLAN mode is enabled
* @hw: pointer to the HW structure
*
* The device is configured in single or double VLAN mode on initialization and
* this cannot be dynamically changed during runtime. Based on this there is no
* need to make an AQ call every time the driver needs to know the VLAN mode.
* Instead, use the cached VLAN mode.
*/
bool ice_is_dvm_ena(struct ice_hw *hw)
{
return hw->dvm_ena;
}
/**
* ice_cache_vlan_mode - cache VLAN mode after DDP is downloaded
* @hw: pointer to the HW structure
*
* This is only called after downloading the DDP and after the global
* configuration lock has been released because all ports on a device need to
* cache the VLAN mode.
*/
static void ice_cache_vlan_mode(struct ice_hw *hw)
{
hw->dvm_ena = ice_aq_is_dvm_ena(hw) ? true : false;
}
/**
* ice_pkg_supports_dvm - find out if DDP supports DVM
* @hw: pointer to the HW structure
*/
static bool ice_pkg_supports_dvm(struct ice_hw *hw)
{
bool pkg_supports_dvm;
int status;
status = ice_pkg_get_supported_vlan_mode(hw, &pkg_supports_dvm);
if (status) {
ice_debug(hw, ICE_DBG_PKG, "Failed to get supported VLAN mode, status %d\n",
status);
return false;
}
return pkg_supports_dvm;
}
/**
* ice_fw_supports_dvm - find out if FW supports DVM
* @hw: pointer to the HW structure
*/
static bool ice_fw_supports_dvm(struct ice_hw *hw)
{
struct ice_aqc_get_vlan_mode get_vlan_mode = { 0 };
int status;
/* If firmware returns success, then it supports DVM, else it only
* supports SVM
*/
status = ice_aq_get_vlan_mode(hw, &get_vlan_mode);
if (status) {
ice_debug(hw, ICE_DBG_NVM, "Failed to get VLAN mode, status %d\n",
status);
return false;
}
return true;
}
/**
* ice_is_dvm_supported - check if Double VLAN Mode is supported
* @hw: pointer to the hardware structure
*
* Returns true if Double VLAN Mode (DVM) is supported and false if only Single
* VLAN Mode (SVM) is supported. In order for DVM to be supported the DDP and
* firmware must support it, otherwise only SVM is supported. This function
* should only be called while the global config lock is held and after the
* package has been successfully downloaded.
*/
static bool ice_is_dvm_supported(struct ice_hw *hw)
{
if (!ice_pkg_supports_dvm(hw)) {
ice_debug(hw, ICE_DBG_PKG, "DDP doesn't support DVM\n");
return false;
}
if (!ice_fw_supports_dvm(hw)) {
ice_debug(hw, ICE_DBG_PKG, "FW doesn't support DVM\n");
return false;
}
return true;
}
#define ICE_EXTERNAL_VLAN_ID_FV_IDX 11
#define ICE_SW_LKUP_VLAN_LOC_LKUP_IDX 1
#define ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX 2
#define ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX 2
#define ICE_PKT_FLAGS_0_TO_15_FV_IDX 1
#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
{
/* Update recipe ICE_SW_LKUP_VLAN to filter based on the
* outer/single VLAN in DVM
*/
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
.ignore_valid = true,
.mask = 0,
.mask_valid = false, /* use pre-existing mask */
.lkup_idx = ICE_SW_LKUP_VLAN_LOC_LKUP_IDX,
},
{
/* Update recipe ICE_SW_LKUP_VLAN to filter based on the VLAN
* packet flags to support VLAN filtering on multiple VLAN
* ethertypes (i.e. 0x8100 and 0x88a8) in DVM
*/
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
.ignore_valid = false,
.mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK,
.mask_valid = true,
.lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
},
{
/* Update recipe ICE_SW_LKUP_PROMISC_VLAN to filter based on the
* outer/single VLAN in DVM
*/
.rid = ICE_SW_LKUP_PROMISC_VLAN,
.fv_idx = ICE_EXTERNAL_VLAN_ID_FV_IDX,
.ignore_valid = true,
.mask = 0,
.mask_valid = false, /* use pre-existing mask */
.lkup_idx = ICE_SW_LKUP_PROMISC_VLAN_LOC_LKUP_IDX,
},
};
/**
* ice_dvm_update_dflt_recipes - update default switch recipes in DVM
* @hw: hardware structure used to update the recipes
*/
static int ice_dvm_update_dflt_recipes(struct ice_hw *hw)
{
unsigned long i;
for (i = 0; i < ARRAY_SIZE(ice_dvm_dflt_recipes); i++) {
struct ice_update_recipe_lkup_idx_params *params;
int status;
params = &ice_dvm_dflt_recipes[i];
status = ice_update_recipe_lkup_idx(hw, params);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to update RID %d lkup_idx %d fv_idx %d mask_valid %s mask 0x%04x\n",
params->rid, params->lkup_idx, params->fv_idx,
params->mask_valid ? "true" : "false",
params->mask);
return status;
}
}
return 0;
}
/**
* ice_aq_set_vlan_mode - set the VLAN mode of the device
* @hw: pointer to the HW structure
* @set_params: requested VLAN mode configuration
*
* Set VLAN Mode Parameters (0x020C)
*/
static int
ice_aq_set_vlan_mode(struct ice_hw *hw,
struct ice_aqc_set_vlan_mode *set_params)
{
u8 rdma_packet, mng_vlan_prot_id;
struct ice_aq_desc desc;
if (!set_params)
return -EINVAL;
if (set_params->l2tag_prio_tagging > ICE_AQ_VLAN_PRIO_TAG_MAX)
return -EINVAL;
rdma_packet = set_params->rdma_packet;
if (rdma_packet != ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING &&
rdma_packet != ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING)
return -EINVAL;
mng_vlan_prot_id = set_params->mng_vlan_prot_id;
if (mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER &&
mng_vlan_prot_id != ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER)
return -EINVAL;
ice_fill_dflt_direct_cmd_desc(&desc,
ice_aqc_opc_set_vlan_mode_parameters);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
return ice_aq_send_cmd(hw, &desc, set_params, sizeof(*set_params),
NULL);
}
/**
* ice_set_dvm - sets up software and hardware for double VLAN mode
* @hw: pointer to the hardware structure
*/
static int ice_set_dvm(struct ice_hw *hw)
{
struct ice_aqc_set_vlan_mode params = { 0 };
int status;
params.l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_OUTER_CTAG;
params.rdma_packet = ICE_AQ_DVM_VLAN_RDMA_PKT_FLAG_SETTING;
params.mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_OUTER;
status = ice_aq_set_vlan_mode(hw, &params);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set double VLAN mode parameters, status %d\n",
status);
return status;
}
status = ice_dvm_update_dflt_recipes(hw);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to update default recipes for double VLAN mode, status %d\n",
status);
return status;
}
status = ice_aq_set_port_params(hw->port_info, true, NULL);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set port in double VLAN mode, status %d\n",
status);
return status;
}
status = ice_set_dvm_boost_entries(hw);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set boost TCAM entries for double VLAN mode, status %d\n",
status);
return status;
}
return 0;
}
/**
* ice_set_svm - set single VLAN mode
* @hw: pointer to the HW structure
*/
static int ice_set_svm(struct ice_hw *hw)
{
struct ice_aqc_set_vlan_mode *set_params;
int status;
status = ice_aq_set_port_params(hw->port_info, false, NULL);
if (status) {
ice_debug(hw, ICE_DBG_INIT, "Failed to set port parameters for single VLAN mode\n");
return status;
}
set_params = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*set_params),
GFP_KERNEL);
if (!set_params)
return -ENOMEM;
/* default configuration for SVM configurations */
set_params->l2tag_prio_tagging = ICE_AQ_VLAN_PRIO_TAG_INNER_CTAG;
set_params->rdma_packet = ICE_AQ_SVM_VLAN_RDMA_PKT_FLAG_SETTING;
set_params->mng_vlan_prot_id = ICE_AQ_VLAN_MNG_PROTOCOL_ID_INNER;
status = ice_aq_set_vlan_mode(hw, set_params);
if (status)
ice_debug(hw, ICE_DBG_INIT, "Failed to configure port in single VLAN mode\n");
devm_kfree(ice_hw_to_dev(hw), set_params);
return status;
}
/**
* ice_set_vlan_mode
* @hw: pointer to the HW structure
*/
int ice_set_vlan_mode(struct ice_hw *hw)
{
if (!ice_is_dvm_supported(hw))
return 0;
if (!ice_set_dvm(hw))
return 0;
return ice_set_svm(hw);
}
/**
* ice_print_dvm_not_supported - print if DDP and/or FW doesn't support DVM
* @hw: pointer to the HW structure
*
* The purpose of this function is to print that QinQ is not supported due to
* incompatibilty from the DDP and/or FW. This will give a hint to the user to
* update one and/or both components if they expect QinQ functionality.
*/
static void ice_print_dvm_not_supported(struct ice_hw *hw)
{
bool pkg_supports_dvm = ice_pkg_supports_dvm(hw);
bool fw_supports_dvm = ice_fw_supports_dvm(hw);
if (!fw_supports_dvm && !pkg_supports_dvm)
dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your DDP package and NVM to versions that support QinQ.\n");
else if (!pkg_supports_dvm)
dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your DDP package to a version that supports QinQ.\n");
else if (!fw_supports_dvm)
dev_info(ice_hw_to_dev(hw), "QinQ functionality cannot be enabled on this device. Update your NVM to a version that supports QinQ.\n");
}
/**
* ice_post_pkg_dwnld_vlan_mode_cfg - configure VLAN mode after DDP download
* @hw: pointer to the HW structure
*
* This function is meant to configure any VLAN mode specific functionality
* after the global configuration lock has been released and the DDP has been
* downloaded.
*
* Since only one PF downloads the DDP and configures the VLAN mode there needs
* to be a way to configure the other PFs after the DDP has been downloaded and
* the global configuration lock has been released. All such code should go in
* this function.
*/
void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw)
{
ice_cache_vlan_mode(hw);
if (ice_is_dvm_ena(hw))
ice_change_proto_id_to_dvm();
else
ice_print_dvm_not_supported(hw);
}

View file

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_VLAN_MODE_H_
#define _ICE_VLAN_MODE_H_
struct ice_hw;
bool ice_is_dvm_ena(struct ice_hw *hw);
int ice_set_vlan_mode(struct ice_hw *hw);
void ice_post_pkg_dwnld_vlan_mode_cfg(struct ice_hw *hw);
#endif /* _ICE_VLAN_MODE_H */

View file

@ -0,0 +1,707 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2021, Intel Corporation. */
#include "ice_vsi_vlan_lib.h"
#include "ice_lib.h"
#include "ice_fltr.h"
#include "ice.h"
static void print_invalid_tpid(struct ice_vsi *vsi, u16 tpid)
{
dev_err(ice_pf_to_dev(vsi->back), "%s %d specified invalid VLAN tpid 0x%04x\n",
ice_vsi_type_str(vsi->type), vsi->idx, tpid);
}
/**
* validate_vlan - check if the ice_vlan passed in is valid
* @vsi: VSI used for printing error message
* @vlan: ice_vlan structure to validate
*
* Return true if the VLAN TPID is valid or if the VLAN TPID is 0 and the VLAN
* VID is 0, which allows for non-zero VLAN filters with the specified VLAN TPID
* and untagged VLAN 0 filters to be added to the prune list respectively.
*/
static bool validate_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
if (vlan->tpid != ETH_P_8021Q && vlan->tpid != ETH_P_8021AD &&
vlan->tpid != ETH_P_QINQ1 && (vlan->tpid || vlan->vid)) {
print_invalid_tpid(vsi, vlan->tpid);
return false;
}
return true;
}
/**
* ice_vsi_add_vlan - default add VLAN implementation for all VSI types
* @vsi: VSI being configured
* @vlan: VLAN filter to add
*/
int ice_vsi_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
int err;
if (!validate_vlan(vsi, vlan))
return -EINVAL;
err = ice_fltr_add_vlan(vsi, vlan);
if (err && err != -EEXIST) {
dev_err(ice_pf_to_dev(vsi->back), "Failure Adding VLAN %d on VSI %i, status %d\n",
vlan->vid, vsi->vsi_num, err);
return err;
}
vsi->num_vlan++;
return 0;
}
/**
* ice_vsi_del_vlan - default del VLAN implementation for all VSI types
* @vsi: VSI being configured
* @vlan: VLAN filter to delete
*/
int ice_vsi_del_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
struct ice_pf *pf = vsi->back;
struct device *dev;
int err;
if (!validate_vlan(vsi, vlan))
return -EINVAL;
dev = ice_pf_to_dev(pf);
err = ice_fltr_remove_vlan(vsi, vlan);
if (!err)
vsi->num_vlan--;
else if (err == -ENOENT || err == -EBUSY)
err = 0;
else
dev_err(dev, "Error removing VLAN %d on VSI %i error: %d\n",
vlan->vid, vsi->vsi_num, err);
return err;
}
/**
* ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
* @vsi: the VSI being changed
*/
static int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int err;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
/* Here we are configuring the VSI to let the driver add VLAN tags by
* setting inner_vlan_flags to ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL. The actual VLAN tag
* insertion happens in the Tx hot path, in ice_tx_map.
*/
ctxt->info.inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL;
/* Preserve existing VLAN strip setting */
ctxt->info.inner_vlan_flags |= (vsi->info.inner_vlan_flags &
ICE_AQ_VSI_INNER_VLAN_EMODE_M);
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err) {
dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
goto out;
}
vsi->info.inner_vlan_flags = ctxt->info.inner_vlan_flags;
out:
kfree(ctxt);
return err;
}
/**
* ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
* @vsi: the VSI being changed
* @ena: boolean value indicating if this is a enable or disable request
*/
static int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int err;
/* do not allow modifying VLAN stripping when a port VLAN is configured
* on this VSI
*/
if (vsi->info.port_based_inner_vlan)
return 0;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
/* Here we are configuring what the VSI should do with the VLAN tag in
* the Rx packet. We can either leave the tag in the packet or put it in
* the Rx descriptor.
*/
if (ena)
/* Strip VLAN tag from Rx packet and put it in the desc */
ctxt->info.inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_EMODE_STR_BOTH;
else
/* Disable stripping. Leave tag in packet */
ctxt->info.inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING;
/* Allow all packets untagged/tagged */
ctxt->info.inner_vlan_flags |= ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL;
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err) {
dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %d aq_err %s\n",
ena, err, ice_aq_str(hw->adminq.sq_last_status));
goto out;
}
vsi->info.inner_vlan_flags = ctxt->info.inner_vlan_flags;
out:
kfree(ctxt);
return err;
}
int ice_vsi_ena_inner_stripping(struct ice_vsi *vsi, const u16 tpid)
{
if (tpid != ETH_P_8021Q) {
print_invalid_tpid(vsi, tpid);
return -EINVAL;
}
return ice_vsi_manage_vlan_stripping(vsi, true);
}
int ice_vsi_dis_inner_stripping(struct ice_vsi *vsi)
{
return ice_vsi_manage_vlan_stripping(vsi, false);
}
int ice_vsi_ena_inner_insertion(struct ice_vsi *vsi, const u16 tpid)
{
if (tpid != ETH_P_8021Q) {
print_invalid_tpid(vsi, tpid);
return -EINVAL;
}
return ice_vsi_manage_vlan_insertion(vsi);
}
int ice_vsi_dis_inner_insertion(struct ice_vsi *vsi)
{
return ice_vsi_manage_vlan_insertion(vsi);
}
/**
* __ice_vsi_set_inner_port_vlan - set port VLAN VSI context settings to enable a port VLAN
* @vsi: the VSI to update
* @pvid_info: VLAN ID and QoS used to set the PVID VSI context field
*/
static int __ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, u16 pvid_info)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_aqc_vsi_props *info;
struct ice_vsi_ctx *ctxt;
int ret;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info = vsi->info;
info = &ctxt->info;
info->inner_vlan_flags = ICE_AQ_VSI_INNER_VLAN_TX_MODE_ACCEPTUNTAGGED |
ICE_AQ_VSI_INNER_VLAN_INSERT_PVID |
ICE_AQ_VSI_INNER_VLAN_EMODE_STR;
info->sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
info->port_based_inner_vlan = cpu_to_le16(pvid_info);
info->valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID |
ICE_AQ_VSI_PROP_SW_VALID);
ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (ret) {
dev_info(ice_hw_to_dev(hw), "update VSI for port VLAN failed, err %d aq_err %s\n",
ret, ice_aq_str(hw->adminq.sq_last_status));
goto out;
}
vsi->info.inner_vlan_flags = info->inner_vlan_flags;
vsi->info.sw_flags2 = info->sw_flags2;
vsi->info.port_based_inner_vlan = info->port_based_inner_vlan;
out:
kfree(ctxt);
return ret;
}
int ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
u16 port_vlan_info;
if (vlan->tpid != ETH_P_8021Q)
return -EINVAL;
if (vlan->prio > 7)
return -EINVAL;
port_vlan_info = vlan->vid | (vlan->prio << VLAN_PRIO_SHIFT);
return __ice_vsi_set_inner_port_vlan(vsi, port_vlan_info);
}
/**
* ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
* @vsi: VSI to enable or disable VLAN pruning on
* @ena: set to true to enable VLAN pruning and false to disable it
*
* returns 0 if VSI is updated, negative otherwise
*/
static int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
{
struct ice_vsi_ctx *ctxt;
struct ice_pf *pf;
int status;
if (!vsi)
return -EINVAL;
/* Don't enable VLAN pruning if the netdev is currently in promiscuous
* mode. VLAN pruning will be enabled when the interface exits
* promiscuous mode if any VLAN filters are active.
*/
if (vsi->netdev && vsi->netdev->flags & IFF_PROMISC && ena)
return 0;
pf = vsi->back;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info = vsi->info;
if (ena)
ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
else
ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
if (status) {
netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %s\n",
ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status,
ice_aq_str(pf->hw.adminq.sq_last_status));
goto err_out;
}
vsi->info.sw_flags2 = ctxt->info.sw_flags2;
kfree(ctxt);
return 0;
err_out:
kfree(ctxt);
return status;
}
int ice_vsi_ena_rx_vlan_filtering(struct ice_vsi *vsi)
{
return ice_cfg_vlan_pruning(vsi, true);
}
int ice_vsi_dis_rx_vlan_filtering(struct ice_vsi *vsi)
{
return ice_cfg_vlan_pruning(vsi, false);
}
static int ice_cfg_vlan_antispoof(struct ice_vsi *vsi, bool enable)
{
struct ice_vsi_ctx *ctx;
int err;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->info.sec_flags = vsi->info.sec_flags;
ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
if (enable)
ctx->info.sec_flags |= ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S;
else
ctx->info.sec_flags &= ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
err = ice_update_vsi(&vsi->back->hw, vsi->idx, ctx, NULL);
if (err)
dev_err(ice_pf_to_dev(vsi->back), "Failed to configure Tx VLAN anti-spoof %s for VSI %d, error %d\n",
enable ? "ON" : "OFF", vsi->vsi_num, err);
else
vsi->info.sec_flags = ctx->info.sec_flags;
kfree(ctx);
return err;
}
int ice_vsi_ena_tx_vlan_filtering(struct ice_vsi *vsi)
{
return ice_cfg_vlan_antispoof(vsi, true);
}
int ice_vsi_dis_tx_vlan_filtering(struct ice_vsi *vsi)
{
return ice_cfg_vlan_antispoof(vsi, false);
}
/**
* tpid_to_vsi_outer_vlan_type - convert from TPID to VSI context based tag_type
* @tpid: tpid used to translate into VSI context based tag_type
* @tag_type: output variable to hold the VSI context based tag type
*/
static int tpid_to_vsi_outer_vlan_type(u16 tpid, u8 *tag_type)
{
switch (tpid) {
case ETH_P_8021Q:
*tag_type = ICE_AQ_VSI_OUTER_TAG_VLAN_8100;
break;
case ETH_P_8021AD:
*tag_type = ICE_AQ_VSI_OUTER_TAG_STAG;
break;
case ETH_P_QINQ1:
*tag_type = ICE_AQ_VSI_OUTER_TAG_VLAN_9100;
break;
default:
*tag_type = 0;
return -EINVAL;
}
return 0;
}
/**
* ice_vsi_ena_outer_stripping - enable outer VLAN stripping
* @vsi: VSI to configure
* @tpid: TPID to enable outer VLAN stripping for
*
* Enable outer VLAN stripping via VSI context. This function should only be
* used if DVM is supported. Also, this function should never be called directly
* as it should be part of ice_vsi_vlan_ops if it's needed.
*
* Since the VSI context only supports a single TPID for insertion and
* stripping, setting the TPID for stripping will affect the TPID for insertion.
* Callers need to be aware of this limitation.
*
* Only modify outer VLAN stripping settings and the VLAN TPID. Outer VLAN
* insertion settings are unmodified.
*
* This enables hardware to strip a VLAN tag with the specified TPID to be
* stripped from the packet and placed in the receive descriptor.
*/
int ice_vsi_ena_outer_stripping(struct ice_vsi *vsi, u16 tpid)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
u8 tag_type;
int err;
/* do not allow modifying VLAN stripping when a port VLAN is configured
* on this VSI
*/
if (vsi->info.port_based_outer_vlan)
return 0;
if (tpid_to_vsi_outer_vlan_type(tpid, &tag_type))
return -EINVAL;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID);
/* clear current outer VLAN strip settings */
ctxt->info.outer_vlan_flags = vsi->info.outer_vlan_flags &
~(ICE_AQ_VSI_OUTER_VLAN_EMODE_M | ICE_AQ_VSI_OUTER_TAG_TYPE_M);
ctxt->info.outer_vlan_flags |=
((ICE_AQ_VSI_OUTER_VLAN_EMODE_SHOW_BOTH <<
ICE_AQ_VSI_OUTER_VLAN_EMODE_S) |
((tag_type << ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
ICE_AQ_VSI_OUTER_TAG_TYPE_M));
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err)
dev_err(ice_pf_to_dev(vsi->back), "update VSI for enabling outer VLAN stripping failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
else
vsi->info.outer_vlan_flags = ctxt->info.outer_vlan_flags;
kfree(ctxt);
return err;
}
/**
* ice_vsi_dis_outer_stripping - disable outer VLAN stripping
* @vsi: VSI to configure
*
* Disable outer VLAN stripping via VSI context. This function should only be
* used if DVM is supported. Also, this function should never be called directly
* as it should be part of ice_vsi_vlan_ops if it's needed.
*
* Only modify the outer VLAN stripping settings. The VLAN TPID and outer VLAN
* insertion settings are unmodified.
*
* This tells the hardware to not strip any VLAN tagged packets, thus leaving
* them in the packet. This enables software offloaded VLAN stripping and
* disables hardware offloaded VLAN stripping.
*/
int ice_vsi_dis_outer_stripping(struct ice_vsi *vsi)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int err;
if (vsi->info.port_based_outer_vlan)
return 0;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID);
/* clear current outer VLAN strip settings */
ctxt->info.outer_vlan_flags = vsi->info.outer_vlan_flags &
~ICE_AQ_VSI_OUTER_VLAN_EMODE_M;
ctxt->info.outer_vlan_flags |= ICE_AQ_VSI_OUTER_VLAN_EMODE_NOTHING <<
ICE_AQ_VSI_OUTER_VLAN_EMODE_S;
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err)
dev_err(ice_pf_to_dev(vsi->back), "update VSI for disabling outer VLAN stripping failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
else
vsi->info.outer_vlan_flags = ctxt->info.outer_vlan_flags;
kfree(ctxt);
return err;
}
/**
* ice_vsi_ena_outer_insertion - enable outer VLAN insertion
* @vsi: VSI to configure
* @tpid: TPID to enable outer VLAN insertion for
*
* Enable outer VLAN insertion via VSI context. This function should only be
* used if DVM is supported. Also, this function should never be called directly
* as it should be part of ice_vsi_vlan_ops if it's needed.
*
* Since the VSI context only supports a single TPID for insertion and
* stripping, setting the TPID for insertion will affect the TPID for stripping.
* Callers need to be aware of this limitation.
*
* Only modify outer VLAN insertion settings and the VLAN TPID. Outer VLAN
* stripping settings are unmodified.
*
* This allows a VLAN tag with the specified TPID to be inserted in the transmit
* descriptor.
*/
int ice_vsi_ena_outer_insertion(struct ice_vsi *vsi, u16 tpid)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
u8 tag_type;
int err;
if (vsi->info.port_based_outer_vlan)
return 0;
if (tpid_to_vsi_outer_vlan_type(tpid, &tag_type))
return -EINVAL;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID);
/* clear current outer VLAN insertion settings */
ctxt->info.outer_vlan_flags = vsi->info.outer_vlan_flags &
~(ICE_AQ_VSI_OUTER_VLAN_PORT_BASED_INSERT |
ICE_AQ_VSI_OUTER_VLAN_BLOCK_TX_DESC |
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M |
ICE_AQ_VSI_OUTER_TAG_TYPE_M);
ctxt->info.outer_vlan_flags |=
((ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL <<
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) &
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M) |
((tag_type << ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
ICE_AQ_VSI_OUTER_TAG_TYPE_M);
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err)
dev_err(ice_pf_to_dev(vsi->back), "update VSI for enabling outer VLAN insertion failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
else
vsi->info.outer_vlan_flags = ctxt->info.outer_vlan_flags;
kfree(ctxt);
return err;
}
/**
* ice_vsi_dis_outer_insertion - disable outer VLAN insertion
* @vsi: VSI to configure
*
* Disable outer VLAN insertion via VSI context. This function should only be
* used if DVM is supported. Also, this function should never be called directly
* as it should be part of ice_vsi_vlan_ops if it's needed.
*
* Only modify the outer VLAN insertion settings. The VLAN TPID and outer VLAN
* settings are unmodified.
*
* This tells the hardware to not allow any VLAN tagged packets in the transmit
* descriptor. This enables software offloaded VLAN insertion and disables
* hardware offloaded VLAN insertion.
*/
int ice_vsi_dis_outer_insertion(struct ice_vsi *vsi)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
int err;
if (vsi->info.port_based_outer_vlan)
return 0;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID);
/* clear current outer VLAN insertion settings */
ctxt->info.outer_vlan_flags = vsi->info.outer_vlan_flags &
~(ICE_AQ_VSI_OUTER_VLAN_PORT_BASED_INSERT |
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M);
ctxt->info.outer_vlan_flags |=
ICE_AQ_VSI_OUTER_VLAN_BLOCK_TX_DESC |
((ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL <<
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) &
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M);
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err)
dev_err(ice_pf_to_dev(vsi->back), "update VSI for disabling outer VLAN insertion failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
else
vsi->info.outer_vlan_flags = ctxt->info.outer_vlan_flags;
kfree(ctxt);
return err;
}
/**
* __ice_vsi_set_outer_port_vlan - set the outer port VLAN and related settings
* @vsi: VSI to configure
* @vlan_info: packed u16 that contains the VLAN prio and ID
* @tpid: TPID of the port VLAN
*
* Set the port VLAN prio, ID, and TPID.
*
* Enable VLAN pruning so the VSI doesn't receive any traffic that doesn't match
* a VLAN prune rule. The caller should take care to add a VLAN prune rule that
* matches the port VLAN ID and TPID.
*
* Tell hardware to strip outer VLAN tagged packets on receive and don't put
* them in the receive descriptor. VSI(s) in port VLANs should not be aware of
* the port VLAN ID or TPID they are assigned to.
*
* Tell hardware to prevent outer VLAN tag insertion on transmit and only allow
* untagged outer packets from the transmit descriptor.
*
* Also, tell the hardware to insert the port VLAN on transmit.
*/
static int
__ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, u16 vlan_info, u16 tpid)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_vsi_ctx *ctxt;
u8 tag_type;
int err;
if (tpid_to_vsi_outer_vlan_type(tpid, &tag_type))
return -EINVAL;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt)
return -ENOMEM;
ctxt->info = vsi->info;
ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
ctxt->info.port_based_outer_vlan = cpu_to_le16(vlan_info);
ctxt->info.outer_vlan_flags =
(ICE_AQ_VSI_OUTER_VLAN_EMODE_SHOW <<
ICE_AQ_VSI_OUTER_VLAN_EMODE_S) |
((tag_type << ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
ICE_AQ_VSI_OUTER_TAG_TYPE_M) |
ICE_AQ_VSI_OUTER_VLAN_BLOCK_TX_DESC |
(ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ACCEPTUNTAGGED <<
ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) |
ICE_AQ_VSI_OUTER_VLAN_PORT_BASED_INSERT;
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_OUTER_TAG_VALID |
ICE_AQ_VSI_PROP_SW_VALID);
err = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
if (err) {
dev_err(ice_pf_to_dev(vsi->back), "update VSI for setting outer port based VLAN failed, err %d aq_err %s\n",
err, ice_aq_str(hw->adminq.sq_last_status));
} else {
vsi->info.port_based_outer_vlan = ctxt->info.port_based_outer_vlan;
vsi->info.outer_vlan_flags = ctxt->info.outer_vlan_flags;
vsi->info.sw_flags2 = ctxt->info.sw_flags2;
}
kfree(ctxt);
return err;
}
/**
* ice_vsi_set_outer_port_vlan - public version of __ice_vsi_set_outer_port_vlan
* @vsi: VSI to configure
* @vlan: ice_vlan structure used to set the port VLAN
*
* Set the outer port VLAN via VSI context. This function should only be
* used if DVM is supported. Also, this function should never be called directly
* as it should be part of ice_vsi_vlan_ops if it's needed.
*
* This function does not support clearing the port VLAN as there is currently
* no use case for this.
*
* Use the ice_vlan structure passed in to set this VSI in a port VLAN.
*/
int ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
{
u16 port_vlan_info;
if (vlan->prio > (VLAN_PRIO_MASK >> VLAN_PRIO_SHIFT))
return -EINVAL;
port_vlan_info = vlan->vid | (vlan->prio << VLAN_PRIO_SHIFT);
return __ice_vsi_set_outer_port_vlan(vsi, port_vlan_info, vlan->tpid);
}

View file

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_VSI_VLAN_LIB_H_
#define _ICE_VSI_VLAN_LIB_H_
#include <linux/types.h>
#include "ice_vlan.h"
struct ice_vsi;
int ice_vsi_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
int ice_vsi_del_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
int ice_vsi_ena_inner_stripping(struct ice_vsi *vsi, u16 tpid);
int ice_vsi_dis_inner_stripping(struct ice_vsi *vsi);
int ice_vsi_ena_inner_insertion(struct ice_vsi *vsi, u16 tpid);
int ice_vsi_dis_inner_insertion(struct ice_vsi *vsi);
int ice_vsi_set_inner_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
int ice_vsi_ena_rx_vlan_filtering(struct ice_vsi *vsi);
int ice_vsi_dis_rx_vlan_filtering(struct ice_vsi *vsi);
int ice_vsi_ena_tx_vlan_filtering(struct ice_vsi *vsi);
int ice_vsi_dis_tx_vlan_filtering(struct ice_vsi *vsi);
int ice_vsi_ena_outer_stripping(struct ice_vsi *vsi, u16 tpid);
int ice_vsi_dis_outer_stripping(struct ice_vsi *vsi);
int ice_vsi_ena_outer_insertion(struct ice_vsi *vsi, u16 tpid);
int ice_vsi_dis_outer_insertion(struct ice_vsi *vsi);
int ice_vsi_set_outer_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
#endif /* _ICE_VSI_VLAN_LIB_H_ */

View file

@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2021, Intel Corporation. */
#include "ice_pf_vsi_vlan_ops.h"
#include "ice_vf_vsi_vlan_ops.h"
#include "ice_lib.h"
#include "ice.h"
static int
op_unsupported_vlan_arg(struct ice_vsi * __always_unused vsi,
struct ice_vlan * __always_unused vlan)
{
return -EOPNOTSUPP;
}
static int
op_unsupported_tpid_arg(struct ice_vsi *__always_unused vsi,
u16 __always_unused tpid)
{
return -EOPNOTSUPP;
}
static int op_unsupported(struct ice_vsi *__always_unused vsi)
{
return -EOPNOTSUPP;
}
/* If any new ops are added to the VSI VLAN ops interface then an unsupported
* implementation should be set here.
*/
static struct ice_vsi_vlan_ops ops_unsupported = {
.add_vlan = op_unsupported_vlan_arg,
.del_vlan = op_unsupported_vlan_arg,
.ena_stripping = op_unsupported_tpid_arg,
.dis_stripping = op_unsupported,
.ena_insertion = op_unsupported_tpid_arg,
.dis_insertion = op_unsupported,
.ena_rx_filtering = op_unsupported,
.dis_rx_filtering = op_unsupported,
.ena_tx_filtering = op_unsupported,
.dis_tx_filtering = op_unsupported,
.set_port_vlan = op_unsupported_vlan_arg,
};
/**
* ice_vsi_init_unsupported_vlan_ops - init all VSI VLAN ops to unsupported
* @vsi: VSI to initialize VSI VLAN ops to unsupported for
*
* By default all inner and outer VSI VLAN ops return -EOPNOTSUPP. This was done
* as oppsed to leaving the ops null to prevent unexpected crashes. Instead if
* an unsupported VSI VLAN op is called it will just return -EOPNOTSUPP.
*
*/
static void ice_vsi_init_unsupported_vlan_ops(struct ice_vsi *vsi)
{
vsi->outer_vlan_ops = ops_unsupported;
vsi->inner_vlan_ops = ops_unsupported;
}
/**
* ice_vsi_init_vlan_ops - initialize type specific VSI VLAN ops
* @vsi: VSI to initialize ops for
*
* If any VSI types are added and/or require different ops than the PF or VF VSI
* then they will have to add a case here to handle that. Also, VSI type
* specific files should be added in the same manner that was done for PF VSI.
*/
void ice_vsi_init_vlan_ops(struct ice_vsi *vsi)
{
/* Initialize all VSI types to have unsupported VSI VLAN ops */
ice_vsi_init_unsupported_vlan_ops(vsi);
switch (vsi->type) {
case ICE_VSI_PF:
case ICE_VSI_SWITCHDEV_CTRL:
ice_pf_vsi_init_vlan_ops(vsi);
break;
case ICE_VSI_VF:
ice_vf_vsi_init_vlan_ops(vsi);
break;
default:
dev_dbg(ice_pf_to_dev(vsi->back), "%s does not support VLAN operations\n",
ice_vsi_type_str(vsi->type));
break;
}
}
/**
* ice_get_compat_vsi_vlan_ops - Get VSI VLAN ops based on VLAN mode
* @vsi: VSI used to get the VSI VLAN ops
*
* This function is meant to be used when the caller doesn't know which VLAN ops
* to use (i.e. inner or outer). This allows backward compatibility for VLANs
* since most of the Outer VSI VLAN functins are not supported when
* the device is configured in Single VLAN Mode (SVM).
*/
struct ice_vsi_vlan_ops *ice_get_compat_vsi_vlan_ops(struct ice_vsi *vsi)
{
if (ice_is_dvm_ena(&vsi->back->hw))
return &vsi->outer_vlan_ops;
else
return &vsi->inner_vlan_ops;
}

View file

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019-2021, Intel Corporation. */
#ifndef _ICE_VSI_VLAN_OPS_H_
#define _ICE_VSI_VLAN_OPS_H_
#include "ice_type.h"
#include "ice_vsi_vlan_lib.h"
struct ice_vsi;
struct ice_vsi_vlan_ops {
int (*add_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan);
int (*del_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan);
int (*ena_stripping)(struct ice_vsi *vsi, const u16 tpid);
int (*dis_stripping)(struct ice_vsi *vsi);
int (*ena_insertion)(struct ice_vsi *vsi, const u16 tpid);
int (*dis_insertion)(struct ice_vsi *vsi);
int (*ena_rx_filtering)(struct ice_vsi *vsi);
int (*dis_rx_filtering)(struct ice_vsi *vsi);
int (*ena_tx_filtering)(struct ice_vsi *vsi);
int (*dis_tx_filtering)(struct ice_vsi *vsi);
int (*set_port_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan);
};
void ice_vsi_init_vlan_ops(struct ice_vsi *vsi);
struct ice_vsi_vlan_ops *ice_get_compat_vsi_vlan_ops(struct ice_vsi *vsi);
#endif /* _ICE_VSI_VLAN_OPS_H_ */

View file

@ -599,7 +599,7 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
rx_desc = ICE_RX_DESC(rx_ring, rx_ring->next_to_clean);
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S);
if (!ice_test_staterr(rx_desc, stat_err_bits))
if (!ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits))
break;
/* This memory barrier is needed to keep us from reading
@ -654,9 +654,7 @@ construct_skb:
total_rx_bytes += skb->len;
total_rx_packets++;
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S);
if (ice_test_staterr(rx_desc, stat_err_bits))
vlan_tag = le16_to_cpu(rx_desc->wb.l2tag1);
vlan_tag = ice_get_vlan_tag_from_rx_desc(rx_desc);
rx_ptype = le16_to_cpu(rx_desc->wb.ptype_flex_flags0) &
ICE_RX_FLEX_DESC_PTYPE_M;