275 lines
11 KiB
Diff
275 lines
11 KiB
Diff
From: Joshua Washington <joshwash@google.com>
|
|
Date: Fri, 5 Jun 2026 00:00:00 +0000
|
|
Subject: gve: Add adminq support for modifiable ring size
|
|
|
|
Add support for the gVNIC "modify ring" device option, which allows the
|
|
device to report the maximum and minimum TX/RX ring sizes it supports.
|
|
Store those bounds in the priv struct and report the device-provided
|
|
maximums through ethtool -g "Pre-set maximums" instead of hardcoding the
|
|
current (default) ring size as the maximum.
|
|
|
|
If the device does not provide minimums, fall back to the default
|
|
minimums of 256 descriptors for TX and 512 for RX.
|
|
|
|
This is the first half of the upstream gve modifiable-ring-size feature.
|
|
It only changes the advertised ring size range; actually resizing the
|
|
rings is added in the following patch.
|
|
|
|
[Jonathan Wright: backported the upstream modifiable-ring-size support to
|
|
this kernel's gve, using the implementation carried by the RHEL 10 /
|
|
AlmaLinux 10 gve driver (kernel 6.12.0-211.7.1.el10_2) as the reference,
|
|
since this 5.14-based gve predates the feature entirely. Adaptations:
|
|
threaded dev_op_modify_ring through this tree's smaller
|
|
gve_parse_device_option()/gve_process_device_options() signatures; seeded
|
|
the default ring-size ranges in both gve_set_desc_cnt() and
|
|
gve_set_desc_cnt_dqo(). Dropped the upstream
|
|
"if (priv->queue_format != GVE_DQO_QPL_FORMAT)" guard around the max ring
|
|
size assignment: that guard exists because DQO-QPL used a fixed QPL page
|
|
budget, which no longer applies now that QPL pages scale with ring size
|
|
(see 1106-gve-Update-QPL-page-registration-logic.patch), and keeping it
|
|
would deny DQO-QPL VMs the larger ring sizes this feature is for.]
|
|
Signed-off-by: Jonathan Wright <jonathan@almalinux.org>
|
|
---
|
|
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
|
|
index f916e81..a3c1caa 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve.h
|
|
+++ b/drivers/net/ethernet/google/gve/gve.h
|
|
@@ -52,6 +52,9 @@
|
|
|
|
#define GVE_DEFAULT_RX_BUFFER_OFFSET 2048
|
|
|
|
+#define GVE_DEFAULT_MIN_TX_RING_SIZE 256
|
|
+#define GVE_DEFAULT_MIN_RX_RING_SIZE 512
|
|
+
|
|
#define GVE_XDP_ACTIONS 5
|
|
|
|
#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
|
|
@@ -647,6 +650,12 @@ struct gve_priv {
|
|
u16 num_event_counters;
|
|
u16 tx_desc_cnt; /* num desc per ring */
|
|
u16 rx_desc_cnt; /* num desc per ring */
|
|
+ u16 max_tx_desc_cnt;
|
|
+ u16 max_rx_desc_cnt;
|
|
+ u16 min_tx_desc_cnt;
|
|
+ u16 min_rx_desc_cnt;
|
|
+ bool modify_ring_size_enabled;
|
|
+ bool default_min_ring_size;
|
|
u16 tx_pages_per_qpl; /* Number of pages per qpl for TX queues */
|
|
u16 rx_pages_per_qpl; /* Number of pages per qpl for RX queues */
|
|
u16 rx_data_slot_cnt; /* rx buffer length */
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
|
|
index 62817f8..b7f86bc 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
|
|
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
|
|
@@ -20,6 +20,8 @@
|
|
|
|
#define GVE_DEVICE_OPTION_TOO_BIG_FMT "Length of %s option larger than expected. Possible older version of guest driver.\n"
|
|
|
|
+#define GVE_DEVICE_OPTION_NO_MIN_RING_SIZE 8
|
|
+
|
|
static
|
|
struct gve_device_option *gve_get_next_option(struct gve_device_descriptor *descriptor,
|
|
struct gve_device_option *option)
|
|
@@ -40,7 +42,8 @@ void gve_parse_device_option(struct gve_priv *priv,
|
|
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
|
|
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
|
|
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
|
|
- struct gve_device_option_dqo_qpl **dev_op_dqo_qpl)
|
|
+ struct gve_device_option_dqo_qpl **dev_op_dqo_qpl,
|
|
+ struct gve_device_option_modify_ring **dev_op_modify_ring)
|
|
{
|
|
u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
|
|
u16 option_length = be16_to_cpu(option->option_length);
|
|
@@ -129,6 +132,27 @@ void gve_parse_device_option(struct gve_priv *priv,
|
|
}
|
|
*dev_op_dqo_qpl = (void *)(option + 1);
|
|
break;
|
|
+ case GVE_DEV_OPT_ID_MODIFY_RING:
|
|
+ if (option_length < GVE_DEVICE_OPTION_NO_MIN_RING_SIZE ||
|
|
+ req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING) {
|
|
+ dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT,
|
|
+ "Modify Ring", (int)sizeof(**dev_op_modify_ring),
|
|
+ GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING,
|
|
+ option_length, req_feat_mask);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (option_length > sizeof(**dev_op_modify_ring)) {
|
|
+ dev_warn(&priv->pdev->dev,
|
|
+ GVE_DEVICE_OPTION_TOO_BIG_FMT, "Modify Ring");
|
|
+ }
|
|
+
|
|
+ *dev_op_modify_ring = (void *)(option + 1);
|
|
+
|
|
+ /* device has not provided min ring size */
|
|
+ if (option_length == GVE_DEVICE_OPTION_NO_MIN_RING_SIZE)
|
|
+ priv->default_min_ring_size = true;
|
|
+ break;
|
|
case GVE_DEV_OPT_ID_JUMBO_FRAMES:
|
|
if (option_length < sizeof(**dev_op_jumbo_frames) ||
|
|
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) {
|
|
@@ -164,7 +188,8 @@ gve_process_device_options(struct gve_priv *priv,
|
|
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
|
|
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
|
|
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
|
|
- struct gve_device_option_dqo_qpl **dev_op_dqo_qpl)
|
|
+ struct gve_device_option_dqo_qpl **dev_op_dqo_qpl,
|
|
+ struct gve_device_option_modify_ring **dev_op_modify_ring)
|
|
{
|
|
const int num_options = be16_to_cpu(descriptor->num_device_options);
|
|
struct gve_device_option *dev_opt;
|
|
@@ -185,7 +210,7 @@ gve_process_device_options(struct gve_priv *priv,
|
|
gve_parse_device_option(priv, descriptor, dev_opt,
|
|
dev_op_gqi_rda, dev_op_gqi_qpl,
|
|
dev_op_dqo_rda, dev_op_jumbo_frames,
|
|
- dev_op_dqo_qpl);
|
|
+ dev_op_dqo_qpl, dev_op_modify_ring);
|
|
dev_opt = next_opt;
|
|
}
|
|
|
|
@@ -728,6 +753,12 @@ static int gve_set_desc_cnt(struct gve_priv *priv,
|
|
{
|
|
priv->tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
|
|
priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
|
|
+
|
|
+ /* set default ranges */
|
|
+ priv->max_tx_desc_cnt = priv->tx_desc_cnt;
|
|
+ priv->max_rx_desc_cnt = priv->rx_desc_cnt;
|
|
+ priv->min_tx_desc_cnt = priv->tx_desc_cnt;
|
|
+ priv->min_rx_desc_cnt = priv->rx_desc_cnt;
|
|
return 0;
|
|
}
|
|
|
|
@@ -739,6 +770,12 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv,
|
|
priv->tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
|
|
priv->rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
|
|
|
|
+ /* set default ranges */
|
|
+ priv->max_tx_desc_cnt = priv->tx_desc_cnt;
|
|
+ priv->max_rx_desc_cnt = priv->rx_desc_cnt;
|
|
+ priv->min_tx_desc_cnt = priv->tx_desc_cnt;
|
|
+ priv->min_rx_desc_cnt = priv->rx_desc_cnt;
|
|
+
|
|
if (priv->queue_format == GVE_DQO_QPL_FORMAT)
|
|
return 0;
|
|
|
|
@@ -755,7 +792,9 @@ static void gve_enable_supported_features(struct gve_priv *priv,
|
|
const struct gve_device_option_jumbo_frames
|
|
*dev_op_jumbo_frames,
|
|
const struct gve_device_option_dqo_qpl
|
|
- *dev_op_dqo_qpl)
|
|
+ *dev_op_dqo_qpl,
|
|
+ const struct gve_device_option_modify_ring
|
|
+ *dev_op_modify_ring)
|
|
{
|
|
/* Before control reaches this point, the page-size-capped max MTU from
|
|
* the gve_device_descriptor field has already been stored in
|
|
@@ -767,10 +806,29 @@ static void gve_enable_supported_features(struct gve_priv *priv,
|
|
"JUMBO FRAMES device option enabled.\n");
|
|
priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
|
|
}
|
|
+
|
|
+ /* Read and store ring size ranges given by device */
|
|
+ if (dev_op_modify_ring &&
|
|
+ (supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) {
|
|
+ priv->modify_ring_size_enabled = true;
|
|
+
|
|
+ priv->max_rx_desc_cnt = be16_to_cpu(dev_op_modify_ring->max_rx_ring_size);
|
|
+ priv->max_tx_desc_cnt = be16_to_cpu(dev_op_modify_ring->max_tx_ring_size);
|
|
+
|
|
+ if (priv->default_min_ring_size) {
|
|
+ /* If device hasn't provided minimums, use default minimums */
|
|
+ priv->min_tx_desc_cnt = GVE_DEFAULT_MIN_TX_RING_SIZE;
|
|
+ priv->min_rx_desc_cnt = GVE_DEFAULT_MIN_RX_RING_SIZE;
|
|
+ } else {
|
|
+ priv->min_rx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_rx_ring_size);
|
|
+ priv->min_tx_desc_cnt = be16_to_cpu(dev_op_modify_ring->min_tx_ring_size);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
int gve_adminq_describe_device(struct gve_priv *priv)
|
|
{
|
|
+ struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
|
|
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
|
|
struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
|
|
struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
|
|
@@ -804,7 +862,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
|
|
err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda,
|
|
&dev_op_gqi_qpl, &dev_op_dqo_rda,
|
|
&dev_op_jumbo_frames,
|
|
- &dev_op_dqo_qpl);
|
|
+ &dev_op_dqo_qpl, &dev_op_modify_ring);
|
|
if (err)
|
|
goto free_device_descriptor;
|
|
|
|
@@ -873,7 +931,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
|
|
priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues);
|
|
|
|
gve_enable_supported_features(priv, supported_features_mask,
|
|
- dev_op_jumbo_frames, dev_op_dqo_qpl);
|
|
+ dev_op_jumbo_frames, dev_op_dqo_qpl,
|
|
+ dev_op_modify_ring);
|
|
|
|
free_device_descriptor:
|
|
dma_pool_free(priv->adminq_pool, descriptor, descriptor_bus);
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
|
|
index 5865ccd..0d1dd38 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_adminq.h
|
|
+++ b/drivers/net/ethernet/google/gve/gve_adminq.h
|
|
@@ -125,6 +125,16 @@ struct gve_device_option_jumbo_frames {
|
|
|
|
static_assert(sizeof(struct gve_device_option_jumbo_frames) == 8);
|
|
|
|
+struct gve_device_option_modify_ring {
|
|
+ __be32 supported_featured_mask;
|
|
+ __be16 max_rx_ring_size;
|
|
+ __be16 max_tx_ring_size;
|
|
+ __be16 min_rx_ring_size;
|
|
+ __be16 min_tx_ring_size;
|
|
+};
|
|
+
|
|
+static_assert(sizeof(struct gve_device_option_modify_ring) == 12);
|
|
+
|
|
/* Terminology:
|
|
*
|
|
* RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
|
|
@@ -138,6 +148,7 @@ enum gve_dev_opt_id {
|
|
GVE_DEV_OPT_ID_GQI_RDA = 0x2,
|
|
GVE_DEV_OPT_ID_GQI_QPL = 0x3,
|
|
GVE_DEV_OPT_ID_DQO_RDA = 0x4,
|
|
+ GVE_DEV_OPT_ID_MODIFY_RING = 0x6,
|
|
GVE_DEV_OPT_ID_DQO_QPL = 0x7,
|
|
GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8,
|
|
};
|
|
@@ -149,9 +160,11 @@ enum gve_dev_opt_req_feat_mask {
|
|
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0,
|
|
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0,
|
|
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL = 0x0,
|
|
+ GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING = 0x0,
|
|
};
|
|
|
|
enum gve_sup_feature_mask {
|
|
+ GVE_SUP_MODIFY_RING_MASK = 1 << 0,
|
|
GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2,
|
|
};
|
|
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
|
|
index e5397aa..fb7b477 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
|
|
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
|
|
@@ -476,8 +476,8 @@ static void gve_get_ringparam(struct net_device *netdev,
|
|
{
|
|
struct gve_priv *priv = netdev_priv(netdev);
|
|
|
|
- cmd->rx_max_pending = priv->rx_desc_cnt;
|
|
- cmd->tx_max_pending = priv->tx_desc_cnt;
|
|
+ cmd->rx_max_pending = priv->max_rx_desc_cnt;
|
|
+ cmd->tx_max_pending = priv->max_tx_desc_cnt;
|
|
cmd->rx_pending = priv->rx_desc_cnt;
|
|
cmd->tx_pending = priv->tx_desc_cnt;
|
|
}
|
|
--
|
|
2.43.0
|
|
|