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);
 
 
 
 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,
 
 
        /* 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);
 
 #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