Netdev List
 help / color / mirror / Atom feed
From: Alexander Lobakin <aleksander.lobakin@intel.com>
To: "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Alexander Lobakin <aleksander.lobakin@intel.com>,
	Maciej Fijalkowski <maciej.fijalkowski@intel.com>,
	Michal Kubiak <michal.kubiak@intel.com>,
	Larysa Zaremba <larysa.zaremba@intel.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Willem de Bruijn <willemdebruijn.kernel@gmail.com>,
	intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH RFC net-next 04/34] libie: support different types of buffers for Rx
Date: Sat, 23 Dec 2023 03:55:24 +0100	[thread overview]
Message-ID: <20231223025554.2316836-5-aleksander.lobakin@intel.com> (raw)
In-Reply-To: <20231223025554.2316836-1-aleksander.lobakin@intel.com>

Unlike previous generations, idpf requires more buffer types for optimal
performance. This includes: header buffers, short buffers, and
no-overhead buffers (w/o headroom and tailroom, for TCP zerocopy when
the header split is enabled).
Introduce libie Rx buffer type and calculate page_pool params
accordingly. All the HW-related details like buffer alignment are still
accounted. For the header buffers, pick 256 bytes as in most places in
the kernel (have you ever seen frames with bigger headers?).

Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
 drivers/net/ethernet/intel/libie/rx.c | 107 +++++++++++++++++++++++---
 include/linux/net/intel/libie/rx.h    |  19 +++++
 2 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/intel/libie/rx.c b/drivers/net/ethernet/intel/libie/rx.c
index 610f16043bcf..3d3b19d2b40d 100644
--- a/drivers/net/ethernet/intel/libie/rx.c
+++ b/drivers/net/ethernet/intel/libie/rx.c
@@ -6,14 +6,14 @@
 /* Rx buffer management */
 
 /**
- * libie_rx_hw_len - get the actual buffer size to be passed to HW
+ * libie_rx_hw_len_mtu - get the actual buffer size to be passed to HW
  * @pp: &page_pool_params of the netdev to calculate the size for
  *
  * Return: HW-writeable length per one buffer to pass it to the HW accounting:
  * MTU the @dev has, HW required alignment, minimum and maximum allowed values,
  * and system's page size.
  */
-static u32 libie_rx_hw_len(const struct page_pool_params *pp)
+static u32 libie_rx_hw_len_mtu(const struct page_pool_params *pp)
 {
 	u32 len;
 
@@ -24,6 +24,96 @@ static u32 libie_rx_hw_len(const struct page_pool_params *pp)
 	return len;
 }
 
+/**
+ * libie_rx_hw_len_truesize - get the short buffer size to be passed to HW
+ * @pp: &page_pool_params of the netdev to calculate the size for
+ * @truesize: desired truesize for the buffers
+ *
+ * Return: HW-writeable length per one buffer to pass it to the HW ignoring the
+ * MTU and closest to the passed truesize. Can be used for "short" buffer
+ * queues to fragment pages more efficiently.
+ */
+static u32 libie_rx_hw_len_truesize(const struct page_pool_params *pp,
+				    u32 truesize)
+{
+	u32 min, len;
+
+	min = SKB_HEAD_ALIGN(pp->offset + LIBIE_RX_BUF_LEN_ALIGN);
+	truesize = clamp(roundup_pow_of_two(truesize), roundup_pow_of_two(min),
+			 PAGE_SIZE << LIBIE_RX_PAGE_ORDER);
+
+	len = SKB_WITH_OVERHEAD(truesize - pp->offset);
+	len = ALIGN_DOWN(len, LIBIE_RX_BUF_LEN_ALIGN);
+	len = clamp(len, LIBIE_MIN_RX_BUF_LEN, pp->max_len);
+
+	return len;
+}
+
+static void libie_rx_page_pool_params(struct libie_buf_queue *bq,
+				      struct page_pool_params *pp)
+{
+	pp->offset = LIBIE_SKB_HEADROOM;
+	/* HW-writeable / syncable length per one page */
+	pp->max_len = LIBIE_RX_BUF_LEN(pp->offset);
+
+	/* HW-writeable length per buffer */
+	switch (bq->type) {
+	case LIBIE_RX_BUF_MTU:
+		bq->rx_buf_len = libie_rx_hw_len_mtu(pp);
+		break;
+	case LIBIE_RX_BUF_SHORT:
+		bq->rx_buf_len = libie_rx_hw_len_truesize(pp, bq->truesize);
+		break;
+	case LIBIE_RX_BUF_HDR:
+		bq->rx_buf_len = ALIGN(LIBIE_MAX_HEAD, LIBIE_RX_BUF_LEN_ALIGN);
+		break;
+	default:
+		break;
+	}
+
+	/* Buffer size to allocate */
+	bq->truesize = roundup_pow_of_two(SKB_HEAD_ALIGN(pp->offset +
+							 bq->rx_buf_len));
+}
+
+/**
+ * libie_rx_page_pool_params_zc - calculate params without the stack overhead
+ * @bq: buffer queue to calculate the size for
+ * @pp: &page_pool_params of the netdev
+ *
+ * Adjusts the PP params to exclude the stack overhead and sets both the buffer
+ * lengh and the truesize, which are equal for the data buffers. Note that this
+ * requires separate header buffers to be always active and account the
+ * overhead.
+ * With the MTU == ``PAGE_SIZE``, this allows the kernel to enable the zerocopy
+ * mode.
+ */
+static bool libie_rx_page_pool_params_zc(struct libie_buf_queue *bq,
+					 struct page_pool_params *pp)
+{
+	u32 mtu;
+
+	pp->offset = 0;
+	pp->max_len = PAGE_SIZE << LIBIE_RX_PAGE_ORDER;
+
+	switch (bq->type) {
+	case LIBIE_RX_BUF_MTU:
+		mtu = READ_ONCE(pp->netdev->mtu);
+		break;
+	case LIBIE_RX_BUF_SHORT:
+		mtu = bq->truesize;
+		break;
+	default:
+		return false;
+	}
+
+	bq->rx_buf_len = clamp(roundup_pow_of_two(mtu), LIBIE_RX_BUF_LEN_ALIGN,
+			       pp->max_len);
+	bq->truesize = bq->rx_buf_len;
+
+	return true;
+}
+
 /**
  * libie_rx_page_pool_create - create a PP with the default libie settings
  * @bq: buffer queue struct to fill
@@ -43,17 +133,12 @@ int libie_rx_page_pool_create(struct libie_buf_queue *bq,
 		.netdev		= napi->dev,
 		.napi		= napi,
 		.dma_dir	= DMA_FROM_DEVICE,
-		.offset		= LIBIE_SKB_HEADROOM,
 	};
 
-	/* HW-writeable / syncable length per one page */
-	pp.max_len = LIBIE_RX_BUF_LEN(pp.offset);
-
-	/* HW-writeable length per buffer */
-	bq->rx_buf_len = libie_rx_hw_len(&pp);
-	/* Buffer size to allocate */
-	bq->truesize = roundup_pow_of_two(SKB_HEAD_ALIGN(pp.offset +
-							 bq->rx_buf_len));
+	if (!bq->hsplit)
+		libie_rx_page_pool_params(bq, &pp);
+	else if (!libie_rx_page_pool_params_zc(bq, &pp))
+		return -EINVAL;
 
 	bq->pp = page_pool_create(&pp);
 
diff --git a/include/linux/net/intel/libie/rx.h b/include/linux/net/intel/libie/rx.h
index 0d6bce19ad6b..87ad8f9e89c7 100644
--- a/include/linux/net/intel/libie/rx.h
+++ b/include/linux/net/intel/libie/rx.h
@@ -19,6 +19,8 @@
 #define LIBIE_MAX_HEADROOM	LIBIE_SKB_HEADROOM
 /* Link layer / L2 overhead: Ethernet, 2 VLAN tags (C + S), FCS */
 #define LIBIE_RX_LL_LEN		(ETH_HLEN + 2 * VLAN_HLEN + ETH_FCS_LEN)
+/* Maximum supported L2-L4 header length */
+#define LIBIE_MAX_HEAD		256
 
 /* Always use order-0 pages */
 #define LIBIE_RX_PAGE_ORDER	0
@@ -64,6 +66,18 @@ struct libie_rx_buffer {
 	u32			truesize;
 };
 
+/**
+ * enum libie_rx_buf_type - enum representing types of Rx buffers
+ * @LIBIE_RX_BUF_MTU: buffer size is determined by MTU
+ * @LIBIE_RX_BUF_SHORT: buffer size is smaller than MTU, for short frames
+ * @LIBIE_RX_BUF_HDR: buffer size is ```LIBIE_MAX_HEAD```-sized, for headers
+ */
+enum libie_rx_buf_type {
+	LIBIE_RX_BUF_MTU	= 0U,
+	LIBIE_RX_BUF_SHORT,
+	LIBIE_RX_BUF_HDR,
+};
+
 /**
  * struct libie_buf_queue - structure representing a buffer queue
  * @pp: &page_pool for buffer management
@@ -71,6 +85,8 @@ struct libie_rx_buffer {
  * @truesize: size to allocate per buffer, w/overhead
  * @count: number of descriptors/buffers the queue has
  * @rx_buf_len: HW-writeable length per each buffer
+ * @type: type of the buffers this queue has
+ * @hsplit: flag whether header split is enabled
  */
 struct libie_buf_queue {
 	struct page_pool	*pp;
@@ -81,6 +97,9 @@ struct libie_buf_queue {
 
 	/* Cold fields */
 	u32			rx_buf_len;
+	enum libie_rx_buf_type	type:2;
+
+	bool			hsplit:1;
 };
 
 int libie_rx_page_pool_create(struct libie_buf_queue *bq,
-- 
2.43.0


  parent reply	other threads:[~2023-12-23  2:58 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-23  2:55 [PATCH RFC net-next 00/34] Christmas 3-serie XDP for idpf (+generic stuff) Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 01/34] idpf: reuse libie's definitions of parsed ptype structures Alexander Lobakin
2023-12-27 15:43   ` Willem de Bruijn
2024-01-08 16:04     ` Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 02/34] idpf: pack &idpf_queue way more efficiently Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 03/34] idpf: remove legacy Page Pool Ethtool stats Alexander Lobakin
2023-12-23  2:55 ` Alexander Lobakin [this message]
2023-12-23  2:55 ` [PATCH RFC net-next 05/34] idpf: convert header split mode to libie + napi_build_skb() Alexander Lobakin
2023-12-27 15:30   ` Willem de Bruijn
2024-01-08 16:17     ` Alexander Lobakin
2024-01-09 13:59       ` Willem de Bruijn
2024-01-11 13:09         ` Alexander Lobakin
2024-01-09 14:43   ` Eric Dumazet
2023-12-23  2:55 ` [PATCH RFC net-next 06/34] idpf: use libie Rx buffer management for payload buffer Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 07/34] libie: add Tx buffer completion helpers Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 08/34] idpf: convert to libie Tx buffer completion Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 09/34] bpf, xdp: constify some bpf_prog * function arguments Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 10/34] xdp: constify read-only arguments of some static inline helpers Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 11/34] xdp: allow attaching already registered memory model to xdp_rxq_info Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 12/34] xdp: add generic xdp_buff_add_frag() Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 13/34] xdp: add generic xdp_build_skb_from_buff() Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 14/34] xdp: get rid of xdp_frame::mem.id Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 15/34] page_pool: add inline helper to sync VA for device (for XDP_TX) Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 16/34] jump_label: export static_key_slow_{inc,dec}_cpuslocked() Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 17/34] libie: support native XDP and register memory model Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 18/34] libie: add a couple of XDP helpers Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 19/34] idpf: stop using macros for accessing queue descriptors Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 20/34] idpf: make complq cleaning dependent on scheduling mode Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 21/34] idpf: prepare structures to support xdp Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 22/34] idpf: implement XDP_SETUP_PROG in ndo_bpf for splitq Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 23/34] idpf: use generic functions to build xdp_buff and skb Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 24/34] idpf: add support for XDP on Rx Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 25/34] idpf: add support for .ndo_xdp_xmit() Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 26/34] xdp: add generic XSk xdp_buff -> skb conversion Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 27/34] idpf: add support for sw interrupt Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 28/34] idpf: add relative queue id member to idpf_queue Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 29/34] idpf: add vc functions to manage selected queues Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 30/34] idpf: move search rx and tx queues to header Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 31/34] idpf: add XSk pool initialization Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 32/34] idpf: implement Tx path for AF_XDP Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 33/34] idpf: implement Rx " Alexander Lobakin
2023-12-23  2:55 ` [PATCH RFC net-next 34/34] idpf: enable XSk features and ndo_xsk_wakeup Alexander Lobakin
2023-12-26 20:23 ` [PATCH RFC net-next 00/34] Christmas 3-serie XDP for idpf (+generic stuff) Willem de Bruijn
2024-01-08 16:01   ` Alexander Lobakin
2024-01-08 16:09     ` Willem de Bruijn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231223025554.2316836-5-aleksander.lobakin@intel.com \
    --to=aleksander.lobakin@intel.com \
    --cc=ast@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=kuba@kernel.org \
    --cc=larysa.zaremba@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maciej.fijalkowski@intel.com \
    --cc=michal.kubiak@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=willemdebruijn.kernel@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox