Commit d76a60ba authored by Anirudh Venkataramanan's avatar Anirudh Venkataramanan Committed by Jeff Kirsher

ice: Add support for VLANs and offloads

This patch adds support for VLANs. When a VLAN is created a switch filter
is added to direct the VLAN traffic to the corresponding VSI. When a VLAN
is deleted, the filter is deleted as well.

This patch also adds support for the following hardware offloads.
    1) VLAN tag insertion/stripping
    2) Receive Side Scaling (RSS)
    3) Tx checksum and TCP segmentation
    4) Rx checksum
Signed-off-by: default avatarAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: default avatarTony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 2b245cb2
......@@ -23,7 +23,10 @@
#include <linux/delay.h>
#include <linux/bitmap.h>
#include <linux/log2.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/if_bridge.h>
#include <net/ipv6.h>
#include "ice_devids.h"
#include "ice_type.h"
#include "ice_txrx.h"
......@@ -47,6 +50,8 @@
#define ICE_MAX_SCATTER_RXQS 16
#define ICE_Q_WAIT_RETRY_LIMIT 10
#define ICE_Q_WAIT_MAX_RETRY (5 * ICE_Q_WAIT_RETRY_LIMIT)
#define ICE_MAX_LG_RSS_QS 256
#define ICE_MAX_SMALL_RSS_QS 8
#define ICE_RES_VALID_BIT 0x8000
#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
#define ICE_INVAL_Q_INDEX 0xffff
......@@ -62,6 +67,7 @@
#define ICE_TX_DESC(R, i) (&(((struct ice_tx_desc *)((R)->desc))[i]))
#define ICE_RX_DESC(R, i) (&(((union ice_32b_rx_flex_desc *)((R)->desc))[i]))
#define ICE_TX_CTX_DESC(R, i) (&(((struct ice_tx_ctx_desc *)((R)->desc))[i]))
#define ice_for_each_txq(vsi, i) \
for ((i) = 0; (i) < (vsi)->num_txq; (i)++)
......@@ -113,6 +119,7 @@ struct ice_vsi {
irqreturn_t (*irq_handler)(int irq, void *data);
DECLARE_BITMAP(state, __ICE_STATE_NBITS);
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
int num_q_vectors;
int base_vector;
enum ice_vsi_type type;
......@@ -122,6 +129,13 @@ struct ice_vsi {
/* Interrupt thresholds */
u16 work_lmt;
/* RSS config */
u16 rss_table_size; /* HW RSS table size */
u16 rss_size; /* Allocated RSS queues */
u8 *rss_hkey_user; /* User configured hash keys */
u8 *rss_lut_user; /* User configured lookup table entries */
u8 rss_lut_type; /* used to configure Get/Set RSS LUT AQ call */
u16 max_frame;
u16 rx_buf_len;
......@@ -181,6 +195,7 @@ struct ice_pf {
struct mutex avail_q_mutex; /* protects access to avail_[rx|tx]qs */
struct mutex sw_mutex; /* lock for protecting VSI alloc flow */
u32 msg_enable;
u32 hw_csum_rx_error;
u32 oicr_idx; /* Other interrupt cause vector index */
u32 num_lan_msix; /* Total MSIX vectors for base driver */
u32 num_avail_msix; /* remaining MSIX vectors left unclaimed */
......@@ -224,4 +239,8 @@ static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
wr32(hw, GLINT_DYN_CTL(vector), val);
}
int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);
void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);
#endif /* _ICE_H_ */
......@@ -968,6 +968,60 @@ struct ice_aqc_nvm {
__le32 addr_low;
};
/* Get/Set RSS key (indirect 0x0B04/0x0B02) */
struct ice_aqc_get_set_rss_key {
#define ICE_AQC_GSET_RSS_KEY_VSI_VALID BIT(15)
#define ICE_AQC_GSET_RSS_KEY_VSI_ID_S 0
#define ICE_AQC_GSET_RSS_KEY_VSI_ID_M (0x3FF << ICE_AQC_GSET_RSS_KEY_VSI_ID_S)
__le16 vsi_id;
u8 reserved[6];
__le32 addr_high;
__le32 addr_low;
};
#define ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE 0x28
#define ICE_AQC_GET_SET_RSS_KEY_DATA_HASH_KEY_SIZE 0xC
struct ice_aqc_get_set_rss_keys {
u8 standard_rss_key[ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE];
u8 extended_hash_key[ICE_AQC_GET_SET_RSS_KEY_DATA_HASH_KEY_SIZE];
};
/* Get/Set RSS LUT (indirect 0x0B05/0x0B03) */
struct ice_aqc_get_set_rss_lut {
#define ICE_AQC_GSET_RSS_LUT_VSI_VALID BIT(15)
#define ICE_AQC_GSET_RSS_LUT_VSI_ID_S 0
#define ICE_AQC_GSET_RSS_LUT_VSI_ID_M (0x1FF << ICE_AQC_GSET_RSS_LUT_VSI_ID_S)
__le16 vsi_id;
#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S 0
#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M \
(0x3 << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S)
#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI 0
#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF 1
#define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL 2
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S 2
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M \
(0x3 << ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S)
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128 128
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG 0
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512 512
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG 1
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K 2048
#define ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG 2
#define ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S 4
#define ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M \
(0xF << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S)
__le16 flags;
__le32 reserved;
__le32 addr_high;
__le32 addr_low;
};
/* Add TX LAN Queues (indirect 0x0C30) */
struct ice_aqc_add_txqs {
u8 num_qgrps;
......@@ -1089,6 +1143,8 @@ struct ice_aq_desc {
struct ice_aqc_query_txsched_res query_sched_res;
struct ice_aqc_add_move_delete_elem add_move_delete_elem;
struct ice_aqc_nvm nvm;
struct ice_aqc_get_set_rss_lut get_set_rss_lut;
struct ice_aqc_get_set_rss_key get_set_rss_key;
struct ice_aqc_add_txqs add_txqs;
struct ice_aqc_dis_txqs dis_txqs;
struct ice_aqc_add_get_update_free_vsi vsi_cmd;
......@@ -1171,6 +1227,12 @@ enum ice_adminq_opc {
/* NVM commands */
ice_aqc_opc_nvm_read = 0x0701,
/* RSS commands */
ice_aqc_opc_set_rss_key = 0x0B02,
ice_aqc_opc_set_rss_lut = 0x0B03,
ice_aqc_opc_get_rss_key = 0x0B04,
ice_aqc_opc_get_rss_lut = 0x0B05,
/* TX queue handling commands/events */
ice_aqc_opc_add_txqs = 0x0C30,
ice_aqc_opc_dis_txqs = 0x0C31,
......
......@@ -1261,6 +1261,194 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
ice_aq_clear_pxe_mode(hw);
}
/**
* __ice_aq_get_set_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: VSI FW index
* @lut_type: LUT table type
* @lut: pointer to the LUT buffer provided by the caller
* @lut_size: size of the LUT buffer
* @glob_lut_idx: global LUT index
* @set: set true to set the table, false to get the table
*
* Internal function to get (0x0B05) or set (0x0B03) RSS look up table
*/
static enum ice_status
__ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
u16 lut_size, u8 glob_lut_idx, bool set)
{
struct ice_aqc_get_set_rss_lut *cmd_resp;
struct ice_aq_desc desc;
enum ice_status status;
u16 flags = 0;
cmd_resp = &desc.params.get_set_rss_lut;
if (set) {
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_lut);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
} else {
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_lut);
}
cmd_resp->vsi_id = cpu_to_le16(((vsi_id <<
ICE_AQC_GSET_RSS_LUT_VSI_ID_S) &
ICE_AQC_GSET_RSS_LUT_VSI_ID_M) |
ICE_AQC_GSET_RSS_LUT_VSI_VALID);
switch (lut_type) {
case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI:
case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF:
case ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL:
flags |= ((lut_type << ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S) &
ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M);
break;
default:
status = ICE_ERR_PARAM;
goto ice_aq_get_set_rss_lut_exit;
}
if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_GLOBAL) {
flags |= ((glob_lut_idx << ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_S) &
ICE_AQC_GSET_RSS_LUT_GLOBAL_IDX_M);
if (!set)
goto ice_aq_get_set_rss_lut_send;
} else if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) {
if (!set)
goto ice_aq_get_set_rss_lut_send;
} else {
goto ice_aq_get_set_rss_lut_send;
}
/* LUT size is only valid for Global and PF table types */
if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128) {
flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG <<
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
} else if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512) {
flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG <<
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
} else if ((lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K) &&
(lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF)) {
flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG <<
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) &
ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M;
} else {
status = ICE_ERR_PARAM;
goto ice_aq_get_set_rss_lut_exit;
}
ice_aq_get_set_rss_lut_send:
cmd_resp->flags = cpu_to_le16(flags);
status = ice_aq_send_cmd(hw, &desc, lut, lut_size, NULL);
ice_aq_get_set_rss_lut_exit:
return status;
}
/**
* ice_aq_get_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: VSI FW index
* @lut_type: LUT table type
* @lut: pointer to the LUT buffer provided by the caller
* @lut_size: size of the LUT buffer
*
* get the RSS lookup table, PF or VSI type
*/
enum ice_status
ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
u16 lut_size)
{
return __ice_aq_get_set_rss_lut(hw, vsi_id, lut_type, lut, lut_size, 0,
false);
}
/**
* ice_aq_set_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: VSI FW index
* @lut_type: LUT table type
* @lut: pointer to the LUT buffer provided by the caller
* @lut_size: size of the LUT buffer
*
* set the RSS lookup table, PF or VSI type
*/
enum ice_status
ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
u16 lut_size)
{
return __ice_aq_get_set_rss_lut(hw, vsi_id, lut_type, lut, lut_size, 0,
true);
}
/**
* __ice_aq_get_set_rss_key
* @hw: pointer to the hw struct
* @vsi_id: VSI FW index
* @key: pointer to key info struct
* @set: set true to set the key, false to get the key
*
* get (0x0B04) or set (0x0B02) the RSS key per VSI
*/
static enum
ice_status __ice_aq_get_set_rss_key(struct ice_hw *hw, u16 vsi_id,
struct ice_aqc_get_set_rss_keys *key,
bool set)
{
struct ice_aqc_get_set_rss_key *cmd_resp;
u16 key_size = sizeof(*key);
struct ice_aq_desc desc;
cmd_resp = &desc.params.get_set_rss_key;
if (set) {
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_rss_key);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
} else {
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_rss_key);
}
cmd_resp->vsi_id = cpu_to_le16(((vsi_id <<
ICE_AQC_GSET_RSS_KEY_VSI_ID_S) &
ICE_AQC_GSET_RSS_KEY_VSI_ID_M) |
ICE_AQC_GSET_RSS_KEY_VSI_VALID);
return ice_aq_send_cmd(hw, &desc, key, key_size, NULL);
}
/**
* ice_aq_get_rss_key
* @hw: pointer to the hw struct
* @vsi_id: VSI FW index
* @key: pointer to key info struct
*
* get the RSS key per VSI
*/
enum ice_status
ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_id,
struct ice_aqc_get_set_rss_keys *key)
{
return __ice_aq_get_set_rss_key(hw, vsi_id, key, false);
}
/**
* ice_aq_set_rss_key
* @hw: pointer to the hw struct
* @vsi_id: VSI FW index
* @keys: pointer to key info struct
*
* set the RSS key per VSI
*/
enum ice_status
ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_id,
struct ice_aqc_get_set_rss_keys *keys)
{
return __ice_aq_get_set_rss_key(hw, vsi_id, keys, true);
}
/**
* ice_aq_add_lan_txq
* @hw: pointer to the hardware structure
......
......@@ -33,6 +33,19 @@ enum ice_status ice_get_caps(struct ice_hw *hw);
enum ice_status
ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
u32 rxq_index);
enum ice_status
ice_aq_get_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
u16 lut_size);
enum ice_status
ice_aq_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut,
u16 lut_size);
enum ice_status
ice_aq_get_rss_key(struct ice_hw *hw, u16 vsi_id,
struct ice_aqc_get_set_rss_keys *keys);
enum ice_status
ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_id,
struct ice_aqc_get_set_rss_keys *keys);
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq);
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading);
void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode);
......
......@@ -40,6 +40,65 @@ union ice_32byte_rx_desc {
} wb; /* writeback */
};
struct ice_rx_ptype_decoded {
u32 ptype:10;
u32 known:1;
u32 outer_ip:1;
u32 outer_ip_ver:2;
u32 outer_frag:1;
u32 tunnel_type:3;
u32 tunnel_end_prot:2;
u32 tunnel_end_frag:1;
u32 inner_prot:4;
u32 payload_layer:3;
};
enum ice_rx_ptype_outer_ip {
ICE_RX_PTYPE_OUTER_L2 = 0,
ICE_RX_PTYPE_OUTER_IP = 1,
};
enum ice_rx_ptype_outer_ip_ver {
ICE_RX_PTYPE_OUTER_NONE = 0,
ICE_RX_PTYPE_OUTER_IPV4 = 1,
ICE_RX_PTYPE_OUTER_IPV6 = 2,
};
enum ice_rx_ptype_outer_fragmented {
ICE_RX_PTYPE_NOT_FRAG = 0,
ICE_RX_PTYPE_FRAG = 1,
};
enum ice_rx_ptype_tunnel_type {
ICE_RX_PTYPE_TUNNEL_NONE = 0,
ICE_RX_PTYPE_TUNNEL_IP_IP = 1,
ICE_RX_PTYPE_TUNNEL_IP_GRENAT = 2,
ICE_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3,
ICE_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
};
enum ice_rx_ptype_tunnel_end_prot {
ICE_RX_PTYPE_TUNNEL_END_NONE = 0,
ICE_RX_PTYPE_TUNNEL_END_IPV4 = 1,
ICE_RX_PTYPE_TUNNEL_END_IPV6 = 2,
};
enum ice_rx_ptype_inner_prot {
ICE_RX_PTYPE_INNER_PROT_NONE = 0,
ICE_RX_PTYPE_INNER_PROT_UDP = 1,
ICE_RX_PTYPE_INNER_PROT_TCP = 2,
ICE_RX_PTYPE_INNER_PROT_SCTP = 3,
ICE_RX_PTYPE_INNER_PROT_ICMP = 4,
ICE_RX_PTYPE_INNER_PROT_TIMESYNC = 5,
};
enum ice_rx_ptype_payload_layer {
ICE_RX_PTYPE_PAYLOAD_LAYER_NONE = 0,
ICE_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1,
ICE_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2,
ICE_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3,
};
/* RX Flex Descriptor
* This descriptor is used instead of the legacy version descriptor when
* ice_rlan_ctx.adv_desc is set
......@@ -88,6 +147,41 @@ union ice_32b_rx_flex_desc {
} wb; /* writeback */
};
/* Rx Flex Descriptor NIC Profile
* This descriptor corresponds to RxDID 2 which contains
* metadata fields for RSS, flow id and timestamp info
*/
struct ice_32b_rx_flex_desc_nic {
/* Qword 0 */
u8 rxdid;
u8 mir_id_umb_cast;
__le16 ptype_flexi_flags0;
__le16 pkt_len;
__le16 hdr_len_sph_flex_flags1;
/* Qword 1 */
__le16 status_error0;
__le16 l2tag1;
__le32 rss_hash;
/* Qword 2 */
__le16 status_error1;
u8 flexi_flags2;
u8 ts_low;
__le16 l2tag2_1st;
__le16 l2tag2_2nd;
/* Qword 3 */
__le32 flow_id;
union {
struct {
__le16 vlan_id;
__le16 flow_id_ipv6;
} flex;
__le32 ts_high;
} flex_ts;
};
/* Receive Flex Descriptor profile IDs: There are a total
* of 64 profiles where profile IDs 0/1 are for legacy; and
* profiles 2-63 are flex profiles that can be programmed
......@@ -241,12 +335,56 @@ enum ice_tx_desc_dtype_value {
enum ice_tx_desc_cmd_bits {
ICE_TX_DESC_CMD_EOP = 0x0001,
ICE_TX_DESC_CMD_RS = 0x0002,
ICE_TX_DESC_CMD_IL2TAG1 = 0x0008,
ICE_TX_DESC_CMD_IIPT_IPV6 = 0x0020, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */
};
#define ICE_TXD_QW1_OFFSET_S 16
#define ICE_TXD_QW1_OFFSET_M (0x3FFFFULL << ICE_TXD_QW1_OFFSET_S)
enum ice_tx_desc_len_fields {
/* Note: These are predefined bit offsets */
ICE_TX_DESC_LEN_MACLEN_S = 0, /* 7 BITS */
ICE_TX_DESC_LEN_IPLEN_S = 7, /* 7 BITS */
ICE_TX_DESC_LEN_L4_LEN_S = 14 /* 4 BITS */
};
#define ICE_TXD_QW1_TX_BUF_SZ_S 34
#define ICE_TXD_QW1_L2TAG1_S 48
/* Context descriptors */
struct ice_tx_ctx_desc {
__le32 tunneling_params;
__le16 l2tag2;
__le16 rsvd;
__le64 qw1;
};
#define ICE_TXD_CTX_QW1_CMD_S 4
#define ICE_TXD_CTX_QW1_CMD_M (0x7FUL << ICE_TXD_CTX_QW1_CMD_S)
#define ICE_TXD_CTX_QW1_TSO_LEN_S 30
#define ICE_TXD_CTX_QW1_TSO_LEN_M \
(0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S)
#define ICE_TXD_CTX_QW1_MSS_S 50
enum ice_tx_ctx_desc_cmd_bits {
ICE_TX_CTX_DESC_TSO = 0x01,
ICE_TX_CTX_DESC_TSYN = 0x02,
ICE_TX_CTX_DESC_IL2TAG2 = 0x04,
ICE_TX_CTX_DESC_IL2TAG2_IL2H = 0x08,
ICE_TX_CTX_DESC_SWTCH_NOTAG = 0x00,
ICE_TX_CTX_DESC_SWTCH_UPLINK = 0x10,
ICE_TX_CTX_DESC_SWTCH_LOCAL = 0x20,
ICE_TX_CTX_DESC_SWTCH_VSI = 0x30,
ICE_TX_CTX_DESC_RESERVED = 0x40
};
#define ICE_LAN_TXQ_MAX_QGRPS 127
#define ICE_LAN_TXQ_MAX_QDIS 1023
......@@ -289,4 +427,35 @@ struct ice_tlan_ctx {
u8 pkt_shaper_prof_idx;
u8 int_q_state; /* width not needed - internal do not write */
};
/* macro to make the table lines short */
#define ICE_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
{ PTYPE, \
1, \
ICE_RX_PTYPE_OUTER_##OUTER_IP, \
ICE_RX_PTYPE_OUTER_##OUTER_IP_VER, \
ICE_RX_PTYPE_##OUTER_FRAG, \
ICE_RX_PTYPE_TUNNEL_##T, \
ICE_RX_PTYPE_TUNNEL_END_##TE, \
ICE_RX_PTYPE_##TEF, \
ICE_RX_PTYPE_INNER_PROT_##I, \
ICE_RX_PTYPE_PAYLOAD_LAYER_##PL }
#define ICE_PTT_UNUSED_ENTRY(PTYPE) { PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
/* shorter macros makes the table fit but are terse */
#define ICE_RX_PTYPE_NOF ICE_RX_PTYPE_NOT_FRAG
/* Lookup table mapping the HW PTYPE to the bit field for decoding */
static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = {
/* L2 Packet types */
ICE_PTT_UNUSED_ENTRY(0),
ICE_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
ICE_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE),
};
static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
{
return ice_ptype_lkup[ptype];
}
#endif /* _ICE_LAN_TX_RX_H_ */
This diff is collapsed.
......@@ -1217,6 +1217,117 @@ ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
return status;
}
/**
* ice_find_vlan_entry
* @hw: pointer to the hardware structure
* @vlan_id: VLAN id to search for
*
* Helper function to search for a VLAN entry using a given VLAN id
* Returns pointer to the entry if found.
*/
static struct ice_fltr_mgmt_list_entry *
ice_find_vlan_entry(struct ice_hw *hw, u16 vlan_id)
{
struct ice_fltr_mgmt_list_entry *vlan_list_itr, *vlan_ret = NULL;
struct ice_switch_info *sw = hw->switch_info;
mutex_lock(&sw->vlan_list_lock);
list_for_each_entry(vlan_list_itr, &sw->vlan_list_head, list_entry)
if (vlan_list_itr->fltr_info.l_data.vlan.vlan_id == vlan_id) {
vlan_ret = vlan_list_itr;
break;
}
mutex_unlock(&sw->vlan_list_lock);
return vlan_ret;
}
/**
* ice_add_vlan_internal - Add one VLAN based filter rule
* @hw: pointer to the hardware structure
* @f_entry: filter entry containing one VLAN information
*/
static enum ice_status
ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
{
struct ice_fltr_info *new_fltr, *cur_fltr;
struct ice_fltr_mgmt_list_entry *v_list_itr;
u16 vlan_id;
new_fltr = &f_entry->fltr_info;
/* VLAN id should only be 12 bits */
if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
return ICE_ERR_PARAM;
vlan_id = new_fltr->l_data.vlan.vlan_id;
v_list_itr = ice_find_vlan_entry(hw, vlan_id);
if (!v_list_itr) {
u16 vsi_id = ICE_VSI_INVAL_ID;
enum ice_status status;
u16 vsi_list_id = 0;
if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
enum ice_sw_lkup_type lkup_type = new_fltr->lkup_type;
/* All VLAN pruning rules use a VSI list.
* Convert the action to forwarding to a VSI list.
*/
vsi_id = new_fltr->fwd_id.vsi_id;
status = ice_create_vsi_list_rule(hw, &vsi_id, 1,
&vsi_list_id,
lkup_type);
if (status)
return status;
new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
new_fltr->fwd_id.vsi_list_id = vsi_list_id;
}
status = ice_create_pkt_fwd_rule(hw, f_entry);
if (!status && vsi_id != ICE_VSI_INVAL_ID) {
v_list_itr = ice_find_vlan_entry(hw, vlan_id);
if (!v_list_itr)
return ICE_ERR_DOES_NOT_EXIST;
v_list_itr->vsi_list_info =
ice_create_vsi_list_map(hw, &vsi_id, 1,
vsi_list_id);
}
return status;
}
cur_fltr = &v_list_itr->fltr_info;
return ice_handle_vsi_list_mgmt(hw, v_list_itr, cur_fltr, new_fltr);
}
/**
* ice_add_vlan - Add VLAN based filter rule
* @hw: pointer to the hardware structure
* @v_list: list of VLAN entries and forwarding information
*/
enum ice_status
ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
{
struct ice_fltr_list_entry *v_list_itr;
if (!v_list || !hw)
return ICE_ERR_PARAM;
list_for_each_entry(v_list_itr, v_list, list_entry) {
enum ice_status status;
if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
return ICE_ERR_PARAM;
status = ice_add_vlan_internal(hw, v_list_itr);
if (status) {
v_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
return status;
}
v_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
}
return 0;
}
/**
* ice_remove_vsi_list_rule
* @hw: pointer to the hardware structure
......@@ -1515,6 +1626,54 @@ ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
return status;
}
/**
* ice_remove_vlan_internal - Remove one VLAN based filter rule
* @hw: pointer to the hardware structure
* @f_entry: filter entry containing one VLAN information
*/
static enum ice_status
ice_remove_vlan_internal(struct ice_hw *hw,
struct ice_fltr_list_entry *f_entry)
{
struct ice_fltr_info *new_fltr;
struct ice_fltr_mgmt_list_entry *v_list_elem;
u16 vsi_id;
new_fltr = &f_entry->fltr_info;
v_list_elem = ice_find_vlan_entry(hw, new_fltr->l_data.vlan.vlan_id);
if (!v_list_elem)
return ICE_ERR_PARAM;
vsi_id = f_entry->fltr_info.fwd_id.vsi_id;
return ice_handle_rem_vsi_list_mgmt(hw, vsi_id, v_list_elem);
}
/**
* ice_remove_vlan - Remove VLAN based filter rule
* @hw: pointer to the hardware structure
* @v_list: list of VLAN entries and forwarding information
*/
enum ice_status
ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
{
struct ice_fltr_list_entry *v_list_itr;
enum ice_status status = 0;
if (!v_list || !hw)
return ICE_ERR_PARAM;
list_for_each_entry(v_list_itr, v_list, list_entry) {
status = ice_remove_vlan_internal(hw, v_list_itr);
if (status) {
v_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
return status;
}
v_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
}
return status;
}
/**
* ice_add_to_vsi_fltr_list - Add VSI filters to the list
* @hw: pointer to the hardware structure
......@@ -1600,6 +1759,16 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_id,
}
break;
case ICE_SW_LKUP_VLAN:
mutex_lock(&sw->vlan_list_lock);
status = ice_add_to_vsi_fltr_list(hw, vsi_id,
&sw->vlan_list_head,
&remove_list_head);
mutex_unlock(&sw->vlan_list_lock);
if (!status) {
ice_remove_vlan(hw, &remove_list_head);
goto free_fltr_list;
}
break;
case ICE_SW_LKUP_MAC_VLAN:
case ICE_SW_LKUP_ETHERTYPE:
case ICE_SW_LKUP_ETHERTYPE_MAC:
......
......@@ -8,6 +8,7 @@
#define ICE_SW_CFG_MAX_BUF_LEN 2048
#define ICE_DFLT_VSI_INVAL 0xff
#define ICE_VSI_INVAL_ID 0xffff
/* VSI context structure for add/get/update/free operations */
struct ice_vsi_ctx {
......@@ -152,4 +153,7 @@ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);
enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_lst);
enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_lst);
void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id);
enum ice_status ice_add_vlan(struct ice_hw *hw, struct list_head *m_list);
enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list);
#endif /* _ICE_SWITCH_H_ */
This diff is collapsed.
......@@ -28,6 +28,12 @@
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
(R)->next_to_clean - (R)->next_to_use - 1)
#define ICE_TX_FLAGS_TSO BIT(0)
#define ICE_TX_FLAGS_HW_VLAN BIT(1)
#define ICE_TX_FLAGS_SW_VLAN BIT(2)
#define ICE_TX_FLAGS_VLAN_M 0xffff0000
#define ICE_TX_FLAGS_VLAN_S 16
struct ice_tx_buf {
struct ice_tx_desc *next_to_watch;
struct sk_buff *skb;
......@@ -38,6 +44,17 @@ struct ice_tx_buf {
DEFINE_DMA_UNMAP_LEN(len);
};
struct ice_tx_offload_params {
u8 header_len;
u32 td_cmd;
u32 td_offset;
u32 td_l2tag1;
u16 cd_l2tag2;
u32 cd_tunnel_params;
u64 cd_qw1;
struct ice_ring *tx_ring;
};
struct ice_rx_buf {
struct sk_buff *skb;
dma_addr_t dma;
......
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