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