From: Ankit Garg Previously, enabling header split via `gve_set_hsplit_config` also implicitly changed the RX buffer length to 4K (if supported by the device). This coupled two settings that should be orthogonal; this patch removes that side effect. After this change, `gve_set_hsplit_config` only toggles the header split configuration. The RX buffer length is no longer affected and must be configured independently. Signed-off-by: Ankit Garg Reviewed-by: Harshitha Ramamurthy Reviewed-by: Jordan Rhee Reviewed-by: Willem de Bruijn Signed-off-by: Joshua Washington --- drivers/net/ethernet/google/gve/gve.h | 3 --- drivers/net/ethernet/google/gve/gve_ethtool.c | 2 -- drivers/net/ethernet/google/gve/gve_main.c | 10 ---------- 3 files changed, 15 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index ac325ab..872dae6 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -59,8 +59,6 @@ #define GVE_DEFAULT_RX_BUFFER_SIZE 2048 -#define GVE_MAX_RX_BUFFER_SIZE 4096 - #define GVE_XDP_RX_BUFFER_SIZE_DQO 4096 #define GVE_DEFAULT_RX_BUFFER_OFFSET 2048 @@ -1247,7 +1245,6 @@ void gve_rx_free_rings_gqi(struct gve_priv *priv, struct gve_rx_alloc_rings_cfg *cfg); void gve_rx_start_ring_gqi(struct gve_priv *priv, int idx); void gve_rx_stop_ring_gqi(struct gve_priv *priv, int idx); -u16 gve_get_pkt_buf_size(const struct gve_priv *priv, bool enable_hplit); bool gve_header_split_supported(const struct gve_priv *priv); int gve_set_hsplit_config(struct gve_priv *priv, u8 tcp_data_split, struct gve_rx_alloc_rings_cfg *rx_alloc_cfg); diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index b030a84..db6fc85 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -606,8 +606,6 @@ static int gve_set_ringparam(struct net_device *netdev, } else { /* Set ring params for the next up */ priv->header_split_enabled = rx_alloc_cfg.enable_header_split; - priv->rx_cfg.packet_buffer_size = - rx_alloc_cfg.packet_buffer_size; priv->tx_desc_cnt = tx_alloc_cfg.ring_size; priv->rx_desc_cnt = rx_alloc_cfg.ring_size; } diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index 347391a..453e40a 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -2041,14 +2041,6 @@ static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue) priv->tx_timeo_cnt++; } -u16 gve_get_pkt_buf_size(const struct gve_priv *priv, bool enable_hsplit) -{ - if (enable_hsplit && priv->max_rx_buffer_size >= GVE_MAX_RX_BUFFER_SIZE) - return GVE_MAX_RX_BUFFER_SIZE; - else - return GVE_DEFAULT_RX_BUFFER_SIZE; -} - /* Header split is only supported on DQ RDA queue format. If XDP is enabled, * header split is not allowed. */ @@ -2080,8 +2072,6 @@ int gve_set_hsplit_config(struct gve_priv *priv, u8 tcp_data_split, return 0; rx_alloc_cfg->enable_header_split = enable_hdr_split; - rx_alloc_cfg->packet_buffer_size = - gve_get_pkt_buf_size(priv, enable_hdr_split); return 0; } -- 2.51.2.997.g839fc31de9-goog From: Ankit Garg Plumb extack as it allows us to send more detailed error messages back and append 'gve' suffix to method name per convention. NL_SET_ERR_MSG_FMT_MOD doesn't support format string longer than 80 chars so keeping netdev warning with actual queue count details. Signed-off-by: Ankit Garg Reviewed-by: Harshitha Ramamurthy Reviewed-by: Willem de Bruijn Signed-off-by: Joshua Washington --- Changes in v3: * Removed newline from extack messages (Jakub Kicinski) Changes in v2: * Add this patch to the series for RX buffer length management (Jakub Kicinski) --- drivers/net/ethernet/google/gve/gve_main.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index 453e40a..c1d9916 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1707,18 +1707,21 @@ static int gve_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags) return 0; } -static int verify_xdp_configuration(struct net_device *dev) +static int gve_verify_xdp_configuration(struct net_device *dev, + struct netlink_ext_ack *extack) { struct gve_priv *priv = netdev_priv(dev); u16 max_xdp_mtu; if (dev->features & NETIF_F_LRO) { - netdev_warn(dev, "XDP is not supported when LRO is on.\n"); + NL_SET_ERR_MSG_MOD(extack, + "XDP is not supported when LRO is on."); return -EOPNOTSUPP; } if (priv->header_split_enabled) { - netdev_warn(dev, "XDP is not supported when header-data split is enabled.\n"); + NL_SET_ERR_MSG_MOD(extack, + "XDP is not supported when header-data split is enabled."); return -EOPNOTSUPP; } @@ -1727,17 +1730,20 @@ static int verify_xdp_configuration(struct net_device *dev) max_xdp_mtu -= GVE_RX_PAD; if (dev->mtu > max_xdp_mtu) { - netdev_warn(dev, "XDP is not supported for mtu %d.\n", - dev->mtu); + NL_SET_ERR_MSG_FMT_MOD(extack, + "XDP is not supported for mtu %d.", + dev->mtu); return -EOPNOTSUPP; } if (priv->rx_cfg.num_queues != priv->tx_cfg.num_queues || (2 * priv->tx_cfg.num_queues > priv->tx_cfg.max_queues)) { - netdev_warn(dev, "XDP load failed: The number of configured RX queues %d should be equal to the number of configured TX queues %d and the number of configured RX/TX queues should be less than or equal to half the maximum number of RX/TX queues %d", - priv->rx_cfg.num_queues, - priv->tx_cfg.num_queues, + netdev_warn(dev, + "XDP load failed: The number of configured RX queues %d should be equal to the number of configured TX queues %d and the number of configured RX/TX queues should be less than or equal to half the maximum number of RX/TX queues %d.", + priv->rx_cfg.num_queues, priv->tx_cfg.num_queues, priv->tx_cfg.max_queues); + NL_SET_ERR_MSG_MOD(extack, + "XDP load failed: The number of configured RX queues should be equal to the number of configured TX queues and the number of configured RX/TX queues should be less than or equal to half the maximum number of RX/TX queues"); return -EINVAL; } return 0; @@ -1748,7 +1754,7 @@ static int gve_xdp(struct net_device *dev, struct netdev_bpf *xdp) struct gve_priv *priv = netdev_priv(dev); int err; - err = verify_xdp_configuration(dev); + err = gve_verify_xdp_configuration(dev, xdp->extack); if (err) return err; switch (xdp->command) { -- 2.51.2.997.g839fc31de9-goog From: Ankit Garg Add support for getting and setting the RX buffer length via the ethtool ring parameters (`ethtool -g`/`-G`). The driver restricts the allowed buffer length to 2048 (SZ_2K) by default and allows 4096 (SZ_4K) based on device options. As XDP is only supported when the `rx_buf_len` is 2048, the driver now enforces this in two places: 1. In `gve_xdp_set`, rejecting XDP programs if the current buffer length is not 2048. 2. In `gve_set_rx_buf_len_config`, rejecting buffer length changes if XDP is loaded and the new length is not 2048. Signed-off-by: Ankit Garg Reviewed-by: Harshitha Ramamurthy Reviewed-by: Jordan Rhee Reviewed-by: Willem de Bruijn Signed-off-by: Joshua Washington --- Changes in v3: * Removed newline from extack messages (Jakub Kicinski) Changes in v2: * Refactored RX buffer length validation to clarify that it handles scenario when device doesn't advertise 4K support (Jakub Kicinski) --- drivers/net/ethernet/google/gve/gve.h | 9 +++++++++ drivers/net/ethernet/google/gve/gve_ethtool.c | 13 ++++++++++++- drivers/net/ethernet/google/gve/gve_main.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h index 872dae6..bebd1ac 100644 --- a/drivers/net/ethernet/google/gve/gve.h +++ b/drivers/net/ethernet/google/gve/gve.h @@ -1165,6 +1165,12 @@ static inline bool gve_is_gqi(struct gve_priv *priv) priv->queue_format == GVE_GQI_QPL_FORMAT; } +static inline bool gve_is_dqo(struct gve_priv *priv) +{ + return priv->queue_format == GVE_DQO_RDA_FORMAT || + priv->queue_format == GVE_DQO_QPL_FORMAT; +} + static inline u32 gve_num_tx_queues(struct gve_priv *priv) { return priv->tx_cfg.num_queues + priv->tx_cfg.num_xdp_queues; @@ -1246,6 +1252,9 @@ void gve_rx_free_rings_gqi(struct gve_priv *priv, void gve_rx_start_ring_gqi(struct gve_priv *priv, int idx); void gve_rx_stop_ring_gqi(struct gve_priv *priv, int idx); bool gve_header_split_supported(const struct gve_priv *priv); +int gve_set_rx_buf_len_config(struct gve_priv *priv, u32 rx_buf_len, + struct netlink_ext_ack *extack, + struct gve_rx_alloc_rings_cfg *rx_alloc_cfg); int gve_set_hsplit_config(struct gve_priv *priv, u8 tcp_data_split, struct gve_rx_alloc_rings_cfg *rx_alloc_cfg); /* rx buffer handling */ diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index db6fc85..52500ae 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -529,6 +529,8 @@ static void gve_get_ringparam(struct net_device *netdev, cmd->rx_pending = priv->rx_desc_cnt; cmd->tx_pending = priv->tx_desc_cnt; + kernel_cmd->rx_buf_len = priv->rx_cfg.packet_buffer_size; + if (!gve_header_split_supported(priv)) kernel_cmd->tcp_data_split = ETHTOOL_TCP_DATA_SPLIT_UNKNOWN; else if (priv->header_split_enabled) @@ -589,6 +591,12 @@ static int gve_set_ringparam(struct net_device *netdev, int err; gve_get_curr_alloc_cfgs(priv, &tx_alloc_cfg, &rx_alloc_cfg); + + err = gve_set_rx_buf_len_config(priv, kernel_cmd->rx_buf_len, extack, + &rx_alloc_cfg); + if (err) + return err; + err = gve_set_hsplit_config(priv, kernel_cmd->tcp_data_split, &rx_alloc_cfg); if (err) @@ -605,6 +613,8 @@ static int gve_set_ringparam(struct net_device *netdev, return err; } else { /* Set ring params for the next up */ + priv->rx_cfg.packet_buffer_size = + rx_alloc_cfg.packet_buffer_size; priv->header_split_enabled = rx_alloc_cfg.enable_header_split; priv->tx_desc_cnt = tx_alloc_cfg.ring_size; priv->rx_desc_cnt = rx_alloc_cfg.ring_size; @@ -944,7 +954,8 @@ static int gve_get_ts_info(struct net_device *netdev, const struct ethtool_ops gve_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS, - .supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT, + .supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT | + ETHTOOL_RING_USE_RX_BUF_LEN, .get_drvinfo = gve_get_drvinfo, .get_strings = gve_get_strings, .get_sset_count = gve_get_sset_count, diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index c1d9916..2a24b3a 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1725,6 +1725,13 @@ static int gve_verify_xdp_configuration(struct net_device *dev, return -EOPNOTSUPP; } + if (priv->rx_cfg.packet_buffer_size != SZ_2K) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "XDP is not supported for Rx buf len %d, only %d supported.", + priv->rx_cfg.packet_buffer_size, SZ_2K); + return -EOPNOTSUPP; + } + max_xdp_mtu = priv->rx_cfg.packet_buffer_size - sizeof(struct ethhdr); if (priv->queue_format == GVE_GQI_QPL_FORMAT) max_xdp_mtu -= GVE_RX_PAD; @@ -2056,6 +2063,38 @@ bool gve_header_split_supported(const struct gve_priv *priv) priv->queue_format == GVE_DQO_RDA_FORMAT && !priv->xdp_prog; } +int gve_set_rx_buf_len_config(struct gve_priv *priv, u32 rx_buf_len, + struct netlink_ext_ack *extack, + struct gve_rx_alloc_rings_cfg *rx_alloc_cfg) +{ + u32 old_rx_buf_len = rx_alloc_cfg->packet_buffer_size; + + if (rx_buf_len == old_rx_buf_len) + return 0; + + /* device options may not always contain support for 4K buffers */ + if (!gve_is_dqo(priv) || priv->max_rx_buffer_size < SZ_4K) { + NL_SET_ERR_MSG_MOD(extack, + "Modifying Rx buf len is not supported"); + return -EOPNOTSUPP; + } + + if (priv->xdp_prog && rx_buf_len != SZ_2K) { + NL_SET_ERR_MSG_MOD(extack, + "Rx buf len can only be 2048 when XDP is on"); + return -EINVAL; + } + + if (rx_buf_len != SZ_2K && rx_buf_len != SZ_4K) { + NL_SET_ERR_MSG_MOD(extack, + "Rx buf len can only be 2048 or 4096"); + return -EINVAL; + } + rx_alloc_cfg->packet_buffer_size = rx_buf_len; + + return 0; +} + int gve_set_hsplit_config(struct gve_priv *priv, u8 tcp_data_split, struct gve_rx_alloc_rings_cfg *rx_alloc_cfg) { -- 2.51.2.997.g839fc31de9-goog From: Ankit Garg Change the driver's default behavior to prefer the largest available RX buffer length supported by the device for DQO format, rather than always using the hardcoded 2K default. Previously, the driver would initialize with `GVE_DEFAULT_RX_BUFFER_SIZE` (2K), even if the device advertised support for a larger length (e.g., 4K). Performance observations: - With LRO disabled, we observed >10% improvement in RX single stream throughput when MTU >=2048. - With LRO enabled, we observed >10% improvement in RX single stream throughput when MTU >=1460. - No regressions were observed. Signed-off-by: Ankit Garg Reviewed-by: Harshitha Ramamurthy Reviewed-by: Jordan Rhee Reviewed-by: Willem de Bruijn Signed-off-by: Joshua Washington --- drivers/net/ethernet/google/gve/gve_adminq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c index 4f33d09..b72cc0f 100644 --- a/drivers/net/ethernet/google/gve/gve_adminq.c +++ b/drivers/net/ethernet/google/gve/gve_adminq.c @@ -987,6 +987,10 @@ static void gve_enable_supported_features(struct gve_priv *priv, dev_info(&priv->pdev->dev, "BUFFER SIZES device option enabled with max_rx_buffer_size of %u, header_buf_size of %u.\n", priv->max_rx_buffer_size, priv->header_buf_size); + if (gve_is_dqo(priv) && + priv->max_rx_buffer_size > GVE_DEFAULT_RX_BUFFER_SIZE) + priv->rx_cfg.packet_buffer_size = + priv->max_rx_buffer_size; } /* Read and store ring size ranges given by device */ -- 2.51.2.997.g839fc31de9-goog