xref: /dpdk/drivers/net/nfp/nfp_rxtx.c (revision 4f0ece5e5a38df8aac666e1f7ea2642b449be848)
179c7601aSHeinrich Kuhn /* SPDX-License-Identifier: BSD-3-Clause
279c7601aSHeinrich Kuhn  * Copyright (c) 2014-2021 Netronome Systems, Inc.
379c7601aSHeinrich Kuhn  * All rights reserved.
479c7601aSHeinrich Kuhn  *
579c7601aSHeinrich Kuhn  * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation.
679c7601aSHeinrich Kuhn  */
779c7601aSHeinrich Kuhn 
8027a02c6SChaoyong He #include "nfp_rxtx.h"
9027a02c6SChaoyong He 
1079c7601aSHeinrich Kuhn #include <ethdev_pci.h>
11310a1780SShihong Wang #include <rte_security.h>
1279c7601aSHeinrich Kuhn 
13ffe84fcbSChaoyong He #include "nfd3/nfp_nfd3.h"
14fc756151SChaoyong He #include "nfdk/nfp_nfdk.h"
154dcbf32fSChaoyong He #include "nfdk/nfp_nfdk_vec.h"
16766d51c9SChaoyong He #include "flower/nfp_flower.h"
1779c7601aSHeinrich Kuhn 
18310a1780SShihong Wang #include "nfp_ipsec.h"
19027a02c6SChaoyong He #include "nfp_logs.h"
20ddcd598fSLong Wu #include "nfp_net_meta.h"
21b6755530SLong Wu #include "nfp_rxtx_vec.h"
22027a02c6SChaoyong He 
23027a02c6SChaoyong He /*
24027a02c6SChaoyong He  * The bit format and map of nfp packet type for rxd.offload_info in Rx descriptor.
25027a02c6SChaoyong He  *
26027a02c6SChaoyong He  * Bit format about nfp packet type refers to the following:
27027a02c6SChaoyong He  * ---------------------------------
28027a02c6SChaoyong He  *            1                   0
29027a02c6SChaoyong He  *  5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
30027a02c6SChaoyong He  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31027a02c6SChaoyong He  * |       |ol3|tunnel |  l3 |  l4 |
32027a02c6SChaoyong He  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33027a02c6SChaoyong He  *
34027a02c6SChaoyong He  * Bit map about nfp packet type refers to the following:
35027a02c6SChaoyong He  *
36027a02c6SChaoyong He  * L4: bit 0~2, used for layer 4 or inner layer 4.
37027a02c6SChaoyong He  * 000: NFP_NET_PTYPE_L4_NONE
38027a02c6SChaoyong He  * 001: NFP_NET_PTYPE_L4_TCP
39027a02c6SChaoyong He  * 010: NFP_NET_PTYPE_L4_UDP
40027a02c6SChaoyong He  * 011: NFP_NET_PTYPE_L4_FRAG
41027a02c6SChaoyong He  * 100: NFP_NET_PTYPE_L4_NONFRAG
42027a02c6SChaoyong He  * 101: NFP_NET_PTYPE_L4_ICMP
43027a02c6SChaoyong He  * 110: NFP_NET_PTYPE_L4_SCTP
44027a02c6SChaoyong He  * 111: reserved
45027a02c6SChaoyong He  *
46027a02c6SChaoyong He  * L3: bit 3~5, used for layer 3 or inner layer 3.
47027a02c6SChaoyong He  * 000: NFP_NET_PTYPE_L3_NONE
48027a02c6SChaoyong He  * 001: NFP_NET_PTYPE_L3_IPV6
49027a02c6SChaoyong He  * 010: NFP_NET_PTYPE_L3_IPV4
50027a02c6SChaoyong He  * 011: NFP_NET_PTYPE_L3_IPV4_EXT
51027a02c6SChaoyong He  * 100: NFP_NET_PTYPE_L3_IPV6_EXT
52027a02c6SChaoyong He  * 101: NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN
53027a02c6SChaoyong He  * 110: NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN
54027a02c6SChaoyong He  * 111: reserved
55027a02c6SChaoyong He  *
56027a02c6SChaoyong He  * Tunnel: bit 6~9, used for tunnel.
57027a02c6SChaoyong He  * 0000: NFP_NET_PTYPE_TUNNEL_NONE
58027a02c6SChaoyong He  * 0001: NFP_NET_PTYPE_TUNNEL_VXLAN
59027a02c6SChaoyong He  * 0100: NFP_NET_PTYPE_TUNNEL_NVGRE
60027a02c6SChaoyong He  * 0101: NFP_NET_PTYPE_TUNNEL_GENEVE
61027a02c6SChaoyong He  * 0010, 0011, 0110~1111: reserved
62027a02c6SChaoyong He  *
63027a02c6SChaoyong He  * Outer L3: bit 10~11, used for outer layer 3.
64027a02c6SChaoyong He  * 00: NFP_NET_PTYPE_OUTER_L3_NONE
65027a02c6SChaoyong He  * 01: NFP_NET_PTYPE_OUTER_L3_IPV6
66027a02c6SChaoyong He  * 10: NFP_NET_PTYPE_OUTER_L3_IPV4
67027a02c6SChaoyong He  * 11: reserved
68027a02c6SChaoyong He  *
69027a02c6SChaoyong He  * Reserved: bit 10~15, used for extension.
70027a02c6SChaoyong He  */
71027a02c6SChaoyong He 
72027a02c6SChaoyong He /* Mask and offset about nfp packet type based on the bit map above. */
73027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_MASK                  0x0007
74027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_MASK                  0x0038
75027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_MASK              0x03c0
76027a02c6SChaoyong He #define NFP_NET_PTYPE_OUTER_L3_MASK            0x0c00
77027a02c6SChaoyong He 
78027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_OFFSET                0
79027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_OFFSET                3
80027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_OFFSET            6
81027a02c6SChaoyong He #define NFP_NET_PTYPE_OUTER_L3_OFFSET          10
82027a02c6SChaoyong He 
83027a02c6SChaoyong He /* Case about nfp packet type based on the bit map above. */
84027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_NONE                  0
85027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_TCP                   1
86027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_UDP                   2
87027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_FRAG                  3
88027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_NONFRAG               4
89027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_ICMP                  5
90027a02c6SChaoyong He #define NFP_NET_PTYPE_L4_SCTP                  6
91027a02c6SChaoyong He 
92027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_NONE                  0
93027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV6                  1
94027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV4                  2
95027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV4_EXT              3
96027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV6_EXT              4
97027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN      5
98027a02c6SChaoyong He #define NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN      6
99027a02c6SChaoyong He 
100027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_NONE              0
101027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_VXLAN             1
102027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_NVGRE             4
103027a02c6SChaoyong He #define NFP_NET_PTYPE_TUNNEL_GENEVE            5
104027a02c6SChaoyong He 
105027a02c6SChaoyong He #define NFP_NET_PTYPE_OUTER_L3_NONE            0
106027a02c6SChaoyong He #define NFP_NET_PTYPE_OUTER_L3_IPV6            1
107027a02c6SChaoyong He #define NFP_NET_PTYPE_OUTER_L3_IPV4            2
108027a02c6SChaoyong He 
109027a02c6SChaoyong He #define NFP_PTYPE2RTE(tunnel, type) ((tunnel) ? RTE_PTYPE_INNER_##type : RTE_PTYPE_##type)
110027a02c6SChaoyong He 
111027a02c6SChaoyong He /* Record NFP packet type parsed from rxd.offload_info. */
112027a02c6SChaoyong He struct nfp_ptype_parsed {
113027a02c6SChaoyong He 	uint8_t l4_ptype;       /**< Packet type of layer 4, or inner layer 4. */
114027a02c6SChaoyong He 	uint8_t l3_ptype;       /**< Packet type of layer 3, or inner layer 3. */
115027a02c6SChaoyong He 	uint8_t tunnel_ptype;   /**< Packet type of tunnel. */
116027a02c6SChaoyong He 	uint8_t outer_l3_ptype; /**< Packet type of outer layer 3. */
117027a02c6SChaoyong He };
118027a02c6SChaoyong He 
11940688372SChaoyong He /* Set mbuf checksum flags based on RX descriptor flags */
120027a02c6SChaoyong He void
121f4d24fe9SChaoyong He nfp_net_rx_cksum(struct nfp_net_rxq *rxq,
122f4d24fe9SChaoyong He 		struct nfp_net_rx_desc *rxd,
123027a02c6SChaoyong He 		struct rte_mbuf *mb)
124027a02c6SChaoyong He {
125027a02c6SChaoyong He 	struct nfp_net_hw *hw = rxq->hw;
126027a02c6SChaoyong He 
127b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RXCSUM) == 0)
128027a02c6SChaoyong He 		return;
129027a02c6SChaoyong He 
130027a02c6SChaoyong He 	/* If IPv4 and IP checksum error, fail */
131c01e5c0cSChaoyong He 	if (unlikely((rxd->rxd.flags & PCIE_DESC_RX_IP4_CSUM) != 0 &&
132c01e5c0cSChaoyong He 			(rxd->rxd.flags & PCIE_DESC_RX_IP4_CSUM_OK) == 0))
133027a02c6SChaoyong He 		mb->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
134027a02c6SChaoyong He 	else
135027a02c6SChaoyong He 		mb->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
136027a02c6SChaoyong He 
137027a02c6SChaoyong He 	/* If neither UDP nor TCP return */
138c01e5c0cSChaoyong He 	if ((rxd->rxd.flags & PCIE_DESC_RX_TCP_CSUM) == 0 &&
139c01e5c0cSChaoyong He 			(rxd->rxd.flags & PCIE_DESC_RX_UDP_CSUM) == 0)
140027a02c6SChaoyong He 		return;
141027a02c6SChaoyong He 
142c01e5c0cSChaoyong He 	if (likely(rxd->rxd.flags & PCIE_DESC_RX_L4_CSUM_OK) != 0)
143027a02c6SChaoyong He 		mb->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
144027a02c6SChaoyong He 	else
145027a02c6SChaoyong He 		mb->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
146027a02c6SChaoyong He }
147027a02c6SChaoyong He 
14879c7601aSHeinrich Kuhn static int
14979c7601aSHeinrich Kuhn nfp_net_rx_fill_freelist(struct nfp_net_rxq *rxq)
15079c7601aSHeinrich Kuhn {
1518ceb85c3SChaoyong He 	uint16_t i;
15249952141SChaoyong He 	uint64_t dma_addr;
15349952141SChaoyong He 	struct nfp_net_dp_buf *rxe = rxq->rxbufs;
15479c7601aSHeinrich Kuhn 
155b6de4353SZerun Fu 	PMD_RX_LOG(DEBUG, "Fill Rx Freelist for %hu descriptors.",
15679c7601aSHeinrich Kuhn 			rxq->rx_count);
15779c7601aSHeinrich Kuhn 
15879c7601aSHeinrich Kuhn 	for (i = 0; i < rxq->rx_count; i++) {
15979c7601aSHeinrich Kuhn 		struct nfp_net_rx_desc *rxd;
16079c7601aSHeinrich Kuhn 		struct rte_mbuf *mbuf = rte_pktmbuf_alloc(rxq->mem_pool);
16179c7601aSHeinrich Kuhn 
16279c7601aSHeinrich Kuhn 		if (mbuf == NULL) {
163b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "RX mbuf alloc failed queue_id=%hu.",
164f061491dSChaoyong He 				rxq->qidx);
16579c7601aSHeinrich Kuhn 			return -ENOMEM;
16679c7601aSHeinrich Kuhn 		}
16779c7601aSHeinrich Kuhn 
16876eaeadaSChaoyong He 		dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
16979c7601aSHeinrich Kuhn 
17079c7601aSHeinrich Kuhn 		rxd = &rxq->rxds[i];
17179c7601aSHeinrich Kuhn 		rxd->fld.dd = 0;
172fd392f84SPeng Zhang 		rxd->fld.dma_addr_hi = (dma_addr >> 32) & 0xffff;
17379c7601aSHeinrich Kuhn 		rxd->fld.dma_addr_lo = dma_addr & 0xffffffff;
174b0c496abSChaoyong He 
17579c7601aSHeinrich Kuhn 		rxe[i].mbuf = mbuf;
17679c7601aSHeinrich Kuhn 	}
17779c7601aSHeinrich Kuhn 
17879c7601aSHeinrich Kuhn 	/* Make sure all writes are flushed before telling the hardware */
17979c7601aSHeinrich Kuhn 	rte_wmb();
18079c7601aSHeinrich Kuhn 
18179c7601aSHeinrich Kuhn 	/* Not advertising the whole ring as the firmware gets confused if so */
182b6de4353SZerun Fu 	PMD_RX_LOG(DEBUG, "Increment FL write pointer in %hu.", rxq->rx_count - 1);
18379c7601aSHeinrich Kuhn 
18479c7601aSHeinrich Kuhn 	nfp_qcp_ptr_add(rxq->qcp_fl, NFP_QCP_WRITE_PTR, rxq->rx_count - 1);
18579c7601aSHeinrich Kuhn 
18679c7601aSHeinrich Kuhn 	return 0;
18779c7601aSHeinrich Kuhn }
18879c7601aSHeinrich Kuhn 
18979c7601aSHeinrich Kuhn int
19079c7601aSHeinrich Kuhn nfp_net_rx_freelist_setup(struct rte_eth_dev *dev)
19179c7601aSHeinrich Kuhn {
1928ceb85c3SChaoyong He 	uint16_t i;
19379c7601aSHeinrich Kuhn 
19479c7601aSHeinrich Kuhn 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
195c01e5c0cSChaoyong He 		if (nfp_net_rx_fill_freelist(dev->data->rx_queues[i]) != 0)
19679c7601aSHeinrich Kuhn 			return -1;
19779c7601aSHeinrich Kuhn 	}
198b0c496abSChaoyong He 
19979c7601aSHeinrich Kuhn 	return 0;
20079c7601aSHeinrich Kuhn }
20179c7601aSHeinrich Kuhn 
20279c7601aSHeinrich Kuhn uint32_t
2038d7d4fcdSKonstantin Ananyev nfp_net_rx_queue_count(void *rx_queue)
20479c7601aSHeinrich Kuhn {
20549952141SChaoyong He 	uint32_t idx;
20649952141SChaoyong He 	uint32_t count = 0;
20779c7601aSHeinrich Kuhn 	struct nfp_net_rxq *rxq;
20879c7601aSHeinrich Kuhn 	struct nfp_net_rx_desc *rxds;
20979c7601aSHeinrich Kuhn 
2108d7d4fcdSKonstantin Ananyev 	rxq = rx_queue;
21179c7601aSHeinrich Kuhn 	idx = rxq->rd_p;
21279c7601aSHeinrich Kuhn 
21379c7601aSHeinrich Kuhn 	/*
21479c7601aSHeinrich Kuhn 	 * Other PMDs are just checking the DD bit in intervals of 4
21579c7601aSHeinrich Kuhn 	 * descriptors and counting all four if the first has the DD
21679c7601aSHeinrich Kuhn 	 * bit on. Of course, this is not accurate but can be good for
21779c7601aSHeinrich Kuhn 	 * performance. But ideally that should be done in descriptors
21840688372SChaoyong He 	 * chunks belonging to the same cache line.
21979c7601aSHeinrich Kuhn 	 */
22079c7601aSHeinrich Kuhn 	while (count < rxq->rx_count) {
22179c7601aSHeinrich Kuhn 		rxds = &rxq->rxds[idx];
22279c7601aSHeinrich Kuhn 		if ((rxds->rxd.meta_len_dd & PCIE_DESC_RX_DD) == 0)
22379c7601aSHeinrich Kuhn 			break;
22479c7601aSHeinrich Kuhn 
22579c7601aSHeinrich Kuhn 		count++;
22679c7601aSHeinrich Kuhn 		idx++;
22779c7601aSHeinrich Kuhn 
22840688372SChaoyong He 		/* Wrapping */
22979c7601aSHeinrich Kuhn 		if ((idx) == rxq->rx_count)
23079c7601aSHeinrich Kuhn 			idx = 0;
23179c7601aSHeinrich Kuhn 	}
23279c7601aSHeinrich Kuhn 
23379c7601aSHeinrich Kuhn 	return count;
23479c7601aSHeinrich Kuhn }
23579c7601aSHeinrich Kuhn 
2362e7c3612SQin Ke /**
2372e7c3612SQin Ke  * Set packet type to mbuf based on parsed structure.
2382e7c3612SQin Ke  *
2392e7c3612SQin Ke  * @param nfp_ptype
2402e7c3612SQin Ke  *   Packet type structure parsing from Rx descriptor.
2412e7c3612SQin Ke  * @param mb
2422e7c3612SQin Ke  *   Mbuf to set the packet type.
2432e7c3612SQin Ke  */
2442e7c3612SQin Ke static void
245f4d24fe9SChaoyong He nfp_net_set_ptype(const struct nfp_ptype_parsed *nfp_ptype,
246f4d24fe9SChaoyong He 		struct rte_mbuf *mb)
2472e7c3612SQin Ke {
2482e7c3612SQin Ke 	uint32_t mbuf_ptype = RTE_PTYPE_L2_ETHER;
2492e7c3612SQin Ke 	uint8_t nfp_tunnel_ptype = nfp_ptype->tunnel_ptype;
2502e7c3612SQin Ke 
2512e7c3612SQin Ke 	if (nfp_tunnel_ptype != NFP_NET_PTYPE_TUNNEL_NONE)
2522e7c3612SQin Ke 		mbuf_ptype |= RTE_PTYPE_INNER_L2_ETHER;
2532e7c3612SQin Ke 
25408a54817SQin Ke 	switch (nfp_ptype->outer_l3_ptype) {
25508a54817SQin Ke 	case NFP_NET_PTYPE_OUTER_L3_NONE:
25608a54817SQin Ke 		break;
25708a54817SQin Ke 	case NFP_NET_PTYPE_OUTER_L3_IPV4:
25808a54817SQin Ke 		mbuf_ptype |= RTE_PTYPE_L3_IPV4;
25908a54817SQin Ke 		break;
26008a54817SQin Ke 	case NFP_NET_PTYPE_OUTER_L3_IPV6:
26108a54817SQin Ke 		mbuf_ptype |= RTE_PTYPE_L3_IPV6;
26208a54817SQin Ke 		break;
26308a54817SQin Ke 	default:
264b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "Unrecognized nfp outer layer 3 packet type: %u.",
26508a54817SQin Ke 				nfp_ptype->outer_l3_ptype);
26608a54817SQin Ke 		break;
26708a54817SQin Ke 	}
26808a54817SQin Ke 
2692e7c3612SQin Ke 	switch (nfp_tunnel_ptype) {
2702e7c3612SQin Ke 	case NFP_NET_PTYPE_TUNNEL_NONE:
2712e7c3612SQin Ke 		break;
2722e7c3612SQin Ke 	case NFP_NET_PTYPE_TUNNEL_VXLAN:
273c48a61b5SQin Ke 		mbuf_ptype |= RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP;
2742e7c3612SQin Ke 		break;
2752e7c3612SQin Ke 	case NFP_NET_PTYPE_TUNNEL_NVGRE:
2762e7c3612SQin Ke 		mbuf_ptype |= RTE_PTYPE_TUNNEL_NVGRE;
2772e7c3612SQin Ke 		break;
2782e7c3612SQin Ke 	case NFP_NET_PTYPE_TUNNEL_GENEVE:
279c48a61b5SQin Ke 		mbuf_ptype |= RTE_PTYPE_TUNNEL_GENEVE | RTE_PTYPE_L4_UDP;
2802e7c3612SQin Ke 		break;
2812e7c3612SQin Ke 	default:
282b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "Unrecognized nfp tunnel packet type: %u.",
2832e7c3612SQin Ke 				nfp_tunnel_ptype);
2842e7c3612SQin Ke 		break;
2852e7c3612SQin Ke 	}
2862e7c3612SQin Ke 
2872e7c3612SQin Ke 	switch (nfp_ptype->l4_ptype) {
2882e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_NONE:
2892e7c3612SQin Ke 		break;
2902e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_TCP:
2912e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_TCP);
2922e7c3612SQin Ke 		break;
2932e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_UDP:
2942e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_UDP);
2952e7c3612SQin Ke 		break;
2962e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_FRAG:
2972e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_FRAG);
2982e7c3612SQin Ke 		break;
2992e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_NONFRAG:
3002e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_NONFRAG);
3012e7c3612SQin Ke 		break;
3022e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_ICMP:
3032e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_ICMP);
3042e7c3612SQin Ke 		break;
3052e7c3612SQin Ke 	case NFP_NET_PTYPE_L4_SCTP:
3062e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_SCTP);
3072e7c3612SQin Ke 		break;
3082e7c3612SQin Ke 	default:
309b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "Unrecognized nfp layer 4 packet type: %u.",
3102e7c3612SQin Ke 				nfp_ptype->l4_ptype);
3112e7c3612SQin Ke 		break;
3122e7c3612SQin Ke 	}
3132e7c3612SQin Ke 
3142e7c3612SQin Ke 	switch (nfp_ptype->l3_ptype) {
3152e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_NONE:
3162e7c3612SQin Ke 		break;
3172e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV4:
3182e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4);
3192e7c3612SQin Ke 		break;
3202e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV6:
3212e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6);
3222e7c3612SQin Ke 		break;
3232e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV4_EXT:
3242e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4_EXT);
3252e7c3612SQin Ke 		break;
3262e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV6_EXT:
3272e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6_EXT);
3282e7c3612SQin Ke 		break;
3292e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN:
3302e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4_EXT_UNKNOWN);
3312e7c3612SQin Ke 		break;
3322e7c3612SQin Ke 	case NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN:
3332e7c3612SQin Ke 		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6_EXT_UNKNOWN);
3342e7c3612SQin Ke 		break;
3352e7c3612SQin Ke 	default:
336b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "Unrecognized nfp layer 3 packet type: %u.",
3372e7c3612SQin Ke 				nfp_ptype->l3_ptype);
3382e7c3612SQin Ke 		break;
3392e7c3612SQin Ke 	}
3402e7c3612SQin Ke 
3412e7c3612SQin Ke 	mb->packet_type = mbuf_ptype;
3422e7c3612SQin Ke }
3432e7c3612SQin Ke 
3442e7c3612SQin Ke /**
3452e7c3612SQin Ke  * Parse the packet type from Rx descriptor and set to mbuf.
3462e7c3612SQin Ke  *
347495846c1SChaoyong He  * @param rxq
348495846c1SChaoyong He  *   Rx queue
3492e7c3612SQin Ke  * @param rxds
3502e7c3612SQin Ke  *   Rx descriptor including the offloading info of packet type.
3512e7c3612SQin Ke  * @param mb
3522e7c3612SQin Ke  *   Mbuf to set the packet type.
3532e7c3612SQin Ke  */
35462edcfd6SLong Wu void
355495846c1SChaoyong He nfp_net_parse_ptype(struct nfp_net_rxq *rxq,
356495846c1SChaoyong He 		struct nfp_net_rx_desc *rxds,
3572e7c3612SQin Ke 		struct rte_mbuf *mb)
3582e7c3612SQin Ke {
359495846c1SChaoyong He 	struct nfp_net_hw *hw = rxq->hw;
3602e7c3612SQin Ke 	struct nfp_ptype_parsed nfp_ptype;
3612e7c3612SQin Ke 	uint16_t rxd_ptype = rxds->rxd.offload_info;
3622e7c3612SQin Ke 
3639177c800SChaoyong He 	if ((hw->super.ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
364495846c1SChaoyong He 		return;
365495846c1SChaoyong He 
3662e7c3612SQin Ke 	if (rxd_ptype == 0 || (rxds->rxd.flags & PCIE_DESC_RX_VLAN) != 0)
3672e7c3612SQin Ke 		return;
3682e7c3612SQin Ke 
3692e7c3612SQin Ke 	nfp_ptype.l4_ptype = (rxd_ptype & NFP_NET_PTYPE_L4_MASK) >>
3702e7c3612SQin Ke 			NFP_NET_PTYPE_L4_OFFSET;
3712e7c3612SQin Ke 	nfp_ptype.l3_ptype = (rxd_ptype & NFP_NET_PTYPE_L3_MASK) >>
3722e7c3612SQin Ke 			NFP_NET_PTYPE_L3_OFFSET;
3732e7c3612SQin Ke 	nfp_ptype.tunnel_ptype = (rxd_ptype & NFP_NET_PTYPE_TUNNEL_MASK) >>
3742e7c3612SQin Ke 			NFP_NET_PTYPE_TUNNEL_OFFSET;
37508a54817SQin Ke 	nfp_ptype.outer_l3_ptype = (rxd_ptype & NFP_NET_PTYPE_OUTER_L3_MASK) >>
37608a54817SQin Ke 			NFP_NET_PTYPE_OUTER_L3_OFFSET;
3772e7c3612SQin Ke 
3782e7c3612SQin Ke 	nfp_net_set_ptype(&nfp_ptype, mb);
3792e7c3612SQin Ke }
3802e7c3612SQin Ke 
3817d89daeaSPeng Zhang /*
38279c7601aSHeinrich Kuhn  * RX path design:
38379c7601aSHeinrich Kuhn  *
38479c7601aSHeinrich Kuhn  * There are some decisions to take:
38579c7601aSHeinrich Kuhn  * 1) How to check DD RX descriptors bit
38679c7601aSHeinrich Kuhn  * 2) How and when to allocate new mbufs
38779c7601aSHeinrich Kuhn  *
38879c7601aSHeinrich Kuhn  * Current implementation checks just one single DD bit each loop. As each
38979c7601aSHeinrich Kuhn  * descriptor is 8 bytes, it is likely a good idea to check descriptors in
39079c7601aSHeinrich Kuhn  * a single cache line instead. Tests with this change have not shown any
39179c7601aSHeinrich Kuhn  * performance improvement but it requires further investigation. For example,
39279c7601aSHeinrich Kuhn  * depending on which descriptor is next, the number of descriptors could be
39379c7601aSHeinrich Kuhn  * less than 8 for just checking those in the same cache line. This implies
39479c7601aSHeinrich Kuhn  * extra work which could be counterproductive by itself. Indeed, last firmware
39579c7601aSHeinrich Kuhn  * changes are just doing this: writing several descriptors with the DD bit
39679c7601aSHeinrich Kuhn  * for saving PCIe bandwidth and DMA operations from the NFP.
39779c7601aSHeinrich Kuhn  *
39879c7601aSHeinrich Kuhn  * Mbuf allocation is done when a new packet is received. Then the descriptor
39979c7601aSHeinrich Kuhn  * is automatically linked with the new mbuf and the old one is given to the
40079c7601aSHeinrich Kuhn  * user. The main drawback with this design is mbuf allocation is heavier than
40179c7601aSHeinrich Kuhn  * using bulk allocations allowed by DPDK with rte_mempool_get_bulk. From the
40279c7601aSHeinrich Kuhn  * cache point of view it does not seem allocating the mbuf early on as we are
40379c7601aSHeinrich Kuhn  * doing now have any benefit at all. Again, tests with this change have not
40479c7601aSHeinrich Kuhn  * shown any improvement. Also, rte_mempool_get_bulk returns all or nothing
40579c7601aSHeinrich Kuhn  * so looking at the implications of this type of allocation should be studied
40640688372SChaoyong He  * deeply.
40779c7601aSHeinrich Kuhn  */
40879c7601aSHeinrich Kuhn uint16_t
409f4d24fe9SChaoyong He nfp_net_recv_pkts(void *rx_queue,
410f4d24fe9SChaoyong He 		struct rte_mbuf **rx_pkts,
411f4d24fe9SChaoyong He 		uint16_t nb_pkts)
41279c7601aSHeinrich Kuhn {
41379c7601aSHeinrich Kuhn 	uint64_t dma_addr;
41449952141SChaoyong He 	uint16_t avail = 0;
41549952141SChaoyong He 	struct rte_mbuf *mb;
41649952141SChaoyong He 	uint16_t nb_hold = 0;
41749952141SChaoyong He 	struct nfp_net_hw *hw;
41849952141SChaoyong He 	struct rte_mbuf *new_mb;
41949952141SChaoyong He 	struct nfp_net_rxq *rxq;
420636e133eSPeng Zhang 	struct nfp_pf_dev *pf_dev;
42149952141SChaoyong He 	struct nfp_net_dp_buf *rxb;
42249952141SChaoyong He 	struct nfp_net_rx_desc *rxds;
423766d51c9SChaoyong He 	uint16_t avail_multiplexed = 0;
42479c7601aSHeinrich Kuhn 
42579c7601aSHeinrich Kuhn 	rxq = rx_queue;
42679c7601aSHeinrich Kuhn 	if (unlikely(rxq == NULL)) {
42779c7601aSHeinrich Kuhn 		/*
42879c7601aSHeinrich Kuhn 		 * DPDK just checks the queue is lower than max queues
42940688372SChaoyong He 		 * enabled. But the queue needs to be configured.
43079c7601aSHeinrich Kuhn 		 */
431b6de4353SZerun Fu 		PMD_RX_LOG(ERR, "RX Bad queue.");
432f061491dSChaoyong He 		return 0;
43379c7601aSHeinrich Kuhn 	}
43479c7601aSHeinrich Kuhn 
43579c7601aSHeinrich Kuhn 	hw = rxq->hw;
436636e133eSPeng Zhang 	pf_dev = rxq->hw_priv->pf_dev;
43779c7601aSHeinrich Kuhn 
438766d51c9SChaoyong He 	while (avail + avail_multiplexed < nb_pkts) {
43979c7601aSHeinrich Kuhn 		rxb = &rxq->rxbufs[rxq->rd_p];
44079c7601aSHeinrich Kuhn 		if (unlikely(rxb == NULL)) {
441f6272c7aSZerun Fu 			PMD_RX_LOG(ERR, "The rxb does not exist!");
44279c7601aSHeinrich Kuhn 			break;
44379c7601aSHeinrich Kuhn 		}
44479c7601aSHeinrich Kuhn 
44579c7601aSHeinrich Kuhn 		rxds = &rxq->rxds[rxq->rd_p];
44679c7601aSHeinrich Kuhn 		if ((rxds->rxd.meta_len_dd & PCIE_DESC_RX_DD) == 0)
44779c7601aSHeinrich Kuhn 			break;
44879c7601aSHeinrich Kuhn 
44979c7601aSHeinrich Kuhn 		/*
45079c7601aSHeinrich Kuhn 		 * Memory barrier to ensure that we won't do other
45179c7601aSHeinrich Kuhn 		 * reads before the DD bit.
45279c7601aSHeinrich Kuhn 		 */
45379c7601aSHeinrich Kuhn 		rte_rmb();
45479c7601aSHeinrich Kuhn 
45579c7601aSHeinrich Kuhn 		/*
45679c7601aSHeinrich Kuhn 		 * We got a packet. Let's alloc a new mbuf for refilling the
45740688372SChaoyong He 		 * free descriptor ring as soon as possible.
45879c7601aSHeinrich Kuhn 		 */
45979c7601aSHeinrich Kuhn 		new_mb = rte_pktmbuf_alloc(rxq->mem_pool);
46079c7601aSHeinrich Kuhn 		if (unlikely(new_mb == NULL)) {
461b6de4353SZerun Fu 			PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u queue_id=%hu.",
462f061491dSChaoyong He 					rxq->port_id, rxq->qidx);
46379c7601aSHeinrich Kuhn 			nfp_net_mbuf_alloc_failed(rxq);
46479c7601aSHeinrich Kuhn 			break;
46579c7601aSHeinrich Kuhn 		}
46679c7601aSHeinrich Kuhn 
46779c7601aSHeinrich Kuhn 		/*
46879c7601aSHeinrich Kuhn 		 * Grab the mbuf and refill the descriptor with the
46940688372SChaoyong He 		 * previously allocated mbuf.
47079c7601aSHeinrich Kuhn 		 */
47179c7601aSHeinrich Kuhn 		mb = rxb->mbuf;
47279c7601aSHeinrich Kuhn 		rxb->mbuf = new_mb;
47379c7601aSHeinrich Kuhn 
474b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "Packet len: %u, mbuf_size: %u.",
47579c7601aSHeinrich Kuhn 				rxds->rxd.data_len, rxq->mbuf_size);
47679c7601aSHeinrich Kuhn 
47779c7601aSHeinrich Kuhn 		/* Size of this segment */
47879c7601aSHeinrich Kuhn 		mb->data_len = rxds->rxd.data_len - NFP_DESC_META_LEN(rxds);
47979c7601aSHeinrich Kuhn 		/* Size of the whole packet. We just support 1 segment */
48079c7601aSHeinrich Kuhn 		mb->pkt_len = rxds->rxd.data_len - NFP_DESC_META_LEN(rxds);
48179c7601aSHeinrich Kuhn 
482f4d24fe9SChaoyong He 		if (unlikely((mb->data_len + hw->rx_offset) > rxq->mbuf_size)) {
48379c7601aSHeinrich Kuhn 			/*
48479c7601aSHeinrich Kuhn 			 * This should not happen and the user has the
48579c7601aSHeinrich Kuhn 			 * responsibility of avoiding it. But we have
48640688372SChaoyong He 			 * to give some info about the error.
48779c7601aSHeinrich Kuhn 			 */
488f6272c7aSZerun Fu 			PMD_RX_LOG(ERR, "The mbuf overflow likely due to the RX offset.");
489bb340f56SLong Wu 			rte_pktmbuf_free(mb);
490bb340f56SLong Wu 			break;
49179c7601aSHeinrich Kuhn 		}
49279c7601aSHeinrich Kuhn 
49379c7601aSHeinrich Kuhn 		/* Filling the received mbuf with packet info */
494c01e5c0cSChaoyong He 		if (hw->rx_offset != 0)
49579c7601aSHeinrich Kuhn 			mb->data_off = RTE_PKTMBUF_HEADROOM + hw->rx_offset;
49679c7601aSHeinrich Kuhn 		else
497f4d24fe9SChaoyong He 			mb->data_off = RTE_PKTMBUF_HEADROOM + NFP_DESC_META_LEN(rxds);
49879c7601aSHeinrich Kuhn 
49979c7601aSHeinrich Kuhn 		/* No scatter mode supported */
50079c7601aSHeinrich Kuhn 		mb->nb_segs = 1;
50179c7601aSHeinrich Kuhn 		mb->next = NULL;
50279c7601aSHeinrich Kuhn 		mb->port = rxq->port_id;
50379c7601aSHeinrich Kuhn 
5045eed6ad5SLong Wu 		struct nfp_net_meta_parsed meta;
5050e131d77SLong Wu 		nfp_net_meta_parse(rxds, rxq, hw, mb, &meta);
50679c7601aSHeinrich Kuhn 
507495846c1SChaoyong He 		nfp_net_parse_ptype(rxq, rxds, mb);
5082e7c3612SQin Ke 
50979c7601aSHeinrich Kuhn 		/* Checking the checksum flag */
51079c7601aSHeinrich Kuhn 		nfp_net_rx_cksum(rxq, rxds, mb);
51179c7601aSHeinrich Kuhn 
51279c7601aSHeinrich Kuhn 		/* Now resetting and updating the descriptor */
51379c7601aSHeinrich Kuhn 		rxds->vals[0] = 0;
51479c7601aSHeinrich Kuhn 		rxds->vals[1] = 0;
51576eaeadaSChaoyong He 		dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(new_mb));
51679c7601aSHeinrich Kuhn 		rxds->fld.dd = 0;
517fd392f84SPeng Zhang 		rxds->fld.dma_addr_hi = (dma_addr >> 32) & 0xffff;
51879c7601aSHeinrich Kuhn 		rxds->fld.dma_addr_lo = dma_addr & 0xffffffff;
5190c48f5adSChaoyong He 		nb_hold++;
52079c7601aSHeinrich Kuhn 
52179c7601aSHeinrich Kuhn 		rxq->rd_p++;
52240688372SChaoyong He 		if (unlikely(rxq->rd_p == rxq->rx_count)) /* Wrapping */
52379c7601aSHeinrich Kuhn 			rxq->rd_p = 0;
524580ea0b0SLong Wu 
525636e133eSPeng Zhang 		if (pf_dev->recv_pkt_meta_check_t(&meta)) {
526580ea0b0SLong Wu 			rx_pkts[avail++] = mb;
527636e133eSPeng Zhang 		} else {
528636e133eSPeng Zhang 			if (nfp_flower_pf_dispatch_pkts(rxq, mb, meta.port_id)) {
529580ea0b0SLong Wu 				avail_multiplexed++;
530580ea0b0SLong Wu 			} else {
531580ea0b0SLong Wu 				rte_pktmbuf_free(mb);
532580ea0b0SLong Wu 				break;
533580ea0b0SLong Wu 			}
53479c7601aSHeinrich Kuhn 		}
535636e133eSPeng Zhang 	}
53679c7601aSHeinrich Kuhn 
53779c7601aSHeinrich Kuhn 	if (nb_hold == 0)
53879c7601aSHeinrich Kuhn 		return nb_hold;
53979c7601aSHeinrich Kuhn 
540b6de4353SZerun Fu 	PMD_RX_LOG(DEBUG, "RX  port_id=%hu queue_id=%hu, %hu packets received.",
541f061491dSChaoyong He 			rxq->port_id, rxq->qidx, avail);
54279c7601aSHeinrich Kuhn 
54379c7601aSHeinrich Kuhn 	nb_hold += rxq->nb_rx_hold;
54479c7601aSHeinrich Kuhn 
54579c7601aSHeinrich Kuhn 	/*
54679c7601aSHeinrich Kuhn 	 * FL descriptors needs to be written before incrementing the
54740688372SChaoyong He 	 * FL queue WR pointer.
54879c7601aSHeinrich Kuhn 	 */
54979c7601aSHeinrich Kuhn 	rte_wmb();
55079c7601aSHeinrich Kuhn 	if (nb_hold > rxq->rx_free_thresh) {
551b6de4353SZerun Fu 		PMD_RX_LOG(DEBUG, "The port=%hu queue=%hu nb_hold=%hu avail=%hu.",
552f061491dSChaoyong He 				rxq->port_id, rxq->qidx, nb_hold, avail);
55379c7601aSHeinrich Kuhn 		nfp_qcp_ptr_add(rxq->qcp_fl, NFP_QCP_WRITE_PTR, nb_hold);
55479c7601aSHeinrich Kuhn 		nb_hold = 0;
55579c7601aSHeinrich Kuhn 	}
55679c7601aSHeinrich Kuhn 	rxq->nb_rx_hold = nb_hold;
55779c7601aSHeinrich Kuhn 
55879c7601aSHeinrich Kuhn 	return avail;
55979c7601aSHeinrich Kuhn }
56079c7601aSHeinrich Kuhn 
56179c7601aSHeinrich Kuhn static void
56279c7601aSHeinrich Kuhn nfp_net_rx_queue_release_mbufs(struct nfp_net_rxq *rxq)
56379c7601aSHeinrich Kuhn {
5648ceb85c3SChaoyong He 	uint16_t i;
56579c7601aSHeinrich Kuhn 
56679c7601aSHeinrich Kuhn 	if (rxq->rxbufs == NULL)
56779c7601aSHeinrich Kuhn 		return;
56879c7601aSHeinrich Kuhn 
56979c7601aSHeinrich Kuhn 	for (i = 0; i < rxq->rx_count; i++) {
570c01e5c0cSChaoyong He 		if (rxq->rxbufs[i].mbuf != NULL) {
57179c7601aSHeinrich Kuhn 			rte_pktmbuf_free_seg(rxq->rxbufs[i].mbuf);
57279c7601aSHeinrich Kuhn 			rxq->rxbufs[i].mbuf = NULL;
57379c7601aSHeinrich Kuhn 		}
57479c7601aSHeinrich Kuhn 	}
57579c7601aSHeinrich Kuhn }
57679c7601aSHeinrich Kuhn 
57779c7601aSHeinrich Kuhn void
578f4d24fe9SChaoyong He nfp_net_rx_queue_release(struct rte_eth_dev *dev,
579f4d24fe9SChaoyong He 		uint16_t queue_idx)
58079c7601aSHeinrich Kuhn {
5817483341aSXueming Li 	struct nfp_net_rxq *rxq = dev->data->rx_queues[queue_idx];
58279c7601aSHeinrich Kuhn 
583c01e5c0cSChaoyong He 	if (rxq != NULL) {
58479c7601aSHeinrich Kuhn 		nfp_net_rx_queue_release_mbufs(rxq);
58515174c40SHeinrich Kuhn 		rte_eth_dma_zone_free(dev, "rx_ring", queue_idx);
58679c7601aSHeinrich Kuhn 		rte_free(rxq->rxbufs);
58779c7601aSHeinrich Kuhn 		rte_free(rxq);
58879c7601aSHeinrich Kuhn 	}
58979c7601aSHeinrich Kuhn }
59079c7601aSHeinrich Kuhn 
59179c7601aSHeinrich Kuhn void
59279c7601aSHeinrich Kuhn nfp_net_reset_rx_queue(struct nfp_net_rxq *rxq)
59379c7601aSHeinrich Kuhn {
59479c7601aSHeinrich Kuhn 	nfp_net_rx_queue_release_mbufs(rxq);
59579c7601aSHeinrich Kuhn 	rxq->rd_p = 0;
59679c7601aSHeinrich Kuhn 	rxq->nb_rx_hold = 0;
59779c7601aSHeinrich Kuhn }
59879c7601aSHeinrich Kuhn 
599b5fae3a5SLong Wu static void
600b5fae3a5SLong Wu nfp_rx_queue_setup_flbufsz(struct nfp_net_hw *hw,
601b5fae3a5SLong Wu 		struct nfp_net_rxq *rxq)
602b5fae3a5SLong Wu {
603b5fae3a5SLong Wu 	if (!hw->flbufsz_set_flag) {
604b5fae3a5SLong Wu 		hw->flbufsz_set_flag = true;
605b5fae3a5SLong Wu 		hw->flbufsz = rxq->mbuf_size;
606b5fae3a5SLong Wu 		return;
607b5fae3a5SLong Wu 	}
608b5fae3a5SLong Wu 
609b5fae3a5SLong Wu 	if (hw->flbufsz < rxq->mbuf_size)
610b5fae3a5SLong Wu 		hw->flbufsz = rxq->mbuf_size;
611b5fae3a5SLong Wu }
612b5fae3a5SLong Wu 
61379c7601aSHeinrich Kuhn int
61479c7601aSHeinrich Kuhn nfp_net_rx_queue_setup(struct rte_eth_dev *dev,
615f4d24fe9SChaoyong He 		uint16_t queue_idx,
616f4d24fe9SChaoyong He 		uint16_t nb_desc,
61779c7601aSHeinrich Kuhn 		unsigned int socket_id,
61879c7601aSHeinrich Kuhn 		const struct rte_eth_rxconf *rx_conf,
61979c7601aSHeinrich Kuhn 		struct rte_mempool *mp)
62079c7601aSHeinrich Kuhn {
62149952141SChaoyong He 	uint32_t rx_desc_sz;
622670049f6SJin Liu 	uint16_t min_rx_desc;
623670049f6SJin Liu 	uint16_t max_rx_desc;
62479c7601aSHeinrich Kuhn 	struct nfp_net_hw *hw;
62549952141SChaoyong He 	struct nfp_net_rxq *rxq;
62649952141SChaoyong He 	const struct rte_memzone *tz;
627d81e2b51SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
62879c7601aSHeinrich Kuhn 
629c4de52ecSChaoyong He 	hw = nfp_net_get_hw(dev);
630d81e2b51SChaoyong He 	hw_priv = dev->process_private;
63179c7601aSHeinrich Kuhn 
632d81e2b51SChaoyong He 	nfp_net_rx_desc_limits(hw_priv, &min_rx_desc, &max_rx_desc);
633670049f6SJin Liu 
63479c7601aSHeinrich Kuhn 	/* Validating number of descriptors */
63579c7601aSHeinrich Kuhn 	rx_desc_sz = nb_desc * sizeof(struct nfp_net_rx_desc);
63679c7601aSHeinrich Kuhn 	if (rx_desc_sz % NFP_ALIGN_RING_DESC != 0 ||
637670049f6SJin Liu 			nb_desc > max_rx_desc || nb_desc < min_rx_desc) {
638b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Wrong nb_desc value.");
63979c7601aSHeinrich Kuhn 		return -EINVAL;
64079c7601aSHeinrich Kuhn 	}
64179c7601aSHeinrich Kuhn 
64279c7601aSHeinrich Kuhn 	/*
64379c7601aSHeinrich Kuhn 	 * Free memory prior to re-allocation if needed. This is the case after
64440688372SChaoyong He 	 * calling @nfp_net_stop().
64579c7601aSHeinrich Kuhn 	 */
646c01e5c0cSChaoyong He 	if (dev->data->rx_queues[queue_idx] != NULL) {
6477483341aSXueming Li 		nfp_net_rx_queue_release(dev, queue_idx);
64879c7601aSHeinrich Kuhn 		dev->data->rx_queues[queue_idx] = NULL;
64979c7601aSHeinrich Kuhn 	}
65079c7601aSHeinrich Kuhn 
65179c7601aSHeinrich Kuhn 	/* Allocating rx queue data structure */
65279c7601aSHeinrich Kuhn 	rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct nfp_net_rxq),
65379c7601aSHeinrich Kuhn 			RTE_CACHE_LINE_SIZE, socket_id);
65479c7601aSHeinrich Kuhn 	if (rxq == NULL)
65579c7601aSHeinrich Kuhn 		return -ENOMEM;
65679c7601aSHeinrich Kuhn 
6577483341aSXueming Li 	dev->data->rx_queues[queue_idx] = rxq;
6587483341aSXueming Li 
65979c7601aSHeinrich Kuhn 	/* Hw queues mapping based on firmware configuration */
66079c7601aSHeinrich Kuhn 	rxq->qidx = queue_idx;
66179c7601aSHeinrich Kuhn 	rxq->fl_qcidx = queue_idx * hw->stride_rx;
66279c7601aSHeinrich Kuhn 	rxq->qcp_fl = hw->rx_bar + NFP_QCP_QUEUE_OFF(rxq->fl_qcidx);
66379c7601aSHeinrich Kuhn 
66479c7601aSHeinrich Kuhn 	/*
66579c7601aSHeinrich Kuhn 	 * Tracking mbuf size for detecting a potential mbuf overflow due to
66640688372SChaoyong He 	 * RX offset.
66779c7601aSHeinrich Kuhn 	 */
66879c7601aSHeinrich Kuhn 	rxq->mem_pool = mp;
66979c7601aSHeinrich Kuhn 	rxq->mbuf_size = rxq->mem_pool->elt_size;
67079c7601aSHeinrich Kuhn 	rxq->mbuf_size -= (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
671b5fae3a5SLong Wu 	nfp_rx_queue_setup_flbufsz(hw, rxq);
67279c7601aSHeinrich Kuhn 
67379c7601aSHeinrich Kuhn 	rxq->rx_count = nb_desc;
67479c7601aSHeinrich Kuhn 	rxq->port_id = dev->data->port_id;
67579c7601aSHeinrich Kuhn 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
67679c7601aSHeinrich Kuhn 
67779c7601aSHeinrich Kuhn 	/*
67879c7601aSHeinrich Kuhn 	 * Allocate RX ring hardware descriptors. A memzone large enough to
67979c7601aSHeinrich Kuhn 	 * handle the maximum ring size is allocated in order to allow for
68079c7601aSHeinrich Kuhn 	 * resizing in later calls to the queue setup function.
68179c7601aSHeinrich Kuhn 	 */
68279c7601aSHeinrich Kuhn 	tz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx,
683f4d24fe9SChaoyong He 			sizeof(struct nfp_net_rx_desc) * max_rx_desc,
684f4d24fe9SChaoyong He 			NFP_MEMZONE_ALIGN, socket_id);
68579c7601aSHeinrich Kuhn 	if (tz == NULL) {
686b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Error allocating rx dma.");
6877483341aSXueming Li 		nfp_net_rx_queue_release(dev, queue_idx);
6887483341aSXueming Li 		dev->data->rx_queues[queue_idx] = NULL;
68979c7601aSHeinrich Kuhn 		return -ENOMEM;
69079c7601aSHeinrich Kuhn 	}
69179c7601aSHeinrich Kuhn 
69279c7601aSHeinrich Kuhn 	/* Saving physical and virtual addresses for the RX ring */
69379c7601aSHeinrich Kuhn 	rxq->dma = (uint64_t)tz->iova;
694dddf701fSChaoyong He 	rxq->rxds = tz->addr;
69579c7601aSHeinrich Kuhn 
69640688372SChaoyong He 	/* Mbuf pointers array for referencing mbufs linked to RX descriptors */
69779c7601aSHeinrich Kuhn 	rxq->rxbufs = rte_zmalloc_socket("rxq->rxbufs",
698f4d24fe9SChaoyong He 			sizeof(*rxq->rxbufs) * nb_desc, RTE_CACHE_LINE_SIZE,
699f4d24fe9SChaoyong He 			socket_id);
70079c7601aSHeinrich Kuhn 	if (rxq->rxbufs == NULL) {
7017483341aSXueming Li 		nfp_net_rx_queue_release(dev, queue_idx);
7027483341aSXueming Li 		dev->data->rx_queues[queue_idx] = NULL;
70379c7601aSHeinrich Kuhn 		return -ENOMEM;
70479c7601aSHeinrich Kuhn 	}
70579c7601aSHeinrich Kuhn 
70679c7601aSHeinrich Kuhn 	nfp_net_reset_rx_queue(rxq);
70779c7601aSHeinrich Kuhn 
70879c7601aSHeinrich Kuhn 	rxq->hw = hw;
709ff9f5a56SChaoyong He 	rxq->hw_priv = dev->process_private;
71079c7601aSHeinrich Kuhn 
71179c7601aSHeinrich Kuhn 	/*
71279c7601aSHeinrich Kuhn 	 * Telling the HW about the physical address of the RX ring and number
71340688372SChaoyong He 	 * of descriptors in log2 format.
71479c7601aSHeinrich Kuhn 	 */
715f58bde00SChaoyong He 	nn_cfg_writeq(&hw->super, NFP_NET_CFG_RXR_ADDR(queue_idx), rxq->dma);
716f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_SZ(queue_idx), rte_log2_u32(nb_desc));
71779c7601aSHeinrich Kuhn 
71879c7601aSHeinrich Kuhn 	return 0;
71979c7601aSHeinrich Kuhn }
72079c7601aSHeinrich Kuhn 
721ff9da649SLong Wu static inline uint32_t
722ff9da649SLong Wu nfp_net_read_tx_free_qcp(struct nfp_net_txq *txq)
723ff9da649SLong Wu {
724ff9da649SLong Wu 	/*
725ff9da649SLong Wu 	 * If TX ring pointer write back is not supported, do a PCIe read.
726ff9da649SLong Wu 	 * Otherwise read qcp value from write back dma address.
727ff9da649SLong Wu 	 */
728ff9da649SLong Wu 	if (txq->txrwb == NULL)
729ff9da649SLong Wu 		return nfp_qcp_read(txq->qcp_q, NFP_QCP_READ_PTR);
730ff9da649SLong Wu 
731ff9da649SLong Wu 	/*
732ff9da649SLong Wu 	 * In most cases the TX count is a power of two and the costly modulus
733ff9da649SLong Wu 	 * operation can be substituted with a subtraction and an AND operation.
734ff9da649SLong Wu 	 */
735ff9da649SLong Wu 	if (rte_is_power_of_2(txq->tx_count) == 1)
736ff9da649SLong Wu 		return (*txq->txrwb) & (txq->tx_count - 1);
737ff9da649SLong Wu 	else
738ff9da649SLong Wu 		return (*txq->txrwb) % txq->tx_count;
739ff9da649SLong Wu }
740ff9da649SLong Wu 
74140688372SChaoyong He /**
74240688372SChaoyong He  * Check for descriptors with a complete status
74340688372SChaoyong He  *
74440688372SChaoyong He  * @param txq
74540688372SChaoyong He  *   TX queue to work with
74640688372SChaoyong He  *
74740688372SChaoyong He  * @return
74840688372SChaoyong He  *   Number of descriptors freed
74979c7601aSHeinrich Kuhn  */
7508ceb85c3SChaoyong He uint32_t
75179c7601aSHeinrich Kuhn nfp_net_tx_free_bufs(struct nfp_net_txq *txq)
75279c7601aSHeinrich Kuhn {
7538ceb85c3SChaoyong He 	uint32_t todo;
75449952141SChaoyong He 	uint32_t qcp_rd_p;
75579c7601aSHeinrich Kuhn 
756f6272c7aSZerun Fu 	PMD_TX_LOG(DEBUG, "Queue %hu. Check for descriptor with a complete"
757b6de4353SZerun Fu 			" status.", txq->qidx);
75879c7601aSHeinrich Kuhn 
75979c7601aSHeinrich Kuhn 	/* Work out how many packets have been sent */
760ff9da649SLong Wu 	qcp_rd_p = nfp_net_read_tx_free_qcp(txq);
76179c7601aSHeinrich Kuhn 
76279c7601aSHeinrich Kuhn 	if (qcp_rd_p == txq->rd_p) {
763f6272c7aSZerun Fu 		PMD_TX_LOG(DEBUG, "Queue %hu: It seems harrier is not sending "
764b6de4353SZerun Fu 				"packets (%u, %u).", txq->qidx,
76579c7601aSHeinrich Kuhn 				qcp_rd_p, txq->rd_p);
76679c7601aSHeinrich Kuhn 		return 0;
76779c7601aSHeinrich Kuhn 	}
76879c7601aSHeinrich Kuhn 
76979c7601aSHeinrich Kuhn 	if (qcp_rd_p > txq->rd_p)
77079c7601aSHeinrich Kuhn 		todo = qcp_rd_p - txq->rd_p;
77179c7601aSHeinrich Kuhn 	else
77279c7601aSHeinrich Kuhn 		todo = qcp_rd_p + txq->tx_count - txq->rd_p;
77379c7601aSHeinrich Kuhn 
774b6de4353SZerun Fu 	PMD_TX_LOG(DEBUG, "The qcp_rd_p %u, txq->rd_p: %u, qcp->rd_p: %u.",
77579c7601aSHeinrich Kuhn 			qcp_rd_p, txq->rd_p, txq->rd_p);
77679c7601aSHeinrich Kuhn 
77779c7601aSHeinrich Kuhn 	if (todo == 0)
77879c7601aSHeinrich Kuhn 		return todo;
77979c7601aSHeinrich Kuhn 
78079c7601aSHeinrich Kuhn 	txq->rd_p += todo;
78179c7601aSHeinrich Kuhn 	if (unlikely(txq->rd_p >= txq->tx_count))
78279c7601aSHeinrich Kuhn 		txq->rd_p -= txq->tx_count;
78379c7601aSHeinrich Kuhn 
78479c7601aSHeinrich Kuhn 	return todo;
78579c7601aSHeinrich Kuhn }
78679c7601aSHeinrich Kuhn 
78779c7601aSHeinrich Kuhn static void
78879c7601aSHeinrich Kuhn nfp_net_tx_queue_release_mbufs(struct nfp_net_txq *txq)
78979c7601aSHeinrich Kuhn {
7908ceb85c3SChaoyong He 	uint32_t i;
79179c7601aSHeinrich Kuhn 
79279c7601aSHeinrich Kuhn 	if (txq->txbufs == NULL)
79379c7601aSHeinrich Kuhn 		return;
79479c7601aSHeinrich Kuhn 
79579c7601aSHeinrich Kuhn 	for (i = 0; i < txq->tx_count; i++) {
796c01e5c0cSChaoyong He 		if (txq->txbufs[i].mbuf != NULL) {
79779c7601aSHeinrich Kuhn 			rte_pktmbuf_free_seg(txq->txbufs[i].mbuf);
79879c7601aSHeinrich Kuhn 			txq->txbufs[i].mbuf = NULL;
79979c7601aSHeinrich Kuhn 		}
80079c7601aSHeinrich Kuhn 	}
80179c7601aSHeinrich Kuhn }
80279c7601aSHeinrich Kuhn 
80379c7601aSHeinrich Kuhn void
804f4d24fe9SChaoyong He nfp_net_tx_queue_release(struct rte_eth_dev *dev,
805f4d24fe9SChaoyong He 		uint16_t queue_idx)
80679c7601aSHeinrich Kuhn {
807ff9da649SLong Wu 	struct nfp_net_hw *net_hw;
8087483341aSXueming Li 	struct nfp_net_txq *txq = dev->data->tx_queues[queue_idx];
80979c7601aSHeinrich Kuhn 
810c01e5c0cSChaoyong He 	if (txq != NULL) {
811ff9da649SLong Wu 		net_hw = nfp_net_get_hw(dev);
812ff9da649SLong Wu 		if (net_hw->txrwb_mz != NULL)
813ff9da649SLong Wu 			nn_cfg_writeq(&net_hw->super, NFP_NET_CFG_TXR_WB_ADDR(queue_idx), 0);
81479c7601aSHeinrich Kuhn 		nfp_net_tx_queue_release_mbufs(txq);
81515174c40SHeinrich Kuhn 		rte_eth_dma_zone_free(dev, "tx_ring", queue_idx);
81679c7601aSHeinrich Kuhn 		rte_free(txq->txbufs);
81779c7601aSHeinrich Kuhn 		rte_free(txq);
81879c7601aSHeinrich Kuhn 	}
81979c7601aSHeinrich Kuhn }
82079c7601aSHeinrich Kuhn 
82179c7601aSHeinrich Kuhn void
82279c7601aSHeinrich Kuhn nfp_net_reset_tx_queue(struct nfp_net_txq *txq)
82379c7601aSHeinrich Kuhn {
82479c7601aSHeinrich Kuhn 	nfp_net_tx_queue_release_mbufs(txq);
82579c7601aSHeinrich Kuhn 	txq->wr_p = 0;
82679c7601aSHeinrich Kuhn 	txq->rd_p = 0;
827ff9da649SLong Wu 	if (txq->txrwb != NULL)
828ff9da649SLong Wu 		*txq->txrwb = 0;
82979c7601aSHeinrich Kuhn }
83079c7601aSHeinrich Kuhn 
8318d961320SJin Liu int
8328d961320SJin Liu nfp_net_tx_queue_setup(struct rte_eth_dev *dev,
8338d961320SJin Liu 		uint16_t queue_idx,
8348d961320SJin Liu 		uint16_t nb_desc,
8358d961320SJin Liu 		unsigned int socket_id,
8368d961320SJin Liu 		const struct rte_eth_txconf *tx_conf)
8378d961320SJin Liu {
838000feb4cSChaoyong He 	struct nfp_net_hw_priv *hw_priv;
8398d961320SJin Liu 
840000feb4cSChaoyong He 	hw_priv = dev->process_private;
8418d961320SJin Liu 
842000feb4cSChaoyong He 	if (hw_priv->pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
8438d961320SJin Liu 		return nfp_net_nfd3_tx_queue_setup(dev, queue_idx,
8448d961320SJin Liu 				nb_desc, socket_id, tx_conf);
845ee8ca64eSChaoyong He 	else
8468d961320SJin Liu 		return nfp_net_nfdk_tx_queue_setup(dev, queue_idx,
8478d961320SJin Liu 				nb_desc, socket_id, tx_conf);
8488d961320SJin Liu }
84930198b3fSLong Wu 
85030198b3fSLong Wu void
85130198b3fSLong Wu nfp_net_rx_queue_info_get(struct rte_eth_dev *dev,
85230198b3fSLong Wu 		uint16_t queue_id,
85330198b3fSLong Wu 		struct rte_eth_rxq_info *info)
85430198b3fSLong Wu {
85530198b3fSLong Wu 	struct rte_eth_dev_info dev_info;
85630198b3fSLong Wu 	struct nfp_net_rxq *rxq = dev->data->rx_queues[queue_id];
85730198b3fSLong Wu 
85830198b3fSLong Wu 	info->mp = rxq->mem_pool;
85930198b3fSLong Wu 	info->nb_desc = rxq->rx_count;
86030198b3fSLong Wu 
86130198b3fSLong Wu 	info->conf.rx_free_thresh = rxq->rx_free_thresh;
86230198b3fSLong Wu 
86330198b3fSLong Wu 	nfp_net_infos_get(dev, &dev_info);
86430198b3fSLong Wu 	info->conf.offloads = dev_info.rx_offload_capa &
86530198b3fSLong Wu 			dev->data->dev_conf.rxmode.offloads;
866*4f0ece5eSChaoyong He 	info->conf.rx_thresh = dev_info.default_rxconf.rx_thresh;
86730198b3fSLong Wu }
868fbe2e2ecSLong Wu 
869fbe2e2ecSLong Wu void
870fbe2e2ecSLong Wu nfp_net_tx_queue_info_get(struct rte_eth_dev *dev,
871fbe2e2ecSLong Wu 		uint16_t queue_id,
872fbe2e2ecSLong Wu 		struct rte_eth_txq_info *info)
873fbe2e2ecSLong Wu {
874fbe2e2ecSLong Wu 	struct rte_eth_dev_info dev_info;
875000feb4cSChaoyong He 	struct nfp_net_hw_priv *hw_priv = dev->process_private;
876fbe2e2ecSLong Wu 	struct nfp_net_txq *txq = dev->data->tx_queues[queue_id];
877fbe2e2ecSLong Wu 
878000feb4cSChaoyong He 	if (hw_priv->pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
879fbe2e2ecSLong Wu 		info->nb_desc = txq->tx_count / NFD3_TX_DESC_PER_PKT;
880fbe2e2ecSLong Wu 	else
881fbe2e2ecSLong Wu 		info->nb_desc = txq->tx_count / NFDK_TX_DESC_PER_SIMPLE_PKT;
882fbe2e2ecSLong Wu 
883fbe2e2ecSLong Wu 	info->conf.tx_free_thresh = txq->tx_free_thresh;
884fbe2e2ecSLong Wu 
885fbe2e2ecSLong Wu 	nfp_net_infos_get(dev, &dev_info);
886fbe2e2ecSLong Wu 	info->conf.offloads = dev_info.tx_offload_capa &
887fbe2e2ecSLong Wu 			dev->data->dev_conf.txmode.offloads;
888*4f0ece5eSChaoyong He 	info->conf.tx_thresh = dev_info.default_txconf.tx_thresh;
889fbe2e2ecSLong Wu }
890b6755530SLong Wu 
891b6755530SLong Wu void
892b6755530SLong Wu nfp_net_recv_pkts_set(struct rte_eth_dev *eth_dev)
893b6755530SLong Wu {
894b6755530SLong Wu 	if (nfp_net_get_avx2_supported())
895b6755530SLong Wu 		eth_dev->rx_pkt_burst = nfp_net_vec_avx2_recv_pkts;
896b6755530SLong Wu 	else
897b6755530SLong Wu 		eth_dev->rx_pkt_burst = nfp_net_recv_pkts;
898b6755530SLong Wu }
8994dcbf32fSChaoyong He 
9004dcbf32fSChaoyong He int
9014dcbf32fSChaoyong He nfp_net_rx_burst_mode_get(struct rte_eth_dev *eth_dev,
9024dcbf32fSChaoyong He 		uint16_t queue_id __rte_unused,
9034dcbf32fSChaoyong He 		struct rte_eth_burst_mode *mode)
9044dcbf32fSChaoyong He {
9054dcbf32fSChaoyong He 	eth_rx_burst_t pkt_burst;
9064dcbf32fSChaoyong He 
9074dcbf32fSChaoyong He 	pkt_burst = eth_dev->rx_pkt_burst;
9084dcbf32fSChaoyong He 	if (pkt_burst == nfp_net_recv_pkts) {
9094dcbf32fSChaoyong He 		strlcpy(mode->info, "Scalar",
9104dcbf32fSChaoyong He 				RTE_ETH_BURST_MODE_INFO_SIZE);
9114dcbf32fSChaoyong He 	} else if (pkt_burst == nfp_net_vec_avx2_recv_pkts) {
9124dcbf32fSChaoyong He 		strlcpy(mode->info, "Vector AVX2",
9134dcbf32fSChaoyong He 				RTE_ETH_BURST_MODE_INFO_SIZE);
9144dcbf32fSChaoyong He 	} else {
9154dcbf32fSChaoyong He 		return -EINVAL;
9164dcbf32fSChaoyong He 	}
9174dcbf32fSChaoyong He 
9184dcbf32fSChaoyong He 	return 0;
9194dcbf32fSChaoyong He }
9204dcbf32fSChaoyong He 
9214dcbf32fSChaoyong He int
9224dcbf32fSChaoyong He nfp_net_tx_burst_mode_get(struct rte_eth_dev *eth_dev,
9234dcbf32fSChaoyong He 		uint16_t queue_id __rte_unused,
9244dcbf32fSChaoyong He 		struct rte_eth_burst_mode *mode)
9254dcbf32fSChaoyong He {
9264dcbf32fSChaoyong He 	eth_tx_burst_t pkt_burst;
9274dcbf32fSChaoyong He 
9284dcbf32fSChaoyong He 	pkt_burst = eth_dev->tx_pkt_burst;
9294dcbf32fSChaoyong He 	if (pkt_burst == nfp_net_nfd3_xmit_pkts) {
9304dcbf32fSChaoyong He 		strlcpy(mode->info, "NFD3 Scalar",
9314dcbf32fSChaoyong He 				RTE_ETH_BURST_MODE_INFO_SIZE);
9324dcbf32fSChaoyong He 	} else if (pkt_burst == nfp_net_nfdk_xmit_pkts) {
9334dcbf32fSChaoyong He 		strlcpy(mode->info, "NFDk Scalar",
9344dcbf32fSChaoyong He 				RTE_ETH_BURST_MODE_INFO_SIZE);
9354dcbf32fSChaoyong He 	} else if (pkt_burst == nfp_net_nfdk_vec_avx2_xmit_pkts) {
9364dcbf32fSChaoyong He 		strlcpy(mode->info, "NFDk Vector AVX2",
9374dcbf32fSChaoyong He 				RTE_ETH_BURST_MODE_INFO_SIZE);
9384dcbf32fSChaoyong He 	} else {
9394dcbf32fSChaoyong He 		return -EINVAL;
9404dcbf32fSChaoyong He 	}
9414dcbf32fSChaoyong He 
9424dcbf32fSChaoyong He 	return 0;
9434dcbf32fSChaoyong He }
944