Add gve patches

This commit is contained in:
eabdullin 2026-08-21 12:35:59 +03:00
parent 3b87ad6a08
commit d5335bead2
6 changed files with 735 additions and 54 deletions

View File

@ -27,6 +27,21 @@ actions:
- type: "patch"
name: "0001-proc-fix-a-dentry-lock-race-between-release_task-and-lookup.patch"
number: 2009
# GVE patches
- type: "patch"
name: "2100-gve-Update-QPL-page-registration-logic.patch"
number: 2100
- type: "patch"
name: "2101-gve-Add-adminq-support-for-modifiable-ring-size.patch"
number: 2101
- type: "patch"
name: "2102-gve-Add-ethtool-support-for-changing-ring-size.patch"
number: 2102
- type: "patch"
name: "2103-gve-harden-modifiable-ring-size-support.patch"
number: 2103
- type: "source"
name: "almalinuxdup1.x509"
number: 100

View File

@ -0,0 +1,160 @@
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

View File

@ -0,0 +1,274 @@
From: Joshua Washington <joshwash@google.com>
Date: Fri, 5 Jun 2026 00:00:00 +0000
Subject: gve: Add adminq support for modifiable ring size
Add support for the gVNIC "modify ring" device option, which allows the
device to report the maximum and minimum TX/RX ring sizes it supports.
Store those bounds in the priv struct and report the device-provided
maximums through ethtool -g "Pre-set maximums" instead of hardcoding the
current (default) ring size as the maximum.
If the device does not provide minimums, fall back to the default
minimums of 256 descriptors for TX and 512 for RX.
This is the first half of the upstream gve modifiable-ring-size feature.
It only changes the advertised ring size range; actually resizing the
rings is added in the following patch.
[Jonathan Wright: backported the upstream modifiable-ring-size support to
this kernel's gve, using the implementation carried by the RHEL 10 /
AlmaLinux 10 gve driver (kernel 6.12.0-211.7.1.el10_2) as the reference,
since this 5.14-based gve predates the feature entirely. Adaptations:
threaded dev_op_modify_ring through this tree's smaller
gve_parse_device_option()/gve_process_device_options() signatures; seeded
the default ring-size ranges in both gve_set_desc_cnt() and
gve_set_desc_cnt_dqo(). Dropped the upstream
"if (priv->queue_format != GVE_DQO_QPL_FORMAT)" guard around the max ring
size assignment: that guard exists because DQO-QPL used a fixed QPL page
budget, which no longer applies now that QPL pages scale with ring size
(see 1106-gve-Update-QPL-page-registration-logic.patch), and keeping it
would deny DQO-QPL VMs the larger ring sizes this feature is for.]
Signed-off-by: Jonathan Wright <jonathan@almalinux.org>
---
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index f916e81..a3c1caa 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -52,6 +52,9 @@
#define GVE_DEFAULT_RX_BUFFER_OFFSET 2048
+#define GVE_DEFAULT_MIN_TX_RING_SIZE 256
+#define GVE_DEFAULT_MIN_RX_RING_SIZE 512
+
#define GVE_XDP_ACTIONS 5
#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
@@ -647,6 +650,12 @@ struct gve_priv {
u16 num_event_counters;
u16 tx_desc_cnt; /* num desc per ring */
u16 rx_desc_cnt; /* num desc per ring */
+ u16 max_tx_desc_cnt;
+ u16 max_rx_desc_cnt;
+ u16 min_tx_desc_cnt;
+ u16 min_rx_desc_cnt;
+ bool modify_ring_size_enabled;
+ bool default_min_ring_size;
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 */
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index 62817f8..b7f86bc 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -20,6 +20,8 @@
#define GVE_DEVICE_OPTION_TOO_BIG_FMT "Length of %s option larger than expected. Possible older version of guest driver.\n"
+#define GVE_DEVICE_OPTION_NO_MIN_RING_SIZE 8
+
static
struct gve_device_option *gve_get_next_option(struct gve_device_descriptor *descriptor,
struct gve_device_option *option)
@@ -40,7 +42,8 @@ void gve_parse_device_option(struct gve_priv *priv,
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
- struct gve_device_option_dqo_qpl **dev_op_dqo_qpl)
+ struct gve_device_option_dqo_qpl **dev_op_dqo_qpl,
+ struct gve_device_option_modify_ring **dev_op_modify_ring)
{
u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
u16 option_length = be16_to_cpu(option->option_length);
@@ -129,6 +132,27 @@ void gve_parse_device_option(struct gve_priv *priv,
}
*dev_op_dqo_qpl = (void *)(option + 1);
break;
+ case GVE_DEV_OPT_ID_MODIFY_RING:
+ if (option_length < GVE_DEVICE_OPTION_NO_MIN_RING_SIZE ||
+ req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING) {
+ dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT,
+ "Modify Ring", (int)sizeof(**dev_op_modify_ring),
+ GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING,
+ option_length, req_feat_mask);
+ break;
+ }
+
+ if (option_length > sizeof(**dev_op_modify_ring)) {
+ dev_warn(&priv->pdev->dev,
+ GVE_DEVICE_OPTION_TOO_BIG_FMT, "Modify Ring");
+ }
+
+ *dev_op_modify_ring = (void *)(option + 1);
+
+ /* device has not provided min ring size */
+ if (option_length == GVE_DEVICE_OPTION_NO_MIN_RING_SIZE)
+ priv->default_min_ring_size = true;
+ break;
case GVE_DEV_OPT_ID_JUMBO_FRAMES:
if (option_length < sizeof(**dev_op_jumbo_frames) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) {
@@ -164,7 +188,8 @@ gve_process_device_options(struct gve_priv *priv,
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
- struct gve_device_option_dqo_qpl **dev_op_dqo_qpl)
+ struct gve_device_option_dqo_qpl **dev_op_dqo_qpl,
+ struct gve_device_option_modify_ring **dev_op_modify_ring)
{
const int num_options = be16_to_cpu(descriptor->num_device_options);
struct gve_device_option *dev_opt;
@@ -185,7 +210,7 @@ gve_process_device_options(struct gve_priv *priv,
gve_parse_device_option(priv, descriptor, dev_opt,
dev_op_gqi_rda, dev_op_gqi_qpl,
dev_op_dqo_rda, dev_op_jumbo_frames,
- dev_op_dqo_qpl);
+ dev_op_dqo_qpl, dev_op_modify_ring);
dev_opt = next_opt;
}
@@ -728,6 +753,12 @@ static int gve_set_desc_cnt(struct gve_priv *priv,
{
priv->tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
+
+ /* set default ranges */
+ priv->max_tx_desc_cnt = priv->tx_desc_cnt;
+ priv->max_rx_desc_cnt = priv->rx_desc_cnt;
+ priv->min_tx_desc_cnt = priv->tx_desc_cnt;
+ priv->min_rx_desc_cnt = priv->rx_desc_cnt;
return 0;
}
@@ -739,6 +770,12 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv,
priv->tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
+ /* set default ranges */
+ priv->max_tx_desc_cnt = priv->tx_desc_cnt;
+ priv->max_rx_desc_cnt = priv->rx_desc_cnt;
+ priv->min_tx_desc_cnt = priv->tx_desc_cnt;
+ priv->min_rx_desc_cnt = priv->rx_desc_cnt;
+
if (priv->queue_format == GVE_DQO_QPL_FORMAT)
return 0;
@@ -755,7 +792,9 @@ static void gve_enable_supported_features(struct gve_priv *priv,
const struct gve_device_option_jumbo_frames
*dev_op_jumbo_frames,
const struct gve_device_option_dqo_qpl
- *dev_op_dqo_qpl)
+ *dev_op_dqo_qpl,
+ const struct gve_device_option_modify_ring
+ *dev_op_modify_ring)
{
/* Before control reaches this point, the page-size-capped max MTU from
* the gve_device_descriptor field has already been stored in
@@ -767,10 +806,29 @@ 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);
}
+
+ /* Read and store ring size ranges given by device */
+ if (dev_op_modify_ring &&
+ (supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) {
+ priv->modify_ring_size_enabled = true;
+
+ priv->max_rx_desc_cnt = be16_to_cpu(dev_op_modify_ring->max_rx_ring_size);
+ priv->max_tx_desc_cnt = be16_to_cpu(dev_op_modify_ring->max_tx_ring_size);
+
+ if (priv->default_min_ring_size) {
+ /* If device hasn't provided minimums, use default minimums */
+ priv->min_tx_desc_cnt = GVE_DEFAULT_MIN_TX_RING_SIZE;
+ priv->min_rx_desc_cnt = GVE_DEFAULT_MIN_RX_RING_SIZE;
+ } else {
+ priv->min_rx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_rx_ring_size);
+ priv->min_tx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_tx_ring_size);
+ }
+ }
}
int gve_adminq_describe_device(struct gve_priv *priv)
{
+ struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
@@ -804,7 +862,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda,
&dev_op_gqi_qpl, &dev_op_dqo_rda,
&dev_op_jumbo_frames,
- &dev_op_dqo_qpl);
+ &dev_op_dqo_qpl, &dev_op_modify_ring);
if (err)
goto free_device_descriptor;
@@ -873,7 +931,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues);
gve_enable_supported_features(priv, supported_features_mask,
- dev_op_jumbo_frames, dev_op_dqo_qpl);
+ dev_op_jumbo_frames, dev_op_dqo_qpl,
+ dev_op_modify_ring);
free_device_descriptor:
dma_pool_free(priv->adminq_pool, descriptor, descriptor_bus);
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
index 5865ccd..0d1dd38 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.h
+++ b/drivers/net/ethernet/google/gve/gve_adminq.h
@@ -125,6 +125,16 @@ struct gve_device_option_jumbo_frames {
static_assert(sizeof(struct gve_device_option_jumbo_frames) == 8);
+struct gve_device_option_modify_ring {
+ __be32 supported_featured_mask;
+ __be16 max_rx_ring_size;
+ __be16 max_tx_ring_size;
+ __be16 min_rx_ring_size;
+ __be16 min_tx_ring_size;
+};
+
+static_assert(sizeof(struct gve_device_option_modify_ring) == 12);
+
/* Terminology:
*
* RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
@@ -138,6 +148,7 @@ enum gve_dev_opt_id {
GVE_DEV_OPT_ID_GQI_RDA = 0x2,
GVE_DEV_OPT_ID_GQI_QPL = 0x3,
GVE_DEV_OPT_ID_DQO_RDA = 0x4,
+ GVE_DEV_OPT_ID_MODIFY_RING = 0x6,
GVE_DEV_OPT_ID_DQO_QPL = 0x7,
GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8,
};
@@ -149,9 +160,11 @@ enum gve_dev_opt_req_feat_mask {
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL = 0x0,
+ GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING = 0x0,
};
enum gve_sup_feature_mask {
+ GVE_SUP_MODIFY_RING_MASK = 1 << 0,
GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2,
};
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index e5397aa..fb7b477 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -476,8 +476,8 @@ static void gve_get_ringparam(struct net_device *netdev,
{
struct gve_priv *priv = netdev_priv(netdev);
- cmd->rx_max_pending = priv->rx_desc_cnt;
- cmd->tx_max_pending = priv->tx_desc_cnt;
+ cmd->rx_max_pending = priv->max_rx_desc_cnt;
+ cmd->tx_max_pending = priv->max_tx_desc_cnt;
cmd->rx_pending = priv->rx_desc_cnt;
cmd->tx_pending = priv->tx_desc_cnt;
}
--
2.43.0

View File

@ -0,0 +1,166 @@
From: Joshua Washington <joshwash@google.com>
Date: Fri, 5 Jun 2026 00:00:01 +0000
Subject: gve: Add ethtool support for changing ring size
Add ethtool -G (set_ringparam) support so the TX/RX ring sizes can
actually be changed within the bounds reported by the device in the
"modify ring" device option.
Requested ring sizes are validated against the device-provided minimums
and maximums and must be a power of two. Changing the ring size tears the
device down, applies the new descriptor counts, and brings it back up.
[Jonathan Wright: backported the upstream modifiable-ring-size support to
this kernel's gve, using the RHEL 10 / AlmaLinux 10 gve driver
(kernel 6.12.0-211.7.1.el10_2) as the reference. Adaptations: upstream's
gve_adjust_ring_sizes() reconfigures via gve_get_curr_alloc_cfgs() /
gve_adjust_config(), which do not exist in this tree (it predates the
gve_{tx,rx}_alloc_rings_cfg / queues_mem_alloc refactor). Instead
gve_adjust_ring_sizes() lives in gve_main.c and follows the existing
gve_adjust_queues() pattern used by this tree for ethtool -L: teardown
with gve_close(), set the new descriptor counts, then gve_open(), which
rebuilds the rings and re-sizes the QPLs from the new ring size via
gve_update_num_qpl_pages() (1106). It is declared in gve.h because
gve_close()/gve_open() are static to gve_main.c. Upstream's
gve_set_ringparam() also handles header-split/tcp_data_split; that
feature does not exist in this tree, so only the ring-size logic is
carried over.]
Signed-off-by: Jonathan Wright <jonathan@almalinux.org>
---
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index a3c1caa..acac856 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -1074,6 +1074,9 @@ int gve_reset(struct gve_priv *priv, bool attempt_teardown);
int gve_adjust_queues(struct gve_priv *priv,
struct gve_queue_config new_rx_config,
struct gve_queue_config new_tx_config);
+int gve_adjust_ring_sizes(struct gve_priv *priv,
+ u16 new_tx_desc_cnt,
+ u16 new_rx_desc_cnt);
/* report stats handling */
void gve_handle_report_stats(struct gve_priv *priv);
/* exported by ethtool.c */
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index fb7b477..a8822c9 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -6,6 +6,7 @@
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
+#include <linux/log2.h>
#include "gve.h"
#include "gve_adminq.h"
#include "gve_dqo.h"
@@ -482,6 +483,50 @@ static void gve_get_ringparam(struct net_device *netdev,
cmd->tx_pending = priv->tx_desc_cnt;
}
+static int gve_validate_req_ring_size(struct gve_priv *priv, u16 new_tx_desc_cnt,
+ u16 new_rx_desc_cnt)
+{
+ /* check for valid range */
+ if (new_tx_desc_cnt < priv->min_tx_desc_cnt ||
+ new_tx_desc_cnt > priv->max_tx_desc_cnt ||
+ new_rx_desc_cnt < priv->min_rx_desc_cnt ||
+ new_rx_desc_cnt > priv->max_rx_desc_cnt) {
+ dev_err(&priv->pdev->dev, "Requested descriptor count out of range\n");
+ return -EINVAL;
+ }
+
+ if (!is_power_of_2(new_tx_desc_cnt) || !is_power_of_2(new_rx_desc_cnt)) {
+ dev_err(&priv->pdev->dev, "Requested descriptor count has to be a power of 2\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int gve_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *cmd,
+ struct kernel_ethtool_ringparam *kernel_cmd,
+ struct netlink_ext_ack *extack)
+{
+ struct gve_priv *priv = netdev_priv(netdev);
+ u16 new_tx_cnt, new_rx_cnt;
+
+ if (cmd->tx_pending == priv->tx_desc_cnt && cmd->rx_pending == priv->rx_desc_cnt)
+ return 0;
+
+ if (!priv->modify_ring_size_enabled) {
+ dev_err(&priv->pdev->dev, "Modify ring size is not supported.\n");
+ return -EOPNOTSUPP;
+ }
+
+ new_tx_cnt = cmd->tx_pending;
+ new_rx_cnt = cmd->rx_pending;
+
+ if (gve_validate_req_ring_size(priv, new_tx_cnt, new_rx_cnt))
+ return -EINVAL;
+
+ return gve_adjust_ring_sizes(priv, new_tx_cnt, new_rx_cnt);
+}
+
static int gve_user_reset(struct net_device *netdev, u32 *flags)
{
struct gve_priv *priv = netdev_priv(netdev);
@@ -667,6 +712,7 @@ const struct ethtool_ops gve_ethtool_ops = {
.get_coalesce = gve_get_coalesce,
.set_coalesce = gve_set_coalesce,
.get_ringparam = gve_get_ringparam,
+ .set_ringparam = gve_set_ringparam,
.reset = gve_user_reset,
.get_tunable = gve_get_tunable,
.set_tunable = gve_set_tunable,
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index a21df52..e939750 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1780,6 +1780,44 @@ err:
return err;
}
+int gve_adjust_ring_sizes(struct gve_priv *priv,
+ u16 new_tx_desc_cnt,
+ u16 new_rx_desc_cnt)
+{
+ int err;
+
+ if (netif_carrier_ok(priv->dev)) {
+ /* To make this process as simple as possible we teardown the
+ * device, set the new ring sizes, and then bring the device
+ * up again.
+ */
+ err = gve_close(priv->dev);
+ /* we have already tried to reset in close,
+ * just fail at this point
+ */
+ if (err)
+ return err;
+ priv->tx_desc_cnt = new_tx_desc_cnt;
+ priv->rx_desc_cnt = new_rx_desc_cnt;
+
+ err = gve_open(priv->dev);
+ if (err)
+ goto err;
+
+ return 0;
+ }
+ /* Set the ring sizes for the next up. */
+ priv->tx_desc_cnt = new_tx_desc_cnt;
+ priv->rx_desc_cnt = new_rx_desc_cnt;
+
+ return 0;
+err:
+ netif_err(priv, drv, priv->dev,
+ "Adjust ring sizes failed! !!! DISABLING ALL QUEUES !!!\n");
+ gve_turndown(priv);
+ return err;
+}
+
static void gve_turndown(struct gve_priv *priv)
{
int idx;
--
2.43.0

View File

@ -0,0 +1,120 @@
From: Jonathan Wright <jonathan@almalinux.org>
Date: Wed, 5 Aug 2026 00:00:00 +0000
Subject: gve: harden modifiable ring size support for the EL9 gve architecture
Follow-up hardening for the modifiable-ring-size backport (patches 1107
and 1108), addressing three ways the older EL9 gve architecture differs
from the EL10/upstream driver the feature was designed against. Found in
review; none affect the DQO resize paths already validated on GCP.
1) Do not enable modifiable ring sizes for GQI queue formats.
In this kernel's gve, the GQI branches of
gve_adminq_create_{tx,rx}_queue carry no ring size (only the DQO
branches send one), so after a resize the device would keep using its
probe-time default ring size against rings the driver re-sized:
device and driver would index the same DMA memory modulo different
sizes. Shrinking the RX ring would additionally let the device DMA
past the smaller allocation, and the GQI datapath sizes its data ring
and mask from the fixed rx_data_slot_cnt (with a NAPI livelock
possible on GQI-RDA once rx_desc_cnt >= 2 * data slots). Gate the
feature on !gve_is_gqi(): GQI keeps the pre-feature fixed-ring
behavior and ethtool -G returns -EOPNOTSUPP.
2) Key gve_adjust_ring_sizes() on netif_running(), not
netif_carrier_ok(), matching the EL10 implementation. The rings are
allocated whenever the interface is administratively up, even while
the link is down; taking the "set for next up" shortcut in that state
would change priv->{tx,rx}_desc_cnt under allocated rings, and the
GQI RX free path sizes dma_free_coherent() from priv->rx_desc_cnt.
3) Clamp the advertised ring size range for DQO-RDA. In this kernel the
DQO-RDA TX completion ring and RX buffer ring keep the fixed sizes
from the DQO-RDA device option and do not scale with the descriptor
rings (upstream removed that coupling before modifiable ring sizes
were introduced). Growing the TX ring beyond tx_comp_ring_entries
could overrun the TX completion queue with report-event completions
(num_pending_packets reserves complq_size/32 slots for REs, but REs
scale with posted descriptors on the grown ring) or have queue
creation rejected; shrinking the RX descriptor/completion ring below
rx_buff_ring_entries could overflow the RX completion queue. Clamp
max_tx_desc_cnt and min_rx_desc_cnt so such sizes cannot be
requested. DQO-QPL is unaffected (its completion/buffer rings track
the descriptor ring size).
Signed-off-by: Jonathan Wright <jonathan@almalinux.org>
---
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index b7f86bc..eef7cca 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -807,8 +807,18 @@ static void gve_enable_supported_features(struct gve_priv *priv,
priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
}
- /* Read and store ring size ranges given by device */
- if (dev_op_modify_ring &&
+ /* Read and store ring size ranges given by device.
+ *
+ * Modifiable ring sizes are supported for DQO queue formats only.
+ * In this kernel's gve, the GQI branches of
+ * gve_adminq_create_{tx,rx}_queue do not carry a ring size, so after
+ * a resize the device would keep using its default ring size against
+ * rings the driver re-sized, desynchronizing device and driver views
+ * of the rings. The GQI datapath (rx_data_slot_cnt data ring, TX
+ * FIFO) also assumes the probe-time fixed ring sizes. Keep GQI at
+ * fixed ring sizes.
+ */
+ if (dev_op_modify_ring && !gve_is_gqi(priv) &&
(supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) {
priv->modify_ring_size_enabled = true;
@@ -823,6 +833,27 @@ static void gve_enable_supported_features(struct gve_priv *priv,
priv->min_rx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_rx_ring_size);
priv->min_tx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_tx_ring_size);
}
+
+ /* In this kernel's gve, the DQO-RDA TX completion ring and RX
+ * buffer ring keep the fixed sizes provided in the DQO-RDA
+ * device option; they do not scale with the descriptor rings
+ * (upstream removed that coupling before modifiable ring
+ * sizes were introduced). Clamp the advertised range so a
+ * resize cannot create a descriptor ring the fixed rings
+ * cannot absorb:
+ * - growing the TX ring beyond tx_comp_ring_entries could
+ * overrun the TX completion queue with report-event
+ * completions (or be rejected at queue creation);
+ * - shrinking the RX ring (the RX completion queue) below
+ * rx_buff_ring_entries could overflow the RX completion
+ * queue.
+ */
+ if (priv->queue_format == GVE_DQO_RDA_FORMAT) {
+ priv->max_tx_desc_cnt = min(priv->max_tx_desc_cnt,
+ priv->options_dqo_rda.tx_comp_ring_entries);
+ priv->min_rx_desc_cnt = max(priv->min_rx_desc_cnt,
+ priv->options_dqo_rda.rx_buff_ring_entries);
+ }
}
}
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index e939750..516f222 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -1786,7 +1786,14 @@ int gve_adjust_ring_sizes(struct gve_priv *priv,
{
int err;
- if (netif_carrier_ok(priv->dev)) {
+ /* Key on the administrative state (netif_running), not the link
+ * state: the rings are allocated whenever the interface is up, even
+ * while the carrier is down. Changing the descriptor counts without
+ * reallocating the rings would desynchronize them from
+ * priv->{tx,rx}_desc_cnt, which the GQI free path uses to size
+ * dma_free_coherent().
+ */
+ if (netif_running(priv->dev)) {
/* To make this process as simple as possible we teardown the
* device, set the new ring sizes, and then bring the device
* up again.
--
2.43.0

View File

@ -1,54 +0,0 @@
From b86dbf455d75ce54314efc826364259b8a87a8d0 Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <okorniev@redhat.com>
Date: Mon, 3 Mar 2025 12:09:08 -0500
Subject: [PATCH] NFSD: fix hang in nfsd4_shutdown_callback
JIRA: https://issues.redhat.com/browse/RHEL-81291
CVE: CVE-2025-21795
commit 036ac2778f7b28885814c6fbc07e156ad1624d03
Author: Dai Ngo <dai.ngo@oracle.com>
Date: Thu Jan 30 11:01:27 2025 -0800
NFSD: fix hang in nfsd4_shutdown_callback
If nfs4_client is in courtesy state then there is no point to send
the callback. This causes nfsd4_shutdown_callback to hang since
cl_cb_inflight is not 0. This hang lasts about 15 minutes until TCP
notifies NFSD that the connection was dropped.
This patch modifies nfsd4_run_cb_work to skip the RPC call if
nfs4_client is in courtesy state.
Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
Fixes: 66af25799940 ("NFSD: add courteous server support for thread with only delegation")
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
---
fs/nfsd/nfs4callback.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 0d7cc2f9a8e07..d8eed853d528d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1480,8 +1480,11 @@ nfsd4_run_cb_work(struct work_struct *work)
nfsd4_process_cb_update(cb);
clnt = clp->cl_cb_client;
- if (!clnt) {
- /* Callback channel broken, or client killed; give up: */
+ if (!clnt || clp->cl_state == NFSD4_COURTESY) {
+ /*
+ * Callback channel broken, client killed or
+ * nfs4_client in courtesy state; give up.
+ */
nfsd41_destroy_cb(cb);
return;
}
--
GitLab