summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMaxim Mikityanskiy <maximmi@nvidia.com>2022-09-29 00:21:43 -0700
committerJakub Kicinski <kuba@kernel.org>2022-09-30 07:55:45 -0700
commitfa5573359aae63d36518e2821f968ff2f5eae02e (patch)
treeff65675fbf271562c7d5dc075a90f5b3ef1c071b /drivers
parente5a3cc83d54019a90119ce0cf17b5e21729b79bf (diff)
downloadlinux-fa5573359aae63d36518e2821f968ff2f5eae02e.tar.bz2
net/mlx5e: xsk: Use XSK frame size as striding RQ page size
XSK RQs support striding RQ linear mode, but the stride size is always set to PAGE_SIZE. It may be larger than the XSK frame size, unnecessarily reducing the useful space in a WQE, but more importantly causing UMEM data corruption in certain cases. Normally, stride size bigger than XSK frame size is not a problem if the hardware enforces the MTU. However, traffic between vports skips the hardware MTU check, and oversized packets may be received. If an oversized packet is bigger than the XSK frame but not bigger than the stride, it will cause overwriting of the adjacent UMEM region. If the packet takes more than one stride, they can be recycled for reuse so it's not a problem when the XSK frame size matches the stride size. To reduce the impact of the above issue, attempt to use the MTT page size for striding RQ that matches the XSK frame size, allowing to safely use 2048-byte frames on an up-to-date firmware. Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com> Reviewed-by: Tariq Toukan <tariqt@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/params.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
index 1a0d8f9102df..593b684d21d5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
@@ -6,6 +6,7 @@
#include "en/port.h"
#include "en_accel/en_accel.h"
#include "en_accel/ipsec.h"
+#include <net/xdp_sock_drv.h>
static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev)
{
@@ -16,8 +17,8 @@ static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev)
u8 mlx5e_mpwrq_page_shift(struct mlx5_core_dev *mdev, struct mlx5e_xsk_param *xsk)
{
+ u8 req_page_shift = xsk ? order_base_2(xsk->chunk_size) : PAGE_SHIFT;
u8 min_page_shift = mlx5e_mpwrq_min_page_shift(mdev);
- u8 req_page_shift = PAGE_SHIFT;
/* Regular RQ uses order-0 pages, the NIC must be able to map them. */
if (WARN_ON_ONCE(!xsk && req_page_shift < min_page_shift))
@@ -933,12 +934,36 @@ static u8 mlx5e_build_icosq_log_wq_sz(struct mlx5_core_dev *mdev,
/* If XDP program is attached, XSK may be turned on at any time without
* restarting the channel. ICOSQ must be big enough to fit UMR WQEs of
* both regular RQ and XSK RQ.
- * Although mlx5e_mpwqe_get_log_rq_size accepts mlx5e_xsk_param, it
- * doesn't affect its return value, as long as params->xdp_prog != NULL,
- * so we can just multiply by 2.
+ *
+ * XSK uses different values of page_shift, and the total number of UMR
+ * WQEBBs depends on it. This dependency is complex and not monotonic,
+ * especially taking into consideration that some of the parameters come
+ * from capabilities. Hence, we have to try all valid values of XSK
+ * frame size (and page_shift) to find the maximum.
*/
- if (params->xdp_prog)
- wqebbs *= 2;
+ if (params->xdp_prog) {
+ u32 max_xsk_wqebbs = 0;
+ u8 frame_shift;
+
+ for (frame_shift = XDP_UMEM_MIN_CHUNK_SHIFT;
+ frame_shift <= PAGE_SHIFT; frame_shift++) {
+ /* The headroom doesn't affect the calculation. */
+ struct mlx5e_xsk_param xsk = {
+ .chunk_size = 1 << frame_shift,
+ };
+ u32 xsk_wqebbs;
+ u8 page_shift;
+
+ page_shift = mlx5e_mpwrq_page_shift(mdev, &xsk);
+ xsk_wqebbs = mlx5e_mpwrq_umr_wqebbs(mdev, page_shift) *
+ (1 << mlx5e_mpwqe_get_log_rq_size(mdev, params, &xsk));
+
+ if (xsk_wqebbs > max_xsk_wqebbs)
+ max_xsk_wqebbs = xsk_wqebbs;
+ }
+
+ wqebbs += max_xsk_wqebbs;
+ }
if (params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO)
wqebbs += mlx5e_shampo_icosq_sz(mdev, params, rqp);