Blame SOURCES/0006-netdrv-mlx5e-Allow-XSK-frames-smaller-than-a-page.patch

d8f823
From d1ac1b641ea39e946e94c155520c590a5a27e23a Mon Sep 17 00:00:00 2001
d8f823
From: Jiri Benc <jbenc@redhat.com>
d8f823
Date: Wed, 22 Apr 2020 18:18:11 -0400
d8f823
Subject: [PATCH 006/312] [netdrv] mlx5e: Allow XSK frames smaller than a page
d8f823
MIME-Version: 1.0
d8f823
Content-Type: text/plain; charset=UTF-8
d8f823
Content-Transfer-Encoding: 8bit
d8f823
d8f823
Message-id: <5c0604430537e1022e4424f8683b5611f3ccceb3.1587578778.git.jbenc@redhat.com>
d8f823
Patchwork-id: 304531
d8f823
Patchwork-instance: patchwork
d8f823
O-Subject: [RHEL8.3 net 20/46] net/mlx5e: Allow XSK frames smaller than a page
d8f823
Bugzilla: 1819630
d8f823
RH-Acked-by: Hangbin Liu <haliu@redhat.com>
d8f823
RH-Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
d8f823
RH-Acked-by: Ivan Vecera <ivecera@redhat.com>
d8f823
d8f823
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1819630
d8f823
d8f823
commit 282c0c798f8ec883c2ac2f1ce2dc06ef9421731c
d8f823
Author: Maxim Mikityanskiy <maximmi@mellanox.com>
d8f823
Date:   Tue Aug 27 02:25:26 2019 +0000
d8f823
d8f823
    net/mlx5e: Allow XSK frames smaller than a page
d8f823
d8f823
    Relax the requirements to the XSK frame size to allow it to be smaller
d8f823
    than a page and even not a power of two. The current implementation can
d8f823
    work in this mode, both with Striding RQ and without it.
d8f823
d8f823
    The code that checks `mtu + headroom <= XSK frame size` is modified
d8f823
    accordingly. Any frame size between 2048 and PAGE_SIZE is accepted.
d8f823
d8f823
    Functions that worked with pages only now work with XSK frames, even if
d8f823
    their size is different from PAGE_SIZE.
d8f823
d8f823
    With XSK queues, regardless of the frame size, Striding RQ uses the
d8f823
    stride size of PAGE_SIZE, and UMR MTTs are posted using starting
d8f823
    addresses of frames, but PAGE_SIZE as page size. MTU guarantees that no
d8f823
    packet data will overlap with other frames. UMR MTT size is made equal
d8f823
    to the stride size of the RQ, because UMEM frames may come in random
d8f823
    order, and we need to handle them one by one. PAGE_SIZE is just a power
d8f823
    of two that is bigger than any allowed XSK frame size, and also it
d8f823
    doesn't require making additional changes to the code.
d8f823
d8f823
    Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com>
d8f823
    Reviewed-by: Saeed Mahameed <saeedm@mellanox.com>
d8f823
    Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com>
d8f823
    Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
d8f823
d8f823
Signed-off-by: Jiri Benc <jbenc@redhat.com>
d8f823
Signed-off-by: Timothy Redaelli <tredaelli@redhat.com>
d8f823
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
d8f823
---
d8f823
 .../net/ethernet/mellanox/mlx5/core/en/params.c    | 23 ++++++++++++++++++----
d8f823
 .../net/ethernet/mellanox/mlx5/core/en/params.h    |  2 ++
d8f823
 .../net/ethernet/mellanox/mlx5/core/en/xsk/rx.c    |  2 +-
d8f823
 .../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 15 +++++++++-----
d8f823
 4 files changed, 32 insertions(+), 10 deletions(-)
d8f823
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
d8f823
index 79301d116667..eb2e1f2138e4 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
d8f823
@@ -25,18 +25,33 @@ u16 mlx5e_get_linear_rq_headroom(struct mlx5e_params *params,
d8f823
 	return headroom;
d8f823
 }
d8f823
 
d8f823
-u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
d8f823
-				struct mlx5e_xsk_param *xsk)
d8f823
+u32 mlx5e_rx_get_min_frag_sz(struct mlx5e_params *params,
d8f823
+			     struct mlx5e_xsk_param *xsk)
d8f823
 {
d8f823
 	u32 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
d8f823
 	u16 linear_rq_headroom = mlx5e_get_linear_rq_headroom(params, xsk);
d8f823
-	u32 frag_sz = linear_rq_headroom + hw_mtu;
d8f823
+
d8f823
+	return linear_rq_headroom + hw_mtu;
d8f823
+}
d8f823
+
d8f823
+u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
d8f823
+				struct mlx5e_xsk_param *xsk)
d8f823
+{
d8f823
+	u32 frag_sz = mlx5e_rx_get_min_frag_sz(params, xsk);
d8f823
 
d8f823
 	/* AF_XDP doesn't build SKBs in place. */
d8f823
 	if (!xsk)
d8f823
 		frag_sz = MLX5_SKB_FRAG_SZ(frag_sz);
d8f823
 
d8f823
-	/* XDP in mlx5e doesn't support multiple packets per page. */
d8f823
+	/* XDP in mlx5e doesn't support multiple packets per page. AF_XDP is a
d8f823
+	 * special case. It can run with frames smaller than a page, as it
d8f823
+	 * doesn't allocate pages dynamically. However, here we pretend that
d8f823
+	 * fragments are page-sized: it allows to treat XSK frames like pages
d8f823
+	 * by redirecting alloc and free operations to XSK rings and by using
d8f823
+	 * the fact there are no multiple packets per "page" (which is a frame).
d8f823
+	 * The latter is important, because frames may come in a random order,
d8f823
+	 * and we will have trouble assemblying a real page of multiple frames.
d8f823
+	 */
d8f823
 	if (mlx5e_rx_is_xdp(params, xsk))
d8f823
 		frag_sz = max_t(u32, frag_sz, PAGE_SIZE);
d8f823
 
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
d8f823
index 3a615d663d84..989d8f429438 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h
d8f823
@@ -76,6 +76,8 @@ static inline bool mlx5e_qid_validate(const struct mlx5e_profile *profile,
d8f823
 
d8f823
 u16 mlx5e_get_linear_rq_headroom(struct mlx5e_params *params,
d8f823
 				 struct mlx5e_xsk_param *xsk);
d8f823
+u32 mlx5e_rx_get_min_frag_sz(struct mlx5e_params *params,
d8f823
+			     struct mlx5e_xsk_param *xsk);
d8f823
 u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params,
d8f823
 				struct mlx5e_xsk_param *xsk);
d8f823
 u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params,
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
d8f823
index 6a55573ec8f2..3783776b6d70 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
d8f823
@@ -104,7 +104,7 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq,
d8f823
 
d8f823
 	/* head_offset is not used in this function, because di->xsk.data and
d8f823
 	 * di->addr point directly to the necessary place. Furthermore, in the
d8f823
-	 * current implementation, one page = one packet = one frame, so
d8f823
+	 * current implementation, UMR pages are mapped to XSK frames, so
d8f823
 	 * head_offset should always be 0.
d8f823
 	 */
d8f823
 	WARN_ON_ONCE(head_offset);
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
d8f823
index d3a173e88e24..81efd2fbc75d 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
d8f823
@@ -4,18 +4,23 @@
d8f823
 #include "setup.h"
d8f823
 #include "en/params.h"
d8f823
 
d8f823
+/* It matches XDP_UMEM_MIN_CHUNK_SIZE, but as this constant is private and may
d8f823
+ * change unexpectedly, and mlx5e has a minimum valid stride size for striding
d8f823
+ * RQ, keep this check in the driver.
d8f823
+ */
d8f823
+#define MLX5E_MIN_XSK_CHUNK_SIZE 2048
d8f823
+
d8f823
 bool mlx5e_validate_xsk_param(struct mlx5e_params *params,
d8f823
 			      struct mlx5e_xsk_param *xsk,
d8f823
 			      struct mlx5_core_dev *mdev)
d8f823
 {
d8f823
-	/* AF_XDP doesn't support frames larger than PAGE_SIZE, and the current
d8f823
-	 * mlx5e XDP implementation doesn't support multiple packets per page.
d8f823
-	 */
d8f823
-	if (xsk->chunk_size != PAGE_SIZE)
d8f823
+	/* AF_XDP doesn't support frames larger than PAGE_SIZE. */
d8f823
+	if (xsk->chunk_size > PAGE_SIZE ||
d8f823
+			xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE)
d8f823
 		return false;
d8f823
 
d8f823
 	/* Current MTU and XSK headroom don't allow packets to fit the frames. */
d8f823
-	if (mlx5e_rx_get_linear_frag_sz(params, xsk) > xsk->chunk_size)
d8f823
+	if (mlx5e_rx_get_min_frag_sz(params, xsk) > xsk->chunk_size)
d8f823
 		return false;
d8f823
 
d8f823
 	/* frag_sz is different for regular and XSK RQs, so ensure that linear
d8f823
-- 
d8f823
2.13.6
d8f823