From d5335bead2b87ffbf9e768dd475f68e0e8ad65a2 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Fri, 21 Aug 2026 12:35:59 +0300 Subject: [PATCH] Add gve patches --- config.yaml | 15 + ...e-Update-QPL-page-registration-logic.patch | 160 ++++++++++ ...inq-support-for-modifiable-ring-size.patch | 274 ++++++++++++++++++ ...htool-support-for-changing-ring-size.patch | 166 +++++++++++ ...-harden-modifiable-ring-size-support.patch | 120 ++++++++ ...bf455d75ce54314efc826364259b8a87a8d0.patch | 54 ---- 6 files changed, 735 insertions(+), 54 deletions(-) create mode 100644 files/2100-gve-Update-QPL-page-registration-logic.patch create mode 100644 files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch create mode 100644 files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch create mode 100644 files/2103-gve-harden-modifiable-ring-size-support.patch delete mode 100644 files/b86dbf455d75ce54314efc826364259b8a87a8d0.patch diff --git a/config.yaml b/config.yaml index e173998..2cd34da 100644 --- a/config.yaml +++ b/config.yaml @@ -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 diff --git a/files/2100-gve-Update-QPL-page-registration-logic.patch b/files/2100-gve-Update-QPL-page-registration-logic.patch new file mode 100644 index 0000000..5cff277 --- /dev/null +++ b/files/2100-gve-Update-QPL-page-registration-logic.patch @@ -0,0 +1,160 @@ +From 07993df560917357610e0625a9a2e7531c3211fc Mon Sep 17 00:00:00 2001 +From: Matt Olson +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 +Signed-off-by: Max Yuan +Reviewed-by: Jordan Rhee +Reviewed-by: Harshitha Ramamurthy +Reviewed-by: Willem de Bruijn +Reviewed-by: Praveen Kaligineedi +Signed-off-by: Joshua Washington +Link: https://patch.msgid.link/20260225182342.1049816-2-joshwash@google.com +Signed-off-by: Jakub Kicinski +[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 +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 diff --git a/files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch b/files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch new file mode 100644 index 0000000..8f0d77c --- /dev/null +++ b/files/2101-gve-Add-adminq-support-for-modifiable-ring-size.patch @@ -0,0 +1,274 @@ +From: Joshua Washington +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 +--- +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 + diff --git a/files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch b/files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch new file mode 100644 index 0000000..3521848 --- /dev/null +++ b/files/2102-gve-Add-ethtool-support-for-changing-ring-size.patch @@ -0,0 +1,166 @@ +From: Joshua Washington +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 +--- +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 + #include ++#include + #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 + diff --git a/files/2103-gve-harden-modifiable-ring-size-support.patch b/files/2103-gve-harden-modifiable-ring-size-support.patch new file mode 100644 index 0000000..74ad158 --- /dev/null +++ b/files/2103-gve-harden-modifiable-ring-size-support.patch @@ -0,0 +1,120 @@ +From: Jonathan Wright +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 +--- +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 + diff --git a/files/b86dbf455d75ce54314efc826364259b8a87a8d0.patch b/files/b86dbf455d75ce54314efc826364259b8a87a8d0.patch deleted file mode 100644 index f68a5e9..0000000 --- a/files/b86dbf455d75ce54314efc826364259b8a87a8d0.patch +++ /dev/null @@ -1,54 +0,0 @@ -From b86dbf455d75ce54314efc826364259b8a87a8d0 Mon Sep 17 00:00:00 2001 -From: Olga Kornievskaia -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 -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 - Fixes: 66af25799940 ("NFSD: add courteous server support for thread with only delegation") - Cc: stable@vger.kernel.org - Reviewed-by: Jeff Layton - Signed-off-by: Chuck Lever - -Signed-off-by: Olga Kornievskaia ---- - 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 -