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

Merge branch 'qed_hw_gro'

Manish Chopra says:

====================
qed/qede: Add hardware GRO support

This patch series enables hardware GRO and add support for handling
HW aggregated TCP packets in driver receive flow by skipping
software GRO handling in stack.

Please consider applying this series to net-next.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 49cc66ea 55482edc
...@@ -2919,7 +2919,19 @@ struct eth_vport_rx_mode { ...@@ -2919,7 +2919,19 @@ struct eth_vport_rx_mode {
}; };
struct eth_vport_tpa_param { struct eth_vport_tpa_param {
u64 reserved[2]; u8 tpa_ipv4_en_flg;
u8 tpa_ipv6_en_flg;
u8 tpa_ipv4_tunn_en_flg;
u8 tpa_ipv6_tunn_en_flg;
u8 tpa_pkt_split_flg;
u8 tpa_hdr_data_split_flg;
u8 tpa_gro_consistent_flg;
u8 tpa_max_aggs_num;
u16 tpa_max_size;
u16 tpa_min_size_to_start;
u16 tpa_min_size_to_cont;
u8 max_buff_num;
u8 reserved;
}; };
struct eth_vport_tx_mode { struct eth_vport_tx_mode {
......
...@@ -132,16 +132,29 @@ struct qed_sp_vport_update_params { ...@@ -132,16 +132,29 @@ struct qed_sp_vport_update_params {
struct qed_filter_accept_flags accept_flags; struct qed_filter_accept_flags accept_flags;
}; };
enum qed_tpa_mode {
QED_TPA_MODE_NONE,
QED_TPA_MODE_UNUSED,
QED_TPA_MODE_GRO,
QED_TPA_MODE_MAX
};
struct qed_sp_vport_start_params {
enum qed_tpa_mode tpa_mode;
bool remove_inner_vlan;
bool drop_ttl0;
u8 max_buffers_per_cqe;
u32 concrete_fid;
u16 opaque_fid;
u8 vport_id;
u16 mtu;
};
#define QED_MAX_SGES_NUM 16 #define QED_MAX_SGES_NUM 16
#define CRC32_POLY 0x1edc6f41 #define CRC32_POLY 0x1edc6f41
static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, static int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
u32 concrete_fid, struct qed_sp_vport_start_params *p_params)
u16 opaque_fid,
u8 vport_id,
u16 mtu,
u8 drop_ttl0_flg,
u8 inner_vlan_removal_en_flg)
{ {
struct vport_start_ramrod_data *p_ramrod = NULL; struct vport_start_ramrod_data *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL; struct qed_spq_entry *p_ent = NULL;
...@@ -150,13 +163,13 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, ...@@ -150,13 +163,13 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
u16 rx_mode = 0; u16 rx_mode = 0;
u8 abs_vport_id = 0; u8 abs_vport_id = 0;
rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id); rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);
if (rc != 0) if (rc != 0)
return rc; return rc;
memset(&init_data, 0, sizeof(init_data)); memset(&init_data, 0, sizeof(init_data));
init_data.cid = qed_spq_get_cid(p_hwfn); init_data.cid = qed_spq_get_cid(p_hwfn);
init_data.opaque_fid = opaque_fid; init_data.opaque_fid = p_params->opaque_fid;
init_data.comp_mode = QED_SPQ_MODE_EBLOCK; init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
rc = qed_sp_init_request(p_hwfn, &p_ent, rc = qed_sp_init_request(p_hwfn, &p_ent,
...@@ -168,9 +181,9 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, ...@@ -168,9 +181,9 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
p_ramrod = &p_ent->ramrod.vport_start; p_ramrod = &p_ent->ramrod.vport_start;
p_ramrod->vport_id = abs_vport_id; p_ramrod->vport_id = abs_vport_id;
p_ramrod->mtu = cpu_to_le16(mtu); p_ramrod->mtu = cpu_to_le16(p_params->mtu);
p_ramrod->inner_vlan_removal_en = inner_vlan_removal_en_flg; p_ramrod->inner_vlan_removal_en = p_params->remove_inner_vlan;
p_ramrod->drop_ttl0_en = drop_ttl0_flg; p_ramrod->drop_ttl0_en = p_params->drop_ttl0;
SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1); SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1);
SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1); SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1);
...@@ -181,9 +194,26 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, ...@@ -181,9 +194,26 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
memset(&p_ramrod->tpa_param, 0, memset(&p_ramrod->tpa_param, 0,
sizeof(struct eth_vport_tpa_param)); sizeof(struct eth_vport_tpa_param));
p_ramrod->tpa_param.max_buff_num = p_params->max_buffers_per_cqe;
switch (p_params->tpa_mode) {
case QED_TPA_MODE_GRO:
p_ramrod->tpa_param.tpa_max_aggs_num = ETH_TPA_MAX_AGGS_NUM;
p_ramrod->tpa_param.tpa_max_size = (u16)-1;
p_ramrod->tpa_param.tpa_min_size_to_cont = p_params->mtu / 2;
p_ramrod->tpa_param.tpa_min_size_to_start = p_params->mtu / 2;
p_ramrod->tpa_param.tpa_ipv4_en_flg = 1;
p_ramrod->tpa_param.tpa_ipv6_en_flg = 1;
p_ramrod->tpa_param.tpa_pkt_split_flg = 1;
p_ramrod->tpa_param.tpa_gro_consistent_flg = 1;
break;
default:
break;
}
/* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */ /* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */
p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev, p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev,
concrete_fid); p_params->concrete_fid);
return qed_spq_post(p_hwfn, p_ent, NULL); return qed_spq_post(p_hwfn, p_ent, NULL);
} }
...@@ -1592,24 +1622,25 @@ static void qed_register_eth_ops(struct qed_dev *cdev, ...@@ -1592,24 +1622,25 @@ static void qed_register_eth_ops(struct qed_dev *cdev,
} }
static int qed_start_vport(struct qed_dev *cdev, static int qed_start_vport(struct qed_dev *cdev,
u8 vport_id, struct qed_start_vport_params *params)
u16 mtu,
u8 drop_ttl0_flg,
u8 inner_vlan_removal_en_flg)
{ {
int rc, i; int rc, i;
for_each_hwfn(cdev, i) { for_each_hwfn(cdev, i) {
struct qed_sp_vport_start_params start = { 0 };
struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
rc = qed_sp_vport_start(p_hwfn, start.tpa_mode = params->gro_enable ? QED_TPA_MODE_GRO :
p_hwfn->hw_info.concrete_fid, QED_TPA_MODE_NONE;
p_hwfn->hw_info.opaque_fid, start.remove_inner_vlan = params->remove_inner_vlan;
vport_id, start.drop_ttl0 = params->drop_ttl0;
mtu, start.opaque_fid = p_hwfn->hw_info.opaque_fid;
drop_ttl0_flg, start.concrete_fid = p_hwfn->hw_info.concrete_fid;
inner_vlan_removal_en_flg); start.vport_id = params->vport_id;
start.max_buffers_per_cqe = 16;
start.mtu = params->mtu;
rc = qed_sp_vport_start(p_hwfn, &start);
if (rc) { if (rc) {
DP_ERR(cdev, "Failed to start VPORT\n"); DP_ERR(cdev, "Failed to start VPORT\n");
return rc; return rc;
...@@ -1619,7 +1650,7 @@ static int qed_start_vport(struct qed_dev *cdev, ...@@ -1619,7 +1650,7 @@ static int qed_start_vport(struct qed_dev *cdev,
DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP),
"Started V-PORT %d with MTU %d\n", "Started V-PORT %d with MTU %d\n",
vport_id, mtu); start.vport_id, start.mtu);
} }
qed_reset_vport_stats(cdev); qed_reset_vport_stats(cdev);
......
...@@ -160,6 +160,7 @@ struct qede_dev { ...@@ -160,6 +160,7 @@ struct qede_dev {
u16 q_num_rx_buffers; /* Must be a power of two */ u16 q_num_rx_buffers; /* Must be a power of two */
u16 q_num_tx_buffers; /* Must be a power of two */ u16 q_num_tx_buffers; /* Must be a power of two */
bool gro_disable;
struct list_head vlan_list; struct list_head vlan_list;
u16 configured_vlans; u16 configured_vlans;
u16 non_configured_vlans; u16 non_configured_vlans;
...@@ -188,6 +189,24 @@ struct sw_rx_data { ...@@ -188,6 +189,24 @@ struct sw_rx_data {
unsigned int page_offset; unsigned int page_offset;
}; };
enum qede_agg_state {
QEDE_AGG_STATE_NONE = 0,
QEDE_AGG_STATE_START = 1,
QEDE_AGG_STATE_ERROR = 2
};
struct qede_agg_info {
struct sw_rx_data replace_buf;
dma_addr_t replace_buf_mapping;
struct sw_rx_data start_buf;
dma_addr_t start_buf_mapping;
struct eth_fast_path_rx_tpa_start_cqe start_cqe;
enum qede_agg_state agg_state;
struct sk_buff *skb;
int frag_id;
u16 vlan_tag;
};
struct qede_rx_queue { struct qede_rx_queue {
__le16 *hw_cons_ptr; __le16 *hw_cons_ptr;
struct sw_rx_data *sw_rx_ring; struct sw_rx_data *sw_rx_ring;
...@@ -197,6 +216,9 @@ struct qede_rx_queue { ...@@ -197,6 +216,9 @@ struct qede_rx_queue {
struct qed_chain rx_comp_ring; struct qed_chain rx_comp_ring;
void __iomem *hw_rxq_prod_addr; void __iomem *hw_rxq_prod_addr;
/* GRO */
struct qede_agg_info tpa_info[ETH_TPA_MAX_AGGS_NUM];
int rx_buf_size; int rx_buf_size;
unsigned int rx_buf_seg_size; unsigned int rx_buf_seg_size;
......
...@@ -39,6 +39,14 @@ struct qed_update_vport_params { ...@@ -39,6 +39,14 @@ struct qed_update_vport_params {
struct qed_update_vport_rss_params rss_params; struct qed_update_vport_rss_params rss_params;
}; };
struct qed_start_vport_params {
bool remove_inner_vlan;
bool gro_enable;
bool drop_ttl0;
u8 vport_id;
u16 mtu;
};
struct qed_stop_rxq_params { struct qed_stop_rxq_params {
u8 rss_id; u8 rss_id;
u8 rx_queue_id; u8 rx_queue_id;
...@@ -118,9 +126,7 @@ struct qed_eth_ops { ...@@ -118,9 +126,7 @@ struct qed_eth_ops {
void *cookie); void *cookie);
int (*vport_start)(struct qed_dev *cdev, int (*vport_start)(struct qed_dev *cdev,
u8 vport_id, u16 mtu, struct qed_start_vport_params *params);
u8 drop_ttl0_flg,
u8 inner_vlan_removal_en_flg);
int (*vport_stop)(struct qed_dev *cdev, int (*vport_stop)(struct qed_dev *cdev,
u8 vport_id); u8 vport_id);
......
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