net/qede: enhance Rx CPU utilization
Use light weight receive packet handler for non-LRO and non-scatter packets to improve CPU utilization in receive data path. We achieved ~18% CPU cycles improvement using this handler. Signed-off-by: Shahed Shaikh <shshaikh@marvell.com>
This commit is contained in:
parent
b0b9fdad24
commit
81f8804992
@ -267,6 +267,29 @@ qede_interrupt_handler(void *param)
|
|||||||
DP_ERR(edev, "rte_intr_ack failed\n");
|
DP_ERR(edev, "rte_intr_ack failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
qede_assign_rxtx_handlers(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct qede_dev *qdev = dev->data->dev_private;
|
||||||
|
struct ecore_dev *edev = &qdev->edev;
|
||||||
|
|
||||||
|
if (ECORE_IS_CMT(edev)) {
|
||||||
|
dev->rx_pkt_burst = qede_recv_pkts_cmt;
|
||||||
|
dev->tx_pkt_burst = qede_xmit_pkts_cmt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->data->lro || dev->data->scattered_rx) {
|
||||||
|
DP_INFO(edev, "Assigning qede_recv_pkts\n");
|
||||||
|
dev->rx_pkt_burst = qede_recv_pkts;
|
||||||
|
} else {
|
||||||
|
DP_INFO(edev, "Assigning qede_recv_pkts_regular\n");
|
||||||
|
dev->rx_pkt_burst = qede_recv_pkts_regular;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->tx_pkt_burst = qede_xmit_pkts;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qede_alloc_etherdev(struct qede_dev *qdev, struct qed_dev_eth_info *info)
|
qede_alloc_etherdev(struct qede_dev *qdev, struct qed_dev_eth_info *info)
|
||||||
{
|
{
|
||||||
@ -1082,6 +1105,7 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev)
|
|||||||
/* Start/resume traffic */
|
/* Start/resume traffic */
|
||||||
qede_fastpath_start(edev);
|
qede_fastpath_start(edev);
|
||||||
|
|
||||||
|
qede_assign_rxtx_handlers(eth_dev);
|
||||||
DP_INFO(edev, "Device started\n");
|
DP_INFO(edev, "Device started\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1992,6 +2016,7 @@ qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (eth_dev->rx_pkt_burst == qede_recv_pkts ||
|
if (eth_dev->rx_pkt_burst == qede_recv_pkts ||
|
||||||
|
eth_dev->rx_pkt_burst == qede_recv_pkts_regular ||
|
||||||
eth_dev->rx_pkt_burst == qede_recv_pkts_cmt)
|
eth_dev->rx_pkt_burst == qede_recv_pkts_cmt)
|
||||||
return ptypes;
|
return ptypes;
|
||||||
|
|
||||||
@ -2287,7 +2312,9 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
|
|||||||
|
|
||||||
/* update max frame size */
|
/* update max frame size */
|
||||||
dev->data->dev_conf.rxmode.max_rx_pkt_len = max_rx_pkt_len;
|
dev->data->dev_conf.rxmode.max_rx_pkt_len = max_rx_pkt_len;
|
||||||
|
|
||||||
/* Reassign back */
|
/* Reassign back */
|
||||||
|
qede_assign_rxtx_handlers(dev);
|
||||||
if (ECORE_IS_CMT(edev)) {
|
if (ECORE_IS_CMT(edev)) {
|
||||||
dev->rx_pkt_burst = qede_recv_pkts_cmt;
|
dev->rx_pkt_burst = qede_recv_pkts_cmt;
|
||||||
dev->tx_pkt_burst = qede_xmit_pkts_cmt;
|
dev->tx_pkt_burst = qede_xmit_pkts_cmt;
|
||||||
@ -2495,14 +2522,7 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf)
|
|||||||
strncpy((char *)params.name, QEDE_PMD_VER_PREFIX,
|
strncpy((char *)params.name, QEDE_PMD_VER_PREFIX,
|
||||||
QEDE_PMD_DRV_VER_STR_SIZE);
|
QEDE_PMD_DRV_VER_STR_SIZE);
|
||||||
|
|
||||||
if (ECORE_IS_CMT(edev)) {
|
qede_assign_rxtx_handlers(eth_dev);
|
||||||
eth_dev->rx_pkt_burst = qede_recv_pkts_cmt;
|
|
||||||
eth_dev->tx_pkt_burst = qede_xmit_pkts_cmt;
|
|
||||||
} else {
|
|
||||||
eth_dev->rx_pkt_burst = qede_recv_pkts;
|
|
||||||
eth_dev->tx_pkt_burst = qede_xmit_pkts;
|
|
||||||
}
|
|
||||||
|
|
||||||
eth_dev->tx_pkt_prepare = qede_xmit_prep_pkts;
|
eth_dev->tx_pkt_prepare = qede_xmit_prep_pkts;
|
||||||
|
|
||||||
/* For CMT mode device do periodic polling for slowpath events.
|
/* For CMT mode device do periodic polling for slowpath events.
|
||||||
|
@ -1518,6 +1518,228 @@ print_rx_bd_info(struct rte_mbuf *m, struct qede_rx_queue *rxq,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
qede_recv_pkts_regular(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
|
||||||
|
{
|
||||||
|
struct eth_fast_path_rx_reg_cqe *fp_cqe = NULL;
|
||||||
|
register struct rte_mbuf *rx_mb = NULL;
|
||||||
|
struct qede_rx_queue *rxq = p_rxq;
|
||||||
|
struct qede_dev *qdev = rxq->qdev;
|
||||||
|
struct ecore_dev *edev = &qdev->edev;
|
||||||
|
union eth_rx_cqe *cqe;
|
||||||
|
uint64_t ol_flags;
|
||||||
|
enum eth_rx_cqe_type cqe_type;
|
||||||
|
int rss_enable = qdev->rss_enable;
|
||||||
|
int rx_alloc_count = 0;
|
||||||
|
uint32_t packet_type;
|
||||||
|
uint32_t rss_hash;
|
||||||
|
uint16_t vlan_tci, port_id;
|
||||||
|
uint16_t hw_comp_cons, sw_comp_cons, sw_rx_index, num_rx_bds;
|
||||||
|
uint16_t rx_pkt = 0;
|
||||||
|
uint16_t pkt_len = 0;
|
||||||
|
uint16_t len; /* Length of first BD */
|
||||||
|
uint16_t preload_idx;
|
||||||
|
uint16_t parse_flag;
|
||||||
|
#ifdef RTE_LIBRTE_QEDE_DEBUG_RX
|
||||||
|
uint8_t bitfield_val;
|
||||||
|
#endif
|
||||||
|
uint8_t offset, flags, bd_num;
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocate buffers that we used in previous loop */
|
||||||
|
if (rxq->rx_alloc_count) {
|
||||||
|
if (unlikely(qede_alloc_rx_bulk_mbufs(rxq,
|
||||||
|
rxq->rx_alloc_count))) {
|
||||||
|
struct rte_eth_dev *dev;
|
||||||
|
|
||||||
|
PMD_RX_LOG(ERR, rxq,
|
||||||
|
"New buffer allocation failed,"
|
||||||
|
"dropping incoming packetn");
|
||||||
|
dev = &rte_eth_devices[rxq->port_id];
|
||||||
|
dev->data->rx_mbuf_alloc_failed +=
|
||||||
|
rxq->rx_alloc_count;
|
||||||
|
rxq->rx_alloc_errors += rxq->rx_alloc_count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
qede_update_rx_prod(qdev, rxq);
|
||||||
|
rxq->rx_alloc_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_comp_cons = rte_le_to_cpu_16(*rxq->hw_cons_ptr);
|
||||||
|
sw_comp_cons = ecore_chain_get_cons_idx(&rxq->rx_comp_ring);
|
||||||
|
|
||||||
|
rte_rmb();
|
||||||
|
|
||||||
|
if (hw_comp_cons == sw_comp_cons)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
num_rx_bds = NUM_RX_BDS(rxq);
|
||||||
|
port_id = rxq->port_id;
|
||||||
|
|
||||||
|
while (sw_comp_cons != hw_comp_cons) {
|
||||||
|
ol_flags = 0;
|
||||||
|
packet_type = RTE_PTYPE_UNKNOWN;
|
||||||
|
vlan_tci = 0;
|
||||||
|
rss_hash = 0;
|
||||||
|
|
||||||
|
/* Get the CQE from the completion ring */
|
||||||
|
cqe =
|
||||||
|
(union eth_rx_cqe *)ecore_chain_consume(&rxq->rx_comp_ring);
|
||||||
|
cqe_type = cqe->fast_path_regular.type;
|
||||||
|
PMD_RX_LOG(INFO, rxq, "Rx CQE type %d\n", cqe_type);
|
||||||
|
|
||||||
|
if (likely(cqe_type == ETH_RX_CQE_TYPE_REGULAR)) {
|
||||||
|
fp_cqe = &cqe->fast_path_regular;
|
||||||
|
} else {
|
||||||
|
if (cqe_type == ETH_RX_CQE_TYPE_SLOW_PATH) {
|
||||||
|
PMD_RX_LOG(INFO, rxq, "Got unexpected slowpath CQE\n");
|
||||||
|
ecore_eth_cqe_completion
|
||||||
|
(&edev->hwfns[rxq->queue_id %
|
||||||
|
edev->num_hwfns],
|
||||||
|
(struct eth_slow_path_rx_cqe *)cqe);
|
||||||
|
}
|
||||||
|
goto next_cqe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the data from the SW ring */
|
||||||
|
sw_rx_index = rxq->sw_rx_cons & num_rx_bds;
|
||||||
|
rx_mb = rxq->sw_rx_ring[sw_rx_index].mbuf;
|
||||||
|
assert(rx_mb != NULL);
|
||||||
|
|
||||||
|
parse_flag = rte_le_to_cpu_16(fp_cqe->pars_flags.flags);
|
||||||
|
offset = fp_cqe->placement_offset;
|
||||||
|
len = rte_le_to_cpu_16(fp_cqe->len_on_first_bd);
|
||||||
|
pkt_len = rte_le_to_cpu_16(fp_cqe->pkt_len);
|
||||||
|
vlan_tci = rte_le_to_cpu_16(fp_cqe->vlan_tag);
|
||||||
|
rss_hash = rte_le_to_cpu_32(fp_cqe->rss_hash);
|
||||||
|
bd_num = fp_cqe->bd_num;
|
||||||
|
#ifdef RTE_LIBRTE_QEDE_DEBUG_RX
|
||||||
|
bitfield_val = fp_cqe->bitfields;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (unlikely(qede_tunn_exist(parse_flag))) {
|
||||||
|
PMD_RX_LOG(INFO, rxq, "Rx tunneled packet\n");
|
||||||
|
if (unlikely(qede_check_tunn_csum_l4(parse_flag))) {
|
||||||
|
PMD_RX_LOG(ERR, rxq,
|
||||||
|
"L4 csum failed, flags = 0x%x\n",
|
||||||
|
parse_flag);
|
||||||
|
rxq->rx_hw_errors++;
|
||||||
|
ol_flags |= PKT_RX_L4_CKSUM_BAD;
|
||||||
|
} else {
|
||||||
|
ol_flags |= PKT_RX_L4_CKSUM_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(qede_check_tunn_csum_l3(parse_flag))) {
|
||||||
|
PMD_RX_LOG(ERR, rxq,
|
||||||
|
"Outer L3 csum failed, flags = 0x%x\n",
|
||||||
|
parse_flag);
|
||||||
|
rxq->rx_hw_errors++;
|
||||||
|
ol_flags |= PKT_RX_EIP_CKSUM_BAD;
|
||||||
|
} else {
|
||||||
|
ol_flags |= PKT_RX_IP_CKSUM_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = fp_cqe->tunnel_pars_flags.flags;
|
||||||
|
|
||||||
|
/* Tunnel_type */
|
||||||
|
packet_type =
|
||||||
|
qede_rx_cqe_to_tunn_pkt_type(flags);
|
||||||
|
|
||||||
|
/* Inner header */
|
||||||
|
packet_type |=
|
||||||
|
qede_rx_cqe_to_pkt_type_inner(parse_flag);
|
||||||
|
|
||||||
|
/* Outer L3/L4 types is not available in CQE */
|
||||||
|
packet_type |= qede_rx_cqe_to_pkt_type_outer(rx_mb);
|
||||||
|
|
||||||
|
/* Outer L3/L4 types is not available in CQE.
|
||||||
|
* Need to add offset to parse correctly,
|
||||||
|
*/
|
||||||
|
rx_mb->data_off = offset + RTE_PKTMBUF_HEADROOM;
|
||||||
|
packet_type |= qede_rx_cqe_to_pkt_type_outer(rx_mb);
|
||||||
|
} else {
|
||||||
|
packet_type |= qede_rx_cqe_to_pkt_type(parse_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common handling for non-tunnel packets and for inner
|
||||||
|
* headers in the case of tunnel.
|
||||||
|
*/
|
||||||
|
if (unlikely(qede_check_notunn_csum_l4(parse_flag))) {
|
||||||
|
PMD_RX_LOG(ERR, rxq,
|
||||||
|
"L4 csum failed, flags = 0x%x\n",
|
||||||
|
parse_flag);
|
||||||
|
rxq->rx_hw_errors++;
|
||||||
|
ol_flags |= PKT_RX_L4_CKSUM_BAD;
|
||||||
|
} else {
|
||||||
|
ol_flags |= PKT_RX_L4_CKSUM_GOOD;
|
||||||
|
}
|
||||||
|
if (unlikely(qede_check_notunn_csum_l3(rx_mb, parse_flag))) {
|
||||||
|
PMD_RX_LOG(ERR, rxq, "IP csum failed, flags = 0x%x\n",
|
||||||
|
parse_flag);
|
||||||
|
rxq->rx_hw_errors++;
|
||||||
|
ol_flags |= PKT_RX_IP_CKSUM_BAD;
|
||||||
|
} else {
|
||||||
|
ol_flags |= PKT_RX_IP_CKSUM_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(CQE_HAS_VLAN(parse_flag) ||
|
||||||
|
CQE_HAS_OUTER_VLAN(parse_flag))) {
|
||||||
|
/* Note: FW doesn't indicate Q-in-Q packet */
|
||||||
|
ol_flags |= PKT_RX_VLAN;
|
||||||
|
if (qdev->vlan_strip_flg) {
|
||||||
|
ol_flags |= PKT_RX_VLAN_STRIPPED;
|
||||||
|
rx_mb->vlan_tci = vlan_tci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rss_enable) {
|
||||||
|
ol_flags |= PKT_RX_RSS_HASH;
|
||||||
|
rx_mb->hash.rss = rss_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_alloc_count++;
|
||||||
|
qede_rx_bd_ring_consume(rxq);
|
||||||
|
|
||||||
|
/* Prefetch next mbuf while processing current one. */
|
||||||
|
preload_idx = rxq->sw_rx_cons & num_rx_bds;
|
||||||
|
rte_prefetch0(rxq->sw_rx_ring[preload_idx].mbuf);
|
||||||
|
|
||||||
|
/* Update rest of the MBUF fields */
|
||||||
|
rx_mb->data_off = offset + RTE_PKTMBUF_HEADROOM;
|
||||||
|
rx_mb->port = port_id;
|
||||||
|
rx_mb->ol_flags = ol_flags;
|
||||||
|
rx_mb->data_len = len;
|
||||||
|
rx_mb->packet_type = packet_type;
|
||||||
|
#ifdef RTE_LIBRTE_QEDE_DEBUG_RX
|
||||||
|
print_rx_bd_info(rx_mb, rxq, bitfield_val);
|
||||||
|
#endif
|
||||||
|
rx_mb->nb_segs = bd_num;
|
||||||
|
rx_mb->pkt_len = pkt_len;
|
||||||
|
|
||||||
|
rx_pkts[rx_pkt] = rx_mb;
|
||||||
|
rx_pkt++;
|
||||||
|
|
||||||
|
next_cqe:
|
||||||
|
ecore_chain_recycle_consumed(&rxq->rx_comp_ring);
|
||||||
|
sw_comp_cons = ecore_chain_get_cons_idx(&rxq->rx_comp_ring);
|
||||||
|
if (rx_pkt == nb_pkts) {
|
||||||
|
PMD_RX_LOG(DEBUG, rxq,
|
||||||
|
"Budget reached nb_pkts=%u received=%u",
|
||||||
|
rx_pkt, nb_pkts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request number of bufferes to be allocated in next loop */
|
||||||
|
rxq->rx_alloc_count = rx_alloc_count;
|
||||||
|
|
||||||
|
rxq->rcv_pkts += rx_pkt;
|
||||||
|
rxq->rx_segs += rx_pkt;
|
||||||
|
PMD_RX_LOG(DEBUG, rxq, "rx_pkts=%u core=%d", rx_pkt, rte_lcore_id());
|
||||||
|
|
||||||
|
return rx_pkt;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
qede_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
|
qede_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
|
||||||
{
|
{
|
||||||
|
@ -283,7 +283,9 @@ uint16_t qede_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts,
|
|||||||
uint16_t nb_pkts);
|
uint16_t nb_pkts);
|
||||||
uint16_t qede_recv_pkts_cmt(void *p_rxq, struct rte_mbuf **rx_pkts,
|
uint16_t qede_recv_pkts_cmt(void *p_rxq, struct rte_mbuf **rx_pkts,
|
||||||
uint16_t nb_pkts);
|
uint16_t nb_pkts);
|
||||||
|
uint16_t
|
||||||
|
qede_recv_pkts_regular(void *p_rxq, struct rte_mbuf **rx_pkts,
|
||||||
|
uint16_t nb_pkts);
|
||||||
uint16_t qede_rxtx_pkts_dummy(void *p_rxq,
|
uint16_t qede_rxtx_pkts_dummy(void *p_rxq,
|
||||||
struct rte_mbuf **pkts,
|
struct rte_mbuf **pkts,
|
||||||
uint16_t nb_pkts);
|
uint16_t nb_pkts);
|
||||||
|
Loading…
Reference in New Issue
Block a user