mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 14:30:06 -04:00
Merge branch '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says:
====================
idpf: XDP chapter I: convert Rx to libeth
Alexander Lobakin says:
XDP for idpf is currently 5 chapters:
* convert Rx to libeth (this);
* convert Tx and stats to libeth;
* generic XDP and XSk code changes, libeth_xdp;
* actual XDP for idpf via libeth_xdp;
* XSk for idpf (^).
Part I does the following:
* splits &idpf_queue into 4 (RQ, SQ, FQ, CQ) and puts them on a diet;
* ensures optimal cacheline placement, strictly asserts CL sizes;
* moves currently unused/dead singleq mode out of line;
* reuses libeth's Rx ptype definitions and helpers;
* uses libeth's Rx buffer management for both header and payload;
* eliminates memcpy()s and coherent DMA uses on hotpath, uses
napi_build_skb() instead of in-place short skb allocation.
Most idpf patches, except for the queue split, removes more lines
than adds.
Expect far better memory utilization and +5-8% on Rx depending on
the case (+17% on skb XDP_DROP :>).
* '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
idpf: use libeth Rx buffer management for payload buffer
idpf: convert header split mode to libeth + napi_build_skb()
libeth: support different types of buffers for Rx
idpf: remove legacy Page Pool Ethtool stats
idpf: reuse libeth's definitions of parsed ptype structures
idpf: compile singleq code only under default-n CONFIG_IDPF_SINGLEQ
idpf: merge singleq and splitq &net_device_ops
idpf: strictly assert cachelines of queue and queue vector structures
idpf: avoid bloating &idpf_q_vector with big %NR_CPUS
idpf: split &idpf_queue into 4 strictly-typed queue structures
idpf: stop using macros for accessing queue descriptors
libeth: add cacheline / struct layout assertion helpers
page_pool: use __cacheline_group_{begin, end}_aligned()
cache: add __cacheline_group_{begin, end}_aligned() (+ couple more)
====================
Link: https://patch.msgid.link/20240710203031.188081-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
66
include/net/libeth/cache.h
Normal file
66
include/net/libeth/cache.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (C) 2024 Intel Corporation */
|
||||
|
||||
#ifndef __LIBETH_CACHE_H
|
||||
#define __LIBETH_CACHE_H
|
||||
|
||||
#include <linux/cache.h>
|
||||
|
||||
/**
|
||||
* libeth_cacheline_group_assert - make sure cacheline group size is expected
|
||||
* @type: type of the structure containing the group
|
||||
* @grp: group name inside the struct
|
||||
* @sz: expected group size
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && SMP_CACHE_BYTES == 64
|
||||
#define libeth_cacheline_group_assert(type, grp, sz) \
|
||||
static_assert(offsetof(type, __cacheline_group_end__##grp) - \
|
||||
offsetofend(type, __cacheline_group_begin__##grp) == \
|
||||
(sz))
|
||||
#define __libeth_cacheline_struct_assert(type, sz) \
|
||||
static_assert(sizeof(type) == (sz))
|
||||
#else /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */
|
||||
#define libeth_cacheline_group_assert(type, grp, sz) \
|
||||
static_assert(offsetof(type, __cacheline_group_end__##grp) - \
|
||||
offsetofend(type, __cacheline_group_begin__##grp) <= \
|
||||
(sz))
|
||||
#define __libeth_cacheline_struct_assert(type, sz) \
|
||||
static_assert(sizeof(type) <= (sz))
|
||||
#endif /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */
|
||||
|
||||
#define __libeth_cls1(sz1) SMP_CACHE_ALIGN(sz1)
|
||||
#define __libeth_cls2(sz1, sz2) (SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2))
|
||||
#define __libeth_cls3(sz1, sz2, sz3) \
|
||||
(SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2) + SMP_CACHE_ALIGN(sz3))
|
||||
#define __libeth_cls(...) \
|
||||
CONCATENATE(__libeth_cls, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* libeth_cacheline_struct_assert - make sure CL-based struct size is expected
|
||||
* @type: type of the struct
|
||||
* @...: from 1 to 3 CL group sizes (read-mostly, read-write, cold)
|
||||
*
|
||||
* When a struct contains several CL groups, it's difficult to predict its size
|
||||
* on different architectures. The macro instead takes sizes of all of the
|
||||
* groups the structure contains and generates the final struct size.
|
||||
*/
|
||||
#define libeth_cacheline_struct_assert(type, ...) \
|
||||
__libeth_cacheline_struct_assert(type, __libeth_cls(__VA_ARGS__)); \
|
||||
static_assert(__alignof(type) >= SMP_CACHE_BYTES)
|
||||
|
||||
/**
|
||||
* libeth_cacheline_set_assert - make sure CL-based struct layout is expected
|
||||
* @type: type of the struct
|
||||
* @ro: expected size of the read-mostly group
|
||||
* @rw: expected size of the read-write group
|
||||
* @c: expected size of the cold group
|
||||
*
|
||||
* Check that each group size is expected and then do final struct size check.
|
||||
*/
|
||||
#define libeth_cacheline_set_assert(type, ro, rw, c) \
|
||||
libeth_cacheline_group_assert(type, read_mostly, ro); \
|
||||
libeth_cacheline_group_assert(type, read_write, rw); \
|
||||
libeth_cacheline_group_assert(type, cold, c); \
|
||||
libeth_cacheline_struct_assert(type, ro, rw, c)
|
||||
|
||||
#endif /* __LIBETH_CACHE_H */
|
||||
@@ -17,6 +17,8 @@
|
||||
#define LIBETH_MAX_HEADROOM LIBETH_SKB_HEADROOM
|
||||
/* Link layer / L2 overhead: Ethernet, 2 VLAN tags (C + S), FCS */
|
||||
#define LIBETH_RX_LL_LEN (ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN)
|
||||
/* Maximum supported L2-L4 header length */
|
||||
#define LIBETH_MAX_HEAD roundup_pow_of_two(max(MAX_HEADER, 256))
|
||||
|
||||
/* Always use order-0 pages */
|
||||
#define LIBETH_RX_PAGE_ORDER 0
|
||||
@@ -43,6 +45,18 @@ struct libeth_fqe {
|
||||
u32 truesize;
|
||||
} __aligned_largest;
|
||||
|
||||
/**
|
||||
* enum libeth_fqe_type - enum representing types of Rx buffers
|
||||
* @LIBETH_FQE_MTU: buffer size is determined by MTU
|
||||
* @LIBETH_FQE_SHORT: buffer size is smaller than MTU, for short frames
|
||||
* @LIBETH_FQE_HDR: buffer size is ```LIBETH_MAX_HEAD```-sized, for headers
|
||||
*/
|
||||
enum libeth_fqe_type {
|
||||
LIBETH_FQE_MTU = 0U,
|
||||
LIBETH_FQE_SHORT,
|
||||
LIBETH_FQE_HDR,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct libeth_fq - structure representing a buffer (fill) queue
|
||||
* @fp: hotpath part of the structure
|
||||
@@ -50,6 +64,8 @@ struct libeth_fqe {
|
||||
* @fqes: array of Rx buffers
|
||||
* @truesize: size to allocate per buffer, w/overhead
|
||||
* @count: number of descriptors/buffers the queue has
|
||||
* @type: type of the buffers this queue has
|
||||
* @hsplit: flag whether header split is enabled
|
||||
* @buf_len: HW-writeable length per each buffer
|
||||
* @nid: ID of the closest NUMA node with memory
|
||||
*/
|
||||
@@ -63,6 +79,9 @@ struct libeth_fq {
|
||||
);
|
||||
|
||||
/* Cold fields */
|
||||
enum libeth_fqe_type type:2;
|
||||
bool hsplit:1;
|
||||
|
||||
u32 buf_len;
|
||||
int nid;
|
||||
};
|
||||
|
||||
@@ -129,6 +129,16 @@ struct page_pool_stats {
|
||||
};
|
||||
#endif
|
||||
|
||||
/* The whole frag API block must stay within one cacheline. On 32-bit systems,
|
||||
* sizeof(long) == sizeof(int), so that the block size is ``3 * sizeof(long)``.
|
||||
* On 64-bit systems, the actual size is ``2 * sizeof(long) + sizeof(int)``.
|
||||
* The closest pow-2 to both of them is ``4 * sizeof(long)``, so just use that
|
||||
* one for simplicity.
|
||||
* Having it aligned to a cacheline boundary may be excessive and doesn't bring
|
||||
* any good.
|
||||
*/
|
||||
#define PAGE_POOL_FRAG_GROUP_ALIGN (4 * sizeof(long))
|
||||
|
||||
struct page_pool {
|
||||
struct page_pool_params_fast p;
|
||||
|
||||
@@ -142,19 +152,11 @@ struct page_pool {
|
||||
bool system:1; /* This is a global percpu pool */
|
||||
#endif
|
||||
|
||||
/* The following block must stay within one cacheline. On 32-bit
|
||||
* systems, sizeof(long) == sizeof(int), so that the block size is
|
||||
* ``3 * sizeof(long)``. On 64-bit systems, the actual size is
|
||||
* ``2 * sizeof(long) + sizeof(int)``. The closest pow-2 to both of
|
||||
* them is ``4 * sizeof(long)``, so just use that one for simplicity.
|
||||
* Having it aligned to a cacheline boundary may be excessive and
|
||||
* doesn't bring any good.
|
||||
*/
|
||||
__cacheline_group_begin(frag) __aligned(4 * sizeof(long));
|
||||
__cacheline_group_begin_aligned(frag, PAGE_POOL_FRAG_GROUP_ALIGN);
|
||||
long frag_users;
|
||||
netmem_ref frag_page;
|
||||
unsigned int frag_offset;
|
||||
__cacheline_group_end(frag);
|
||||
__cacheline_group_end_aligned(frag, PAGE_POOL_FRAG_GROUP_ALIGN);
|
||||
|
||||
struct delayed_work release_dw;
|
||||
void (*disconnect)(void *pool);
|
||||
|
||||
Reference in New Issue
Block a user