Add gve patches
This commit is contained in:
parent
3b87ad6a08
commit
d5335bead2
15
config.yaml
15
config.yaml
@ -27,6 +27,21 @@ actions:
|
|||||||
- type: "patch"
|
- type: "patch"
|
||||||
name: "0001-proc-fix-a-dentry-lock-race-between-release_task-and-lookup.patch"
|
name: "0001-proc-fix-a-dentry-lock-race-between-release_task-and-lookup.patch"
|
||||||
number: 2009
|
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"
|
- type: "source"
|
||||||
name: "almalinuxdup1.x509"
|
name: "almalinuxdup1.x509"
|
||||||
number: 100
|
number: 100
|
||||||
|
|||||||
160
files/2100-gve-Update-QPL-page-registration-logic.patch
Normal file
160
files/2100-gve-Update-QPL-page-registration-logic.patch
Normal 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
|
||||||
274
files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch
Normal file
274
files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch
Normal 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
|
||||||
|
|
||||||
166
files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch
Normal file
166
files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch
Normal 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
|
||||||
|
|
||||||
120
files/2103-gve-harden-modifiable-ring-size-support.patch
Normal file
120
files/2103-gve-harden-modifiable-ring-size-support.patch
Normal 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
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user