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 <stdint.h> 7f0d2114fSYongseok Koh #include <string.h> 8f0d2114fSYongseok Koh #include <stdlib.h> 9f0d2114fSYongseok Koh 10f0d2114fSYongseok Koh /* Verbs header. */ 11f0d2114fSYongseok Koh /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 12f0d2114fSYongseok Koh #ifdef PEDANTIC 13f0d2114fSYongseok Koh #pragma GCC diagnostic ignored "-Wpedantic" 14f0d2114fSYongseok Koh #endif 15f0d2114fSYongseok Koh #include <infiniband/verbs.h> 16f0d2114fSYongseok Koh #include <infiniband/mlx5dv.h> 17f0d2114fSYongseok Koh #ifdef PEDANTIC 18f0d2114fSYongseok Koh #pragma GCC diagnostic error "-Wpedantic" 19f0d2114fSYongseok Koh #endif 20f0d2114fSYongseok Koh 21f0d2114fSYongseok Koh #include <rte_mbuf.h> 22f0d2114fSYongseok Koh #include <rte_mempool.h> 23f0d2114fSYongseok Koh #include <rte_prefetch.h> 24f0d2114fSYongseok Koh 257b4f1e6bSMatan Azrad #include <mlx5_prm.h> 267b4f1e6bSMatan Azrad 277b4f1e6bSMatan Azrad #include "mlx5_defs.h" 28f0d2114fSYongseok Koh #include "mlx5.h" 29f0d2114fSYongseok Koh #include "mlx5_utils.h" 30f0d2114fSYongseok Koh #include "mlx5_rxtx.h" 315bfc9fc1SYongseok Koh #include "mlx5_rxtx_vec.h" 32f0d2114fSYongseok Koh #include "mlx5_autoconf.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" 382e542da7SDavid Christensen #elif defined RTE_ARCH_PPC_64 392e542da7SDavid 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; 106*c9cc554bSAlexander Kozyrev uint16_t nb_rx = 0; 107*c9cc554bSAlexander Kozyrev uint16_t tn = 0; 108d27fb0deSYongseok Koh uint64_t err = 0; 109*c9cc554bSAlexander Kozyrev bool no_cq = false; 110f0d2114fSYongseok Koh 111*c9cc554bSAlexander Kozyrev do { 112*c9cc554bSAlexander Kozyrev nb_rx = rxq_burst_v(rxq, pkts + tn, pkts_n - tn, &err, &no_cq); 11388c07335SMatan Azrad if (unlikely(err | rxq->err_state)) 114*c9cc554bSAlexander Kozyrev nb_rx = rxq_handle_pending_error(rxq, pkts + tn, nb_rx); 115*c9cc554bSAlexander Kozyrev tn += nb_rx; 116*c9cc554bSAlexander Kozyrev if (unlikely(no_cq)) 117*c9cc554bSAlexander Kozyrev break; 118*c9cc554bSAlexander Kozyrev } while (tn != pkts_n); 119*c9cc554bSAlexander Kozyrev return tn; 120f0d2114fSYongseok Koh } 121f0d2114fSYongseok Koh 122f0d2114fSYongseok Koh /** 123f0d2114fSYongseok Koh * Check a RX queue can support vectorized RX. 124f0d2114fSYongseok Koh * 125f0d2114fSYongseok Koh * @param rxq 126f0d2114fSYongseok Koh * Pointer to RX queue. 127f0d2114fSYongseok Koh * 128f0d2114fSYongseok Koh * @return 129f0d2114fSYongseok Koh * 1 if supported, negative errno value if not. 130f0d2114fSYongseok Koh */ 131ce6427ddSThomas Monjalon int __rte_cold 132af4f09f2SNélio Laranjeiro mlx5_rxq_check_vec_support(struct mlx5_rxq_data *rxq) 133f0d2114fSYongseok Koh { 134f0d2114fSYongseok Koh struct mlx5_rxq_ctrl *ctrl = 135f0d2114fSYongseok Koh container_of(rxq, struct mlx5_rxq_ctrl, rxq); 136f0d2114fSYongseok Koh 1377d6bf6b8SYongseok Koh if (mlx5_mprq_enabled(ETH_DEV(ctrl->priv))) 1387d6bf6b8SYongseok Koh return -ENOTSUP; 1397fe24446SShahaf Shuler if (!ctrl->priv->config.rx_vec_en || rxq->sges_n != 0) 140f0d2114fSYongseok Koh return -ENOTSUP; 14117ed314cSMatan Azrad if (rxq->lro) 14217ed314cSMatan Azrad return -ENOTSUP; 143f0d2114fSYongseok Koh return 1; 144f0d2114fSYongseok Koh } 145f0d2114fSYongseok Koh 146f0d2114fSYongseok Koh /** 147f0d2114fSYongseok Koh * Check a device can support vectorized RX. 148f0d2114fSYongseok Koh * 149af4f09f2SNélio Laranjeiro * @param dev 150af4f09f2SNélio Laranjeiro * Pointer to Ethernet device. 151f0d2114fSYongseok Koh * 152f0d2114fSYongseok Koh * @return 153f0d2114fSYongseok Koh * 1 if supported, negative errno value if not. 154f0d2114fSYongseok Koh */ 155ce6427ddSThomas Monjalon int __rte_cold 156af4f09f2SNélio Laranjeiro mlx5_check_vec_rx_support(struct rte_eth_dev *dev) 157f0d2114fSYongseok Koh { 158dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 159f0d2114fSYongseok Koh uint16_t i; 160f0d2114fSYongseok Koh 1617fe24446SShahaf Shuler if (!priv->config.rx_vec_en) 162f0d2114fSYongseok Koh return -ENOTSUP; 1637d6bf6b8SYongseok Koh if (mlx5_mprq_enabled(dev)) 1647d6bf6b8SYongseok Koh return -ENOTSUP; 165f0d2114fSYongseok Koh /* All the configured queues should support. */ 166f0d2114fSYongseok Koh for (i = 0; i < priv->rxqs_n; ++i) { 167f0d2114fSYongseok Koh struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; 168f0d2114fSYongseok Koh 169f0d2114fSYongseok Koh if (!rxq) 170f0d2114fSYongseok Koh continue; 171af4f09f2SNélio Laranjeiro if (mlx5_rxq_check_vec_support(rxq) < 0) 172f0d2114fSYongseok Koh break; 173f0d2114fSYongseok Koh } 174f0d2114fSYongseok Koh if (i != priv->rxqs_n) 175f0d2114fSYongseok Koh return -ENOTSUP; 176f0d2114fSYongseok Koh return 1; 177f0d2114fSYongseok Koh } 178