net/mlx5: allow LRO in regular Rx queue
[dpdk.git] / drivers / net / mlx5 / mlx5_rxq.c
index bd26ee2..ad5b0a9 100644 (file)
@@ -93,7 +93,6 @@ mlx5_rxq_mprq_enabled(struct mlx5_rxq_data *rxq)
 
 /**
  * Check whether Multi-Packet RQ is enabled for the device.
- * MPRQ can be enabled explicitly, or implicitly by enabling LRO.
  *
  * @param dev
  *   Pointer to Ethernet device.
@@ -1090,7 +1089,7 @@ mlx5_devx_rq_new(struct rte_eth_dev *dev, uint16_t idx, uint32_t cqn)
        struct mlx5_rxq_ctrl *rxq_ctrl =
                container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
        struct mlx5_devx_create_rq_attr rq_attr;
-       uint32_t wqe_n = 1 << rxq_data->elts_n;
+       uint32_t wqe_n = 1 << (rxq_data->elts_n - rxq_data->sges_n);
        uint32_t wq_size = 0;
        uint32_t wqe_size = 0;
        uint32_t log_wqe_size = 0;
@@ -1118,17 +1117,12 @@ mlx5_devx_rq_new(struct rte_eth_dev *dev, uint16_t idx, uint32_t cqn)
                                MLX5_MIN_SINGLE_STRIDE_LOG_NUM_BYTES;
                wqe_size = sizeof(struct mlx5_wqe_mprq);
        } else {
-               int max_sge = 0;
-               int num_scatter = 0;
-
                rq_attr.wq_attr.wq_type = MLX5_WQ_TYPE_CYCLIC;
-               max_sge = 1 << rxq_data->sges_n;
-               num_scatter = RTE_MAX(max_sge, 1);
-               wqe_size = sizeof(struct mlx5_wqe_data_seg) * num_scatter;
+               wqe_size = sizeof(struct mlx5_wqe_data_seg);
        }
-       log_wqe_size = log2above(wqe_size);
+       log_wqe_size = log2above(wqe_size) + rxq_data->sges_n;
        rq_attr.wq_attr.log_wq_stride = log_wqe_size;
-       rq_attr.wq_attr.log_wq_sz = rxq_data->elts_n;
+       rq_attr.wq_attr.log_wq_sz = rxq_data->elts_n - rxq_data->sges_n;
        /* Calculate and allocate WQ memory space. */
        wqe_size = 1 << log_wqe_size; /* round up power of two.*/
        wq_size = wqe_n * wqe_size;
@@ -1599,12 +1593,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        unsigned int mb_len = rte_pktmbuf_data_room_size(mp);
        unsigned int mprq_stride_size;
        struct mlx5_dev_config *config = &priv->config;
-       /*
-        * LRO packet may consume all the stride memory, hence we cannot
-        * guaranty head-room. A new striding RQ feature may be added in CX6 DX
-        * to allow head-room and tail-room for the LRO packets.
-        */
-       unsigned int strd_headroom_en = mlx5_lro_on(dev) ? 0 : 1;
+       unsigned int strd_headroom_en;
        /*
         * Always allocate extra slots, even if eventually
         * the vector Rx will not be used.
@@ -1617,6 +1606,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        unsigned int max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
        unsigned int non_scatter_min_mbuf_size = max_rx_pkt_len +
                                                        RTE_PKTMBUF_HEADROOM;
+       unsigned int max_lro_size = 0;
 
        if (non_scatter_min_mbuf_size > mb_len && !(offloads &
                                                    DEV_RX_OFFLOAD_SCATTER)) {
@@ -1644,6 +1634,21 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        tmpl->socket = socket;
        if (dev->data->dev_conf.intr_conf.rxq)
                tmpl->irq = 1;
+       /*
+        * LRO packet may consume all the stride memory, hence we cannot
+        * guaranty head-room near the packet memory in the stride.
+        * In this case scatter is, for sure, enabled and an empty mbuf may be
+        * added in the start for the head-room.
+        */
+       if (mlx5_lro_on(dev) && RTE_PKTMBUF_HEADROOM > 0 &&
+           non_scatter_min_mbuf_size > mb_len) {
+               strd_headroom_en = 0;
+               mprq_stride_size = RTE_MIN(max_rx_pkt_len,
+                                       1u << config->mprq.max_stride_size_n);
+       } else {
+               strd_headroom_en = 1;
+               mprq_stride_size = non_scatter_min_mbuf_size;
+       }
        /*
         * This Rx queue can be configured as a Multi-Packet RQ if all of the
         * following conditions are met:
@@ -1653,8 +1658,6 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
         *    stride.
         *  Otherwise, enable Rx scatter if necessary.
         */
-       mprq_stride_size = max_rx_pkt_len + RTE_PKTMBUF_HEADROOM *
-                               strd_headroom_en;
        if (mprq_en &&
            desc > (1U << config->mprq.stride_num_n) &&
            mprq_stride_size <= (1U << config->mprq.max_stride_size_n)) {
@@ -1669,8 +1672,9 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
                tmpl->rxq.strd_headroom_en = strd_headroom_en;
                tmpl->rxq.mprq_max_memcpy_len = RTE_MIN(mb_len -
                            RTE_PKTMBUF_HEADROOM, config->mprq.max_memcpy_len);
-               mlx5_max_lro_msg_size_adjust(dev, RTE_MIN(max_rx_pkt_len,
-                  (1u << tmpl->rxq.strd_num_n) * (1u << tmpl->rxq.strd_sz_n)));
+               max_lro_size = RTE_MIN(max_rx_pkt_len,
+                                      (1u << tmpl->rxq.strd_num_n) *
+                                      (1u << tmpl->rxq.strd_sz_n));
                DRV_LOG(DEBUG,
                        "port %u Rx queue %u: Multi-Packet RQ is enabled"
                        " strd_num_n = %u, strd_sz_n = %u",
@@ -1678,6 +1682,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
                        tmpl->rxq.strd_num_n, tmpl->rxq.strd_sz_n);
        } else if (max_rx_pkt_len <= (mb_len - RTE_PKTMBUF_HEADROOM)) {
                tmpl->rxq.sges_n = 0;
+               max_lro_size = max_rx_pkt_len;
        } else if (offloads & DEV_RX_OFFLOAD_SCATTER) {
                unsigned int size = non_scatter_min_mbuf_size;
                unsigned int sges_n;
@@ -1687,20 +1692,18 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
                 * and round it to the next power of two.
                 */
                sges_n = log2above((size / mb_len) + !!(size % mb_len));
-               tmpl->rxq.sges_n = sges_n;
-               /* Make sure rxq.sges_n did not overflow. */
-               size = mb_len * (1 << tmpl->rxq.sges_n);
-               size -= RTE_PKTMBUF_HEADROOM;
-               if (size < max_rx_pkt_len) {
+               if (sges_n > MLX5_MAX_LOG_RQ_SEGS) {
                        DRV_LOG(ERR,
                                "port %u too many SGEs (%u) needed to handle"
-                               " requested maximum packet size %u",
-                               dev->data->port_id,
-                               1 << sges_n,
-                               max_rx_pkt_len);
-                       rte_errno = EOVERFLOW;
+                               " requested maximum packet size %u, the maximum"
+                               " supported are %u", dev->data->port_id,
+                               1 << sges_n, max_rx_pkt_len,
+                               1u << MLX5_MAX_LOG_RQ_SEGS);
+                       rte_errno = ENOTSUP;
                        goto error;
                }
+               tmpl->rxq.sges_n = sges_n;
+               max_lro_size = max_rx_pkt_len;
        }
        if (mprq_en && !mlx5_rxq_mprq_enabled(&tmpl->rxq))
                DRV_LOG(WARNING,
@@ -1722,6 +1725,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
                rte_errno = EINVAL;
                goto error;
        }
+       mlx5_max_lro_msg_size_adjust(dev, max_lro_size);
        /* Toggle RX checksum offload if hardware supports it. */
        tmpl->rxq.csum = !!(offloads & DEV_RX_OFFLOAD_CHECKSUM);
        tmpl->rxq.hw_timestamp = !!(offloads & DEV_RX_OFFLOAD_TIMESTAMP);