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_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_ethtool.c b/build/gve_ethtool.c index 3e674e0..d2f2cfa 100644 --- a/build/gve_ethtool.c +++ b/build/gve_ethtool.c @@ -222,11 +222,13 @@ 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; - int stats_idx, base_stats_idx, max_stats_idx; + 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; int *rx_qid_to_stats_idx; int *tx_qid_to_stats_idx; @@ -271,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) { @@ -288,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; @@ -297,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; @@ -322,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; @@ -338,20 +346,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); @@ -384,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; @@ -394,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 */ @@ -427,14 +457,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); @@ -991,15 +1016,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(7,0,0) + case ETHTOOL_GRXRINGS: cmd->data = gve_get_rx_ring_count(netdev); break; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(7,0,0) */ case ETHTOOL_GRXCLSRLCNT: if (!priv->max_flow_rules) return -EOPNOTSUPP; @@ -1192,9 +1225,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; @@ -1204,7 +1236,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; } @@ -1233,6 +1264,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 9a0e239..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--34ae86a-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) @@ -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 @@ -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); @@ -855,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); @@ -2589,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"); @@ -3124,8 +3134,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(7,0,0) + , + struct netdev_queue_config *qcfg +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ + , + void *per_q_mem, int idx) { struct gve_priv *priv = netdev_priv(dev); struct gve_rx_alloc_rings_cfg cfg = {0}; @@ -3148,7 +3163,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(7,0,0) + , + struct netdev_queue_config *qcfg +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,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/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 f0d0da4..29b2498 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)) @@ -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); @@ -934,15 +929,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) */ } @@ -1046,7 +1039,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. @@ -1143,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/build/gve_tx_dqo.c b/build/gve_tx_dqo.c index 458faa3..734a642 100644 --- a/build/gve_tx_dqo.c +++ b/build/gve_tx_dqo.c @@ -1032,14 +1032,12 @@ 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; -#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/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.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 52500ae..42a0a6f 100644 --- a/google/gve/gve_ethtool.c +++ b/google/gve/gve_ethtool.c @@ -152,11 +152,13 @@ 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; - int stats_idx, base_stats_idx, max_stats_idx; + 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; int *rx_qid_to_stats_idx; int *tx_qid_to_stats_idx; @@ -198,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) { @@ -215,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; @@ -224,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; @@ -249,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; @@ -265,20 +273,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); @@ -311,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; @@ -321,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 */ @@ -354,14 +384,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); @@ -815,15 +840,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; @@ -938,7 +967,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; @@ -966,6 +995,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/google/gve/gve_main.c b/google/gve/gve_main.c index 2590028..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) @@ -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 = @@ -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); @@ -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; @@ -2616,8 +2618,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 +2641,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/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)) 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 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/ethtool_ntuple.cocci b/patches/ethtool_ntuple.cocci index cbfe099..a714229 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(7,0,0) ++ case ETHTOOL_GRXRINGS: ++ cmd->data = gve_get_rx_ring_count(netdev); ++ break; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(7,0,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) */ +}; + 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 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) */ + + ... + } + diff --git a/patches/netmem_conversion.cocci b/patches/netmem_conversion.cocci index c906fe6..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); - ... } @@ @@ -198,26 +179,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 diff --git a/patches/patch_netdev_queue_api.cocci b/patches/patch_netdev_queue_api.cocci index 40b49b6..15a38b9 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(7,0,0) + ,P2 ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,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(7,0,0) + ,P2 ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(7,0,0) */ + ,P3, P4) { ... }