18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause 2f0d2114fSYongseok Koh * Copyright 2017 6WIND S.A. 35feecc57SShahaf Shuler * Copyright 2017 Mellanox Technologies, Ltd 4f0d2114fSYongseok Koh */ 5f0d2114fSYongseok Koh 6f0d2114fSYongseok Koh #include <assert.h> 7f0d2114fSYongseok Koh #include <stdint.h> 8f0d2114fSYongseok Koh #include <string.h> 9f0d2114fSYongseok Koh #include <stdlib.h> 10f0d2114fSYongseok Koh 11f0d2114fSYongseok Koh /* Verbs header. */ 12f0d2114fSYongseok Koh /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 13f0d2114fSYongseok Koh #ifdef PEDANTIC 14f0d2114fSYongseok Koh #pragma GCC diagnostic ignored "-Wpedantic" 15f0d2114fSYongseok Koh #endif 16f0d2114fSYongseok Koh #include <infiniband/verbs.h> 17f0d2114fSYongseok Koh #include <infiniband/mlx5dv.h> 18f0d2114fSYongseok Koh #ifdef PEDANTIC 19f0d2114fSYongseok Koh #pragma GCC diagnostic error "-Wpedantic" 20f0d2114fSYongseok Koh #endif 21f0d2114fSYongseok Koh 22f0d2114fSYongseok Koh #include <rte_mbuf.h> 23f0d2114fSYongseok Koh #include <rte_mempool.h> 24f0d2114fSYongseok Koh #include <rte_prefetch.h> 25f0d2114fSYongseok Koh 26f0d2114fSYongseok Koh #include "mlx5.h" 27f0d2114fSYongseok Koh #include "mlx5_utils.h" 28f0d2114fSYongseok Koh #include "mlx5_rxtx.h" 295bfc9fc1SYongseok Koh #include "mlx5_rxtx_vec.h" 30f0d2114fSYongseok Koh #include "mlx5_autoconf.h" 31f0d2114fSYongseok Koh #include "mlx5_defs.h" 32f0d2114fSYongseok Koh #include "mlx5_prm.h" 33f0d2114fSYongseok Koh 34570acdb1SYongseok Koh #if defined RTE_ARCH_X86_64 353c2ddbd4SYongseok Koh #include "mlx5_rxtx_vec_sse.h" 36570acdb1SYongseok Koh #elif defined RTE_ARCH_ARM64 37570acdb1SYongseok Koh #include "mlx5_rxtx_vec_neon.h" 38*2e542da7SDavid Christensen #elif defined RTE_ARCH_PPC_64 39*2e542da7SDavid Christensen #include "mlx5_rxtx_vec_altivec.h" 403c2ddbd4SYongseok Koh #else 413c2ddbd4SYongseok Koh #error "This should not be compiled if SIMD instructions are not supported." 42f0d2114fSYongseok Koh #endif 43f0d2114fSYongseok Koh 44f0d2114fSYongseok Koh /** 45f0d2114fSYongseok Koh * Skip error packets. 46f0d2114fSYongseok Koh * 47f0d2114fSYongseok Koh * @param rxq 48f0d2114fSYongseok Koh * Pointer to RX queue structure. 49f0d2114fSYongseok Koh * @param[out] pkts 50f0d2114fSYongseok Koh * Array to store received packets. 51f0d2114fSYongseok Koh * @param pkts_n 52f0d2114fSYongseok Koh * Maximum number of packets in array. 53f0d2114fSYongseok Koh * 54f0d2114fSYongseok Koh * @return 55f0d2114fSYongseok Koh * Number of packets successfully received (<= pkts_n). 56f0d2114fSYongseok Koh */ 57f0d2114fSYongseok Koh static uint16_t 58f0d2114fSYongseok Koh rxq_handle_pending_error(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, 59f0d2114fSYongseok Koh uint16_t pkts_n) 60f0d2114fSYongseok Koh { 61f0d2114fSYongseok Koh uint16_t n = 0; 62f0d2114fSYongseok Koh unsigned int i; 63f0d2114fSYongseok Koh #ifdef MLX5_PMD_SOFT_COUNTERS 64f0d2114fSYongseok Koh uint32_t err_bytes = 0; 65f0d2114fSYongseok Koh #endif 66f0d2114fSYongseok Koh 67f0d2114fSYongseok Koh for (i = 0; i < pkts_n; ++i) { 68f0d2114fSYongseok Koh struct rte_mbuf *pkt = pkts[i]; 69f0d2114fSYongseok Koh 7088c07335SMatan Azrad if (pkt->packet_type == RTE_PTYPE_ALL_MASK || rxq->err_state) { 71f0d2114fSYongseok Koh #ifdef MLX5_PMD_SOFT_COUNTERS 72f0d2114fSYongseok Koh err_bytes += PKT_LEN(pkt); 73f0d2114fSYongseok Koh #endif 74f0d2114fSYongseok Koh rte_pktmbuf_free_seg(pkt); 75f0d2114fSYongseok Koh } else { 76f0d2114fSYongseok Koh pkts[n++] = pkt; 77f0d2114fSYongseok Koh } 78f0d2114fSYongseok Koh } 79f0d2114fSYongseok Koh rxq->stats.idropped += (pkts_n - n); 80f0d2114fSYongseok Koh #ifdef MLX5_PMD_SOFT_COUNTERS 81f0d2114fSYongseok Koh /* Correct counters of errored completions. */ 82f0d2114fSYongseok Koh rxq->stats.ipackets -= (pkts_n - n); 83f0d2114fSYongseok Koh rxq->stats.ibytes -= err_bytes; 84f0d2114fSYongseok Koh #endif 8588c07335SMatan Azrad mlx5_rx_err_handle(rxq, 1); 86f0d2114fSYongseok Koh return n; 87f0d2114fSYongseok Koh } 88f0d2114fSYongseok Koh 89f0d2114fSYongseok Koh /** 90f0d2114fSYongseok Koh * DPDK callback for vectorized RX. 91f0d2114fSYongseok Koh * 92f0d2114fSYongseok Koh * @param dpdk_rxq 93f0d2114fSYongseok Koh * Generic pointer to RX queue structure. 94f0d2114fSYongseok Koh * @param[out] pkts 95f0d2114fSYongseok Koh * Array to store received packets. 96f0d2114fSYongseok Koh * @param pkts_n 97f0d2114fSYongseok Koh * Maximum number of packets in array. 98f0d2114fSYongseok Koh * 99f0d2114fSYongseok Koh * @return 100f0d2114fSYongseok Koh * Number of packets successfully received (<= pkts_n). 101f0d2114fSYongseok Koh */ 102f0d2114fSYongseok Koh uint16_t 103f0d2114fSYongseok Koh mlx5_rx_burst_vec(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 104f0d2114fSYongseok Koh { 105f0d2114fSYongseok Koh struct mlx5_rxq_data *rxq = dpdk_rxq; 106f0d2114fSYongseok Koh uint16_t nb_rx; 107d27fb0deSYongseok Koh uint64_t err = 0; 108f0d2114fSYongseok Koh 109d27fb0deSYongseok Koh nb_rx = rxq_burst_v(rxq, pkts, pkts_n, &err); 11088c07335SMatan Azrad if (unlikely(err | rxq->err_state)) 111f0d2114fSYongseok Koh nb_rx = rxq_handle_pending_error(rxq, pkts, nb_rx); 112f0d2114fSYongseok Koh return nb_rx; 113f0d2114fSYongseok Koh } 114f0d2114fSYongseok Koh 115f0d2114fSYongseok Koh /** 116f0d2114fSYongseok Koh * Check a RX queue can support vectorized RX. 117f0d2114fSYongseok Koh * 118f0d2114fSYongseok Koh * @param rxq 119f0d2114fSYongseok Koh * Pointer to RX queue. 120f0d2114fSYongseok Koh * 121f0d2114fSYongseok Koh * @return 122f0d2114fSYongseok Koh * 1 if supported, negative errno value if not. 123f0d2114fSYongseok Koh */ 124f0d2114fSYongseok Koh int __attribute__((cold)) 125af4f09f2SNélio Laranjeiro mlx5_rxq_check_vec_support(struct mlx5_rxq_data *rxq) 126f0d2114fSYongseok Koh { 127f0d2114fSYongseok Koh struct mlx5_rxq_ctrl *ctrl = 128f0d2114fSYongseok Koh container_of(rxq, struct mlx5_rxq_ctrl, rxq); 129f0d2114fSYongseok Koh 1307d6bf6b8SYongseok Koh if (mlx5_mprq_enabled(ETH_DEV(ctrl->priv))) 1317d6bf6b8SYongseok Koh return -ENOTSUP; 1327fe24446SShahaf Shuler if (!ctrl->priv->config.rx_vec_en || rxq->sges_n != 0) 133f0d2114fSYongseok Koh return -ENOTSUP; 13417ed314cSMatan Azrad if (rxq->lro) 13517ed314cSMatan Azrad return -ENOTSUP; 136f0d2114fSYongseok Koh return 1; 137f0d2114fSYongseok Koh } 138f0d2114fSYongseok Koh 139f0d2114fSYongseok Koh /** 140f0d2114fSYongseok Koh * Check a device can support vectorized RX. 141f0d2114fSYongseok Koh * 142af4f09f2SNélio Laranjeiro * @param dev 143af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 144f0d2114fSYongseok Koh * 145f0d2114fSYongseok Koh * @return 146f0d2114fSYongseok Koh * 1 if supported, negative errno value if not. 147f0d2114fSYongseok Koh */ 148f0d2114fSYongseok Koh int __attribute__((cold)) 149af4f09f2SNélio Laranjeiro mlx5_check_vec_rx_support(struct rte_eth_dev *dev) 150f0d2114fSYongseok Koh { 151dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 152f0d2114fSYongseok Koh uint16_t i; 153f0d2114fSYongseok Koh 1547fe24446SShahaf Shuler if (!priv->config.rx_vec_en) 155f0d2114fSYongseok Koh return -ENOTSUP; 1567d6bf6b8SYongseok Koh if (mlx5_mprq_enabled(dev)) 1577d6bf6b8SYongseok Koh return -ENOTSUP; 158f0d2114fSYongseok Koh /* All the configured queues should support. */ 159f0d2114fSYongseok Koh for (i = 0; i < priv->rxqs_n; ++i) { 160f0d2114fSYongseok Koh struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 161f0d2114fSYongseok Koh 162f0d2114fSYongseok Koh if (!rxq) 163f0d2114fSYongseok Koh continue; 164af4f09f2SNélio Laranjeiro if (mlx5_rxq_check_vec_support(rxq) < 0) 165f0d2114fSYongseok Koh break; 166f0d2114fSYongseok Koh } 167f0d2114fSYongseok Koh if (i != priv->rxqs_n) 168f0d2114fSYongseok Koh return -ENOTSUP; 169f0d2114fSYongseok Koh return 1; 170f0d2114fSYongseok Koh } 171