kernel/files/2100-gve-Update-QPL-page-registration-logic.patch
2026-08-21 12:35:59 +03:00

161 lines
6.7 KiB
Diff

From 07993df560917357610e0625a9a2e7531c3211fc Mon Sep 17 00:00:00 2001
From: Matt Olson <maolson@google.com>
Date: Wed, 25 Feb 2026 10:23:41 -0800
Subject: gve: Update QPL page registration logic
For DQO, change QPL page registration logic to be more flexible to honor
the "max_registered_pages" parameter from the gVNIC device.
Previously the number of RX pages per QPL was hardcoded to twice the
ring size, and the number of TX pages per QPL was dictated by the device
in the DQO-QPL device option. Now [in DQO-QPL mode], the driver will
ignore the "tx_pages_per_qpl" parameter indicated in the DQO-QPL device
option and instead allocate up to (tx_queue_length / 2) pages per TX QPL
and up to (rx_queue_length * 2) pages per RX QPL while keeping the total
number of pages under the "max_registered_pages".
Merge DQO and GQI QPL page calculation logic into a unified
gve_update_num_qpl_pages function. Add rx_pages_per_qpl to the priv
struct for consumption by both DQO and GQI.
Signed-off-by: Matt Olson <maolson@google.com>
Signed-off-by: Max Yuan <maxyuan@google.com>
Reviewed-by: Jordan Rhee <jordanrhee@google.com>
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Praveen Kaligineedi <pkaligineedi@google.com>
Signed-off-by: Joshua Washington <joshwash@google.com>
Link: https://patch.msgid.link/20260225182342.1049816-2-joshwash@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[Jonathan Wright: adapted to the centralized QPL-allocation model in this kernel,
which predates the upstream gve_{tx,rx}_alloc_rings_cfg / queues_mem_alloc
per-ring QPL refactor and the gve_buffer_mgmt_dqo split. There are no
alloc_rings_cfg structs here, so gve_update_num_qpl_pages operates on
priv directly (priv->{tx,rx}_pages_per_qpl already exist) and is called
from gve_alloc_qpls() before the QPLs are allocated. rx_pages_per_qpl is
already consumed by gve_rx_alloc_ring_dqo() and gve_alloc_qpl_page_dqo().
The GQI path is left unchanged: it already sizes RX QPLs from
rx_data_slot_cnt and TX QPLs from the device-provided tx_pages_per_qpl.]
Signed-off-by: Jonathan Wright <jonathan@almalinux.org>
---
drivers/net/ethernet/google/gve/gve.h | 7 ++----
drivers/net/ethernet/google/gve/gve_adminq.c | 12 ----------
drivers/net/ethernet/google/gve/gve_main.c | 40 +++++++++++++++++++++++++++++
3 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index cbdf3a842cfe0..1d66d3834f7e6 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -56,9 +56,6 @@
#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
-#define DQO_QPL_DEFAULT_TX_PAGES 512
-#define DQO_QPL_DEFAULT_RX_PAGES 2048
-
/* Maximum TSO size supported on DQO */
#define GVE_DQO_TX_MAX 0x3FFFF
@@ -650,8 +647,8 @@ struct gve_priv {
u16 num_event_counters;
u16 tx_desc_cnt; /* num desc per ring */
u16 rx_desc_cnt; /* num desc per ring */
- u16 tx_pages_per_qpl; /* Suggested number of pages per qpl for TX queues by NIC */
- u16 rx_pages_per_qpl; /* Suggested number of pages per qpl for RX queues by NIC */
+ u16 tx_pages_per_qpl; /* Number of pages per qpl for TX queues */
+ u16 rx_pages_per_qpl; /* Number of pages per qpl for RX queues */
u16 rx_data_slot_cnt; /* rx buffer length */
u64 max_registered_pages;
u64 num_registered_pages; /* num pages registered with NIC */
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index b72cc0fa2ba2b..2c233009621bc 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -767,18 +767,6 @@ static void gve_enable_supported_features(struct gve_priv *priv,
"JUMBO FRAMES device option enabled.\n");
priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
}
-
- /* Override pages for qpl for DQO-QPL */
- if (dev_op_dqo_qpl) {
- priv->tx_pages_per_qpl =
- be16_to_cpu(dev_op_dqo_qpl->tx_pages_per_qpl);
- priv->rx_pages_per_qpl =
- be16_to_cpu(dev_op_dqo_qpl->rx_pages_per_qpl);
- if (priv->tx_pages_per_qpl == 0)
- priv->tx_pages_per_qpl = DQO_QPL_DEFAULT_TX_PAGES;
- if (priv->rx_pages_per_qpl == 0)
- priv->rx_pages_per_qpl = DQO_QPL_DEFAULT_RX_PAGES;
- }
}
int gve_adminq_describe_device(struct gve_priv *priv)
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 9eb4b3614c4f5..c654cf503c1a2 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -9,6 +9,7 @@
#include <linux/etherdevice.h>
#include <linux/filter.h>
#include <linux/interrupt.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/sched.h>
@@ -1106,6 +1107,43 @@ static int gve_alloc_xdp_qpls(struct gve_priv *priv)
return err;
}
+/* For DQO, update the suggested number of pages per qpl to be more flexible
+ * and honor the "max_registered_pages" parameter from the gVNIC device.
+ *
+ * Ignore the "tx_pages_per_qpl"/"rx_pages_per_qpl" parameters indicated in the
+ * DQO-QPL device option and instead allocate up to (tx_queue_length / 2) pages
+ * per TX QPL and up to (rx_queue_length * 2) pages per RX QPL while keeping the
+ * total number of pages under "max_registered_pages".
+ */
+static void gve_update_num_qpl_pages(struct gve_priv *priv)
+{
+ u64 ideal_tx_pages, ideal_rx_pages;
+ u16 tx_num_queues, rx_num_queues;
+ u64 max_pages, tx_pages;
+
+ if (priv->queue_format != GVE_DQO_QPL_FORMAT)
+ return;
+
+ /* We want 2 pages per RX descriptor and half a page per TX descriptor,
+ * which means the fraction ideal_tx_pages / (ideal_tx_pages +
+ * ideal_rx_pages) of the pages we allocate should be for TX. Shrink
+ * proportionally as necessary to avoid allocating more than
+ * max_registered_pages total pages.
+ */
+ tx_num_queues = priv->tx_cfg.num_queues;
+ rx_num_queues = priv->rx_cfg.num_queues;
+
+ ideal_tx_pages = (u64)priv->tx_desc_cnt * tx_num_queues / 2;
+ ideal_rx_pages = (u64)priv->rx_desc_cnt * rx_num_queues * 2;
+ max_pages = min(priv->max_registered_pages,
+ ideal_tx_pages + ideal_rx_pages);
+
+ tx_pages = div64_u64(max_pages * ideal_tx_pages,
+ ideal_tx_pages + ideal_rx_pages);
+ priv->tx_pages_per_qpl = div_u64(tx_pages, tx_num_queues);
+ priv->rx_pages_per_qpl = div_u64(max_pages - tx_pages, rx_num_queues);
+}
+
static int gve_alloc_qpls(struct gve_priv *priv)
{
int max_queues = priv->tx_cfg.max_queues + priv->rx_cfg.max_queues;
@@ -1117,6 +1155,8 @@ static int gve_alloc_qpls(struct gve_priv *priv)
if (!gve_is_qpl(priv))
return 0;
+ gve_update_num_qpl_pages(priv);
+
priv->qpls = kvcalloc(max_queues, sizeof(*priv->qpls), GFP_KERNEL);
if (!priv->qpls)
return -ENOMEM;
--
2.43.0