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