Commit adc27288 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 45230829 f1da5a08
......@@ -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
......
......@@ -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 */
};
......
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -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;
}
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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_ */
......@@ -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_ */
......@@ -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);
}
/**
......
......@@ -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,
......
......@@ -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!!! */
};
......
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
......@@ -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))
......
// 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;
}
}
/* 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_ */
......@@ -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
......
......@@ -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_ */
......@@ -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 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
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);
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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 */
......
// 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");
}
/* 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_ */
......@@ -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),
};
/**
......
......@@ -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_ */
/* 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_ */
This diff is collapsed.
/* 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 */
This diff is collapsed.
/* 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_ */
// 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;
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment