From fe180f67321a550a6d6631967567f23c348b9596 Mon Sep 17 00:00:00 2001 From: Ankit Garg Date: Fri, 19 Dec 2025 10:29:45 +0000 Subject: [PATCH 01/12] gve: defer interrupt enabling until NAPI registration Currently, interrupts are automatically enabled immediately upon request. This allows interrupt to fire before the associated NAPI context is fully initialized and cause failures like below: [ 0.946369] Call Trace: [ 0.946369] [ 0.946369] __napi_poll+0x2a/0x1e0 [ 0.946369] net_rx_action+0x2f9/0x3f0 [ 0.946369] handle_softirqs+0xd6/0x2c0 [ 0.946369] ? handle_edge_irq+0xc1/0x1b0 [ 0.946369] __irq_exit_rcu+0xc3/0xe0 [ 0.946369] common_interrupt+0x81/0xa0 [ 0.946369] [ 0.946369] [ 0.946369] asm_common_interrupt+0x22/0x40 [ 0.946369] RIP: 0010:pv_native_safe_halt+0xb/0x10 Use the `IRQF_NO_AUTOEN` flag when requesting interrupts to prevent auto enablement and explicitly enable the interrupt in NAPI initialization path (and disable it during NAPI teardown). This ensures that interrupt lifecycle is strictly coupled with readiness of NAPI context. Cc: stable@vger.kernel.org Fixes: 1dfc2e46117e ("gve: Refactor napi add and remove functions") Signed-off-by: Ankit Garg Reviewed-by: Jordan Rhee Reviewed-by: Joshua Washington Signed-off-by: Harshitha Ramamurthy Link: https://patch.msgid.link/20251219102945.2193617-1-hramamurthy@google.com Signed-off-by: Paolo Abeni net-next: 3d970eda003441f66551a91fda16478ac0711617 --- build/gve_desc_dqo.h | 2 +- build/gve_main.c | 10 +++++++++- build/gve_rx_dqo.c | 2 +- build/gve_utils.c | 2 ++ google/gve/gve_main.c | 2 +- google/gve/gve_utils.c | 2 ++ patches/irq.cocci | 13 +++++++++++++ 7 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 patches/irq.cocci diff --git a/build/gve_desc_dqo.h b/build/gve_desc_dqo.h index db7378c..9354e2c 100644 --- a/build/gve_desc_dqo.h +++ b/build/gve_desc_dqo.h @@ -19,7 +19,7 @@ #define GVE_TX_MIN_TSO_MSS_DQO 88 #ifndef __LITTLE_ENDIAN_BITFIELD -#error "Only little endian supported" +"Only little endian supported" #endif /* Basic TX descriptor (DTYPE 0x0C) */ diff --git a/build/gve_main.c b/build/gve_main.c index 9a0e239..b54f35d 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--34ae86a-oot" +#define GVE_VERSION "1.4.8-0--92f2d02-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) @@ -706,9 +706,17 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv) snprintf(block->name, sizeof(block->name), "gve-ntfy-blk%d@pci:%s", i, pci_name(priv->pdev)); block->priv = priv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) + err = request_irq(priv->msix_vectors[msix_idx].vector, + gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, + IRQF_NO_AUTOEN, block->name, block); +#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) */ + irq_set_status_flags(priv->msix_vectors[msix_idx].vector, + IRQ_NOAUTOEN); err = request_irq(priv->msix_vectors[msix_idx].vector, gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, 0, block->name, block); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) */ if (err) { dev_err(&priv->pdev->dev, "Failed to receive msix vector %d\n", i); diff --git a/build/gve_rx_dqo.c b/build/gve_rx_dqo.c index f0d0da4..db08c65 100644 --- a/build/gve_rx_dqo.c +++ b/build/gve_rx_dqo.c @@ -1046,7 +1046,7 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) if (!rx->ctx.skb_head && rx->dqo.page_pool && netmem_is_net_iov(buf_state->page_info.netmem)) { - /* when header split is disabled, the header went to the packet + /* when header split is disabled, the header went to the packet * buffer. If the packet buffer is a net_iov, those can't be * easily mapped into the kernel space to access the header * required to process the packet. diff --git a/build/gve_utils.c b/build/gve_utils.c index fc7304c..1d259d7 100644 --- a/build/gve_utils.c +++ b/build/gve_utils.c @@ -133,12 +133,14 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx, netif_napi_set_irq(&block->napi, block->irq); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ + enable_irq(block->irq); } void gve_remove_napi(struct gve_priv *priv, int ntfy_idx) { struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx]; + disable_irq(block->irq); #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) netif_napi_del_locked(&block->napi); #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ diff --git a/google/gve/gve_main.c b/google/gve/gve_main.c index 2590028..6dd4f3b 100644 --- a/google/gve/gve_main.c +++ b/google/gve/gve_main.c @@ -558,7 +558,7 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv) block->priv = priv; err = request_irq(priv->msix_vectors[msix_idx].vector, gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, - 0, block->name, block); + IRQF_NO_AUTOEN, block->name, block); if (err) { dev_err(&priv->pdev->dev, "Failed to receive msix vector %d\n", i); diff --git a/google/gve/gve_utils.c b/google/gve/gve_utils.c index ace9b86..b53b7fc 100644 --- a/google/gve/gve_utils.c +++ b/google/gve/gve_utils.c @@ -112,11 +112,13 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx, netif_napi_add_locked(priv->dev, &block->napi, gve_poll); netif_napi_set_irq_locked(&block->napi, block->irq); + enable_irq(block->irq); } void gve_remove_napi(struct gve_priv *priv, int ntfy_idx) { struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx]; + disable_irq(block->irq); netif_napi_del_locked(&block->napi); } diff --git a/patches/irq.cocci b/patches/irq.cocci new file mode 100644 index 0000000..5f45324 --- /dev/null +++ b/patches/irq.cocci @@ -0,0 +1,13 @@ +@@ +@@ + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) +err = request_irq(priv->msix_vectors[msix_idx].vector, + gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, + IRQF_NO_AUTOEN, block->name, block); ++#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) */ ++irq_set_status_flags(priv->msix_vectors[msix_idx].vector, IRQ_NOAUTOEN); ++err = request_irq(priv->msix_vectors[msix_idx].vector, ++ gve_is_gqi(priv) ? gve_intr : gve_intr_dqo, ++ 0, block->name, block); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0) */ \ No newline at end of file From b93bba155524dd3b662d41b3598d7eed2bd426c7 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Mon, 5 Jan 2026 07:28:26 -0800 Subject: [PATCH 02/12] net: gve: convert to use .get_rx_ring_count Convert the Google Virtual Ethernet (GVE) driver to use the new .get_rx_ring_count ethtool operation instead of handling ETHTOOL_GRXRINGS in .get_rxnfc. This simplifies the code by moving the ring count query to a dedicated callback. The new callback provides the same functionality in a more direct way, following the ongoing ethtool API modernization. Reviewed-by: Subbaraya Sundeep Reviewed-by: Harshitha Ramamurthy Signed-off-by: Breno Leitao Link: https://patch.msgid.link/20260105-gxring_google-v2-1-e7cfe924d429@debian.org Signed-off-by: Jakub Kicinski net-next: 48b27ea6239a797b286919d549e8d8a5a54d89f3 --- build/gve_ethtool.c | 15 +++++++++++++-- build/gve_main.c | 2 +- google/gve/gve_ethtool.c | 11 ++++++++--- patches/ethtool_ntuple.cocci | 28 ++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/build/gve_ethtool.c b/build/gve_ethtool.c index 3e674e0..b381eb2 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -991,15 +991,23 @@ static int gve_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) return err; } +static u32 gve_get_rx_ring_count(struct net_device *netdev) +{ + struct gve_priv *priv = netdev_priv(netdev); + + return priv->rx_cfg.num_queues; +} + static int gve_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { struct gve_priv *priv = netdev_priv(netdev); int err = 0; switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = priv->rx_cfg.num_queues; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) + case ETHTOOL_GRXRINGS: cmd->data = gve_get_rx_ring_count(netdev); break; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) */ case ETHTOOL_GRXCLSRLCNT: if (!priv->max_flow_rules) return -EOPNOTSUPP; @@ -1233,6 +1241,9 @@ const struct ethtool_ops gve_ethtool_ops = { .get_channels = gve_get_channels, .set_rxnfc = gve_set_rxnfc, .get_rxnfc = gve_get_rxnfc, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + .get_rx_ring_count = gve_get_rx_ring_count, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ .get_rxfh_indir_size = gve_get_rxfh_indir_size, .get_rxfh_key_size = gve_get_rxfh_key_size, .get_rxfh = gve_get_rxfh, diff --git a/build/gve_main.c b/build/gve_main.c index b54f35d..34398ff 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--92f2d02-oot" +#define GVE_VERSION "1.4.8-0--caa4e54-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/google/gve/gve_ethtool.c b/google/gve/gve_ethtool.c index 52500ae..9ed1d45 100644 --- a/google/gve/gve_ethtool.c +++ b/google/gve/gve_ethtool.c @@ -815,15 +815,19 @@ static int gve_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) return err; } +static u32 gve_get_rx_ring_count(struct net_device *netdev) +{ + struct gve_priv *priv = netdev_priv(netdev); + + return priv->rx_cfg.num_queues; +} + static int gve_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { struct gve_priv *priv = netdev_priv(netdev); int err = 0; switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = priv->rx_cfg.num_queues; - break; case ETHTOOL_GRXCLSRLCNT: if (!priv->max_flow_rules) return -EOPNOTSUPP; @@ -966,6 +970,7 @@ const struct ethtool_ops gve_ethtool_ops = { .get_channels = gve_get_channels, .set_rxnfc = gve_set_rxnfc, .get_rxnfc = gve_get_rxnfc, + .get_rx_ring_count = gve_get_rx_ring_count, .get_rxfh_indir_size = gve_get_rxfh_indir_size, .get_rxfh_key_size = gve_get_rxfh_key_size, .get_rxfh = gve_get_rxfh, diff --git a/patches/ethtool_ntuple.cocci b/patches/ethtool_ntuple.cocci index cbfe099..7773b71 100644 --- a/patches/ethtool_ntuple.cocci +++ b/patches/ethtool_ntuple.cocci @@ -57,3 +57,31 @@ static int gve_set_channels(struct net_device *netdev, return gve_adjust_queues(priv, new_rx_cfg, new_tx_cfg, reset_rss); } + +@@ +@@ +static int gve_get_rxnfc(...) +{ + ... + switch (cmd->cmd) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) ++ case ETHTOOL_GRXRINGS: ++ cmd->data = gve_get_rx_ring_count(netdev); ++ break; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) */ + case ETHTOOL_GRXCLSRLCNT: + ... + } +} + +@ gve_ethtool_ops @ +identifier gve_ethtool_ops; +expression gve_get_rx_ring_count; +@@ + +const struct ethtool_ops gve_ethtool_ops = { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + .get_rx_ring_count = gve_get_rx_ring_count, ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ +}; + From 5bbc3e4c15c4013e945a0247b46632c56a25ad98 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 6 Jan 2026 13:25:40 +0000 Subject: [PATCH 03/12] net: add bare bone queue configs We'll need to pass extra parameters when allocating a queue for memory providers. Define a new structure for queue configurations, and pass it to qapi callbacks. It's empty for now, actual parameters will be added in following patches. Configurations should persist across resets, and for that they're default-initialised on device registration and stored in struct netdev_rx_queue. We also add a new qapi callback for defaulting a given config. It must be implemented if a driver wants to use queue configs and is optional otherwise. Suggested-by: Jakub Kicinski Signed-off-by: Pavel Begunkov net-next: efcb9a4d32d3d9b924642c086b868bfbb9a07c13 --- build/gve_main.c | 19 +++++++++++++++---- google/gve/gve_main.c | 9 ++++++--- patches/patch_netdev_queue_api.cocci | 15 ++++++++++++--- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/build/gve_main.c b/build/gve_main.c index 34398ff..b4e3ebd 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--caa4e54-oot" +#define GVE_VERSION "1.4.8-0--3bd3c90-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) @@ -3132,8 +3132,13 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem) #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) -static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem, - int idx) +static int gve_rx_queue_mem_alloc(struct net_device *dev +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + , + struct netdev_queue_config *qcfg +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ + , + void *per_q_mem, int idx) { struct gve_priv *priv = netdev_priv(dev); struct gve_rx_alloc_rings_cfg cfg = {0}; @@ -3156,7 +3161,13 @@ static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem, #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) -static int gve_rx_queue_start(struct net_device *dev, void *per_q_mem, int idx) +static int gve_rx_queue_start(struct net_device *dev +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + , + struct netdev_queue_config *qcfg +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ + , + void *per_q_mem, int idx) { struct gve_priv *priv = netdev_priv(dev); struct gve_rx_ring *gve_per_q_mem; diff --git a/google/gve/gve_main.c b/google/gve/gve_main.c index 6dd4f3b..129f760 100644 --- a/google/gve/gve_main.c +++ b/google/gve/gve_main.c @@ -2616,8 +2616,9 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem) gve_rx_free_ring_dqo(priv, gve_per_q_mem, &cfg); } -static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem, - int idx) +static int gve_rx_queue_mem_alloc(struct net_device *dev, + struct netdev_queue_config *qcfg, + void *per_q_mem, int idx) { struct gve_priv *priv = netdev_priv(dev); struct gve_rx_alloc_rings_cfg cfg = {0}; @@ -2638,7 +2639,9 @@ static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem, return err; } -static int gve_rx_queue_start(struct net_device *dev, void *per_q_mem, int idx) +static int gve_rx_queue_start(struct net_device *dev, + struct netdev_queue_config *qcfg, + void *per_q_mem, int idx) { struct gve_priv *priv = netdev_priv(dev); struct gve_rx_ring *gve_per_q_mem; diff --git a/patches/patch_netdev_queue_api.cocci b/patches/patch_netdev_queue_api.cocci index 40b49b6..44a7c48 100644 --- a/patches/patch_netdev_queue_api.cocci +++ b/patches/patch_netdev_queue_api.cocci @@ -34,10 +34,14 @@ static void gve_turnup_and_check_status(struct gve_priv *priv) +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) */ @@ +parameter P1, P2, P3, P4; @@ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) -static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem, - int idx) +static int gve_rx_queue_mem_alloc(P1 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + ,P2 ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ + ,P3, P4) { ... } @@ -53,9 +57,14 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem) +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) */ @@ +parameter P1, P2, P3, P4; @@ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) -static int gve_rx_queue_start(struct net_device *dev, void *per_q_mem, int idx) +static int gve_rx_queue_start(P1 ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) + ,P2 ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ + ,P3, P4) { ... } From 931965a7e3415cd32275de2d5615f0163ff3754c Mon Sep 17 00:00:00 2001 From: Jordan Rhee Date: Tue, 27 Jan 2026 01:02:10 +0000 Subject: [PATCH 04/12] gve: fix probe failure if clock read fails If timestamping is supported, GVE reads the clock during probe, which can fail for various reasons. Previously, this failure would abort the driver probe, rendering the device unusable. This behavior has been observed on production GCP VMs, causing driver initialization to fail completely. This patch allows the driver to degrade gracefully. If gve_init_clock() fails, it logs a warning and continues loading the driver without PTP support. Cc: stable@vger.kernel.org Fixes: a479a27f4da4 ("gve: Move gve_init_clock to after AQ CONFIGURE_DEVICE_RESOURCES call") Signed-off-by: Jordan Rhee Reviewed-by: Shachar Raindel Signed-off-by: Harshitha Ramamurthy Link: https://patch.msgid.link/20260127010210.969823-1-hramamurthy@google.com Signed-off-by: Jakub Kicinski net-next: a040afa3bca415019d96a586b96b5f17b1f55a90 --- build/gve.h | 5 +++++ build/gve_ethtool.c | 4 +--- build/gve_main.c | 14 ++++++++------ build/gve_ptp.c | 8 -------- build/gve_rx_dqo.c | 2 +- google/gve/gve.h | 5 +++++ google/gve/gve_ethtool.c | 2 +- google/gve/gve_main.c | 12 +++++++----- google/gve/gve_ptp.c | 8 -------- google/gve/gve_rx_dqo.c | 2 +- 10 files changed, 29 insertions(+), 33 deletions(-) diff --git a/build/gve.h b/build/gve.h index 43dbf8d..0d62a47 100644 --- a/build/gve.h +++ b/build/gve.h @@ -1266,6 +1266,11 @@ static inline bool gve_supports_xdp_xmit(struct gve_priv *priv) } } +static inline bool gve_is_clock_enabled(struct gve_priv *priv) +{ + return priv->nic_ts_report; +} + /* gqi napi handler defined in gve_main.c */ int gve_napi_poll(struct napi_struct *napi, int budget); diff --git a/build/gve_ethtool.c b/build/gve_ethtool.c index b381eb2..d8dfbdb 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -1200,9 +1200,8 @@ static int gve_get_ts_info(struct net_device *netdev struct gve_priv *priv = netdev_priv(netdev); ethtool_op_get_ts_info(netdev, info); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) - if (priv->nic_timestamp_supported) { + if (gve_is_clock_enabled(priv)) { info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -1212,7 +1211,6 @@ static int gve_get_ts_info(struct net_device *netdev if (priv->ptp) info->phc_index = ptp_clock_index(priv->ptp->clock); } -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) */ return 0; } diff --git a/build/gve_main.c b/build/gve_main.c index b4e3ebd..39f12f9 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--3bd3c90-oot" +#define GVE_VERSION "1.4.8-0--4010f8c-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) @@ -863,10 +863,12 @@ static int gve_setup_device_resources(struct gve_priv *priv) } } - err = gve_init_clock(priv); - if (err) { - dev_err(&priv->pdev->dev, "Failed to init clock"); - goto abort_with_ptype_lut; + if (priv->nic_timestamp_supported) { + err = gve_init_clock(priv); + if (err) { + dev_warn(&priv->pdev->dev, "Failed to init clock, continuing without PTP support"); + err = 0; + } } err = gve_init_rss_config(priv, priv->rx_cfg.num_queues); @@ -2597,7 +2599,7 @@ static int gve_set_ts_config(struct net_device *dev, } if (kernel_config->rx_filter != HWTSTAMP_FILTER_NONE) { - if (!priv->nic_ts_report) { + if (!gve_is_clock_enabled(priv)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) NL_SET_ERR_MSG_MOD(extack, "RX timestamping is not supported"); diff --git a/build/gve_ptp.c b/build/gve_ptp.c index 2e07401..7a03bec 100644 --- a/build/gve_ptp.c +++ b/build/gve_ptp.c @@ -84,11 +84,6 @@ static int gve_ptp_init(struct gve_priv *priv) struct gve_ptp *ptp; int err; - if (!priv->nic_timestamp_supported) { - dev_dbg(&priv->pdev->dev, "Device does not support PTP\n"); - return -EOPNOTSUPP; - } - priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL); if (!priv->ptp) return -ENOMEM; @@ -130,9 +125,6 @@ int gve_init_clock(struct gve_priv *priv) { int err; - if (!priv->nic_timestamp_supported) - return 0; - err = gve_ptp_init(priv); if (err) return err; diff --git a/build/gve_rx_dqo.c b/build/gve_rx_dqo.c index db08c65..400cbf1 100644 --- a/build/gve_rx_dqo.c +++ b/build/gve_rx_dqo.c @@ -591,7 +591,7 @@ int gve_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp) { const struct gve_xdp_buff *ctx = (void *)_ctx; - if (!ctx->gve->nic_ts_report) + if (!gve_is_clock_enabled(ctx->gve)) return -ENODATA; if (!(ctx->compl_desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID)) diff --git a/google/gve/gve.h b/google/gve/gve.h index 970d5ca..cbdf3a8 100644 --- a/google/gve/gve.h +++ b/google/gve/gve.h @@ -1206,6 +1206,11 @@ static inline bool gve_supports_xdp_xmit(struct gve_priv *priv) } } +static inline bool gve_is_clock_enabled(struct gve_priv *priv) +{ + return priv->nic_ts_report; +} + /* gqi napi handler defined in gve_main.c */ int gve_napi_poll(struct napi_struct *napi, int budget); diff --git a/google/gve/gve_ethtool.c b/google/gve/gve_ethtool.c index 9ed1d45..42f0fde 100644 --- a/google/gve/gve_ethtool.c +++ b/google/gve/gve_ethtool.c @@ -942,7 +942,7 @@ static int gve_get_ts_info(struct net_device *netdev, ethtool_op_get_ts_info(netdev, info); - if (priv->nic_timestamp_supported) { + if (gve_is_clock_enabled(priv)) { info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; diff --git a/google/gve/gve_main.c b/google/gve/gve_main.c index 129f760..6ed1a6b 100644 --- a/google/gve/gve_main.c +++ b/google/gve/gve_main.c @@ -680,10 +680,12 @@ static int gve_setup_device_resources(struct gve_priv *priv) } } - err = gve_init_clock(priv); - if (err) { - dev_err(&priv->pdev->dev, "Failed to init clock"); - goto abort_with_ptype_lut; + if (priv->nic_timestamp_supported) { + err = gve_init_clock(priv); + if (err) { + dev_warn(&priv->pdev->dev, "Failed to init clock, continuing without PTP support"); + err = 0; + } } err = gve_init_rss_config(priv, priv->rx_cfg.num_queues); @@ -2183,7 +2185,7 @@ static int gve_set_ts_config(struct net_device *dev, } if (kernel_config->rx_filter != HWTSTAMP_FILTER_NONE) { - if (!priv->nic_ts_report) { + if (!gve_is_clock_enabled(priv)) { NL_SET_ERR_MSG_MOD(extack, "RX timestamping is not supported"); kernel_config->rx_filter = HWTSTAMP_FILTER_NONE; diff --git a/google/gve/gve_ptp.c b/google/gve/gve_ptp.c index 073677d..de42fc2 100644 --- a/google/gve/gve_ptp.c +++ b/google/gve/gve_ptp.c @@ -70,11 +70,6 @@ static int gve_ptp_init(struct gve_priv *priv) struct gve_ptp *ptp; int err; - if (!priv->nic_timestamp_supported) { - dev_dbg(&priv->pdev->dev, "Device does not support PTP\n"); - return -EOPNOTSUPP; - } - priv->ptp = kzalloc(sizeof(*priv->ptp), GFP_KERNEL); if (!priv->ptp) return -ENOMEM; @@ -116,9 +111,6 @@ int gve_init_clock(struct gve_priv *priv) { int err; - if (!priv->nic_timestamp_supported) - return 0; - err = gve_ptp_init(priv); if (err) return err; diff --git a/google/gve/gve_rx_dqo.c b/google/gve/gve_rx_dqo.c index f1bd8f5..63a9610 100644 --- a/google/gve/gve_rx_dqo.c +++ b/google/gve/gve_rx_dqo.c @@ -484,7 +484,7 @@ int gve_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp) { const struct gve_xdp_buff *ctx = (void *)_ctx; - if (!ctx->gve->nic_ts_report) + if (!gve_is_clock_enabled(ctx->gve)) return -ENODATA; if (!(ctx->compl_desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID)) From e52757f747d467dc7317b67f64589ae745963ea4 Mon Sep 17 00:00:00 2001 From: Debarghya Kundu Date: Mon, 2 Feb 2026 19:39:24 +0000 Subject: [PATCH 05/12] gve: Fix stats report corruption on queue count change The driver and the NIC share a region in memory for stats reporting. The NIC calculates its offset into this region based on the total size of the stats region and the size of the NIC's stats. When the number of queues is changed, the driver's stats region is resized. If the queue count is increased, the NIC can write past the end of the allocated stats region, causing memory corruption. If the queue count is decreased, there is a gap between the driver and NIC stats, leading to incorrect stats reporting. This change fixes the issue by allocating stats region with maximum size, and the offset calculation for NIC stats is changed to match with the calculation of the NIC. Cc: stable@vger.kernel.org Fixes: 24aeb56f2d38 ("gve: Add Gvnic stats AQ command and ethtool show/set-priv-flags.") Signed-off-by: Debarghya Kundu Reviewed-by: Joshua Washington Signed-off-by: Harshitha Ramamurthy Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20260202193925.3106272-2-hramamurthy@google.com Signed-off-by: Jakub Kicinski net-next: 7b9ebcce0296e104a0d82a6b09d68564806158ff --- build/gve_ethtool.c | 54 +++++++++++++++++++++++++--------------- build/gve_main.c | 6 ++--- google/gve/gve_ethtool.c | 54 +++++++++++++++++++++++++--------------- google/gve/gve_main.c | 4 +-- 4 files changed, 73 insertions(+), 45 deletions(-) diff --git a/build/gve_ethtool.c b/build/gve_ethtool.c index d8dfbdb..cdb0197 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -226,7 +226,8 @@ gve_get_ethtool_stats(struct net_device *netdev, u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt, rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped; - int stats_idx, base_stats_idx, max_stats_idx; + int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; + int stats_idx, stats_region_len, nic_stats_len; struct stats *report_stats; int *rx_qid_to_stats_idx; int *tx_qid_to_stats_idx; @@ -338,20 +339,38 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = priv->stats_report_trigger_cnt; i = GVE_MAIN_STATS_LEN; - /* For rx cross-reporting stats, start from nic rx stats in report */ - base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues + - GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues; - /* The boundary between driver stats and NIC stats shifts if there are - * stopped queues. - */ - base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs + - NIC_TX_STATS_REPORT_NUM * num_stopped_txqs; - max_stats_idx = NIC_RX_STATS_REPORT_NUM * - (priv->rx_cfg.num_queues - num_stopped_rxqs) + - base_stats_idx; + rx_base_stats_idx = 0; + max_rx_stats_idx = 0; + max_tx_stats_idx = 0; + stats_region_len = priv->stats_report_len - + sizeof(struct gve_stats_report); + nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues + + NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats); + if (unlikely((stats_region_len - + nic_stats_len) % sizeof(struct stats))) { + net_err_ratelimited("Starting index of NIC stats should be multiple of stats size"); + } else { + /* For rx cross-reporting stats, + * start from nic rx stats in report + */ + rx_base_stats_idx = (stats_region_len - nic_stats_len) / + sizeof(struct stats); + /* The boundary between driver stats and NIC stats + * shifts if there are stopped queues + */ + rx_base_stats_idx += NIC_RX_STATS_REPORT_NUM * + num_stopped_rxqs + NIC_TX_STATS_REPORT_NUM * + num_stopped_txqs; + max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM * + (priv->rx_cfg.num_queues - num_stopped_rxqs) + + rx_base_stats_idx; + max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM * + (num_tx_queues - num_stopped_txqs) + + max_rx_stats_idx; + } /* Preprocess the stats report for rx, map queue id to start index */ skip_nic_stats = false; - for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; + for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx; stats_idx += NIC_RX_STATS_REPORT_NUM) { u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); @@ -427,14 +446,9 @@ gve_get_ethtool_stats(struct net_device *netdev, i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS; } - /* For tx cross-reporting stats, start from nic tx stats in report */ - base_stats_idx = max_stats_idx; - max_stats_idx = NIC_TX_STATS_REPORT_NUM * - (num_tx_queues - num_stopped_txqs) + - max_stats_idx; - /* Preprocess the stats report for tx, map queue id to start index */ skip_nic_stats = false; - for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; + /* NIC TX stats start right after NIC RX stats */ + for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx; stats_idx += NIC_TX_STATS_REPORT_NUM) { u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); diff --git a/build/gve_main.c b/build/gve_main.c index 39f12f9..19f3f42 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--4010f8c-oot" +#define GVE_VERSION "1.4.8-0--056b6ba-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) @@ -336,9 +336,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv) int tx_stats_num, rx_stats_num; tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) * - gve_num_tx_queues(priv); + priv->tx_cfg.max_queues; rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) * - priv->rx_cfg.num_queues; + priv->rx_cfg.max_queues; #if !defined(struct_size) || !defined(size_add) priv->stats_report_len = sizeof(*priv->stats_report) + sizeof((priv->stats_report)->stats[0]) * (tx_stats_num + rx_stats_num); #else diff --git a/google/gve/gve_ethtool.c b/google/gve/gve_ethtool.c index 42f0fde..0c907dc 100644 --- a/google/gve/gve_ethtool.c +++ b/google/gve/gve_ethtool.c @@ -156,7 +156,8 @@ gve_get_ethtool_stats(struct net_device *netdev, u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt, rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, tx_dropped; - int stats_idx, base_stats_idx, max_stats_idx; + int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; + int stats_idx, stats_region_len, nic_stats_len; struct stats *report_stats; int *rx_qid_to_stats_idx; int *tx_qid_to_stats_idx; @@ -265,20 +266,38 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = priv->stats_report_trigger_cnt; i = GVE_MAIN_STATS_LEN; - /* For rx cross-reporting stats, start from nic rx stats in report */ - base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues + - GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues; - /* The boundary between driver stats and NIC stats shifts if there are - * stopped queues. - */ - base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs + - NIC_TX_STATS_REPORT_NUM * num_stopped_txqs; - max_stats_idx = NIC_RX_STATS_REPORT_NUM * - (priv->rx_cfg.num_queues - num_stopped_rxqs) + - base_stats_idx; + rx_base_stats_idx = 0; + max_rx_stats_idx = 0; + max_tx_stats_idx = 0; + stats_region_len = priv->stats_report_len - + sizeof(struct gve_stats_report); + nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues + + NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats); + if (unlikely((stats_region_len - + nic_stats_len) % sizeof(struct stats))) { + net_err_ratelimited("Starting index of NIC stats should be multiple of stats size"); + } else { + /* For rx cross-reporting stats, + * start from nic rx stats in report + */ + rx_base_stats_idx = (stats_region_len - nic_stats_len) / + sizeof(struct stats); + /* The boundary between driver stats and NIC stats + * shifts if there are stopped queues + */ + rx_base_stats_idx += NIC_RX_STATS_REPORT_NUM * + num_stopped_rxqs + NIC_TX_STATS_REPORT_NUM * + num_stopped_txqs; + max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM * + (priv->rx_cfg.num_queues - num_stopped_rxqs) + + rx_base_stats_idx; + max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM * + (num_tx_queues - num_stopped_txqs) + + max_rx_stats_idx; + } /* Preprocess the stats report for rx, map queue id to start index */ skip_nic_stats = false; - for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; + for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx; stats_idx += NIC_RX_STATS_REPORT_NUM) { u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); @@ -354,14 +373,9 @@ gve_get_ethtool_stats(struct net_device *netdev, i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS; } - /* For tx cross-reporting stats, start from nic tx stats in report */ - base_stats_idx = max_stats_idx; - max_stats_idx = NIC_TX_STATS_REPORT_NUM * - (num_tx_queues - num_stopped_txqs) + - max_stats_idx; - /* Preprocess the stats report for tx, map queue id to start index */ skip_nic_stats = false; - for (stats_idx = base_stats_idx; stats_idx < max_stats_idx; + /* NIC TX stats start right after NIC RX stats */ + for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx; stats_idx += NIC_TX_STATS_REPORT_NUM) { u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name); u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id); diff --git a/google/gve/gve_main.c b/google/gve/gve_main.c index 6ed1a6b..f25403b 100644 --- a/google/gve/gve_main.c +++ b/google/gve/gve_main.c @@ -283,9 +283,9 @@ static int gve_alloc_stats_report(struct gve_priv *priv) int tx_stats_num, rx_stats_num; tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) * - gve_num_tx_queues(priv); + priv->tx_cfg.max_queues; rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) * - priv->rx_cfg.num_queues; + priv->rx_cfg.max_queues; priv->stats_report_len = struct_size(priv->stats_report, stats, size_add(tx_stats_num, rx_stats_num)); priv->stats_report = From 2819ba93e2b0f8cb9bd523c29d6675e1620f0edd Mon Sep 17 00:00:00 2001 From: Max Yuan Date: Mon, 2 Feb 2026 19:39:25 +0000 Subject: [PATCH 06/12] gve: Correct ethtool rx_dropped calculation The gve driver's "rx_dropped" statistic, exposed via `ethtool -S`, incorrectly includes `rx_buf_alloc_fail` counts. These failures represent an inability to allocate receive buffers, not true packet drops where a received packet is discarded. This misrepresentation can lead to inaccurate diagnostics. This patch rectifies the ethtool "rx_dropped" calculation. It removes `rx_buf_alloc_fail` from the total and adds `xdp_tx_errors` and `xdp_redirect_errors`, which represent legitimate packet drops within the XDP path. Cc: stable@vger.kernel.org Fixes: 433e274b8f7b ("gve: Add stats for gve.") Signed-off-by: Max Yuan Reviewed-by: Jordan Rhee Reviewed-by: Joshua Washington Reviewed-by: Matt Olson Signed-off-by: Harshitha Ramamurthy Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20260202193925.3106272-3-hramamurthy@google.com Signed-off-by: Jakub Kicinski net-next: c7db85d579a1dccb624235534508c75fbf2dfe46 --- build/gve_ethtool.c | 23 +++++++++++++++++------ build/gve_main.c | 2 +- google/gve/gve_ethtool.c | 23 +++++++++++++++++------ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/build/gve_ethtool.c b/build/gve_ethtool.c index cdb0197..ad7448d 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -222,10 +222,11 @@ gve_get_ethtool_stats(struct net_device *netdev, u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes, tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail, tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt, - tmp_tx_pkts, tmp_tx_bytes; + tmp_tx_pkts, tmp_tx_bytes, + tmp_xdp_tx_errors, tmp_xdp_redirect_errors; u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt, rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, - tx_dropped; + tx_dropped, xdp_tx_errors, xdp_redirect_errors; int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; int stats_idx, stats_region_len, nic_stats_len; struct stats *report_stats; @@ -272,6 +273,7 @@ gve_get_ethtool_stats(struct net_device *netdev, for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0, rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0, + xdp_tx_errors = 0, xdp_redirect_errors = 0, ring = 0; ring < priv->rx_cfg.num_queues; ring++) { if (priv->rx) { @@ -289,6 +291,9 @@ gve_get_ethtool_stats(struct net_device *netdev, rx->rx_desc_err_dropped_pkt; tmp_rx_hsplit_unsplit_pkt = rx->rx_hsplit_unsplit_pkt; + tmp_xdp_tx_errors = rx->xdp_tx_errors; + tmp_xdp_redirect_errors = + rx->xdp_redirect_errors; } while (u64_stats_fetch_retry(&priv->rx[ring].statss, start)); rx_pkts += tmp_rx_pkts; @@ -298,6 +303,8 @@ gve_get_ethtool_stats(struct net_device *netdev, rx_buf_alloc_fail += tmp_rx_buf_alloc_fail; rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt; rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt; + xdp_tx_errors += tmp_xdp_tx_errors; + xdp_redirect_errors += tmp_xdp_redirect_errors; } } for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0; @@ -323,8 +330,8 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = rx_bytes; data[i++] = tx_bytes; /* total rx dropped packets */ - data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail + - rx_desc_err_dropped_pkt; + data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt + + xdp_tx_errors + xdp_redirect_errors; data[i++] = tx_dropped; data[i++] = priv->tx_timeo_cnt; data[i++] = rx_skb_alloc_fail; @@ -403,6 +410,9 @@ gve_get_ethtool_stats(struct net_device *netdev, tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; tmp_rx_desc_err_dropped_pkt = rx->rx_desc_err_dropped_pkt; + tmp_xdp_tx_errors = rx->xdp_tx_errors; + tmp_xdp_redirect_errors = + rx->xdp_redirect_errors; } while (u64_stats_fetch_retry(&priv->rx[ring].statss, start)); data[i++] = tmp_rx_bytes; @@ -413,8 +423,9 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = rx->rx_frag_alloc_cnt; /* rx dropped packets */ data[i++] = tmp_rx_skb_alloc_fail + - tmp_rx_buf_alloc_fail + - tmp_rx_desc_err_dropped_pkt; + tmp_rx_desc_err_dropped_pkt + + tmp_xdp_tx_errors + + tmp_xdp_redirect_errors; data[i++] = rx->rx_copybreak_pkt; data[i++] = rx->rx_copied_pkt; /* stats from NIC */ diff --git a/build/gve_main.c b/build/gve_main.c index 19f3f42..f1ea2c3 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--056b6ba-oot" +#define GVE_VERSION "1.4.8-0--04dfbab-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/google/gve/gve_ethtool.c b/google/gve/gve_ethtool.c index 0c907dc..42a0a6f 100644 --- a/google/gve/gve_ethtool.c +++ b/google/gve/gve_ethtool.c @@ -152,10 +152,11 @@ gve_get_ethtool_stats(struct net_device *netdev, u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes, tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail, tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt, - tmp_tx_pkts, tmp_tx_bytes; + tmp_tx_pkts, tmp_tx_bytes, + tmp_xdp_tx_errors, tmp_xdp_redirect_errors; u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt, rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes, - tx_dropped; + tx_dropped, xdp_tx_errors, xdp_redirect_errors; int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx; int stats_idx, stats_region_len, nic_stats_len; struct stats *report_stats; @@ -199,6 +200,7 @@ gve_get_ethtool_stats(struct net_device *netdev, for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0, rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0, rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0, + xdp_tx_errors = 0, xdp_redirect_errors = 0, ring = 0; ring < priv->rx_cfg.num_queues; ring++) { if (priv->rx) { @@ -216,6 +218,9 @@ gve_get_ethtool_stats(struct net_device *netdev, rx->rx_desc_err_dropped_pkt; tmp_rx_hsplit_unsplit_pkt = rx->rx_hsplit_unsplit_pkt; + tmp_xdp_tx_errors = rx->xdp_tx_errors; + tmp_xdp_redirect_errors = + rx->xdp_redirect_errors; } while (u64_stats_fetch_retry(&priv->rx[ring].statss, start)); rx_pkts += tmp_rx_pkts; @@ -225,6 +230,8 @@ gve_get_ethtool_stats(struct net_device *netdev, rx_buf_alloc_fail += tmp_rx_buf_alloc_fail; rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt; rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt; + xdp_tx_errors += tmp_xdp_tx_errors; + xdp_redirect_errors += tmp_xdp_redirect_errors; } } for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0; @@ -250,8 +257,8 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = rx_bytes; data[i++] = tx_bytes; /* total rx dropped packets */ - data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail + - rx_desc_err_dropped_pkt; + data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt + + xdp_tx_errors + xdp_redirect_errors; data[i++] = tx_dropped; data[i++] = priv->tx_timeo_cnt; data[i++] = rx_skb_alloc_fail; @@ -330,6 +337,9 @@ gve_get_ethtool_stats(struct net_device *netdev, tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; tmp_rx_desc_err_dropped_pkt = rx->rx_desc_err_dropped_pkt; + tmp_xdp_tx_errors = rx->xdp_tx_errors; + tmp_xdp_redirect_errors = + rx->xdp_redirect_errors; } while (u64_stats_fetch_retry(&priv->rx[ring].statss, start)); data[i++] = tmp_rx_bytes; @@ -340,8 +350,9 @@ gve_get_ethtool_stats(struct net_device *netdev, data[i++] = rx->rx_frag_alloc_cnt; /* rx dropped packets */ data[i++] = tmp_rx_skb_alloc_fail + - tmp_rx_buf_alloc_fail + - tmp_rx_desc_err_dropped_pkt; + tmp_rx_desc_err_dropped_pkt + + tmp_xdp_tx_errors + + tmp_xdp_redirect_errors; data[i++] = rx->rx_copybreak_pkt; data[i++] = rx->rx_copied_pkt; /* stats from NIC */ From b0a192f7fff40473b3947a07b5181930c3eb2bf1 Mon Sep 17 00:00:00 2001 From: Alice Mikityanska Date: Thu, 5 Feb 2026 15:39:22 +0200 Subject: [PATCH 07/12] gve: Remove jumbo_remove step from TX path Now that the kernel doesn't insert HBH for BIG TCP IPv6 packets, remove unnecessary steps from the gve TX path, that used to check and remove HBH. Signed-off-by: Alice Mikityanska Acked-by: Paolo Abeni Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20260205133925.526371-10-alice.kernel@fastmail.im Signed-off-by: Jakub Kicinski net-next: 275da93ce2b8fa2f82da1e8785d6f1930670ef88 --- build/gve_main.c | 2 +- build/gve_tx_dqo.c | 5 ----- google/gve/gve_tx_dqo.c | 3 --- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/build/gve_main.c b/build/gve_main.c index f1ea2c3..3921f4f 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--04dfbab-oot" +#define GVE_VERSION "1.4.8-0--98cea9a-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/build/gve_tx_dqo.c b/build/gve_tx_dqo.c index 458faa3..5fc2e4d 100644 --- a/build/gve_tx_dqo.c +++ b/build/gve_tx_dqo.c @@ -1035,11 +1035,6 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, int num_buffer_descs; int total_num_descs; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,1)) - if (skb_is_gso(skb) && unlikely(ipv6_hopopt_jumbo_remove(skb))) - goto drop; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,1) */ - if (tx->dqo.qpl) { /* We do not need to verify the number of buffers used per * packet or per segment in case of TSO as with 2K size buffers diff --git a/google/gve/gve_tx_dqo.c b/google/gve/gve_tx_dqo.c index 40b89b3..28e8573 100644 --- a/google/gve/gve_tx_dqo.c +++ b/google/gve/gve_tx_dqo.c @@ -963,9 +963,6 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, int num_buffer_descs; int total_num_descs; - if (skb_is_gso(skb) && unlikely(ipv6_hopopt_jumbo_remove(skb))) - goto drop; - if (tx->dqo.qpl) { /* We do not need to verify the number of buffers used per * packet or per segment in case of TSO as with 2K size buffers From 0b8b415b4e3164553d9ab82a72c14b61dc8e027b Mon Sep 17 00:00:00 2001 From: Joshua Washington Date: Mon, 8 Dec 2025 13:39:00 -0800 Subject: [PATCH 08/12] cocci: make netmem dma sync patch more generic Including full arguemnt list for coccinelle patches can be quite fragile, as if a single argument changes, the patch will no longer apply, and compile tests can break. Signed-off-by: Joshua Washington --- build/gve_main.c | 2 +- build/gve_rx_dqo.c | 6 ++---- patches/netmem_conversion.cocci | 18 +++++------------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/build/gve_main.c b/build/gve_main.c index 3921f4f..41c2985 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--98cea9a-oot" +#define GVE_VERSION "1.4.8-0--449fe96-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/build/gve_rx_dqo.c b/build/gve_rx_dqo.c index 400cbf1..4c07e5e 100644 --- a/build/gve_rx_dqo.c +++ b/build/gve_rx_dqo.c @@ -934,15 +934,13 @@ static void gve_dma_sync(struct gve_priv *priv, struct gve_rx_ring *rx, page_info->page_offset, buf_len); } else { +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ dma_sync_single_range_for_cpu(&priv->pdev->dev, buf_state->addr, page_info->page_offset + page_info->pad, buf_len, DMA_FROM_DEVICE); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) } -#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ - dma_sync_single_range_for_cpu(&priv->pdev->dev, buf_state->addr, - page_info->page_offset, buf_len, - DMA_FROM_DEVICE); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ } diff --git a/patches/netmem_conversion.cocci b/patches/netmem_conversion.cocci index c906fe6..972d7d8 100644 --- a/patches/netmem_conversion.cocci +++ b/patches/netmem_conversion.cocci @@ -198,26 +198,18 @@ if (!rx->ctx.skb_head && rx->dqo.page_pool && +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ @@ +expression dev, offset, pad, buf_len, dma_mode, addr; @@ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) if (rx->dqo.page_pool) { - page_pool_dma_sync_netmem_for_cpu(rx->dqo.page_pool, - page_info->netmem, - page_info->page_offset, - buf_len); + page_pool_dma_sync_netmem_for_cpu(...); } else { - dma_sync_single_range_for_cpu(&priv->pdev->dev, buf_state->addr, - page_info->page_offset + - page_info->pad, - buf_len, DMA_FROM_DEVICE); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ + dma_sync_single_range_for_cpu(...); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) } -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ -+ dma_sync_single_range_for_cpu(&priv->pdev->dev, buf_state->addr, -+ page_info->page_offset, -+ buf_len, DMA_FROM_DEVICE); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ - @@ @@ if (eop && buf_len <= priv->rx_copybreak From e4cc19ec4c2c6b30a9fe2ddf356da6adf76f0383 Mon Sep 17 00:00:00 2001 From: Joshua Washington Date: Tue, 3 Feb 2026 11:49:33 -0800 Subject: [PATCH 09/12] cocci: fix skb_add_rx_frag for XDP Kernel versions between 6.7 (when page pool was introduced) and 6.14 do not currently have skb_add_rx_frag working properly in the XDP_PASS case, as the coccinelle patch does not make use of the newer gve_skb_add_rx_frag. Update the coccinelle patch to use gve_skb_add_rx_frag in all cases, patching out the behavior in the function itself instead of patching out the function entirely for older kernel versions. Fixes: 3d7cf4062cbe5 ("gve: convert to use netmem for DQO RDA mode") Signed-off-by: Joshua Washington --- build/gve_main.c | 2 +- build/gve_rx_dqo.c | 19 ++++------------ patches/netmem_conversion.cocci | 39 +++++++++------------------------ 3 files changed, 15 insertions(+), 45 deletions(-) diff --git a/build/gve_main.c b/build/gve_main.c index 41c2985..6cdb169 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--449fe96-oot" +#define GVE_VERSION "1.4.8-0--a1dc850-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/build/gve_rx_dqo.c b/build/gve_rx_dqo.c index 4c07e5e..29b2498 100644 --- a/build/gve_rx_dqo.c +++ b/build/gve_rx_dqo.c @@ -652,11 +652,11 @@ static int gve_rx_copy_ondemand(struct gve_rx_ring *rx, return 0; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) static void gve_skb_add_rx_frag(struct gve_rx_ring *rx, struct gve_rx_buf_state_dqo *buf_state, int num_frags, u16 buf_len) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) if (rx->dqo.page_pool) { skb_add_rx_frag_netmem(rx->ctx.skb_tail, num_frags, buf_state->page_info.netmem, @@ -664,14 +664,16 @@ static void gve_skb_add_rx_frag(struct gve_rx_ring *rx, buf_state->page_info.pad, buf_len, buf_state->page_info.buf_size); } else { +#endif skb_add_rx_frag(rx->ctx.skb_tail, num_frags, buf_state->page_info.page, buf_state->page_info.page_offset + buf_state->page_info.pad, buf_len, buf_state->page_info.buf_size); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) } +#endif } -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) */ /* Chains multi skbs for single rx packet. * Returns 0 if buffer is appended, -1 otherwise. @@ -711,15 +713,8 @@ static int gve_rx_append_frags(struct napi_struct *napi, /* Trigger ondemand page allocation if we are running low on buffers */ if (gve_rx_should_trigger_copy_ondemand(rx)) return gve_rx_copy_ondemand(rx, buf_state, buf_len); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) gve_skb_add_rx_frag(rx, buf_state, num_frags, buf_len); -#else - skb_add_rx_frag(rx->ctx.skb_tail, num_frags, - buf_state->page_info.page, - buf_state->page_info.page_offset, buf_len, - buf_state->page_info.buf_size); -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(6,7,0)) gve_dec_pagecnt_bias(&buf_state->page_info); gve_try_recycle_buf(priv, rx, buf_state); @@ -1141,13 +1136,7 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, skb_mark_for_recycle(rx->ctx.skb_head); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6,7,0)) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) gve_skb_add_rx_frag(rx, buf_state, 0, buf_len); -#else - skb_add_rx_frag(rx->ctx.skb_head, 0, buf_state->page_info.page, - buf_state->page_info.page_offset, buf_len, - buf_state->page_info.buf_size); -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(6,7,0)) gve_dec_pagecnt_bias(&buf_state->page_info); gve_try_recycle_buf(priv, rx, buf_state); diff --git a/patches/netmem_conversion.cocci b/patches/netmem_conversion.cocci index 972d7d8..36d02a0 100644 --- a/patches/netmem_conversion.cocci +++ b/patches/netmem_conversion.cocci @@ -14,31 +14,21 @@ struct gve_rx_slot_page_info { }; @@ +expression pp; @@ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) -static void gve_skb_add_rx_frag(...) +void gve_skb_add_rx_frag(...) { - ... ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) +if (pp) { +... +} else { ++#endif +... ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) } -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) */ ++#endif -@@ -@@ -static int gve_rx_append_frags(...) -{ - ... - if (gve_rx_should_trigger_copy_ondemand(rx)) - return gve_rx_copy_ondemand(rx, buf_state, buf_len); -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) - gve_skb_add_rx_frag(rx, buf_state, num_frags, buf_len); -+#else -+ skb_add_rx_frag(rx->ctx.skb_tail, num_frags, -+ buf_state->page_info.page, -+ buf_state->page_info.page_offset, -+ buf_len, buf_state->page_info.buf_size); -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) */ - ... } @@ @@ -57,15 +47,6 @@ static int gve_rx_dqo(...) + prefetch(buf_state->page_info.page); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ ... -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0)) - gve_skb_add_rx_frag(rx, buf_state, 0, buf_len); -+#else -+ skb_add_rx_frag(rx->ctx.skb_head, 0, buf_state->page_info.page, -+ buf_state->page_info.page_offset, buf_len, -+ buf_state->page_info.buf_size); -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,14,0) */ - gve_reuse_buffer(rx, buf_state); - ... } @@ From 491a8c03233237160eada8ae47760c91661a2fb0 Mon Sep 17 00:00:00 2001 From: Eddie Phillips Date: Fri, 13 Feb 2026 00:14:43 +0000 Subject: [PATCH 10/12] cocci: patch for d43ab0d (gve: Remove jumbo_remove step from TX path) --- build/gve_main.c | 2 +- build/gve_tx_dqo.c | 3 +++ patches/jumbo_remove_hopopt_ipv6.cocci | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 patches/jumbo_remove_hopopt_ipv6.cocci diff --git a/build/gve_main.c b/build/gve_main.c index 6cdb169..2769e3c 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--a1dc850-oot" +#define GVE_VERSION "1.4.8-0--620bd14-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/build/gve_tx_dqo.c b/build/gve_tx_dqo.c index 5fc2e4d..734a642 100644 --- a/build/gve_tx_dqo.c +++ b/build/gve_tx_dqo.c @@ -1032,6 +1032,9 @@ netdev_features_t gve_features_check_dqo(struct sk_buff *skb, static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, struct sk_buff *skb) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(6,19,0) + if (skb_is_gso(skb) && unlikely(ipv6_hopopt_jumbo_remove(skb))) goto drop; +#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(6,19,0) */ int num_buffer_descs; int total_num_descs; diff --git a/patches/jumbo_remove_hopopt_ipv6.cocci b/patches/jumbo_remove_hopopt_ipv6.cocci new file mode 100644 index 0000000..5ddfc9b --- /dev/null +++ b/patches/jumbo_remove_hopopt_ipv6.cocci @@ -0,0 +1,14 @@ +@@ +@@ + + static int gve_try_tx_skb(...) + { + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(6,19,0) ++ if (skb_is_gso(skb) && unlikely(ipv6_hopopt_jumbo_remove(skb))) ++ goto drop; ++#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(6,19,0) */ + + ... + } + From 6f07dff8a31fc8c5a835aee223001f21f3be5ba6 Mon Sep 17 00:00:00 2001 From: Eddie Phillips Date: Fri, 13 Feb 2026 21:40:08 +0000 Subject: [PATCH 11/12] cocci: Correct kernel versioning for config and ethtool patch --- build/gve_ethtool.c | 4 ++-- build/gve_main.c | 10 +++++----- patches/ethtool_ntuple.cocci | 4 ++-- patches/patch_netdev_queue_api.cocci | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/gve_ethtool.c b/build/gve_ethtool.c index ad7448d..d2f2cfa 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -1029,10 +1029,10 @@ static int gve_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u int err = 0; switch (cmd->cmd) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(7,0,0) case ETHTOOL_GRXRINGS: cmd->data = gve_get_rx_ring_count(netdev); break; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) */ +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(7,0,0) */ case ETHTOOL_GRXCLSRLCNT: if (!priv->max_flow_rules) return -EOPNOTSUPP; diff --git a/build/gve_main.c b/build/gve_main.c index 2769e3c..212e886 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--620bd14-oot" +#define GVE_VERSION "1.4.8-0--6cc52f7-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) @@ -3135,10 +3135,10 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) static int gve_rx_queue_mem_alloc(struct net_device *dev -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) , struct netdev_queue_config *qcfg -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ , void *per_q_mem, int idx) { @@ -3164,10 +3164,10 @@ static int gve_rx_queue_mem_alloc(struct net_device *dev #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) static int gve_rx_queue_start(struct net_device *dev -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) , struct netdev_queue_config *qcfg -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ , void *per_q_mem, int idx) { diff --git a/patches/ethtool_ntuple.cocci b/patches/ethtool_ntuple.cocci index 7773b71..a714229 100644 --- a/patches/ethtool_ntuple.cocci +++ b/patches/ethtool_ntuple.cocci @@ -64,11 +64,11 @@ static int gve_get_rxnfc(...) { ... switch (cmd->cmd) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(7,0,0) + case ETHTOOL_GRXRINGS: + cmd->data = gve_get_rx_ring_count(netdev); + break; -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0) */ ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(7,0,0) */ case ETHTOOL_GRXCLSRLCNT: ... } diff --git a/patches/patch_netdev_queue_api.cocci b/patches/patch_netdev_queue_api.cocci index 44a7c48..15a38b9 100644 --- a/patches/patch_netdev_queue_api.cocci +++ b/patches/patch_netdev_queue_api.cocci @@ -38,9 +38,9 @@ parameter P1, P2, P3, P4; @@ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) static int gve_rx_queue_mem_alloc(P1 -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) ,P2 -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ ,P3, P4) { ... @@ -61,9 +61,9 @@ parameter P1, P2, P3, P4; @@ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,10,0)) static int gve_rx_queue_start(P1 -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) ,P2 -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,19,0) */ ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ ,P3, P4) { ... From 328e95fda54916a7549a726558426d8cee065de5 Mon Sep 17 00:00:00 2001 From: Eddie Phillips Date: Fri, 13 Feb 2026 23:08:23 +0000 Subject: [PATCH 12/12] Bump driver version to v1.4.9 --- build/gve_main.c | 2 +- google/gve/gve_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/gve_main.c b/build/gve_main.c index 212e886..9d09b41 100644 --- a/build/gve_main.c +++ b/build/gve_main.c @@ -39,7 +39,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8-0--6cc52f7-oot" +#define GVE_VERSION "1.4.9-0--6cc52f7-oot" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds) diff --git a/google/gve/gve_main.c b/google/gve/gve_main.c index f25403b..10ad184 100644 --- a/google/gve/gve_main.c +++ b/google/gve/gve_main.c @@ -30,7 +30,7 @@ #define GVE_DEFAULT_RX_COPYBREAK (256) #define DEFAULT_MSG_LEVEL (NETIF_MSG_DRV | NETIF_MSG_LINK) -#define GVE_VERSION "1.4.8" +#define GVE_VERSION "1.4.9" #define GVE_VERSION_PREFIX "GVE-" // Minimum amount of time between queue kicks in msec (10 seconds)