161 lines
6.7 KiB
Diff
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
|